Report errors from ChromiumEnv::GetChildren in Posix.
[chromium-blink-merge.git] / media / audio / virtual_audio_input_stream_unittest.cc
blobaab67cca5719a15a63db2db7d47eed6e81d7285d
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/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::TestWithParam<bool> {
101 public:
102 VirtualAudioInputStreamTest()
103 : audio_thread_(new base::Thread("AudioThread")),
104 worker_thread_(new base::Thread("AudioWorkerThread")),
105 stream_(NULL),
106 closed_stream_(false, false) {
107 audio_thread_->Start();
108 audio_message_loop_ = audio_thread_->message_loop_proxy();
111 virtual ~VirtualAudioInputStreamTest() {
112 SyncWithAudioThread();
114 DCHECK(output_streams_.empty());
115 DCHECK(stopped_output_streams_.empty());
118 void Create() {
119 const bool worker_is_separate_thread = GetParam();
120 stream_ = new VirtualAudioInputStream(
121 kParams, GetWorkerLoop(worker_is_separate_thread),
122 base::Bind(&base::DeletePointer<VirtualAudioInputStream>));
123 stream_->Open();
126 void Start() {
127 EXPECT_CALL(input_callback_, OnClose(_));
128 EXPECT_CALL(input_callback_, OnData(_, NotNull(), _, _, _))
129 .Times(AtLeast(1));
131 ASSERT_TRUE(!!stream_);
132 stream_->Start(&input_callback_);
135 void CreateAndStartOneOutputStream() {
136 ASSERT_TRUE(!!stream_);
137 AudioOutputStream* const output_stream = new VirtualAudioOutputStream(
138 kParams,
139 stream_,
140 base::Bind(&base::DeletePointer<VirtualAudioOutputStream>));
141 output_streams_.push_back(output_stream);
143 output_stream->Open();
144 output_stream->Start(&source_);
147 void Stop() {
148 ASSERT_TRUE(!!stream_);
149 stream_->Stop();
152 void Close() {
153 ASSERT_TRUE(!!stream_);
154 stream_->Close();
155 stream_ = NULL;
156 closed_stream_.Signal();
159 void WaitForDataToFlow() {
160 // Wait until audio thread is idle before calling output_streams_.size().
161 SyncWithAudioThread();
163 const int count = output_streams_.size();
164 for (int i = 0; i < count; ++i) {
165 source_.WaitForDataPulls();
168 input_callback_.WaitForDataPushes();
171 void WaitUntilClosed() {
172 closed_stream_.Wait();
175 void StopAndCloseOneOutputStream() {
176 ASSERT_TRUE(!output_streams_.empty());
177 AudioOutputStream* const output_stream = output_streams_.front();
178 ASSERT_TRUE(!!output_stream);
179 output_streams_.pop_front();
181 output_stream->Stop();
182 output_stream->Close();
185 void StopFirstOutputStream() {
186 ASSERT_TRUE(!output_streams_.empty());
187 AudioOutputStream* const output_stream = output_streams_.front();
188 ASSERT_TRUE(!!output_stream);
189 output_streams_.pop_front();
190 output_stream->Stop();
191 stopped_output_streams_.push_back(output_stream);
194 void StopSomeOutputStreams() {
195 ASSERT_LE(2, static_cast<int>(output_streams_.size()));
196 for (int remaning = base::RandInt(1, output_streams_.size() - 1);
197 remaning > 0; --remaning) {
198 StopFirstOutputStream();
202 void RestartAllStoppedOutputStreams() {
203 typedef std::list<AudioOutputStream*>::const_iterator ConstIter;
204 for (ConstIter it = stopped_output_streams_.begin();
205 it != stopped_output_streams_.end(); ++it) {
206 (*it)->Start(&source_);
207 output_streams_.push_back(*it);
209 stopped_output_streams_.clear();
212 const scoped_refptr<base::MessageLoopProxy>& audio_message_loop() const {
213 return audio_message_loop_;
216 const scoped_refptr<base::MessageLoopProxy>& GetWorkerLoop(
217 bool worker_is_separate_thread) {
218 if (worker_is_separate_thread) {
219 if (!worker_thread_->IsRunning()) {
220 worker_thread_->Start();
221 worker_message_loop_ = worker_thread_->message_loop_proxy();
223 return worker_message_loop_;
224 } else {
225 return audio_message_loop_;
229 private:
230 void SyncWithAudioThread() {
231 base::WaitableEvent done(false, false);
232 audio_message_loop_->PostTask(
233 FROM_HERE,
234 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&done)));
235 done.Wait();
238 scoped_ptr<base::Thread> audio_thread_;
239 scoped_refptr<base::MessageLoopProxy> audio_message_loop_;
240 scoped_ptr<base::Thread> worker_thread_;
241 scoped_refptr<base::MessageLoopProxy> worker_message_loop_;
243 VirtualAudioInputStream* stream_;
244 MockInputCallback input_callback_;
245 base::WaitableEvent closed_stream_;
247 std::list<AudioOutputStream*> output_streams_;
248 std::list<AudioOutputStream*> stopped_output_streams_;
249 TestAudioSource source_;
251 DISALLOW_COPY_AND_ASSIGN(VirtualAudioInputStreamTest);
254 #define RUN_ON_AUDIO_THREAD(method) \
255 audio_message_loop()->PostTask( \
256 FROM_HERE, base::Bind(&VirtualAudioInputStreamTest::method, \
257 base::Unretained(this)))
259 TEST_P(VirtualAudioInputStreamTest, CreateAndClose) {
260 RUN_ON_AUDIO_THREAD(Create);
261 RUN_ON_AUDIO_THREAD(Close);
262 WaitUntilClosed();
265 TEST_P(VirtualAudioInputStreamTest, NoOutputs) {
266 RUN_ON_AUDIO_THREAD(Create);
267 RUN_ON_AUDIO_THREAD(Start);
268 WaitForDataToFlow();
269 RUN_ON_AUDIO_THREAD(Stop);
270 RUN_ON_AUDIO_THREAD(Close);
271 WaitUntilClosed();
274 TEST_P(VirtualAudioInputStreamTest, SingleOutput) {
275 RUN_ON_AUDIO_THREAD(Create);
276 RUN_ON_AUDIO_THREAD(Start);
277 RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream);
278 WaitForDataToFlow();
279 RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream);
280 RUN_ON_AUDIO_THREAD(Stop);
281 RUN_ON_AUDIO_THREAD(Close);
282 WaitUntilClosed();
285 TEST_P(VirtualAudioInputStreamTest, SingleOutputPausedAndRestarted) {
286 RUN_ON_AUDIO_THREAD(Create);
287 RUN_ON_AUDIO_THREAD(Start);
288 RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream);
289 WaitForDataToFlow();
290 RUN_ON_AUDIO_THREAD(StopFirstOutputStream);
291 RUN_ON_AUDIO_THREAD(RestartAllStoppedOutputStreams);
292 WaitForDataToFlow();
293 RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream);
294 RUN_ON_AUDIO_THREAD(Stop);
295 RUN_ON_AUDIO_THREAD(Close);
296 WaitUntilClosed();
299 TEST_P(VirtualAudioInputStreamTest, MultipleOutputs) {
300 RUN_ON_AUDIO_THREAD(Create);
301 RUN_ON_AUDIO_THREAD(Start);
302 RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream);
303 WaitForDataToFlow();
304 RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream);
305 RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream);
306 WaitForDataToFlow();
307 RUN_ON_AUDIO_THREAD(StopFirstOutputStream);
308 RUN_ON_AUDIO_THREAD(StopFirstOutputStream);
309 WaitForDataToFlow();
310 RUN_ON_AUDIO_THREAD(StopFirstOutputStream);
311 RUN_ON_AUDIO_THREAD(RestartAllStoppedOutputStreams);
312 WaitForDataToFlow();
313 RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream);
314 RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream);
315 RUN_ON_AUDIO_THREAD(Stop);
316 RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream);
317 RUN_ON_AUDIO_THREAD(Close);
318 WaitUntilClosed();
321 // A combination of all of the above tests with many output streams.
322 TEST_P(VirtualAudioInputStreamTest, ComprehensiveTest) {
323 static const int kNumOutputs = 8;
324 static const int kHalfNumOutputs = kNumOutputs / 2;
325 static const int kPauseIterations = 5;
327 RUN_ON_AUDIO_THREAD(Create);
328 for (int i = 0; i < kHalfNumOutputs; ++i) {
329 RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream);
331 RUN_ON_AUDIO_THREAD(Start);
332 WaitForDataToFlow();
333 for (int i = 0; i < kHalfNumOutputs; ++i) {
334 RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream);
336 WaitForDataToFlow();
337 for (int i = 0; i < kPauseIterations; ++i) {
338 RUN_ON_AUDIO_THREAD(StopSomeOutputStreams);
339 WaitForDataToFlow();
340 RUN_ON_AUDIO_THREAD(RestartAllStoppedOutputStreams);
341 WaitForDataToFlow();
343 for (int i = 0; i < kHalfNumOutputs; ++i) {
344 RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream);
346 RUN_ON_AUDIO_THREAD(Stop);
347 for (int i = 0; i < kHalfNumOutputs; ++i) {
348 RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream);
350 RUN_ON_AUDIO_THREAD(Close);
351 WaitUntilClosed();
354 INSTANTIATE_TEST_CASE_P(SingleVersusMultithreaded,
355 VirtualAudioInputStreamTest,
356 ::testing::Values(false, true));
358 } // namespace media