Separate Simple Backend creation from initialization.
[chromium-blink-merge.git] / media / audio / virtual_audio_input_stream_unittest.cc
blob0c886723031d9270371b3f40a94b7efd51cf4f8f
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include <list>
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/message_loop.h"
10 #include "base/rand_util.h"
11 #include "base/synchronization/waitable_event.h"
12 #include "base/threading/thread.h"
13 #include "media/audio/audio_io.h"
14 #include "media/audio/simple_sources.h"
15 #include "media/audio/virtual_audio_input_stream.h"
16 #include "media/audio/virtual_audio_output_stream.h"
17 #include "testing/gmock/include/gmock/gmock.h"
18 #include "testing/gtest/include/gtest/gtest.h"
20 using ::testing::_;
21 using ::testing::AtLeast;
22 using ::testing::InvokeWithoutArgs;
23 using ::testing::NotNull;
25 namespace media {
27 namespace {
29 const AudioParameters kParams(
30 AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO, 8000, 8, 10);
32 class MockInputCallback : public AudioInputStream::AudioInputCallback {
33 public:
34 MockInputCallback()
35 : data_pushed_(false, false) {
36 ON_CALL(*this, OnData(_, _, _, _, _))
37 .WillByDefault(InvokeWithoutArgs(&data_pushed_,
38 &base::WaitableEvent::Signal));
41 virtual ~MockInputCallback() {}
43 MOCK_METHOD5(OnData, void(AudioInputStream* stream, const uint8* data,
44 uint32 size, uint32 hardware_delay_bytes,
45 double volume));
46 MOCK_METHOD1(OnClose, void(AudioInputStream* stream));
47 MOCK_METHOD1(OnError, void(AudioInputStream* stream));
49 void WaitForDataPushes() {
50 for (int i = 0; i < 3; ++i) {
51 data_pushed_.Wait();
55 private:
56 base::WaitableEvent data_pushed_;
58 DISALLOW_COPY_AND_ASSIGN(MockInputCallback);
61 class TestAudioSource : public SineWaveAudioSource {
62 public:
63 TestAudioSource()
64 : SineWaveAudioSource(
65 kParams.channel_layout(), 200.0, kParams.sample_rate()),
66 data_pulled_(false, false) {}
68 virtual ~TestAudioSource() {}
70 virtual int OnMoreData(AudioBus* audio_bus,
71 AudioBuffersState audio_buffers) OVERRIDE {
72 const int ret = SineWaveAudioSource::OnMoreData(audio_bus, audio_buffers);
73 data_pulled_.Signal();
74 return ret;
77 virtual int OnMoreIOData(AudioBus* source,
78 AudioBus* dest,
79 AudioBuffersState audio_buffers) OVERRIDE {
80 const int ret =
81 SineWaveAudioSource::OnMoreIOData(source, dest, audio_buffers);
82 data_pulled_.Signal();
83 return ret;
86 void WaitForDataPulls() {
87 for (int i = 0; i < 3; ++i) {
88 data_pulled_.Wait();
92 private:
93 base::WaitableEvent data_pulled_;
95 DISALLOW_COPY_AND_ASSIGN(TestAudioSource);
98 } // namespace
100 class VirtualAudioInputStreamTest : public testing::Test {
101 public:
102 VirtualAudioInputStreamTest()
103 : audio_thread_(new base::Thread("AudioThread")),
104 stream_(NULL),
105 closed_stream_(false, false) {
106 audio_thread_->Start();
107 audio_message_loop_ = audio_thread_->message_loop_proxy();
110 virtual ~VirtualAudioInputStreamTest() {
111 SyncWithAudioThread();
113 DCHECK(output_streams_.empty());
114 DCHECK(stopped_output_streams_.empty());
117 void Create() {
118 stream_ = new VirtualAudioInputStream(
119 kParams, audio_message_loop_,
120 base::Bind(&base::DeletePointer<VirtualAudioInputStream>));
121 stream_->Open();
124 void Start() {
125 EXPECT_CALL(input_callback_, OnClose(_));
126 EXPECT_CALL(input_callback_, OnData(_, NotNull(), _, _, _))
127 .Times(AtLeast(1));
129 ASSERT_TRUE(!!stream_);
130 stream_->Start(&input_callback_);
133 void CreateAndStartOneOutputStream() {
134 ASSERT_TRUE(!!stream_);
135 AudioOutputStream* const output_stream =
136 new VirtualAudioOutputStream(
137 kParams, audio_message_loop_, stream_,
138 base::Bind(&base::DeletePointer<VirtualAudioOutputStream>));
139 output_streams_.push_back(output_stream);
141 output_stream->Open();
142 output_stream->Start(&source_);
145 void Stop() {
146 ASSERT_TRUE(!!stream_);
147 stream_->Stop();
150 void Close() {
151 ASSERT_TRUE(!!stream_);
152 stream_->Close();
153 stream_ = NULL;
154 closed_stream_.Signal();
157 void WaitForDataToFlow() {
158 // Wait until audio thread is idle before calling output_streams_.size().
159 SyncWithAudioThread();
161 const int count = output_streams_.size();
162 for (int i = 0; i < count; ++i) {
163 source_.WaitForDataPulls();
166 input_callback_.WaitForDataPushes();
169 void WaitUntilClosed() {
170 closed_stream_.Wait();
173 void StopAndCloseOneOutputStream() {
174 ASSERT_TRUE(!output_streams_.empty());
175 AudioOutputStream* const output_stream = output_streams_.front();
176 ASSERT_TRUE(!!output_stream);
177 output_streams_.pop_front();
179 output_stream->Stop();
180 output_stream->Close();
183 void StopFirstOutputStream() {
184 ASSERT_TRUE(!output_streams_.empty());
185 AudioOutputStream* const output_stream = output_streams_.front();
186 ASSERT_TRUE(!!output_stream);
187 output_streams_.pop_front();
188 output_stream->Stop();
189 stopped_output_streams_.push_back(output_stream);
192 void StopSomeOutputStreams() {
193 ASSERT_LE(2, static_cast<int>(output_streams_.size()));
194 for (int remaning = base::RandInt(1, output_streams_.size() - 1);
195 remaning > 0; --remaning) {
196 StopFirstOutputStream();
200 void RestartAllStoppedOutputStreams() {
201 typedef std::list<AudioOutputStream*>::const_iterator ConstIter;
202 for (ConstIter it = stopped_output_streams_.begin();
203 it != stopped_output_streams_.end(); ++it) {
204 (*it)->Start(&source_);
205 output_streams_.push_back(*it);
207 stopped_output_streams_.clear();
210 const scoped_refptr<base::MessageLoopProxy>& audio_message_loop() const {
211 return audio_message_loop_;
214 private:
215 void SyncWithAudioThread() {
216 base::WaitableEvent done(false, false);
217 audio_message_loop_->PostTask(
218 FROM_HERE,
219 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&done)));
220 done.Wait();
223 scoped_ptr<base::Thread> audio_thread_;
224 scoped_refptr<base::MessageLoopProxy> audio_message_loop_;
226 VirtualAudioInputStream* stream_;
227 MockInputCallback input_callback_;
228 base::WaitableEvent closed_stream_;
230 std::list<AudioOutputStream*> output_streams_;
231 std::list<AudioOutputStream*> stopped_output_streams_;
232 TestAudioSource source_;
234 DISALLOW_COPY_AND_ASSIGN(VirtualAudioInputStreamTest);
237 #define RUN_ON_AUDIO_THREAD(method) \
238 audio_message_loop()->PostTask( \
239 FROM_HERE, base::Bind(&VirtualAudioInputStreamTest::method, \
240 base::Unretained(this)))
242 TEST_F(VirtualAudioInputStreamTest, CreateAndClose) {
243 RUN_ON_AUDIO_THREAD(Create);
244 RUN_ON_AUDIO_THREAD(Close);
245 WaitUntilClosed();
248 TEST_F(VirtualAudioInputStreamTest, NoOutputs) {
249 RUN_ON_AUDIO_THREAD(Create);
250 RUN_ON_AUDIO_THREAD(Start);
251 WaitForDataToFlow();
252 RUN_ON_AUDIO_THREAD(Stop);
253 RUN_ON_AUDIO_THREAD(Close);
254 WaitUntilClosed();
257 TEST_F(VirtualAudioInputStreamTest, SingleOutput) {
258 RUN_ON_AUDIO_THREAD(Create);
259 RUN_ON_AUDIO_THREAD(Start);
260 RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream);
261 WaitForDataToFlow();
262 RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream);
263 RUN_ON_AUDIO_THREAD(Stop);
264 RUN_ON_AUDIO_THREAD(Close);
265 WaitUntilClosed();
268 TEST_F(VirtualAudioInputStreamTest, SingleOutputPausedAndRestarted) {
269 RUN_ON_AUDIO_THREAD(Create);
270 RUN_ON_AUDIO_THREAD(Start);
271 RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream);
272 WaitForDataToFlow();
273 RUN_ON_AUDIO_THREAD(StopFirstOutputStream);
274 RUN_ON_AUDIO_THREAD(RestartAllStoppedOutputStreams);
275 WaitForDataToFlow();
276 RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream);
277 RUN_ON_AUDIO_THREAD(Stop);
278 RUN_ON_AUDIO_THREAD(Close);
279 WaitUntilClosed();
282 TEST_F(VirtualAudioInputStreamTest, MultipleOutputs) {
283 RUN_ON_AUDIO_THREAD(Create);
284 RUN_ON_AUDIO_THREAD(Start);
285 RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream);
286 WaitForDataToFlow();
287 RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream);
288 RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream);
289 WaitForDataToFlow();
290 RUN_ON_AUDIO_THREAD(StopFirstOutputStream);
291 RUN_ON_AUDIO_THREAD(StopFirstOutputStream);
292 WaitForDataToFlow();
293 RUN_ON_AUDIO_THREAD(StopFirstOutputStream);
294 RUN_ON_AUDIO_THREAD(RestartAllStoppedOutputStreams);
295 WaitForDataToFlow();
296 RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream);
297 RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream);
298 RUN_ON_AUDIO_THREAD(Stop);
299 RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream);
300 RUN_ON_AUDIO_THREAD(Close);
301 WaitUntilClosed();
304 // A combination of all of the above tests with many output streams.
305 TEST_F(VirtualAudioInputStreamTest, ComprehensiveTest) {
306 static const int kNumOutputs = 8;
307 static const int kHalfNumOutputs = kNumOutputs / 2;
308 static const int kPauseIterations = 5;
310 RUN_ON_AUDIO_THREAD(Create);
311 for (int i = 0; i < kHalfNumOutputs; ++i) {
312 RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream);
314 RUN_ON_AUDIO_THREAD(Start);
315 WaitForDataToFlow();
316 for (int i = 0; i < kHalfNumOutputs; ++i) {
317 RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream);
319 WaitForDataToFlow();
320 for (int i = 0; i < kPauseIterations; ++i) {
321 RUN_ON_AUDIO_THREAD(StopSomeOutputStreams);
322 WaitForDataToFlow();
323 RUN_ON_AUDIO_THREAD(RestartAllStoppedOutputStreams);
324 WaitForDataToFlow();
326 for (int i = 0; i < kHalfNumOutputs; ++i) {
327 RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream);
329 RUN_ON_AUDIO_THREAD(Stop);
330 for (int i = 0; i < kHalfNumOutputs; ++i) {
331 RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream);
333 RUN_ON_AUDIO_THREAD(Close);
334 WaitUntilClosed();
337 } // namespace media