Index: media/audio/virtual_audio_input_stream_unittest.cc |
diff --git a/media/audio/virtual_audio_input_stream_unittest.cc b/media/audio/virtual_audio_input_stream_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..eb65b9652a799e3cfbe530f0c778fe5cdc8e4e55 |
--- /dev/null |
+++ b/media/audio/virtual_audio_input_stream_unittest.cc |
@@ -0,0 +1,335 @@ |
+// Copyright (c) 2012 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 <vector> |
+ |
+#include "base/message_loop.h" |
+#include "base/synchronization/waitable_event.h" |
+#include "media/audio/audio_manager.h" |
+#include "media/audio/simple_sources.h" |
+#include "media/audio/virtual_audio_input_stream.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+namespace media { |
+ |
+class MockInputCallback : public AudioInputStream::AudioInputCallback { |
+ public: |
+ MockInputCallback() {} |
+ virtual void OnData(AudioInputStream* stream, const uint8* data, |
+ uint32 size, uint32 hardware_delay_bytes, |
+ double volume) {} |
+ virtual void OnClose(AudioInputStream* stream) {} |
+ virtual void OnError(AudioInputStream* stream, int code) {} |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(MockInputCallback); |
+}; |
+ |
+class VirtualAudioInputStreamTest : public testing::Test { |
+ public: |
+ VirtualAudioInputStreamTest() |
+ : audio_manager_(AudioManager::Create()), |
+ params_( |
+ AudioParameters::AUDIO_VIRTUAL,CHANNEL_LAYOUT_MONO, 8000, 8, 128), |
+ output_params_( |
+ AudioParameters::AUDIO_PCM_LINEAR, CHANNEL_LAYOUT_MONO, 8000, 8, |
+ 128), |
+ stream_(NULL), |
+ source_(CHANNEL_LAYOUT_STEREO, 200.0, 128), |
+ done_(false, false) { |
+ } |
+ |
+ void StartStreamAndRunTestsOnAudioThread(int num_output_streams, |
+ int num_callback_iterations, |
+ int num_streams_removed_per_round, |
+ int num_expected_source_callbacks) { |
+ ASSERT_TRUE(audio_manager_->GetMessageLoop()->BelongsToCurrentThread()); |
+ stream_->Open(); |
+ stream_->Start(&input_callback_); |
+ AddStreamsAndDoCallbacks(num_output_streams, |
+ num_callback_iterations, |
+ num_streams_removed_per_round, |
+ num_expected_source_callbacks); |
+ } |
+ |
+ void AddStreamsAndDoCallbacks(int num_output_streams, |
+ int num_callback_iterations, |
+ int num_streams_removed_per_round, |
+ int num_expected_source_callbacks) { |
+ ASSERT_TRUE(audio_manager_->GetMessageLoop()->BelongsToCurrentThread()); |
+ |
+ for (int i = 0; i < num_output_streams; ++i) { |
+ AudioOutputStream* output_stream = |
+ audio_manager_->MakeAudioOutputStream(output_params_); |
+ DCHECK(output_stream); |
+ output_streams_.push_back(output_stream); |
+ |
+ output_stream->Open(); |
+ output_stream->Start(&source_); |
+ } |
+ |
+ if (num_output_streams == 0 && num_streams_removed_per_round > 0) { |
+ AudioOutputStream* output_stream = output_streams_.back(); |
+ output_streams_.pop_back(); |
+ output_stream->Stop(); |
+ output_stream->Close(); |
+ } |
+ |
+ if (num_callback_iterations > 0) { |
+ // Force the next callback to be immediate. |
+ stream_->buffer_duration_ms_ = base::TimeDelta(); |
+ audio_manager_->GetMessageLoop()->PostTask( |
+ FROM_HERE, base::Bind( |
+ &VirtualAudioInputStreamTest::AddStreamsAndDoCallbacks, |
+ base::Unretained(this), |
+ 0, |
+ --num_callback_iterations, |
+ num_streams_removed_per_round, |
+ num_expected_source_callbacks)); |
+ } else { |
+ // Finish the test. |
+ EXPECT_EQ(num_expected_source_callbacks, source_.callbacks()); |
+ EXPECT_EQ(0, source_.errors()); |
+ |
+ for (std::vector<AudioOutputStream*>::iterator it = |
+ output_streams_.begin(); it != output_streams_.end(); ++it) |
+ (*it)->Stop(); |
+ |
+ stream_->Stop(); |
+ |
+ audio_manager_->GetMessageLoop()->PostTask( |
+ FROM_HERE, base::Bind(&VirtualAudioInputStreamTest::EndTest, |
+ base::Unretained(this))); |
+ } |
+ } |
+ |
+ void OpenAndCloseOnAudioThread() { |
+ ASSERT_TRUE(audio_manager_->GetMessageLoop()->BelongsToCurrentThread()); |
+ stream_->Open(); |
+ |
+ // Create 2 output streams, which we just open and close without starting. |
+ const int num_output_stream = 2; |
+ |
+ for (int i = 0; i < num_output_stream; ++i) { |
+ AudioOutputStream* output_stream = |
+ audio_manager_->MakeAudioOutputStream(output_params_); |
+ DCHECK(output_stream); |
+ output_streams_.push_back(output_stream); |
+ |
+ output_stream->Open(); |
+ } |
+ |
+ audio_manager_->GetMessageLoop()->PostTask( |
+ FROM_HERE, base::Bind(&VirtualAudioInputStreamTest::EndTest, |
+ base::Unretained(this))); |
+ } |
+ |
+ void StartStopOnAudioThread(int num_output_streams, |
+ int num_callback_iterations, |
+ int num_expected_source_callbacks) { |
+ ASSERT_TRUE(audio_manager_->GetMessageLoop()->BelongsToCurrentThread()); |
+ stream_->Open(); |
+ stream_->Start(&input_callback_); |
+ StartStopCallback(true, num_output_streams, num_callback_iterations, |
+ num_expected_source_callbacks); |
+ } |
+ |
+ void StartStopCallback(bool init, |
+ int num_output_streams, |
+ int num_callback_iterations, |
+ int num_expected_source_callbacks) { |
+ ASSERT_TRUE(audio_manager_->GetMessageLoop()->BelongsToCurrentThread()); |
+ |
+ if (init) { |
+ for (int i = 0; i < num_output_streams; ++i) { |
+ AudioOutputStream* output_stream = |
+ audio_manager_->MakeAudioOutputStream(output_params_); |
+ DCHECK(output_stream); |
+ output_streams_.push_back(output_stream); |
+ |
+ output_stream->Open(); |
+ output_stream->Start(&source_); |
+ } |
+ |
+ // Start with an odd iteration number so we call Stop() first below. |
+ DCHECK_NE(0, num_callback_iterations % 2); |
+ } |
+ |
+ // Start or stop half the streams. |
+ for (int i = 0; i < num_output_streams / 2; ++i) { |
+ if (num_callback_iterations % 2 != 0) |
+ output_streams_[i]->Stop(); |
+ else |
+ output_streams_[i]->Start(&source_); |
+ } |
+ |
+ if (num_callback_iterations > 0) { |
+ // Force the next callback to be immediate. |
+ stream_->buffer_duration_ms_ = base::TimeDelta::FromMilliseconds(0); |
+ audio_manager_->GetMessageLoop()->PostTask( |
+ FROM_HERE, base::Bind( |
+ &VirtualAudioInputStreamTest::StartStopCallback, |
+ base::Unretained(this), |
+ false, |
+ num_output_streams, |
+ --num_callback_iterations, |
+ num_expected_source_callbacks)); |
+ } else { |
+ // Finish the test. |
+ EXPECT_EQ(num_expected_source_callbacks, source_.callbacks()); |
+ EXPECT_EQ(0, source_.errors()); |
+ |
+ for (std::vector<AudioOutputStream*>::iterator it = |
+ output_streams_.begin(); it != output_streams_.end(); ++it) |
+ (*it)->Stop(); |
+ |
+ stream_->Stop(); |
+ |
+ audio_manager_->GetMessageLoop()->PostTask(FROM_HERE, |
+ base::Bind(&VirtualAudioInputStreamTest::EndTest, |
+ base::Unretained(this))); |
+ } |
+ } |
+ |
+ void EndTest() { |
+ for (std::vector<AudioOutputStream*>::iterator it = |
+ output_streams_.begin(); it != output_streams_.end(); ++it) |
+ (*it)->Close(); |
+ |
+ stream_->Close(); |
+ |
+ done_.Signal(); |
+ } |
+ |
+ protected: |
+ scoped_ptr<AudioManager> audio_manager_; |
+ AudioParameters params_; |
+ AudioParameters output_params_; |
+ VirtualAudioInputStream* stream_; |
+ MockInputCallback input_callback_; |
+ std::vector<AudioOutputStream*> output_streams_; |
+ SineWaveAudioSource source_; |
+ base::WaitableEvent done_; |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(VirtualAudioInputStreamTest); |
+}; |
+ |
+TEST_F(VirtualAudioInputStreamTest, AttachAndDriveSingleStream) { |
+ stream_ = static_cast<VirtualAudioInputStream*>( |
+ audio_manager_->MakeAudioInputStream(params_, "1")); |
+ DCHECK(stream_); |
+ |
+ const int num_output_streams = 1; |
+ const int num_callback_iterations = 1; |
+ const int num_streams_removed_per_round = 0; |
+ const int num_expected_source_callbacks = 1; |
+ |
+ audio_manager_->GetMessageLoop()->PostTask( |
+ FROM_HERE, base::Bind( |
+ &VirtualAudioInputStreamTest::StartStreamAndRunTestsOnAudioThread, |
+ base::Unretained(this), |
+ num_output_streams, |
+ num_callback_iterations, |
+ num_streams_removed_per_round, |
+ num_expected_source_callbacks)); |
+ |
+ done_.Wait(); |
+} |
+ |
+TEST_F(VirtualAudioInputStreamTest, AttachAndDriveMultipleStreams) { |
+ stream_ = static_cast<VirtualAudioInputStream*>( |
+ audio_manager_->MakeAudioInputStream(params_, "1")); |
+ DCHECK(stream_); |
+ |
+ const int num_output_streams = 5; |
+ const int num_callback_iterations = 5; |
+ const int num_streams_removed_per_round = 0; |
+ const int num_expected_source_callbacks = 25; |
+ |
+ audio_manager_->GetMessageLoop()->PostTask( |
+ FROM_HERE, base::Bind( |
+ &VirtualAudioInputStreamTest::StartStreamAndRunTestsOnAudioThread, |
+ base::Unretained(this), |
+ num_output_streams, |
+ num_callback_iterations, |
+ num_streams_removed_per_round, |
+ num_expected_source_callbacks)); |
+ |
+ done_.Wait(); |
+} |
+ |
+TEST_F(VirtualAudioInputStreamTest, AttachAndRemoveStreams) { |
+ stream_ = static_cast<VirtualAudioInputStream*>( |
+ audio_manager_->MakeAudioInputStream(params_, "1")); |
+ DCHECK(stream_); |
+ |
+ const int num_output_streams = 8; |
+ const int num_callback_iterations = 5; |
+ const int num_streams_removed_per_round = 1; |
+ const int num_expected_source_callbacks = 8 + 7 + 6 + 5 + 4; |
+ |
+ audio_manager_->GetMessageLoop()->PostTask( |
+ FROM_HERE, base::Bind( |
+ &VirtualAudioInputStreamTest::StartStreamAndRunTestsOnAudioThread, |
+ base::Unretained(this), |
+ num_output_streams, |
+ num_callback_iterations, |
+ num_streams_removed_per_round, |
+ num_expected_source_callbacks)); |
+ |
+ done_.Wait(); |
+} |
+ |
+// Opens/closes a VirtualAudioInputStream and a number of attached |
+// VirtualAudioOutputStreams without calling Start()/Stop(). |
+TEST_F(VirtualAudioInputStreamTest, OpenAndClose) { |
+ stream_ = static_cast<VirtualAudioInputStream*>( |
+ audio_manager_->MakeAudioInputStream(params_, "1")); |
+ DCHECK(stream_); |
+ |
+ audio_manager_->GetMessageLoop()->PostTask( |
+ FROM_HERE, base::Bind( |
+ &VirtualAudioInputStreamTest::OpenAndCloseOnAudioThread, |
+ base::Unretained(this))); |
+ |
+ done_.Wait(); |
+} |
+ |
+// Creates and closes and VirtualAudioInputStream. |
+TEST_F(VirtualAudioInputStreamTest, CreateAndClose) { |
+ stream_ = static_cast<VirtualAudioInputStream*>( |
+ audio_manager_->MakeAudioInputStream(params_, "1")); |
+ DCHECK(stream_); |
+ |
+ audio_manager_->GetMessageLoop()->PostTask( |
+ FROM_HERE, base::Bind(&VirtualAudioInputStreamTest::EndTest, |
+ base::Unretained(this))); |
+ |
+ done_.Wait(); |
+} |
+ |
+// Starts and stops VirtualAudioOutputStreams while attached to a |
+// VirtualAudioInputStream. |
+TEST_F(VirtualAudioInputStreamTest, AttachAndStartStopStreams) { |
+ stream_ = static_cast<VirtualAudioInputStream*>( |
+ audio_manager_->MakeAudioInputStream(params_, "1")); |
+ DCHECK(stream_); |
+ |
+ const int num_output_streams = 4; |
+ const int num_callback_iterations = 5; |
+ const int num_expected_source_callbacks = 2 + 4 + 2 + 4 + 2; |
+ |
+ audio_manager_->GetMessageLoop()->PostTask( |
+ FROM_HERE, base::Bind( |
+ &VirtualAudioInputStreamTest::StartStopOnAudioThread, |
+ base::Unretained(this), |
+ num_output_streams, |
+ num_callback_iterations, |
+ num_expected_source_callbacks)); |
+ |
+ done_.Wait(); |
+} |
+ |
+} // namespace media |