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

Unified Diff: media/audio/audio_output_device_unittest.cc

Issue 1703473002: Make AudioOutputDevice restartable and reinitializable (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@new_mixing
Patch Set: Code review (dalecurtis@). Created 4 years, 6 months 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
« media/audio/audio_output_device.cc ('K') | « media/audio/audio_output_device.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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) {
« media/audio/audio_output_device.cc ('K') | « media/audio/audio_output_device.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698