// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/callback.h" #include "base/process_util.h" #include "chrome/common/render_messages.h" #include "chrome/renderer/media/audio_renderer_impl.h" #include "media/base/data_buffer.h" #include "media/base/media_format.h" #include "media/base/mock_filter_host.h" #include "media/base/mock_filters.h" #include "testing/gtest/include/gtest/gtest.h" using ::testing::ReturnRef; class AudioRendererImplTest : public ::testing::Test { public: static const int kRouteId = 0; static const int kSize = 1024; AudioRendererImplTest() { message_loop_.reset(new MessageLoop(MessageLoop::TYPE_IO)); // TODO(scherkus): use gmock with AudioMessageFilter to verify // AudioRendererImpl calls or doesn't call Send(). filter_ = new AudioMessageFilter(kRouteId); filter_->message_loop_ = message_loop_.get(); // Create temporary shared memory. CHECK(shared_mem_.Create(L"", false, false, kSize)); // Setup expectations for initialization. EXPECT_CALL(callback_, OnFilterCallback()); EXPECT_CALL(callback_, OnCallbackDestroyed()); decoder_ = new media::MockAudioDecoder(); // Associate media format with decoder decoder_media_format_.SetAsString(media::MediaFormat::kMimeType, media::mime_type::kUncompressedAudio); decoder_media_format_.SetAsInteger(media::MediaFormat::kChannels, 2); decoder_media_format_.SetAsInteger(media::MediaFormat::kSampleRate, 48000); decoder_media_format_.SetAsInteger(media::MediaFormat::kSampleBits, 16); EXPECT_CALL(*decoder_, media_format()) .WillRepeatedly(ReturnRef(decoder_media_format_)); // Create and initialize audio renderer. renderer_ = new AudioRendererImpl(filter_); renderer_->set_host(&host_); renderer_->set_message_loop(message_loop_.get()); renderer_->Initialize(decoder_, callback_.NewCallback()); // Run pending tasks and simulate responding with a created audio stream. message_loop_->RunAllPending(); // Duplicate the shared memory handle so both the test and the callee can // close their copy. base::SharedMemoryHandle duplicated_handle; EXPECT_TRUE(shared_mem_.ShareToProcess(base::GetCurrentProcessHandle(), &duplicated_handle)); renderer_->OnCreated(duplicated_handle, kSize); } virtual ~AudioRendererImplTest() { } protected: // Fixtures. scoped_ptr message_loop_; scoped_refptr filter_; base::SharedMemory shared_mem_; media::MockFilterHost host_; media::MockFilterCallback callback_; media::MockFilterCallback stop_callback_; scoped_refptr decoder_; scoped_refptr renderer_; media::MediaFormat decoder_media_format_; private: DISALLOW_COPY_AND_ASSIGN(AudioRendererImplTest); }; TEST_F(AudioRendererImplTest, SetPlaybackRate) { // Execute SetPlaybackRate() codepath to create an IPC message. // Toggle play/pause to generate some IPC messages. renderer_->SetPlaybackRate(0.0f); renderer_->SetPlaybackRate(1.0f); renderer_->SetPlaybackRate(0.0f); EXPECT_CALL(stop_callback_, OnFilterCallback()); renderer_->Stop(stop_callback_.NewCallback()); message_loop_->RunAllPending(); } TEST_F(AudioRendererImplTest, SetVolume) { // Execute SetVolume() codepath to create an IPC message. renderer_->SetVolume(0.5f); EXPECT_CALL(stop_callback_, OnFilterCallback()); renderer_->Stop(stop_callback_.NewCallback()); message_loop_->RunAllPending(); } TEST_F(AudioRendererImplTest, Stop) { // Declare some state messages. const ViewMsg_AudioStreamState_Params kError = { ViewMsg_AudioStreamState_Params::kError }; const ViewMsg_AudioStreamState_Params kPlaying = { ViewMsg_AudioStreamState_Params::kPlaying }; const ViewMsg_AudioStreamState_Params kPaused = { ViewMsg_AudioStreamState_Params::kPaused }; // Execute Stop() codepath to create an IPC message. EXPECT_CALL(stop_callback_, OnFilterCallback()); renderer_->Stop(stop_callback_.NewCallback()); message_loop_->RunAllPending(); // Run AudioMessageFilter::Delegate methods, which can be executed after being // stopped. AudioRendererImpl shouldn't create any messages. renderer_->OnRequestPacket(kSize, base::Time()); renderer_->OnStateChanged(kError); renderer_->OnStateChanged(kPlaying); renderer_->OnStateChanged(kPaused); renderer_->OnCreated(shared_mem_.handle(), kSize); renderer_->OnVolume(0.5); // It's possible that the upstream decoder replies right after being stopped. scoped_refptr buffer = new media::DataBuffer(kSize); renderer_->OnReadComplete(buffer); } TEST_F(AudioRendererImplTest, DestroyedMessageLoop_SetPlaybackRate) { // Kill the message loop and verify SetPlaybackRate() still works. message_loop_.reset(); renderer_->SetPlaybackRate(0.0f); renderer_->SetPlaybackRate(1.0f); renderer_->SetPlaybackRate(0.0f); EXPECT_CALL(stop_callback_, OnFilterCallback()); renderer_->Stop(stop_callback_.NewCallback()); } TEST_F(AudioRendererImplTest, DestroyedMessageLoop_SetVolume) { // Kill the message loop and verify SetVolume() still works. message_loop_.reset(); renderer_->SetVolume(0.5f); EXPECT_CALL(stop_callback_, OnFilterCallback()); renderer_->Stop(stop_callback_.NewCallback()); } TEST_F(AudioRendererImplTest, DestroyedMessageLoop_OnReadComplete) { // Kill the message loop and verify OnReadComplete() still works. message_loop_.reset(); scoped_refptr buffer = new media::DataBuffer(kSize); renderer_->OnReadComplete(buffer); EXPECT_CALL(stop_callback_, OnFilterCallback()); renderer_->Stop(stop_callback_.NewCallback()); }