Index: media/audio/restartable_audio_output_device_impl_unittest.cc |
diff --git a/media/audio/restartable_audio_output_device_impl_unittest.cc b/media/audio/restartable_audio_output_device_impl_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..046a0de8311296c45d8529043a62ee383daf66c4 |
--- /dev/null |
+++ b/media/audio/restartable_audio_output_device_impl_unittest.cc |
@@ -0,0 +1,436 @@ |
+// Copyright 2016 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "media/audio/restartable_audio_output_device_impl.h" |
+ |
+#include "base/single_thread_task_runner.h" |
+#include "media/audio/audio_output_device.h" |
+#include "media/audio/audio_output_ipc.h" |
+#include "media/audio/mock_audio_output_ipc.h" |
+#include "media/audio/mock_render_callback.h" |
+#include "testing/gmock/include/gmock/gmock.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+using testing::_; |
+using testing::Exactly; |
+using testing::InSequence; |
+ |
+namespace media { |
+ |
+namespace { |
+ |
+const int kHWSampleRate = 22500; |
+const int kDefaultSampleRate = 32000; |
+const int kNewSampleRate = 44100; |
+const char kDefaultDeviceId[] = ""; |
+const char kBrokenDeviceId[] = "broken-device"; |
+ |
+AudioParameters BuildHWParams() { |
+ return AudioParameters(AudioParameters::AUDIO_PCM_LINEAR, |
+ CHANNEL_LAYOUT_STEREO, kHWSampleRate, 16, 512); |
+} |
+ |
+class FakeAudioOutputDevice : NON_EXPORTED_BASE(public AudioOutputDevice) { |
+ public: |
+ FakeAudioOutputDevice( |
+ scoped_ptr<AudioOutputIPC> ipc, |
+ const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner, |
+ const std::string& device_id) |
+ : AudioOutputDevice(std::move(ipc), |
+ io_task_runner, |
+ 0, |
+ std::string(), |
+ url::Origin()), |
+ device_id_(device_id), |
+ sample_rate_(0), |
+ volume_(1.0), |
+ initialized_(false), |
+ started_(false), |
+ playing_(false) {} |
+ |
+ MOCK_METHOD0(MockStop, void()); |
+ |
+ void Initialize(const AudioParameters& params, RenderCallback*) override { |
+ initialized_ = true; |
+ sample_rate_ = params.sample_rate(); |
+ } |
+ |
+ void Start() override { |
+ EXPECT_TRUE(initialized_); |
+ started_ = true; |
+ playing_ = true; // AudioOutputDevice plays on start. |
+ } |
+ |
+ void Play() override { |
+ EXPECT_TRUE(initialized_); |
+ playing_ = true; |
+ } |
+ |
+ void Pause() override { |
+ EXPECT_TRUE(initialized_); |
+ playing_ = false; |
+ } |
+ |
+ void Stop() override { |
+ started_ = false; |
+ playing_ = false; |
+ MockStop(); |
+ } |
+ |
+ bool SetVolume(double volume) override { |
+ EXPECT_TRUE(initialized_); |
+ if (device_id_ == kBrokenDeviceId) { |
+ volume_ = 0; |
+ return false; |
+ } |
+ volume_ = volume; |
+ return true; |
+ } |
+ |
+ double GetVolume() { return volume_; } |
+ int GetSampleRate() { return sample_rate_; } |
+ bool IsPlaying() { return started_ && playing_; } |
+ |
+ OutputDeviceStatus GetDeviceStatus() override { |
+ return device_id_ == kBrokenDeviceId ? OUTPUT_DEVICE_STATUS_ERROR_INTERNAL |
+ : OUTPUT_DEVICE_STATUS_OK; |
+ } |
+ |
+ AudioParameters GetOutputParameters() override { |
+ AudioParameters params = BuildHWParams(); |
+ if (device_id_ == kBrokenDeviceId) |
+ params.set_format(AudioParameters::AUDIO_FAKE); |
+ return params; |
+ } |
+ |
+ protected: |
+ virtual ~FakeAudioOutputDevice() {} |
+ |
+ private: |
+ const std::string device_id_; |
+ int sample_rate_; |
+ double volume_; |
+ bool initialized_; |
+ bool started_; |
+ bool playing_; |
+}; |
+ |
+} // namespace |
+ |
+class RestartableAudioOutputDeviceImplTest : public testing::Test { |
+ protected: |
+ RestartableAudioOutputDeviceImplTest() |
+ : message_loop_(new base::MessageLoopForIO), |
+ mock_ipc_(nullptr), |
+ default_params_(AudioParameters::AUDIO_PCM_LINEAR, |
+ CHANNEL_LAYOUT_STEREO, |
+ kDefaultSampleRate, |
+ 16, |
+ 512), |
+ new_params_(AudioParameters::AUDIO_PCM_LINEAR, |
+ CHANNEL_LAYOUT_STEREO, |
+ kNewSampleRate, |
+ 16, |
+ 512) {} |
+ |
+ MOCK_METHOD0(MockCreateOutputDevice, void()); |
+ |
+ scoped_refptr<media::AudioOutputDevice> CreateOutputDevice( |
+ int render_frame_id, |
+ int session_id, |
+ const std::string& device_id, |
+ const url::Origin& security_origin) { |
+ mock_ipc_ = new MockAudioOutputIPC(); |
+ mock_output_device_ = |
+ new FakeAudioOutputDevice(scoped_ptr<media::AudioOutputIPC>(mock_ipc_), |
+ message_loop_->task_runner(), device_id); |
+ ; |
+ EXPECT_CALL(*mock_output_device_.get(), MockStop()).Times(Exactly(1)); |
+ MockCreateOutputDevice(); |
+ return mock_output_device_; |
+ } |
+ |
+ void PrepareSink(const std::string& device_id, int times_to_restart = 0) { |
+ static const int kRendererFrameId = 0; |
+ static const int kSessionId = 0; |
+ static const url::Origin kSecurityOrigin; |
+ EXPECT_CALL(*this, MockCreateOutputDevice()).Times(times_to_restart + 1); |
+ sink_ = new media::RestartableAudioOutputDeviceImpl( |
+ base::Bind(&RestartableAudioOutputDeviceImplTest::CreateOutputDevice, |
+ base::Unretained(this), kRendererFrameId, kSessionId, |
+ device_id, kSecurityOrigin), |
+ base::Bind(&BuildHWParams)); |
+ } |
+ |
+ void TearDown() override { |
+ mock_output_device_ = nullptr; |
+ sink_ = nullptr; |
+ } |
+ |
+ // Used to construct |mock_output_device_|. |
+ scoped_ptr<base::MessageLoopForIO> message_loop_; |
+ MockAudioOutputIPC* mock_ipc_; // Owned by AudioOuputDevice. |
+ scoped_refptr<FakeAudioOutputDevice> mock_output_device_; |
+ |
+ // Sink under test. |
+ scoped_refptr<media::RestartableAudioOutputDeviceImpl> sink_; |
+ |
+ // Data used for initializations. |
+ media::AudioParameters default_params_; |
+ media::AudioParameters new_params_; |
+ MockRenderCallback callback_; |
+}; |
+ |
+TEST_F(RestartableAudioOutputDeviceImplTest, StopNotInitializedSink) { |
+ PrepareSink(kDefaultDeviceId); |
+ EXPECT_FALSE(mock_output_device_->IsPlaying()); |
+ sink_->Stop(); |
+} |
+ |
+TEST_F(RestartableAudioOutputDeviceImplTest, InitializeAndStopSink) { |
+ PrepareSink(kDefaultDeviceId); |
+ sink_->Initialize(default_params_, &callback_); |
+ EXPECT_FALSE(mock_output_device_->IsPlaying()); |
+ EXPECT_EQ(OUTPUT_DEVICE_STATUS_OK, sink_->GetDeviceStatus()); |
+ sink_->Stop(); |
+} |
+ |
+TEST_F(RestartableAudioOutputDeviceImplTest, StartAndStopSink) { |
+ PrepareSink(kDefaultDeviceId); |
+ |
+ sink_->Initialize(default_params_, &callback_); |
+ EXPECT_EQ(OUTPUT_DEVICE_STATUS_OK, sink_->GetDeviceStatus()); |
+ EXPECT_FALSE(mock_output_device_->IsPlaying()); |
+ |
+ sink_->Start(); |
+ EXPECT_EQ(OUTPUT_DEVICE_STATUS_OK, sink_->GetDeviceStatus()); |
+ EXPECT_FALSE(mock_output_device_->IsPlaying()); |
+ |
+ sink_->Stop(); |
+} |
+ |
+TEST_F(RestartableAudioOutputDeviceImplTest, StartPlayAndStopSink) { |
+ PrepareSink(kDefaultDeviceId); |
+ |
+ sink_->Initialize(default_params_, &callback_); |
+ EXPECT_EQ(OUTPUT_DEVICE_STATUS_OK, sink_->GetDeviceStatus()); |
+ EXPECT_FALSE(mock_output_device_->IsPlaying()); |
+ |
+ sink_->Start(); |
+ EXPECT_FALSE(mock_output_device_->IsPlaying()); |
+ EXPECT_EQ(OUTPUT_DEVICE_STATUS_OK, sink_->GetDeviceStatus()); |
+ |
+ EXPECT_EQ(kDefaultSampleRate, mock_output_device_->GetSampleRate()); |
+ |
+ sink_->Play(); |
+ EXPECT_EQ(OUTPUT_DEVICE_STATUS_OK, sink_->GetDeviceStatus()); |
+ EXPECT_TRUE(mock_output_device_->IsPlaying()); |
+ |
+ sink_->Stop(); |
+} |
+ |
+TEST_F(RestartableAudioOutputDeviceImplTest, StartPauseStopSink) { |
+ PrepareSink(kDefaultDeviceId); |
+ |
+ sink_->Initialize(default_params_, &callback_); |
+ EXPECT_EQ(OUTPUT_DEVICE_STATUS_OK, sink_->GetDeviceStatus()); |
+ EXPECT_FALSE(mock_output_device_->IsPlaying()); |
+ |
+ sink_->Start(); |
+ EXPECT_EQ(OUTPUT_DEVICE_STATUS_OK, sink_->GetDeviceStatus()); |
+ EXPECT_FALSE(mock_output_device_->IsPlaying()); |
+ |
+ sink_->Pause(); |
+ EXPECT_EQ(OUTPUT_DEVICE_STATUS_OK, sink_->GetDeviceStatus()); |
+ EXPECT_FALSE(mock_output_device_->IsPlaying()); |
+ |
+ sink_->Stop(); |
+} |
+ |
+//* |
+TEST_F(RestartableAudioOutputDeviceImplTest, PausePausedSink) { |
+ PrepareSink(kDefaultDeviceId); |
+ |
+ sink_->Initialize(default_params_, &callback_); |
+ EXPECT_FALSE(mock_output_device_->IsPlaying()); |
+ sink_->Start(); |
+ EXPECT_FALSE(mock_output_device_->IsPlaying()); |
+ sink_->Play(); |
+ EXPECT_TRUE(mock_output_device_->IsPlaying()); |
+ sink_->Pause(); |
+ EXPECT_FALSE(mock_output_device_->IsPlaying()); |
+ sink_->Pause(); |
+ EXPECT_FALSE(mock_output_device_->IsPlaying()); |
+ EXPECT_EQ(OUTPUT_DEVICE_STATUS_OK, sink_->GetDeviceStatus()); |
+ sink_->Stop(); |
+} |
+//* |
+TEST_F(RestartableAudioOutputDeviceImplTest, PlayPlayingSink) { |
+ PrepareSink(kDefaultDeviceId); |
+ |
+ sink_->Initialize(default_params_, &callback_); |
+ sink_->Start(); |
+ EXPECT_FALSE(mock_output_device_->IsPlaying()); |
+ sink_->Play(); |
+ EXPECT_TRUE(mock_output_device_->IsPlaying()); |
+ sink_->Play(); |
+ EXPECT_TRUE(mock_output_device_->IsPlaying()); |
+ EXPECT_EQ(OUTPUT_DEVICE_STATUS_OK, sink_->GetDeviceStatus()); |
+ sink_->Play(); |
+ EXPECT_TRUE(mock_output_device_->IsPlaying()); |
+ EXPECT_EQ(OUTPUT_DEVICE_STATUS_OK, sink_->GetDeviceStatus()); |
+ sink_->Stop(); |
+} |
+ |
+TEST_F(RestartableAudioOutputDeviceImplTest, StartPausePlayStopSink) { |
+ PrepareSink(kDefaultDeviceId); |
+ |
+ sink_->Initialize(default_params_, &callback_); |
+ sink_->Start(); |
+ EXPECT_FALSE(mock_output_device_->IsPlaying()); |
+ sink_->Pause(); |
+ EXPECT_FALSE(mock_output_device_->IsPlaying()); |
+ EXPECT_EQ(OUTPUT_DEVICE_STATUS_OK, sink_->GetDeviceStatus()); |
+ sink_->Play(); |
+ EXPECT_TRUE(mock_output_device_->IsPlaying()); |
+ EXPECT_EQ(OUTPUT_DEVICE_STATUS_OK, sink_->GetDeviceStatus()); |
+ sink_->Stop(); |
+} |
+ |
+TEST_F(RestartableAudioOutputDeviceImplTest, PauseAfterPlay) { |
+ PrepareSink(kDefaultDeviceId); |
+ |
+ sink_->Initialize(default_params_, &callback_); |
+ sink_->Start(); |
+ EXPECT_FALSE(mock_output_device_->IsPlaying()); |
+ sink_->Play(); |
+ EXPECT_TRUE(mock_output_device_->IsPlaying()); |
+ sink_->Pause(); |
+ EXPECT_FALSE(mock_output_device_->IsPlaying()); |
+ EXPECT_EQ(OUTPUT_DEVICE_STATUS_OK, sink_->GetDeviceStatus()); |
+ sink_->Stop(); |
+} |
+ |
+TEST_F(RestartableAudioOutputDeviceImplTest, MultiplePlayPause) { |
+ PrepareSink(kDefaultDeviceId); |
+ |
+ sink_->Initialize(default_params_, &callback_); |
+ sink_->Start(); |
+ EXPECT_FALSE(mock_output_device_->IsPlaying()); |
+ sink_->Play(); |
+ EXPECT_TRUE(mock_output_device_->IsPlaying()); |
+ sink_->Pause(); |
+ EXPECT_FALSE(mock_output_device_->IsPlaying()); |
+ sink_->Play(); |
+ EXPECT_TRUE(mock_output_device_->IsPlaying()); |
+ EXPECT_EQ(OUTPUT_DEVICE_STATUS_OK, sink_->GetDeviceStatus()); |
+ sink_->Pause(); |
+ EXPECT_FALSE(mock_output_device_->IsPlaying()); |
+ EXPECT_EQ(OUTPUT_DEVICE_STATUS_OK, sink_->GetDeviceStatus()); |
+ sink_->Stop(); |
+} |
+ |
+TEST_F(RestartableAudioOutputDeviceImplTest, RestartSinkNoReinit) { |
+ PrepareSink(kDefaultDeviceId, 1); |
+ |
+ sink_->Initialize(default_params_, &callback_); |
+ sink_->Start(); |
+ EXPECT_FALSE(mock_output_device_->IsPlaying()); |
+ EXPECT_EQ(kDefaultSampleRate, mock_output_device_->GetSampleRate()); |
+ sink_->Play(); |
+ EXPECT_TRUE(mock_output_device_->IsPlaying()); |
+ sink_->Stop(); |
+ EXPECT_EQ(OUTPUT_DEVICE_STATUS_OK, sink_->GetDeviceStatus()); |
+ sink_->Start(); |
+ EXPECT_FALSE(mock_output_device_->IsPlaying()); |
+ EXPECT_EQ(kDefaultSampleRate, mock_output_device_->GetSampleRate()); |
+ sink_->Play(); |
+ EXPECT_TRUE(mock_output_device_->IsPlaying()); |
+ sink_->Stop(); |
+} |
+ |
+TEST_F(RestartableAudioOutputDeviceImplTest, RestartAndReinitSink) { |
+ PrepareSink(kDefaultDeviceId, 1); |
+ |
+ sink_->Initialize(default_params_, &callback_); |
+ sink_->Start(); |
+ EXPECT_FALSE(mock_output_device_->IsPlaying()); |
+ EXPECT_EQ(kDefaultSampleRate, mock_output_device_->GetSampleRate()); |
+ sink_->Play(); |
+ EXPECT_TRUE(mock_output_device_->IsPlaying()); |
+ sink_->Stop(); |
+ |
+ sink_->Initialize(new_params_, &callback_); |
+ EXPECT_EQ(OUTPUT_DEVICE_STATUS_OK, sink_->GetDeviceStatus()); |
+ sink_->Start(); |
+ EXPECT_FALSE(mock_output_device_->IsPlaying()); |
+ EXPECT_EQ(kNewSampleRate, mock_output_device_->GetSampleRate()); |
+ sink_->Play(); |
+ EXPECT_TRUE(mock_output_device_->IsPlaying()); |
+ sink_->Stop(); |
+} |
+ |
+TEST_F(RestartableAudioOutputDeviceImplTest, GetOutputParameters) { |
+ PrepareSink(kDefaultDeviceId, 1); |
+ EXPECT_EQ(kHWSampleRate, sink_->GetOutputParameters().sample_rate()); |
+ sink_->Initialize(default_params_, &callback_); |
+ EXPECT_EQ(kHWSampleRate, sink_->GetOutputParameters().sample_rate()); |
+ sink_->Start(); |
+ EXPECT_EQ(kHWSampleRate, sink_->GetOutputParameters().sample_rate()); |
+ sink_->Play(); |
+ EXPECT_EQ(kHWSampleRate, sink_->GetOutputParameters().sample_rate()); |
+ sink_->Stop(); |
+ EXPECT_EQ(kHWSampleRate, sink_->GetOutputParameters().sample_rate()); |
+ sink_->Start(); |
+ EXPECT_EQ(kHWSampleRate, sink_->GetOutputParameters().sample_rate()); |
+ sink_->Stop(); |
+} |
+ |
+TEST_F(RestartableAudioOutputDeviceImplTest, SetVolume) { |
+ PrepareSink(kDefaultDeviceId, 1); |
+ |
+ sink_->SetVolume(0.8); // Set volume before starting sink. |
+ sink_->Initialize(default_params_, &callback_); |
+ sink_->Start(); |
+ sink_->Play(); |
+ EXPECT_DOUBLE_EQ(0.8, mock_output_device_->GetVolume()); |
+ sink_->Stop(); |
+ |
+ EXPECT_TRUE(sink_->SetVolume(0.1)); |
+ sink_->Initialize(default_params_, &callback_); |
+ EXPECT_TRUE(sink_->SetVolume(0.2)); |
+ sink_->Start(); |
+ EXPECT_TRUE(sink_->SetVolume(0.3)); |
+ sink_->Play(); |
+ EXPECT_DOUBLE_EQ(0.3, mock_output_device_->GetVolume()); |
+ EXPECT_TRUE(sink_->SetVolume(0.4)); |
+ EXPECT_DOUBLE_EQ(0.4, mock_output_device_->GetVolume()); |
+ EXPECT_TRUE(sink_->SetVolume(0.5)); |
+ EXPECT_DOUBLE_EQ(0.5, mock_output_device_->GetVolume()); |
+ sink_->Pause(); |
+ EXPECT_TRUE(sink_->SetVolume(0.6)); |
+ EXPECT_TRUE(sink_->SetVolume(0.7)); |
+ sink_->Play(); |
+ EXPECT_DOUBLE_EQ(0.7, mock_output_device_->GetVolume()); |
+ sink_->Stop(); |
+} |
+ |
+TEST_F(RestartableAudioOutputDeviceImplTest, CorrectStatusFromInvalidDevice) { |
+ PrepareSink(kBrokenDeviceId, 1); |
+ |
+ sink_->Initialize(default_params_, &callback_); |
+ sink_->Start(); |
+ EXPECT_NE(OUTPUT_DEVICE_STATUS_OK, sink_->GetDeviceStatus()); |
+ |
+ sink_->Stop(); |
+ // Stopped device is OK. |
+ EXPECT_EQ(OUTPUT_DEVICE_STATUS_OK, sink_->GetDeviceStatus()); |
+ |
+ sink_->Start(); |
+ EXPECT_NE(OUTPUT_DEVICE_STATUS_OK, sink_->GetDeviceStatus()); |
+ |
+ sink_->Stop(); |
+} |
+ |
+} // namespace content |