| 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..ff37b5a88a15b66540dbd14b527c99e7b1c7e2cf 100644
|
| --- a/media/audio/audio_output_controller_unittest.cc
|
| +++ b/media/audio/audio_output_controller_unittest.cc
|
| @@ -2,23 +2,24 @@
|
| // 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::Invoke;
|
| using ::testing::NotNull;
|
| using ::testing::Return;
|
|
|
| @@ -27,9 +28,10 @@ namespace media {
|
| static const int kSampleRate = AudioParameters::kAudioCDSampleRate;
|
| static const int kBitsPerSample = 16;
|
| static const ChannelLayout kChannelLayout = CHANNEL_LAYOUT_STEREO;
|
| -static const int kSamplesPerPacket = kSampleRate / 10;
|
| +static const int kSamplesPerPacket = kSampleRate / 100;
|
| static const int kHardwareBufferSize = kSamplesPerPacket *
|
| ChannelLayoutToChannelCount(kChannelLayout) * kBitsPerSample / 8;
|
| +static const double kTestVolume = 0.25;
|
|
|
| class MockAudioOutputControllerEventHandler
|
| : public AudioOutputController::EventHandler {
|
| @@ -60,227 +62,321 @@ class MockAudioOutputControllerSyncReader
|
| DISALLOW_COPY_AND_ASSIGN(MockAudioOutputControllerSyncReader);
|
| };
|
|
|
| +class MockAudioOutputStream : public AudioOutputStream {
|
| + public:
|
| + MOCK_METHOD0(Open, bool());
|
| + MOCK_METHOD1(Start, void(AudioSourceCallback* callback));
|
| + MOCK_METHOD0(Stop, void());
|
| + MOCK_METHOD1(SetVolume, void(double volume));
|
| + MOCK_METHOD1(GetVolume, void(double* volume));
|
| + MOCK_METHOD0(Close, void());
|
| +
|
| + // Set/get the callback passed to Start().
|
| + AudioSourceCallback* callback() const { return callback_; }
|
| + void SetCallback(AudioSourceCallback* asc) { callback_ = asc; }
|
| +
|
| + private:
|
| + AudioSourceCallback* callback_;
|
| +};
|
| +
|
| ACTION_P(SignalEvent, event) {
|
| event->Signal();
|
| }
|
|
|
| -// Custom action to clear a memory buffer.
|
| -ACTION(ClearBuffer) {
|
| +static const float kBufferNonZeroData = 1.0f;
|
| +ACTION(PopulateBuffer) {
|
| arg1->Zero();
|
| -}
|
| -
|
| -// Closes AudioOutputController synchronously.
|
| -static void CloseAudioController(AudioOutputController* controller) {
|
| - controller->Close(MessageLoop::QuitClosure());
|
| - MessageLoop::current()->Run();
|
| + // 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] = kBufferNonZeroData;
|
| }
|
|
|
| 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) {
|
| + }
|
| +
|
| + virtual ~AudioOutputControllerTest() {
|
| + }
|
|
|
| protected:
|
| - MessageLoopForIO message_loop_;
|
| + void Create(int samples_per_packet) {
|
| + EXPECT_FALSE(create_event_.IsSignaled());
|
| + EXPECT_FALSE(play_event_.IsSignaled());
|
| + EXPECT_FALSE(read_event_.IsSignaled());
|
| + EXPECT_FALSE(pause_event_.IsSignaled());
|
| +
|
| + params_ = AudioParameters(
|
| + AudioParameters::AUDIO_FAKE, kChannelLayout,
|
| + kSampleRate, kBitsPerSample, samples_per_packet);
|
| +
|
| + if (params_.IsValid()) {
|
| + EXPECT_CALL(mock_event_handler_, OnCreated(NotNull()))
|
| + .WillOnce(SignalEvent(&create_event_));
|
| + }
|
| +
|
| + controller_ = AudioOutputController::Create(
|
| + audio_manager_.get(), &mock_event_handler_, params_,
|
| + &mock_sync_reader_);
|
| + if (controller_)
|
| + controller_->SetVolume(kTestVolume);
|
| +
|
| + EXPECT_EQ(params_.IsValid(), 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(),
|
| + 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(bool was_playing, bool will_be_playing) {
|
| + if (was_playing) {
|
| + // Expect the handler to receive one OnPlaying() call as a result of the
|
| + // stream switching.
|
| + EXPECT_CALL(mock_event_handler_, OnPlaying(NotNull()))
|
| + .WillOnce(SignalEvent(&play_event_));
|
| + }
|
| +
|
| + EXPECT_CALL(mock_stream_, Open())
|
| + .WillOnce(Return(true));
|
| + EXPECT_CALL(mock_stream_, SetVolume(kTestVolume));
|
| + if (will_be_playing) {
|
| + EXPECT_CALL(mock_stream_, Start(NotNull()))
|
| + .Times(AtLeast(1))
|
| + .WillRepeatedly(
|
| + Invoke(&mock_stream_, &MockAudioOutputStream::SetCallback));
|
| + }
|
| + // Always expect a Stop() call--even without a Start() call--since
|
| + // AudioOutputController likes to play it safe and Stop() before any
|
| + // Close().
|
| + EXPECT_CALL(mock_stream_, Stop())
|
| + .Times(AtLeast(1));
|
| +
|
| + controller_->StartDiverting(&mock_stream_);
|
| + }
|
| +
|
| + void ReadDivertedAudioData() {
|
| + scoped_ptr<AudioBus> dest = AudioBus::Create(params_);
|
| + ASSERT_TRUE(!!mock_stream_.callback());
|
| + const int frames_read =
|
| + mock_stream_.callback()->OnMoreData(dest.get(), AudioBuffersState());
|
| + EXPECT_LT(0, frames_read);
|
| + EXPECT_EQ(kBufferNonZeroData, dest->channel(0)[0]);
|
| + }
|
| +
|
| + void Revert(bool was_playing) {
|
| + if (was_playing) {
|
| + // Expect the handler to receive one OnPlaying() call as a result of the
|
| + // stream switching back.
|
| + EXPECT_CALL(mock_event_handler_, OnPlaying(NotNull()))
|
| + .WillOnce(SignalEvent(&play_event_));
|
| + }
|
| +
|
| + EXPECT_CALL(mock_stream_, Close());
|
| +
|
| + controller_->StopDiverting();
|
| + }
|
| +
|
| + void Close() {
|
| + EXPECT_CALL(mock_sync_reader_, Close());
|
| +
|
| + controller_->Close(MessageLoop::QuitClosure());
|
| + MessageLoop::current()->Run();
|
| + }
|
| +
|
| + // These help make test sequences more readable.
|
| + void DivertNeverPlaying() { Divert(false, false); }
|
| + void DivertWillEventuallyBePlaying() { Divert(false, true); }
|
| + void DivertWhilePlaying() { Divert(true, true); }
|
| + void RevertWasNotPlaying() { Revert(false); }
|
| + void RevertWhilePlaying() { Revert(true); }
|
| +
|
| + // 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_;
|
| + MockAudioOutputStream mock_stream_;
|
| + base::WaitableEvent create_event_;
|
| + base::WaitableEvent play_event_;
|
| + base::WaitableEvent read_event_;
|
| + base::WaitableEvent pause_event_;
|
| + AudioParameters params_;
|
| + scoped_refptr<AudioOutputController> controller_;
|
| +
|
| DISALLOW_COPY_AND_ASSIGN(AudioOutputControllerTest);
|
| };
|
|
|
| TEST_F(AudioOutputControllerTest, CreateAndClose) {
|
| - scoped_ptr<AudioManager> audio_manager(AudioManager::Create());
|
| - if (!audio_manager->HasAudioOutputDevices())
|
| - return;
|
| + Create(kSamplesPerPacket);
|
| + Close();
|
| +}
|
|
|
| - MockAudioOutputControllerEventHandler event_handler;
|
| +TEST_F(AudioOutputControllerTest, HardwareBufferTooLarge) {
|
| + Create(kSamplesPerPacket * 1000);
|
| +}
|
|
|
| - EXPECT_CALL(event_handler, OnCreated(NotNull()))
|
| - .Times(1);
|
| +TEST_F(AudioOutputControllerTest, PlayAndClose) {
|
| + Create(kSamplesPerPacket);
|
| + WaitForCreate();
|
| + Play();
|
| + WaitForPlay();
|
| + WaitForReads();
|
| + Close();
|
| +}
|
|
|
| - MockAudioOutputControllerSyncReader sync_reader;
|
| - EXPECT_CALL(sync_reader, Close());
|
| +TEST_F(AudioOutputControllerTest, PlayPauseClose) {
|
| + Create(kSamplesPerPacket);
|
| + WaitForCreate();
|
| + Play();
|
| + WaitForPlay();
|
| + WaitForReads();
|
| + Pause();
|
| + WaitForPause();
|
| + 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, PlayPausePlayClose) {
|
| + Create(kSamplesPerPacket);
|
| + WaitForCreate();
|
| + Play();
|
| + WaitForPlay();
|
| + WaitForReads();
|
| + Pause();
|
| + WaitForPause();
|
| + Play();
|
| + WaitForPlay();
|
| + Close();
|
| +}
|
|
|
| - // Close the controller immediately.
|
| - CloseAudioController(controller);
|
| +TEST_F(AudioOutputControllerTest, PlayDeviceChangeClose) {
|
| + Create(kSamplesPerPacket);
|
| + WaitForCreate();
|
| + Play();
|
| + WaitForPlay();
|
| + WaitForReads();
|
| + ChangeDevice();
|
| + WaitForPlay();
|
| + WaitForReads();
|
| + Close();
|
| }
|
|
|
| -TEST_F(AudioOutputControllerTest, PlayPauseClose) {
|
| - scoped_ptr<AudioManager> audio_manager(AudioManager::Create());
|
| - if (!audio_manager->HasAudioOutputDevices())
|
| - 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);
|
| +TEST_F(AudioOutputControllerTest, PlayDivertRevertClose) {
|
| + Create(kSamplesPerPacket);
|
| + WaitForCreate();
|
| + Play();
|
| + WaitForPlay();
|
| + WaitForReads();
|
| + DivertWhilePlaying();
|
| + WaitForPlay();
|
| + ReadDivertedAudioData();
|
| + RevertWhilePlaying();
|
| + WaitForPlay();
|
| + WaitForReads();
|
| + Close();
|
| }
|
|
|
| -TEST_F(AudioOutputControllerTest, HardwareBufferTooLarge) {
|
| - scoped_ptr<AudioManager> audio_manager(AudioManager::Create());
|
| - if (!audio_manager->HasAudioOutputDevices())
|
| - 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);
|
| +TEST_F(AudioOutputControllerTest, PlayDivertRevertDivertRevertClose) {
|
| + Create(kSamplesPerPacket);
|
| + WaitForCreate();
|
| + Play();
|
| + WaitForPlay();
|
| + WaitForReads();
|
| + DivertWhilePlaying();
|
| + WaitForPlay();
|
| + ReadDivertedAudioData();
|
| + RevertWhilePlaying();
|
| + WaitForPlay();
|
| + WaitForReads();
|
| + DivertWhilePlaying();
|
| + WaitForPlay();
|
| + ReadDivertedAudioData();
|
| + RevertWhilePlaying();
|
| + WaitForPlay();
|
| + WaitForReads();
|
| + Close();
|
| }
|
|
|
| -TEST_F(AudioOutputControllerTest, PlayPausePlayClose) {
|
| - scoped_ptr<AudioManager> audio_manager(AudioManager::Create());
|
| - if (!audio_manager->HasAudioOutputDevices())
|
| - return;
|
| -
|
| - 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, DivertPlayPausePlayRevertClose) {
|
| + Create(kSamplesPerPacket);
|
| + WaitForCreate();
|
| + DivertWillEventuallyBePlaying();
|
| + Play();
|
| + WaitForPlay();
|
| + ReadDivertedAudioData();
|
| + Pause();
|
| + WaitForPause();
|
| + Play();
|
| + WaitForPlay();
|
| + ReadDivertedAudioData();
|
| + RevertWhilePlaying();
|
| + WaitForPlay();
|
| + WaitForReads();
|
| + Close();
|
| }
|
|
|
| -// Ensure state change events are handled.
|
| -TEST_F(AudioOutputControllerTest, PlayStateChangeClose) {
|
| - scoped_ptr<AudioManager> audio_manager(AudioManager::Create());
|
| - if (!audio_manager->HasAudioOutputDevices())
|
| - return;
|
| -
|
| - 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) {
|
| + Create(kSamplesPerPacket);
|
| + WaitForCreate();
|
| + DivertNeverPlaying();
|
| + RevertWasNotPlaying();
|
| + Close();
|
| }
|
|
|
| } // namespace media
|
|
|