Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(846)

Unified Diff: media/audio/audio_output_controller_unittest.cc

Issue 11413078: Tab Audio Capture: Browser-side connect/disconnect functionality. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Remove WCAudioInputStream changes (split into another change). Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: media/audio/audio_output_controller_unittest.cc
diff --git a/media/audio/audio_output_controller_unittest.cc b/media/audio/audio_output_controller_unittest.cc
index fe29ce59af3f969a10191e1b5742cbe64acfd389..05077e46afe4ade5050c398e7353fdecec66d483 100644
--- a/media/audio/audio_output_controller_unittest.cc
+++ b/media/audio/audio_output_controller_unittest.cc
@@ -2,23 +2,23 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/basictypes.h"
#include "base/bind.h"
#include "base/environment.h"
-#include "base/basictypes.h"
#include "base/logging.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
#include "base/message_loop.h"
#include "base/synchronization/waitable_event.h"
#include "media/audio/audio_output_controller.h"
+#include "media/audio/audio_parameters.h"
+#include "media/base/audio_bus.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-// TODO(vrk): These tests need to be rewritten! (crbug.com/112500)
-
using ::testing::_;
using ::testing::AtLeast;
using ::testing::DoAll;
-using ::testing::Exactly;
-using ::testing::InvokeWithoutArgs;
using ::testing::NotNull;
using ::testing::Return;
@@ -64,223 +64,296 @@ ACTION_P(SignalEvent, event) {
event->Signal();
}
-// Custom action to clear a memory buffer.
-ACTION(ClearBuffer) {
- arg1->Zero();
-}
-
-// Closes AudioOutputController synchronously.
-static void CloseAudioController(AudioOutputController* controller) {
- controller->Close(MessageLoop::QuitClosure());
- MessageLoop::current()->Run();
+static const float kBufferZeroData = 0.0f;
+static const float kBufferNonZeroData = 1.0f;
+ACTION_P(PopulateBuffer, value) {
+ // Note: To confirm the buffer will be populated in these tests, it's
+ // sufficient that only the first float in channel 0 is set to the value.
+ arg1->channel(0)[0] = value;
}
class AudioOutputControllerTest : public testing::Test {
public:
- AudioOutputControllerTest() {}
- virtual ~AudioOutputControllerTest() {}
+ AudioOutputControllerTest()
+ : audio_manager_(AudioManager::Create()),
+ create_event_(false, false),
+ play_event_(false, false),
+ read_event_(false, false),
+ pause_event_(false, false),
+ diverted_callback_(NULL) {
+ if (ShouldSkipTest()) {
DaleCurtis 2012/12/05 23:35:14 Shouldn't be necessary anymore since we have FakeA
miu 2012/12/11 02:30:45 Done.
+ DLOG(WARNING)
+ << "Skipping tests because OS provides no audio output devices.";
+ }
+ }
+
+ virtual ~AudioOutputControllerTest() {
+ ASSERT_FALSE(diverted_callback_);
+ }
protected:
- MessageLoopForIO message_loop_;
+ bool ShouldSkipTest() {
+ return !audio_manager_->HasAudioOutputDevices();
+ }
+
+ // Returns true if a controller was successfully created.
+ bool Create(int samples_per_packet) {
+ params_ = AudioParameters(
+ AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout,
+ kSampleRate, kBitsPerSample, samples_per_packet);
+ controller_ = AudioOutputController::Create(
+ audio_manager_.get(), &mock_event_handler_, params_,
+ &mock_sync_reader_);
+
+ if (controller_) {
+ EXPECT_FALSE(create_event_.IsSignaled());
+ EXPECT_CALL(mock_event_handler_, OnCreated(NotNull()))
+ .WillOnce(SignalEvent(&create_event_));
+ EXPECT_CALL(mock_sync_reader_, Close());
+ } else {
+ EXPECT_CALL(mock_event_handler_, OnCreated(NotNull()))
+ .Times(0);
+ EXPECT_CALL(mock_sync_reader_, Close())
+ .Times(0);
+ }
+
+ EXPECT_FALSE(play_event_.IsSignaled());
+ EXPECT_FALSE(read_event_.IsSignaled());
+ EXPECT_FALSE(pause_event_.IsSignaled());
+
+ return controller_ != NULL;
+ }
+
+ void Play() {
+ // Expect the event handler to receive one OnPlaying() call.
+ EXPECT_CALL(mock_event_handler_, OnPlaying(NotNull()))
+ .WillOnce(SignalEvent(&play_event_));
+
+ // During playback, the mock pretends to provide audio data rendered and
+ // sent from the render process.
+ EXPECT_CALL(mock_sync_reader_, UpdatePendingBytes(_))
+ .Times(AtLeast(2));
+ EXPECT_CALL(mock_sync_reader_, Read(_, _))
+ .WillRepeatedly(DoAll(PopulateBuffer(kBufferNonZeroData),
+ SignalEvent(&read_event_),
+ Return(params_.frames_per_buffer())));
+ EXPECT_CALL(mock_sync_reader_, DataReady())
+ .WillRepeatedly(Return(true));
+
+ controller_->Play();
+ }
+
+ void Pause() {
+ // Expect the event handler to receive one OnPaused() call.
+ EXPECT_CALL(mock_event_handler_, OnPaused(NotNull()))
+ .WillOnce(SignalEvent(&pause_event_));
+
+ controller_->Pause();
+ }
+
+ void ChangeDevice() {
+ // Expect the event handler to receive one OnPaying() call and no OnPaused()
+ // call.
+ EXPECT_CALL(mock_event_handler_, OnPlaying(NotNull()))
+ .WillOnce(SignalEvent(&play_event_));
+ EXPECT_CALL(mock_event_handler_, OnPaused(NotNull()))
+ .Times(0);
+
+ // Simulate a device change event to AudioOutputController from the
+ // AudioManager.
+ audio_manager_->GetMessageLoop()->PostTask(
+ FROM_HERE,
+ base::Bind(&AudioOutputController::OnDeviceChange, controller_));
+ }
+
+ void Divert() {
+ EXPECT_FALSE(diverted_callback_);
+ diverted_callback_ = controller_->Divert();
+ EXPECT_TRUE(diverted_callback_);
+ }
+
+ // |expected_buffer_data| is used to differentiate between: 1) expecting to
+ // see audio data rendered from the render process; versus 2) expecting
+ // AudioOutputController to be filling-in zeros (i.e., it is not in a playback
+ // state).
+ void ReadDivertedAudioData(float expected_buffer_data) {
+ ASSERT_TRUE(diverted_callback_);
+ scoped_ptr<AudioBus> dest = AudioBus::Create(params_);
+ const int frames_read =
+ diverted_callback_->OnMoreData(dest.get(), AudioBuffersState());
+ EXPECT_EQ(dest->frames(), frames_read);
+ EXPECT_EQ(expected_buffer_data, dest->channel(0)[0]);
+ }
+
+ // |expect_playback_restored| is true if the revert happened during the
+ // playback state. In this case, we expect event handler to receive one call
+ // to OnPlaying().
+ void Revert(bool expect_playback_restored) {
+ EXPECT_TRUE(diverted_callback_);
+ if (expect_playback_restored) {
+ EXPECT_CALL(mock_event_handler_, OnPlaying(NotNull()))
+ .WillOnce(SignalEvent(&play_event_));
+ } else {
+ EXPECT_CALL(mock_event_handler_, OnPlaying(NotNull()))
+ .Times(0);
+ }
+ controller_->Revert(diverted_callback_);
+ diverted_callback_ = NULL;
+ }
+
+ void Close() {
+ controller_->Close(MessageLoop::QuitClosure());
+ MessageLoop::current()->Run();
+ }
+
+ // These synchronize the main thread with key events taking place on other
+ // threads.
+ void WaitForCreate() { create_event_.Wait(); }
+ void WaitForPlay() { play_event_.Wait(); }
+ void WaitForReads() {
+ // Note: Arbitrarily chosen, but more iterations causes tests to take
+ // significantly more time.
+ static const int kNumIterations = 3;
+ for (int i = 0; i < kNumIterations; ++i) {
+ read_event_.Wait();
+ }
+ }
+ void WaitForPause() { pause_event_.Wait(); }
private:
+ MessageLoopForIO message_loop_;
+ scoped_ptr<AudioManager> audio_manager_;
+ MockAudioOutputControllerEventHandler mock_event_handler_;
+ MockAudioOutputControllerSyncReader mock_sync_reader_;
+ base::WaitableEvent create_event_;
+ base::WaitableEvent play_event_;
+ base::WaitableEvent read_event_;
+ base::WaitableEvent pause_event_;
+ AudioParameters params_;
+ scoped_refptr<AudioOutputController> controller_;
+ AudioOutputStream::AudioSourceCallback* diverted_callback_;
+
DISALLOW_COPY_AND_ASSIGN(AudioOutputControllerTest);
};
TEST_F(AudioOutputControllerTest, CreateAndClose) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::Create());
- if (!audio_manager->HasAudioOutputDevices())
+ if (ShouldSkipTest())
return;
+ ASSERT_TRUE(Create(kSamplesPerPacket));
+ Close();
+}
- MockAudioOutputControllerEventHandler event_handler;
-
- EXPECT_CALL(event_handler, OnCreated(NotNull()))
- .Times(1);
-
- MockAudioOutputControllerSyncReader sync_reader;
- EXPECT_CALL(sync_reader, Close());
-
- AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout,
- kSampleRate, kBitsPerSample, kSamplesPerPacket);
- scoped_refptr<AudioOutputController> controller =
- AudioOutputController::Create(
- audio_manager.get(), &event_handler, params, &sync_reader);
- ASSERT_TRUE(controller.get());
+TEST_F(AudioOutputControllerTest, HardwareBufferTooLarge) {
+ if (ShouldSkipTest())
+ return;
+ EXPECT_FALSE(Create(kSamplesPerPacket * 1000));
+}
- // Close the controller immediately.
- CloseAudioController(controller);
+TEST_F(AudioOutputControllerTest, PlayAndClose) {
+ if (ShouldSkipTest())
+ return;
+ ASSERT_TRUE(Create(kSamplesPerPacket));
+ WaitForCreate();
+ Play();
+ WaitForPlay();
+ WaitForReads();
+ Close();
}
TEST_F(AudioOutputControllerTest, PlayPauseClose) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::Create());
- if (!audio_manager->HasAudioOutputDevices())
+ if (ShouldSkipTest())
return;
-
- MockAudioOutputControllerEventHandler event_handler;
- base::WaitableEvent event(false, false);
- base::WaitableEvent pause_event(false, false);
-
- // If OnCreated is called then signal the event.
- EXPECT_CALL(event_handler, OnCreated(NotNull()))
- .WillOnce(InvokeWithoutArgs(&event, &base::WaitableEvent::Signal));
-
- // OnPlaying() will be called only once.
- EXPECT_CALL(event_handler, OnPlaying(NotNull()));
-
- MockAudioOutputControllerSyncReader sync_reader;
- EXPECT_CALL(sync_reader, UpdatePendingBytes(_))
- .Times(AtLeast(2));
- EXPECT_CALL(sync_reader, Read(_, _))
- .WillRepeatedly(DoAll(ClearBuffer(), SignalEvent(&event),
- Return(4)));
- EXPECT_CALL(sync_reader, DataReady())
- .WillRepeatedly(Return(true));
- EXPECT_CALL(event_handler, OnPaused(NotNull()))
- .WillOnce(InvokeWithoutArgs(&pause_event, &base::WaitableEvent::Signal));
- EXPECT_CALL(sync_reader, Close());
-
- AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout,
- kSampleRate, kBitsPerSample, kSamplesPerPacket);
- scoped_refptr<AudioOutputController> controller =
- AudioOutputController::Create(
- audio_manager.get(), &event_handler, params, &sync_reader);
- ASSERT_TRUE(controller.get());
-
- // Wait for OnCreated() to be called.
- event.Wait();
-
- ASSERT_FALSE(pause_event.IsSignaled());
- controller->Play();
- controller->Pause();
- pause_event.Wait();
-
- // Now stop the controller.
- CloseAudioController(controller);
+ ASSERT_TRUE(Create(kSamplesPerPacket));
+ WaitForCreate();
+ Play();
+ WaitForPlay();
+ WaitForReads();
+ Pause();
+ WaitForPause();
+ Close();
}
-TEST_F(AudioOutputControllerTest, HardwareBufferTooLarge) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::Create());
- if (!audio_manager->HasAudioOutputDevices())
+TEST_F(AudioOutputControllerTest, PlayPausePlayClose) {
+ if (ShouldSkipTest())
return;
-
- // Create an audio device with a very large hardware buffer size.
- MockAudioOutputControllerEventHandler event_handler;
-
- MockAudioOutputControllerSyncReader sync_reader;
- AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout,
- kSampleRate, kBitsPerSample,
- kSamplesPerPacket * 1000);
- scoped_refptr<AudioOutputController> controller =
- AudioOutputController::Create(
- audio_manager.get(), &event_handler, params, &sync_reader);
-
- // Use assert because we don't stop the device and assume we can't
- // create one.
- ASSERT_FALSE(controller);
+ ASSERT_TRUE(Create(kSamplesPerPacket));
+ WaitForCreate();
+ Play();
+ WaitForPlay();
+ WaitForReads();
+ Pause();
+ WaitForPause();
+ Play();
+ WaitForPlay();
+ Close();
}
-TEST_F(AudioOutputControllerTest, PlayPausePlayClose) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::Create());
- if (!audio_manager->HasAudioOutputDevices())
+TEST_F(AudioOutputControllerTest, PlayDeviceChangeClose) {
+ if (ShouldSkipTest())
return;
+ ASSERT_TRUE(Create(kSamplesPerPacket));
+ WaitForCreate();
+ Play();
+ WaitForPlay();
+ WaitForReads();
+ ChangeDevice();
+ WaitForPlay();
+ WaitForReads();
+ Close();
+}
- MockAudioOutputControllerEventHandler event_handler;
- base::WaitableEvent event(false, false);
- EXPECT_CALL(event_handler, OnCreated(NotNull()))
- .WillOnce(InvokeWithoutArgs(&event, &base::WaitableEvent::Signal));
-
- // OnPlaying() will be called only once.
- base::WaitableEvent play_event(false, false);
- EXPECT_CALL(event_handler, OnPlaying(NotNull()))
- .WillOnce(InvokeWithoutArgs(&play_event, &base::WaitableEvent::Signal));
-
- // OnPaused() should never be called since the pause during kStarting is
- // dropped when the second play comes in.
- EXPECT_CALL(event_handler, OnPaused(NotNull()))
- .Times(0);
-
- MockAudioOutputControllerSyncReader sync_reader;
- EXPECT_CALL(sync_reader, UpdatePendingBytes(_))
- .Times(AtLeast(1));
- EXPECT_CALL(sync_reader, Read(_, _))
- .WillRepeatedly(DoAll(ClearBuffer(), SignalEvent(&event), Return(4)));
- EXPECT_CALL(sync_reader, DataReady())
- .WillRepeatedly(Return(true));
- EXPECT_CALL(sync_reader, Close());
-
- AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout,
- kSampleRate, kBitsPerSample, kSamplesPerPacket);
- scoped_refptr<AudioOutputController> controller =
- AudioOutputController::Create(
- audio_manager.get(), &event_handler, params, &sync_reader);
- ASSERT_TRUE(controller.get());
-
- // Wait for OnCreated() to be called.
- event.Wait();
-
- ASSERT_FALSE(play_event.IsSignaled());
- controller->Play();
- controller->Pause();
- controller->Play();
- play_event.Wait();
-
- // Now stop the controller.
- CloseAudioController(controller);
+TEST_F(AudioOutputControllerTest, PlayDivertRevertClose) {
+ if (ShouldSkipTest())
+ return;
+ ASSERT_TRUE(Create(kSamplesPerPacket));
+ WaitForCreate();
+ Play();
+ WaitForPlay();
+ WaitForReads();
+ Divert();
+ ReadDivertedAudioData(kBufferNonZeroData);
+ Revert(true);
+ WaitForPlay();
+ WaitForReads();
+ Close();
}
-// Ensure state change events are handled.
-TEST_F(AudioOutputControllerTest, PlayStateChangeClose) {
- scoped_ptr<AudioManager> audio_manager(AudioManager::Create());
- if (!audio_manager->HasAudioOutputDevices())
+TEST_F(AudioOutputControllerTest, DivertPlayPausePlayRevertClose) {
+ if (ShouldSkipTest())
return;
+ ASSERT_TRUE(Create(kSamplesPerPacket));
+ WaitForCreate();
+ Divert();
+ // Read back zeros before playback starts.
+ ReadDivertedAudioData(kBufferZeroData);
+ Play();
+ WaitForPlay();
+ // Normal read of audio data from renderer.
+ ReadDivertedAudioData(kBufferNonZeroData);
+ Pause();
+ WaitForPause();
+ // Read back zeros while paused.
+ ReadDivertedAudioData(kBufferZeroData);
+ Play();
+ WaitForPlay();
+ // Normal read of audio data from renderer again.
+ ReadDivertedAudioData(kBufferNonZeroData);
+ Revert(true);
+ WaitForPlay();
+ WaitForReads();
+ Close();
+}
- MockAudioOutputControllerEventHandler event_handler;
- base::WaitableEvent event(false, false);
- EXPECT_CALL(event_handler, OnCreated(NotNull()))
- .WillOnce(InvokeWithoutArgs(&event, &base::WaitableEvent::Signal));
-
- // OnPlaying() will be called once normally and once after being recreated.
- base::WaitableEvent play_event(false, false);
- EXPECT_CALL(event_handler, OnPlaying(NotNull()))
- .Times(2)
- .WillRepeatedly(InvokeWithoutArgs(
- &play_event, &base::WaitableEvent::Signal));
-
- // OnPaused() should not be called during the state change event.
- EXPECT_CALL(event_handler, OnPaused(NotNull()))
- .Times(0);
-
- MockAudioOutputControllerSyncReader sync_reader;
- EXPECT_CALL(sync_reader, UpdatePendingBytes(_))
- .Times(AtLeast(1));
- EXPECT_CALL(sync_reader, Read(_, _))
- .WillRepeatedly(DoAll(ClearBuffer(), SignalEvent(&event), Return(4)));
- EXPECT_CALL(sync_reader, DataReady())
- .WillRepeatedly(Return(true));
- EXPECT_CALL(sync_reader, Close());
-
- AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout,
- kSampleRate, kBitsPerSample, kSamplesPerPacket);
- scoped_refptr<AudioOutputController> controller =
- AudioOutputController::Create(
- audio_manager.get(), &event_handler, params, &sync_reader);
- ASSERT_TRUE(controller.get());
-
- // Wait for OnCreated() to be called.
- event.Wait();
-
- ASSERT_FALSE(play_event.IsSignaled());
- controller->Play();
- play_event.Wait();
-
- // Force a state change and wait for the stream to come back to playing state.
- play_event.Reset();
- audio_manager->GetMessageLoop()->PostTask(FROM_HERE,
- base::Bind(&AudioOutputController::OnDeviceChange, controller));
- play_event.Wait();
-
- // Now stop the controller.
- CloseAudioController(controller);
+TEST_F(AudioOutputControllerTest, DivertRevertClose) {
+ if (ShouldSkipTest())
+ return;
+ ASSERT_TRUE(Create(kSamplesPerPacket));
+ WaitForCreate();
+ Divert();
+ // Read back zeros since playback was not requested.
+ ReadDivertedAudioData(kBufferZeroData);
+ Revert(false);
+ Close();
}
} // namespace media
« media/audio/audio_output_controller.cc ('K') | « media/audio/audio_output_controller.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698