| Index: chromecast/media/audio/cast_audio_output_stream_unittest.cc
 | 
| diff --git a/chromecast/media/audio/cast_audio_output_stream_unittest.cc b/chromecast/media/audio/cast_audio_output_stream_unittest.cc
 | 
| index d529077e8516a87e775ca6919927ec85dae359cd..67bf2952cce4d5a824a05e70083241d060a18da0 100644
 | 
| --- a/chromecast/media/audio/cast_audio_output_stream_unittest.cc
 | 
| +++ b/chromecast/media/audio/cast_audio_output_stream_unittest.cc
 | 
| @@ -10,7 +10,9 @@
 | 
|  
 | 
|  #include "base/bind.h"
 | 
|  #include "base/macros.h"
 | 
| +#include "base/run_loop.h"
 | 
|  #include "base/synchronization/waitable_event.h"
 | 
| +#include "base/thread_task_runner_handle.h"
 | 
|  #include "chromecast/base/metrics/cast_metrics_test_helper.h"
 | 
|  #include "chromecast/media/audio/cast_audio_manager.h"
 | 
|  #include "chromecast/media/base/media_message_loop.h"
 | 
| @@ -184,8 +186,9 @@ class FakeAudioSourceCallback
 | 
|  
 | 
|  class FakeAudioManager : public CastAudioManager {
 | 
|   public:
 | 
| -  FakeAudioManager()
 | 
| -      : CastAudioManager(nullptr, nullptr), media_pipeline_backend_(nullptr) {}
 | 
| +  FakeAudioManager(scoped_refptr<base::SingleThreadTaskRunner> task_runner)
 | 
| +      : CastAudioManager(task_runner, task_runner, nullptr, nullptr),
 | 
| +        media_pipeline_backend_(nullptr) {}
 | 
|    ~FakeAudioManager() override {}
 | 
|  
 | 
|    // CastAudioManager overrides.
 | 
| @@ -231,9 +234,9 @@ class CastAudioOutputStreamTest : public ::testing::Test {
 | 
|    void SetUp() override {
 | 
|      metrics::InitializeMetricsHelperForTesting();
 | 
|  
 | 
| -    audio_manager_.reset(new FakeAudioManager);
 | 
| -    audio_task_runner_ = audio_manager_->GetTaskRunner();
 | 
| +    audio_task_runner_ = base::ThreadTaskRunnerHandle::Get();
 | 
|      backend_task_runner_ = media::MediaMessageLoop::GetTaskRunner();
 | 
| +    audio_manager_.reset(new FakeAudioManager(audio_task_runner_));
 | 
|    }
 | 
|  
 | 
|    void TearDown() override {
 | 
| @@ -256,107 +259,68 @@ class CastAudioOutputStreamTest : public ::testing::Test {
 | 
|  
 | 
|    // Synchronous utility functions.
 | 
|    ::media::AudioOutputStream* CreateStream() {
 | 
| -    ::media::AudioOutputStream* stream = nullptr;
 | 
| -
 | 
| -    base::WaitableEvent completion_event(false, false);
 | 
| -    audio_task_runner_->PostTask(
 | 
| -        FROM_HERE,
 | 
| -        base::Bind(&CastAudioOutputStreamTest::CreateStreamOnAudioThread,
 | 
| -                   base::Unretained(this), GetAudioParams(), &stream,
 | 
| -                   &completion_event));
 | 
| -    completion_event.Wait();
 | 
| -
 | 
| -    return stream;
 | 
| +    return audio_manager_->MakeAudioOutputStream(GetAudioParams(),
 | 
| +                                                 kDefaultDeviceId);
 | 
|    }
 | 
|    bool OpenStream(::media::AudioOutputStream* stream) {
 | 
| -    DCHECK(stream);
 | 
| -
 | 
| -    bool success = false;
 | 
| -    base::WaitableEvent completion_event(false, false);
 | 
| -    audio_task_runner_->PostTask(
 | 
| -        FROM_HERE,
 | 
| -        base::Bind(&CastAudioOutputStreamTest::OpenStreamOnAudioThread,
 | 
| -                   base::Unretained(this), stream, &success,
 | 
| -                   &completion_event));
 | 
| -    completion_event.Wait();
 | 
| -
 | 
| +    bool success = stream->Open();
 | 
|      // Drain the backend task runner so that appropriate states are set on
 | 
|      // the backend pipeline devices.
 | 
|      RunUntilIdle(backend_task_runner_.get());
 | 
|      return success;
 | 
|    }
 | 
|    void CloseStream(::media::AudioOutputStream* stream) {
 | 
| -    audio_task_runner_->PostTask(FROM_HERE,
 | 
| -                                 base::Bind(&::media::AudioOutputStream::Close,
 | 
| -                                            base::Unretained(stream)));
 | 
| -    RunUntilIdle(audio_task_runner_.get());
 | 
| +    stream->Close();
 | 
|      RunUntilIdle(backend_task_runner_.get());
 | 
|      // Backend task runner may have posted more tasks to the audio task runner.
 | 
|      // So we need to drain it once more.
 | 
| -    RunUntilIdle(audio_task_runner_.get());
 | 
| +    message_loop_.RunUntilIdle();
 | 
|    }
 | 
|    void StartStream(
 | 
|        ::media::AudioOutputStream* stream,
 | 
|        ::media::AudioOutputStream::AudioSourceCallback* source_callback) {
 | 
| -    audio_task_runner_->PostTask(
 | 
| -        FROM_HERE, base::Bind(&::media::AudioOutputStream::Start,
 | 
| -                              base::Unretained(stream), source_callback));
 | 
| -    // Drain the audio task runner twice so that tasks posted by
 | 
| +    stream->Start(source_callback);
 | 
| +    // Drain the audio task runner so that tasks posted by
 | 
|      // media::AudioOutputStream::Start are run as well.
 | 
| -    RunUntilIdle(audio_task_runner_.get());
 | 
| -    RunUntilIdle(audio_task_runner_.get());
 | 
| +    message_loop_.RunUntilIdle();
 | 
|      // Drain the backend task runner so that appropriate states are set on
 | 
|      // the backend pipeline devices.
 | 
|      RunUntilIdle(backend_task_runner_.get());
 | 
|      // Drain the audio task runner again to run the tasks posted by the
 | 
|      // backend on audio task runner.
 | 
| -    RunUntilIdle(audio_task_runner_.get());
 | 
| +    message_loop_.RunUntilIdle();
 | 
|    }
 | 
|    void StopStream(::media::AudioOutputStream* stream) {
 | 
| -    audio_task_runner_->PostTask(FROM_HERE,
 | 
| -                                 base::Bind(&::media::AudioOutputStream::Stop,
 | 
| -                                            base::Unretained(stream)));
 | 
| -    RunUntilIdle(audio_task_runner_.get());
 | 
| +    stream->Stop();
 | 
|      // Drain the backend task runner so that appropriate states are set on
 | 
|      // the backend pipeline devices.
 | 
|      RunUntilIdle(backend_task_runner_.get());
 | 
|    }
 | 
|    void SetStreamVolume(::media::AudioOutputStream* stream, double volume) {
 | 
| -    audio_task_runner_->PostTask(
 | 
| -        FROM_HERE, base::Bind(&::media::AudioOutputStream::SetVolume,
 | 
| -                              base::Unretained(stream), volume));
 | 
| -    RunUntilIdle(audio_task_runner_.get());
 | 
| +    stream->SetVolume(volume);
 | 
|      // Drain the backend task runner so that appropriate states are set on
 | 
|      // the backend pipeline devices.
 | 
|      RunUntilIdle(backend_task_runner_.get());
 | 
|    }
 | 
|    double GetStreamVolume(::media::AudioOutputStream* stream) {
 | 
|      double volume = 0.0;
 | 
| -    audio_task_runner_->PostTask(
 | 
| -        FROM_HERE, base::Bind(&::media::AudioOutputStream::GetVolume,
 | 
| -                              base::Unretained(stream), &volume));
 | 
| -    RunUntilIdle(audio_task_runner_.get());
 | 
| +    stream->GetVolume(&volume);
 | 
|      // No need to drain the backend task runner because getting the volume
 | 
|      // does not involve posting any task to the backend.
 | 
|      return volume;
 | 
|    }
 | 
|  
 | 
| -  void CreateStreamOnAudioThread(const ::media::AudioParameters& audio_params,
 | 
| -                                 ::media::AudioOutputStream** stream,
 | 
| -                                 base::WaitableEvent* completion_event) {
 | 
| -    DCHECK(audio_task_runner_->BelongsToCurrentThread());
 | 
| -    *stream = audio_manager_->MakeAudioOutputStream(GetAudioParams(),
 | 
| -                                                    kDefaultDeviceId);
 | 
| -    completion_event->Signal();
 | 
| -  }
 | 
| -  void OpenStreamOnAudioThread(::media::AudioOutputStream* stream,
 | 
| -                               bool* success,
 | 
| -                               base::WaitableEvent* completion_event) {
 | 
| -    DCHECK(audio_task_runner_->BelongsToCurrentThread());
 | 
| -    *success = stream->Open();
 | 
| -    completion_event->Signal();
 | 
| +  void RunAudioLoopFor(int frames) {
 | 
| +    ::media::AudioParameters audio_params = GetAudioParams();
 | 
| +    base::TimeDelta duration = audio_params.GetBufferDuration() * frames;
 | 
| +
 | 
| +    base::RunLoop run_loop;
 | 
| +    message_loop_.task_runner()->PostDelayedTask(
 | 
| +        FROM_HERE, run_loop.QuitClosure(), duration);
 | 
| +    run_loop.Run();
 | 
|    }
 | 
|  
 | 
| +  base::MessageLoop message_loop_;
 | 
|    std::unique_ptr<FakeAudioManager> audio_manager_;
 | 
|    scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner_;
 | 
|    scoped_refptr<base::SingleThreadTaskRunner> backend_task_runner_;
 | 
| @@ -476,6 +440,7 @@ TEST_F(CastAudioOutputStreamTest, PushFrame) {
 | 
|    std::unique_ptr<FakeAudioSourceCallback> source_callback(
 | 
|        new FakeAudioSourceCallback);
 | 
|    StartStream(stream, source_callback.get());
 | 
| +  RunAudioLoopFor(2);
 | 
|    StopStream(stream);
 | 
|  
 | 
|    // Verify that the stream pushed frames to the backend.
 | 
| @@ -518,10 +483,7 @@ TEST_F(CastAudioOutputStreamTest, DeviceBusy) {
 | 
|  
 | 
|    // Sleep for a few frames and verify that more frames were not pushed
 | 
|    // because the backend device was busy.
 | 
| -  ::media::AudioParameters audio_params = GetAudioParams();
 | 
| -  base::TimeDelta pause = audio_params.GetBufferDuration() * 5;
 | 
| -  base::PlatformThread::Sleep(pause);
 | 
| -  RunUntilIdle(audio_task_runner_.get());
 | 
| +  RunAudioLoopFor(5);
 | 
|    RunUntilIdle(backend_task_runner_.get());
 | 
|    EXPECT_EQ(1u, audio_decoder->pushed_buffer_count());
 | 
|  
 | 
| @@ -532,9 +494,7 @@ TEST_F(CastAudioOutputStreamTest, DeviceBusy) {
 | 
|        base::Bind(&FakeAudioDecoder::set_pipeline_status,
 | 
|                   base::Unretained(audio_decoder),
 | 
|                   FakeAudioDecoder::PIPELINE_STATUS_OK));
 | 
| -
 | 
| -  base::PlatformThread::Sleep(pause);
 | 
| -  RunUntilIdle(audio_task_runner_.get());
 | 
| +  RunAudioLoopFor(5);
 | 
|    RunUntilIdle(backend_task_runner_.get());
 | 
|    EXPECT_LT(1u, audio_decoder->pushed_buffer_count());
 | 
|    EXPECT_FALSE(source_callback->error());
 | 
| @@ -555,6 +515,7 @@ TEST_F(CastAudioOutputStreamTest, DeviceError) {
 | 
|    std::unique_ptr<FakeAudioSourceCallback> source_callback(
 | 
|        new FakeAudioSourceCallback);
 | 
|    StartStream(stream, source_callback.get());
 | 
| +  RunAudioLoopFor(2);
 | 
|  
 | 
|    // Make sure that AudioOutputStream attempted to push the initial frame.
 | 
|    EXPECT_LT(0u, audio_decoder->pushed_buffer_count());
 | 
| @@ -578,6 +539,7 @@ TEST_F(CastAudioOutputStreamTest, DeviceAsyncError) {
 | 
|    std::unique_ptr<FakeAudioSourceCallback> source_callback(
 | 
|        new FakeAudioSourceCallback);
 | 
|    StartStream(stream, source_callback.get());
 | 
| +  RunAudioLoopFor(5);
 | 
|  
 | 
|    // Make sure that one frame was pushed.
 | 
|    EXPECT_EQ(1u, audio_decoder->pushed_buffer_count());
 | 
| @@ -590,7 +552,7 @@ TEST_F(CastAudioOutputStreamTest, DeviceAsyncError) {
 | 
|                   base::Unretained(audio_decoder),
 | 
|                   FakeAudioDecoder::PIPELINE_STATUS_OK));
 | 
|  
 | 
| -  RunUntilIdle(audio_task_runner_.get());
 | 
| +  RunAudioLoopFor(5);
 | 
|    RunUntilIdle(backend_task_runner_.get());
 | 
|    // AudioOutputStream must report error to source callback.
 | 
|    EXPECT_TRUE(source_callback->error());
 | 
| @@ -625,16 +587,11 @@ TEST_F(CastAudioOutputStreamTest, StartStopStart) {
 | 
|  
 | 
|    std::unique_ptr<FakeAudioSourceCallback> source_callback(
 | 
|        new FakeAudioSourceCallback);
 | 
| -  audio_task_runner_->PostTask(
 | 
| -      FROM_HERE, base::Bind(&::media::AudioOutputStream::Start,
 | 
| -                            base::Unretained(stream), source_callback.get()));
 | 
| -  audio_task_runner_->PostTask(
 | 
| -      FROM_HERE,
 | 
| -      base::Bind(&::media::AudioOutputStream::Stop, base::Unretained(stream)));
 | 
| -  audio_task_runner_->PostTask(
 | 
| -      FROM_HERE, base::Bind(&::media::AudioOutputStream::Start,
 | 
| -                            base::Unretained(stream), source_callback.get()));
 | 
| -  RunUntilIdle(audio_task_runner_.get());
 | 
| +  stream->Start(source_callback.get());
 | 
| +  RunAudioLoopFor(2);
 | 
| +  stream->Stop();
 | 
| +  stream->Start(source_callback.get());
 | 
| +  RunAudioLoopFor(2);
 | 
|    RunUntilIdle(backend_task_runner_.get());
 | 
|  
 | 
|    FakeAudioDecoder* audio_device = GetAudio();
 | 
| 
 |