| // 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 <memory> |
| |
| #include "base/bind.h" |
| #include "base/bind_helpers.h" |
| #include "base/macros.h" |
| #include "base/synchronization/waitable_event.h" |
| #include "base/threading/thread.h" |
| #include "media/audio/audio_manager.h" |
| #include "media/audio/simple_sources.h" |
| #include "media/audio/virtual_audio_input_stream.h" |
| #include "media/audio/virtual_audio_output_stream.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| using ::testing::_; |
| |
| namespace media { |
| |
| namespace { |
| const AudioParameters kParams( |
| AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_MONO, 8000, 8, 128); |
| } |
| |
| class MockVirtualAudioInputStream : public VirtualAudioInputStream { |
| public: |
| explicit MockVirtualAudioInputStream( |
| const scoped_refptr<base::SingleThreadTaskRunner>& worker_task_runner) |
| : VirtualAudioInputStream( |
| kParams, |
| worker_task_runner, |
| base::Bind(&base::DeletePointer<VirtualAudioInputStream>)) {} |
| ~MockVirtualAudioInputStream() {} |
| |
| MOCK_METHOD2(AddInputProvider, |
| void(AudioConverter::InputCallback* input, |
| const AudioParameters& params)); |
| MOCK_METHOD2(RemoveInputProvider, |
| void(AudioConverter::InputCallback* input, |
| const AudioParameters& params)); |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(MockVirtualAudioInputStream); |
| }; |
| |
| class MockAudioDeviceListener : public AudioManager::AudioDeviceListener { |
| public: |
| MOCK_METHOD0(OnDeviceChange, void()); |
| }; |
| |
| class VirtualAudioOutputStreamTest : public testing::Test { |
| public: |
| VirtualAudioOutputStreamTest() |
| : audio_thread_(new base::Thread("AudioThread")) { |
| audio_thread_->Start(); |
| audio_task_runner_ = audio_thread_->task_runner(); |
| } |
| |
| const scoped_refptr<base::SingleThreadTaskRunner>& audio_task_runner() const { |
| return audio_task_runner_; |
| } |
| |
| void SyncWithAudioThread() { |
| base::WaitableEvent done(base::WaitableEvent::ResetPolicy::AUTOMATIC, |
| base::WaitableEvent::InitialState::NOT_SIGNALED); |
| audio_task_runner()->PostTask( |
| FROM_HERE, base::Bind(&base::WaitableEvent::Signal, |
| base::Unretained(&done))); |
| done.Wait(); |
| } |
| |
| private: |
| std::unique_ptr<base::Thread> audio_thread_; |
| scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner_; |
| |
| DISALLOW_COPY_AND_ASSIGN(VirtualAudioOutputStreamTest); |
| }; |
| |
| TEST_F(VirtualAudioOutputStreamTest, StartStopStartStop) { |
| static const int kCycles = 3; |
| |
| MockVirtualAudioInputStream* const input_stream = |
| new MockVirtualAudioInputStream(audio_task_runner()); |
| audio_task_runner()->PostTask( |
| FROM_HERE, base::Bind( |
| base::IgnoreResult(&MockVirtualAudioInputStream::Open), |
| base::Unretained(input_stream))); |
| |
| VirtualAudioOutputStream* const output_stream = new VirtualAudioOutputStream( |
| kParams, |
| input_stream, |
| base::Bind(&base::DeletePointer<VirtualAudioOutputStream>)); |
| |
| EXPECT_CALL(*input_stream, AddInputProvider(output_stream, _)).Times(kCycles); |
| EXPECT_CALL(*input_stream, RemoveInputProvider(output_stream, _)) |
| .Times(kCycles); |
| |
| audio_task_runner()->PostTask( |
| FROM_HERE, base::Bind(base::IgnoreResult(&VirtualAudioOutputStream::Open), |
| base::Unretained(output_stream))); |
| SineWaveAudioSource source(CHANNEL_LAYOUT_STEREO, 200.0, 128); |
| for (int i = 0; i < kCycles; ++i) { |
| audio_task_runner()->PostTask( |
| FROM_HERE, base::Bind(&VirtualAudioOutputStream::Start, |
| base::Unretained(output_stream), |
| &source)); |
| audio_task_runner()->PostTask( |
| FROM_HERE, base::Bind(&VirtualAudioOutputStream::Stop, |
| base::Unretained(output_stream))); |
| } |
| audio_task_runner()->PostTask( |
| FROM_HERE, base::Bind(&VirtualAudioOutputStream::Close, |
| base::Unretained(output_stream))); |
| |
| audio_task_runner()->PostTask( |
| FROM_HERE, base::Bind(&MockVirtualAudioInputStream::Close, |
| base::Unretained(input_stream))); |
| |
| SyncWithAudioThread(); |
| } |
| |
| } // namespace media |