| 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
|
|
|