| Index: media/audio/audio_output_device_unittest.cc
|
| diff --git a/media/audio/audio_output_device_unittest.cc b/media/audio/audio_output_device_unittest.cc
|
| index 3fe5b01d58e217fd0a36edc105d58593047f3157..cf6bbe601d6913f943ff96278a95e4c76b115ed4 100644
|
| --- a/media/audio/audio_output_device_unittest.cc
|
| +++ b/media/audio/audio_output_device_unittest.cc
|
| @@ -15,6 +15,7 @@
|
| #include "base/message_loop/message_loop.h"
|
| #include "base/process/process_handle.h"
|
| #include "base/sync_socket.h"
|
| +#include "base/synchronization/waitable_event.h"
|
| #include "base/task_runner.h"
|
| #include "base/test/test_timeouts.h"
|
| #include "base/threading/thread.h"
|
| @@ -96,14 +97,17 @@ class AudioOutputDeviceTest
|
| AudioOutputDeviceTest();
|
| ~AudioOutputDeviceTest();
|
|
|
| + void SetDevice(const std::string& device_id);
|
| void ReceiveAuthorization(OutputDeviceStatus device_status);
|
| + void InitializeAudioDevice(const AudioParameters& params);
|
| void StartAudioDevice();
|
| void CreateStream();
|
| void ExpectRenderCallback();
|
| void WaitUntilRenderCallback();
|
| void StopAudioDevice();
|
| + void GetOutputDeviceInfo(base::WaitableEvent* event);
|
| + void SetDeviceInfoToGarbage();
|
| void CreateDevice(const std::string& device_id);
|
| - void SetDevice(const std::string& device_id);
|
| void CheckDeviceStatus(OutputDeviceStatus device_status);
|
|
|
| protected:
|
| @@ -116,13 +120,14 @@ class AudioOutputDeviceTest
|
| MockAudioOutputIPC* audio_output_ipc_; // owned by audio_device_
|
| scoped_refptr<AudioOutputDevice> audio_device_;
|
| OutputDeviceStatus device_status_;
|
| + OutputDeviceInfo device_info_;
|
| + std::unique_ptr<CancelableSyncSocket> browser_socket_;
|
| + std::unique_ptr<CancelableSyncSocket> renderer_socket_;
|
|
|
| private:
|
| int CalculateMemorySize();
|
|
|
| - SharedMemory shared_memory_;
|
| - CancelableSyncSocket browser_socket_;
|
| - CancelableSyncSocket renderer_socket_;
|
| + std::unique_ptr<SharedMemory> shared_memory_;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(AudioOutputDeviceTest);
|
| };
|
| @@ -134,10 +139,12 @@ int AudioOutputDeviceTest::CalculateMemorySize() {
|
| }
|
|
|
| AudioOutputDeviceTest::AudioOutputDeviceTest()
|
| - : device_status_(OUTPUT_DEVICE_STATUS_ERROR_INTERNAL) {
|
| + : device_status_(OUTPUT_DEVICE_STATUS_ERROR_INTERNAL),
|
| + browser_socket_(new base::CancelableSyncSocket()),
|
| + renderer_socket_(new base::CancelableSyncSocket()) {
|
| default_audio_parameters_.Reset(AudioParameters::AUDIO_PCM_LINEAR,
|
| CHANNEL_LAYOUT_STEREO, 48000, 16, 1024);
|
| - SetDevice(kDefaultDeviceId);
|
| + SetDeviceInfoToGarbage();
|
| }
|
|
|
| AudioOutputDeviceTest::~AudioOutputDeviceTest() {
|
| @@ -166,8 +173,7 @@ void AudioOutputDeviceTest::SetDevice(const std::string& device_id) {
|
| : OUTPUT_DEVICE_STATUS_OK;
|
| ReceiveAuthorization(device_status);
|
|
|
| - audio_device_->Initialize(default_audio_parameters_,
|
| - &callback_);
|
| + InitializeAudioDevice(default_audio_parameters_);
|
| }
|
|
|
| void AudioOutputDeviceTest::CheckDeviceStatus(OutputDeviceStatus status) {
|
| @@ -195,24 +201,31 @@ void AudioOutputDeviceTest::StartAudioDevice() {
|
| io_loop_.RunUntilIdle();
|
| }
|
|
|
| +void AudioOutputDeviceTest::InitializeAudioDevice(
|
| + const AudioParameters& params) {
|
| + audio_device_->Initialize(params, &callback_);
|
| +}
|
| +
|
| void AudioOutputDeviceTest::CreateStream() {
|
| const int kMemorySize = CalculateMemorySize();
|
|
|
| - ASSERT_TRUE(shared_memory_.CreateAndMapAnonymous(kMemorySize));
|
| - memset(shared_memory_.memory(), 0xff, kMemorySize);
|
| + shared_memory_.reset(new SharedMemory());
|
| +
|
| + ASSERT_TRUE(shared_memory_->CreateAndMapAnonymous(kMemorySize));
|
| + memset(shared_memory_->memory(), 0xff, kMemorySize);
|
|
|
| - ASSERT_TRUE(CancelableSyncSocket::CreatePair(&browser_socket_,
|
| - &renderer_socket_));
|
| + ASSERT_TRUE(CancelableSyncSocket::CreatePair(browser_socket_.get(),
|
| + renderer_socket_.get()));
|
|
|
| // Create duplicates of the handles we pass to AudioOutputDevice since
|
| // ownership will be transferred and AudioOutputDevice is responsible for
|
| // freeing.
|
| SyncSocket::TransitDescriptor audio_device_socket_descriptor;
|
| - ASSERT_TRUE(renderer_socket_.PrepareTransitDescriptor(
|
| + ASSERT_TRUE(renderer_socket_->PrepareTransitDescriptor(
|
| base::GetCurrentProcessHandle(), &audio_device_socket_descriptor));
|
| base::SharedMemoryHandle duplicated_memory_handle;
|
| - ASSERT_TRUE(shared_memory_.ShareToProcess(base::GetCurrentProcessHandle(),
|
| - &duplicated_memory_handle));
|
| + ASSERT_TRUE(shared_memory_->ShareToProcess(base::GetCurrentProcessHandle(),
|
| + &duplicated_memory_handle));
|
|
|
| audio_device_->OnStreamCreated(
|
| duplicated_memory_handle,
|
| @@ -227,8 +240,9 @@ void AudioOutputDeviceTest::ExpectRenderCallback() {
|
| // shared memory section.
|
| const int kMemorySize = CalculateMemorySize();
|
|
|
| + ASSERT_TRUE(browser_socket_.get());
|
| EXPECT_CALL(*audio_output_ipc_, PlayStream())
|
| - .WillOnce(SendPendingBytes(&browser_socket_, kMemorySize));
|
| + .WillOnce(SendPendingBytes(browser_socket_.get(), kMemorySize));
|
|
|
| // We expect calls to our audio renderer callback, which returns the number
|
| // of frames written to the memory section.
|
| @@ -258,30 +272,62 @@ void AudioOutputDeviceTest::StopAudioDevice() {
|
| io_loop_.RunUntilIdle();
|
| }
|
|
|
| +void AudioOutputDeviceTest::GetOutputDeviceInfo(base::WaitableEvent* event) {
|
| + device_info_ = audio_device_->GetOutputDeviceInfo();
|
| + event->Signal();
|
| +}
|
| +
|
| +void AudioOutputDeviceTest::SetDeviceInfoToGarbage() {
|
| + device_info_ =
|
| + OutputDeviceInfo("qwertyuiop", OUTPUT_DEVICE_STATUS_ERROR_INTERNAL,
|
| + AudioParameters(AudioParameters::AUDIO_FAKE,
|
| + CHANNEL_LAYOUT_NONE, 1, 2, 3));
|
| +}
|
| +
|
| TEST_P(AudioOutputDeviceTest, Initialize) {
|
| // Tests that the object can be constructed, initialized and destructed
|
| // without having ever been started.
|
| + SetDevice(kDefaultDeviceId);
|
| StopAudioDevice();
|
| }
|
|
|
| // Calls Start() followed by an immediate Stop() and check for the basic message
|
| // filter messages being sent in that case.
|
| TEST_P(AudioOutputDeviceTest, StartStop) {
|
| + SetDevice(kDefaultDeviceId);
|
| StartAudioDevice();
|
| StopAudioDevice();
|
| }
|
|
|
| -// AudioOutputDevice supports multiple start/stop sequences.
|
| +TEST_P(AudioOutputDeviceTest, StartStopStop) {
|
| + SetDevice(kDefaultDeviceId);
|
| + StartAudioDevice();
|
| + StopAudioDevice();
|
| +
|
| + // Stop again, but don't expect a CloseStream() IPC call as StopAudioDevice()
|
| + // does.
|
| + audio_device_->Stop();
|
| + io_loop_.RunUntilIdle();
|
| +}
|
| +
|
| +// AudioOutputDevice supports multiple intialize/start/stop sequences.
|
| TEST_P(AudioOutputDeviceTest, StartStopStartStop) {
|
| + SetDevice(kDefaultDeviceId);
|
| StartAudioDevice();
|
| StopAudioDevice();
|
| + InitializeAudioDevice(default_audio_parameters_);
|
| + EXPECT_CALL(*audio_output_ipc_,
|
| + RequestDeviceAuthorization(audio_device_.get(), 0, _, _));
|
| StartAudioDevice();
|
| + // Simulate reply from browser
|
| + ReceiveAuthorization(OUTPUT_DEVICE_STATUS_OK);
|
| StopAudioDevice();
|
| }
|
|
|
| // Simulate receiving OnStreamCreated() prior to processing ShutDownOnIOThread()
|
| // on the IO loop.
|
| TEST_P(AudioOutputDeviceTest, StopBeforeRender) {
|
| + SetDevice(kDefaultDeviceId);
|
| StartAudioDevice();
|
|
|
| // Call Stop() but don't run the IO loop yet.
|
| @@ -295,11 +341,27 @@ TEST_P(AudioOutputDeviceTest, StopBeforeRender) {
|
|
|
| // Full test with output only.
|
| TEST_P(AudioOutputDeviceTest, CreateStream) {
|
| + SetDevice(kDefaultDeviceId);
|
| + StartAudioDevice();
|
| + ExpectRenderCallback();
|
| + CreateStream();
|
| + WaitUntilRenderCallback();
|
| + StopAudioDevice();
|
| +}
|
| +
|
| +// Full test with output only.
|
| +TEST_P(AudioOutputDeviceTest, CreateStreamMultipleStop) {
|
| + SetDevice(kDefaultDeviceId);
|
| StartAudioDevice();
|
| ExpectRenderCallback();
|
| CreateStream();
|
| WaitUntilRenderCallback();
|
| StopAudioDevice();
|
| +
|
| + // Stop again, but don't expect a CloseStream() IPC call as StopAudioDevice()
|
| + // does.
|
| + audio_device_->Stop();
|
| + io_loop_.RunUntilIdle();
|
| }
|
|
|
| // Full test with output only with nondefault device.
|
| @@ -312,25 +374,184 @@ TEST_P(AudioOutputDeviceTest, NonDefaultCreateStream) {
|
| StopAudioDevice();
|
| }
|
|
|
| +TEST_P(AudioOutputDeviceTest, MultipleCreateStream) {
|
| + SetDevice(kDefaultDeviceId);
|
| + StartAudioDevice();
|
| + ExpectRenderCallback();
|
| + CreateStream();
|
| + WaitUntilRenderCallback();
|
| + StopAudioDevice();
|
| +
|
| + // Create a new pair of sockets and keep the old ones so that new handles
|
| + // are used, otherwise AudioDeviceThread will keep an old socket with the same
|
| + // handle as the new one, ending up closing the new socket instead of the old.
|
| + std::unique_ptr<base::CancelableSyncSocket> new_browser_socket(
|
| + new base::CancelableSyncSocket());
|
| + std::unique_ptr<base::CancelableSyncSocket> new_renderer_socket(
|
| + new base::CancelableSyncSocket());
|
| + browser_socket_.swap(new_browser_socket);
|
| + renderer_socket_.swap(new_renderer_socket);
|
| +
|
| + InitializeAudioDevice(default_audio_parameters_);
|
| + EXPECT_CALL(*audio_output_ipc_,
|
| + RequestDeviceAuthorization(audio_device_.get(), 0, _, _));
|
| + StartAudioDevice();
|
| + // Simulate reply from browser
|
| + ReceiveAuthorization(OUTPUT_DEVICE_STATUS_OK);
|
| +
|
| + ExpectRenderCallback();
|
| + CreateStream();
|
| + WaitUntilRenderCallback();
|
| + StopAudioDevice();
|
| +}
|
| +
|
| // Multiple start/stop with nondefault device
|
| TEST_P(AudioOutputDeviceTest, NonDefaultStartStopStartStop) {
|
| SetDevice(kNonDefaultDeviceId);
|
| StartAudioDevice();
|
| StopAudioDevice();
|
| + InitializeAudioDevice(default_audio_parameters_);
|
| + EXPECT_CALL(*audio_output_ipc_,
|
| + RequestDeviceAuthorization(audio_device_.get(), 0, _, _));
|
| + StartAudioDevice();
|
| + // Simulate reply from browser
|
| + ReceiveAuthorization(OUTPUT_DEVICE_STATUS_OK);
|
| + StopAudioDevice();
|
| +}
|
| +
|
| +TEST_P(AudioOutputDeviceTest, UnauthorizedDevice) {
|
| + SetDevice(kUnauthorizedDeviceId);
|
| + StartAudioDevice();
|
| + StopAudioDevice();
|
| +}
|
| +
|
| +TEST_P(AudioOutputDeviceTest, MultipleStartStopDifferentParameters) {
|
| + SetDevice(kDefaultDeviceId);
|
| + StartAudioDevice();
|
| + StopAudioDevice();
|
|
|
| + // Initialize with different parameters.
|
| + AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO,
|
| + 16000, 16, 512);
|
| + InitializeAudioDevice(params);
|
| EXPECT_CALL(*audio_output_ipc_,
|
| RequestDeviceAuthorization(audio_device_.get(), 0, _, _));
|
| StartAudioDevice();
|
| // Simulate reply from browser
|
| ReceiveAuthorization(OUTPUT_DEVICE_STATUS_OK);
|
| + StopAudioDevice();
|
|
|
| + // Back to default parameters.
|
| + InitializeAudioDevice(default_audio_parameters_);
|
| + EXPECT_CALL(*audio_output_ipc_,
|
| + RequestDeviceAuthorization(audio_device_.get(), 0, _, _));
|
| + StartAudioDevice();
|
| + // Simulate reply from browser
|
| + ReceiveAuthorization(OUTPUT_DEVICE_STATUS_OK);
|
| StopAudioDevice();
|
| }
|
|
|
| -TEST_P(AudioOutputDeviceTest, UnauthorizedDevice) {
|
| +TEST_P(AudioOutputDeviceTest, MultipleStartStopDifferentDevices) {
|
| + SetDevice(kDefaultDeviceId);
|
| + StartAudioDevice();
|
| + StopAudioDevice();
|
| +
|
| + SetDevice(kNonDefaultDeviceId);
|
| + StartAudioDevice();
|
| + StopAudioDevice();
|
| +
|
| SetDevice(kUnauthorizedDeviceId);
|
| StartAudioDevice();
|
| StopAudioDevice();
|
| +
|
| + SetDevice(kDefaultDeviceId);
|
| + StartAudioDevice();
|
| + StopAudioDevice();
|
| +}
|
| +
|
| +// Test getting output device info.
|
| +// GetOutputDeviceInfo() must be called on a different thread than the IO task
|
| +// runner we hand to the AudioOutputDevice. Since we use the task runner for the
|
| +// thread the test runs on as the IO task runner, we must spin up a new thread
|
| +// and call GetOutputDeviceInfo() on that.
|
| +TEST_P(AudioOutputDeviceTest, GetOutputDeviceInfo) {
|
| + SetDevice(kDefaultDeviceId);
|
| +
|
| + base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
|
| + base::WaitableEvent::InitialState::NOT_SIGNALED);
|
| + base::Thread thread("get_output_device_info");
|
| + thread.Start();
|
| +
|
| + // Get device info on the other thread and wait until finished.
|
| + thread.task_runner()->PostTask(
|
| + FROM_HERE, base::Bind(&AudioOutputDeviceTest::GetOutputDeviceInfo,
|
| + base::Unretained(this), &event));
|
| + event.Wait();
|
| +
|
| + EXPECT_EQ(kDefaultDeviceId, device_info_.device_id());
|
| + EXPECT_EQ(OUTPUT_DEVICE_STATUS_OK, device_info_.device_status());
|
| + EXPECT_TRUE(device_info_.output_params().Equals(default_audio_parameters_));
|
| +
|
| + StopAudioDevice();
|
| +}
|
| +
|
| +TEST_P(AudioOutputDeviceTest, NonDefaultGetOutputDeviceInfo) {
|
| + SetDevice(kNonDefaultDeviceId);
|
| +
|
| + // AudioOutputDevice::GetOutputDeviceInfo must be called on a different thread
|
| + // than the task runner given to it.
|
| + base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
|
| + base::WaitableEvent::InitialState::NOT_SIGNALED);
|
| + base::Thread thread("get_output_device_info");
|
| + thread.Start();
|
| +
|
| + // Get device info on the other thread and wait until finished.
|
| + thread.task_runner()->PostTask(
|
| + FROM_HERE, base::Bind(&AudioOutputDeviceTest::GetOutputDeviceInfo,
|
| + base::Unretained(this), &event));
|
| + event.Wait();
|
| +
|
| + EXPECT_EQ(kNonDefaultDeviceId, device_info_.device_id());
|
| + EXPECT_EQ(OUTPUT_DEVICE_STATUS_OK, device_info_.device_status());
|
| + EXPECT_TRUE(device_info_.output_params().Equals(default_audio_parameters_));
|
| +
|
| + StopAudioDevice();
|
| +}
|
| +
|
| +TEST_P(AudioOutputDeviceTest, MultipleNonDefaultGetOutputDeviceInfo) {
|
| + SetDevice(kNonDefaultDeviceId);
|
| +
|
| + // AudioOutputDevice::GetOutputDeviceInfo must be called on a different thread
|
| + // than the task runner given to it.
|
| + base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
|
| + base::WaitableEvent::InitialState::NOT_SIGNALED);
|
| + base::Thread thread("get_output_device_info");
|
| + thread.Start();
|
| +
|
| + // Get device info on the other thread and wait until finished.
|
| + thread.task_runner()->PostTask(
|
| + FROM_HERE, base::Bind(&AudioOutputDeviceTest::GetOutputDeviceInfo,
|
| + base::Unretained(this), &event));
|
| + event.Wait();
|
| +
|
| + EXPECT_EQ(kNonDefaultDeviceId, device_info_.device_id());
|
| + EXPECT_EQ(OUTPUT_DEVICE_STATUS_OK, device_info_.device_status());
|
| + EXPECT_TRUE(device_info_.output_params().Equals(default_audio_parameters_));
|
| +
|
| + SetDeviceInfoToGarbage();
|
| + event.Reset();
|
| +
|
| + // Get device info on the other thread and wait until finished.
|
| + thread.task_runner()->PostTask(
|
| + FROM_HERE, base::Bind(&AudioOutputDeviceTest::GetOutputDeviceInfo,
|
| + base::Unretained(this), &event));
|
| + event.Wait();
|
| +
|
| + EXPECT_EQ(kNonDefaultDeviceId, device_info_.device_id());
|
| + EXPECT_EQ(OUTPUT_DEVICE_STATUS_OK, device_info_.device_status());
|
| + EXPECT_TRUE(device_info_.output_params().Equals(default_audio_parameters_));
|
| +
|
| + StopAudioDevice();
|
| }
|
|
|
| TEST_P(AudioOutputDeviceTest, AuthorizationTimedOut) {
|
|
|