Add elapsed time and timeout value to feedback data.
[chromium-blink-merge.git] / media / audio / virtual_audio_input_stream_unittest.cc
blobc960f36c7edec8b8e16ff56d3353647df02fd316
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/rand_util.h"
10 #include "base/synchronization/waitable_event.h"
11 #include "base/threading/thread.h"
12 #include "media/audio/audio_io.h"
13 #include "media/audio/simple_sources.h"
14 #include "media/audio/virtual_audio_input_stream.h"
15 #include "media/audio/virtual_audio_output_stream.h"
16 #include "testing/gmock/include/gmock/gmock.h"
17 #include "testing/gtest/include/gtest/gtest.h"
19 using ::testing::_;
20 using ::testing::AtLeast;
21 using ::testing::InvokeWithoutArgs;
22 using ::testing::NotNull;
24 namespace media {
26 namespace {
28 const AudioParameters kParams(
29 AudioParameters::AUDIO_PCM_LOW_LATENCY, CHANNEL_LAYOUT_STEREO, 8000, 8, 10);
31 class MockInputCallback : public AudioInputStream::AudioInputCallback {
32 public:
33 MockInputCallback()
34 : data_pushed_(false, false) {
35 ON_CALL(*this, OnData(_, _, _, _)).WillByDefault(
36 InvokeWithoutArgs(&data_pushed_, &base::WaitableEvent::Signal));
39 virtual ~MockInputCallback() {}
41 MOCK_METHOD4(OnData,
42 void(AudioInputStream* stream,
43 const AudioBus* source,
44 uint32 hardware_delay_bytes,
45 double volume));
46 MOCK_METHOD1(OnError, void(AudioInputStream* stream));
48 void WaitForDataPushes() {
49 for (int i = 0; i < 3; ++i) {
50 data_pushed_.Wait();
54 private:
55 base::WaitableEvent data_pushed_;
57 DISALLOW_COPY_AND_ASSIGN(MockInputCallback);
60 class TestAudioSource : public SineWaveAudioSource {
61 public:
62 TestAudioSource()
63 : SineWaveAudioSource(
64 kParams.channel_layout(), 200.0, kParams.sample_rate()),
65 data_pulled_(false, false) {}
67 ~TestAudioSource() override {}
69 int OnMoreData(AudioBus* audio_bus, uint32 total_bytes_delay) override {
70 const int ret = SineWaveAudioSource::OnMoreData(audio_bus,
71 total_bytes_delay);
72 data_pulled_.Signal();
73 return ret;
76 void WaitForDataPulls() {
77 for (int i = 0; i < 3; ++i) {
78 data_pulled_.Wait();
82 private:
83 base::WaitableEvent data_pulled_;
85 DISALLOW_COPY_AND_ASSIGN(TestAudioSource);
88 } // namespace
90 class VirtualAudioInputStreamTest : public testing::TestWithParam<bool> {
91 public:
92 VirtualAudioInputStreamTest()
93 : audio_thread_(new base::Thread("AudioThread")),
94 worker_thread_(new base::Thread("AudioWorkerThread")),
95 stream_(NULL),
96 closed_stream_(false, false) {
97 audio_thread_->Start();
98 audio_task_runner_ = audio_thread_->message_loop_proxy();
101 virtual ~VirtualAudioInputStreamTest() {
102 SyncWithAudioThread();
104 DCHECK(output_streams_.empty());
105 DCHECK(stopped_output_streams_.empty());
108 void Create() {
109 const bool worker_is_separate_thread = GetParam();
110 stream_ = new VirtualAudioInputStream(
111 kParams, GetWorkerTaskRunner(worker_is_separate_thread),
112 base::Bind(&base::DeletePointer<VirtualAudioInputStream>));
113 stream_->Open();
116 void Start() {
117 EXPECT_CALL(input_callback_, OnData(_, NotNull(), _, _)).Times(AtLeast(1));
119 ASSERT_TRUE(stream_);
120 stream_->Start(&input_callback_);
123 void CreateAndStartOneOutputStream() {
124 ASSERT_TRUE(stream_);
125 AudioOutputStream* const output_stream = new VirtualAudioOutputStream(
126 kParams,
127 stream_,
128 base::Bind(&base::DeletePointer<VirtualAudioOutputStream>));
129 output_streams_.push_back(output_stream);
131 output_stream->Open();
132 output_stream->Start(&source_);
135 void Stop() {
136 ASSERT_TRUE(stream_);
137 stream_->Stop();
140 void Close() {
141 ASSERT_TRUE(stream_);
142 stream_->Close();
143 stream_ = NULL;
144 closed_stream_.Signal();
147 void WaitForDataToFlow() {
148 // Wait until audio thread is idle before calling output_streams_.size().
149 SyncWithAudioThread();
151 const int count = output_streams_.size();
152 for (int i = 0; i < count; ++i) {
153 source_.WaitForDataPulls();
156 input_callback_.WaitForDataPushes();
159 void WaitUntilClosed() {
160 closed_stream_.Wait();
163 void StopAndCloseOneOutputStream() {
164 ASSERT_TRUE(!output_streams_.empty());
165 AudioOutputStream* const output_stream = output_streams_.front();
166 ASSERT_TRUE(output_stream);
167 output_streams_.pop_front();
169 output_stream->Stop();
170 output_stream->Close();
173 void StopFirstOutputStream() {
174 ASSERT_TRUE(!output_streams_.empty());
175 AudioOutputStream* const output_stream = output_streams_.front();
176 ASSERT_TRUE(output_stream);
177 output_streams_.pop_front();
178 output_stream->Stop();
179 stopped_output_streams_.push_back(output_stream);
182 void StopSomeOutputStreams() {
183 ASSERT_LE(2, static_cast<int>(output_streams_.size()));
184 for (int remaning = base::RandInt(1, output_streams_.size() - 1);
185 remaning > 0; --remaning) {
186 StopFirstOutputStream();
190 void RestartAllStoppedOutputStreams() {
191 typedef std::list<AudioOutputStream*>::const_iterator ConstIter;
192 for (ConstIter it = stopped_output_streams_.begin();
193 it != stopped_output_streams_.end(); ++it) {
194 (*it)->Start(&source_);
195 output_streams_.push_back(*it);
197 stopped_output_streams_.clear();
200 const scoped_refptr<base::SingleThreadTaskRunner>& audio_task_runner() const {
201 return audio_task_runner_;
204 const scoped_refptr<base::SingleThreadTaskRunner>& GetWorkerTaskRunner(
205 bool worker_is_separate_thread) {
206 if (worker_is_separate_thread) {
207 if (!worker_thread_->IsRunning()) {
208 worker_thread_->Start();
209 worker_task_runner_ = worker_thread_->message_loop_proxy();
211 return worker_task_runner_;
212 } else {
213 return audio_task_runner_;
217 private:
218 void SyncWithAudioThread() {
219 base::WaitableEvent done(false, false);
220 audio_task_runner_->PostTask(
221 FROM_HERE,
222 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&done)));
223 done.Wait();
226 scoped_ptr<base::Thread> audio_thread_;
227 scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner_;
228 scoped_ptr<base::Thread> worker_thread_;
229 scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner_;
231 VirtualAudioInputStream* stream_;
232 MockInputCallback input_callback_;
233 base::WaitableEvent closed_stream_;
235 std::list<AudioOutputStream*> output_streams_;
236 std::list<AudioOutputStream*> stopped_output_streams_;
237 TestAudioSource source_;
239 DISALLOW_COPY_AND_ASSIGN(VirtualAudioInputStreamTest);
242 #define RUN_ON_AUDIO_THREAD(method) \
243 audio_task_runner()->PostTask( \
244 FROM_HERE, base::Bind(&VirtualAudioInputStreamTest::method, \
245 base::Unretained(this)))
247 TEST_P(VirtualAudioInputStreamTest, CreateAndClose) {
248 RUN_ON_AUDIO_THREAD(Create);
249 RUN_ON_AUDIO_THREAD(Close);
250 WaitUntilClosed();
253 TEST_P(VirtualAudioInputStreamTest, NoOutputs) {
254 RUN_ON_AUDIO_THREAD(Create);
255 RUN_ON_AUDIO_THREAD(Start);
256 WaitForDataToFlow();
257 RUN_ON_AUDIO_THREAD(Stop);
258 RUN_ON_AUDIO_THREAD(Close);
259 WaitUntilClosed();
262 TEST_P(VirtualAudioInputStreamTest, SingleOutput) {
263 RUN_ON_AUDIO_THREAD(Create);
264 RUN_ON_AUDIO_THREAD(Start);
265 RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream);
266 WaitForDataToFlow();
267 RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream);
268 RUN_ON_AUDIO_THREAD(Stop);
269 RUN_ON_AUDIO_THREAD(Close);
270 WaitUntilClosed();
273 TEST_P(VirtualAudioInputStreamTest, SingleOutputPausedAndRestarted) {
274 RUN_ON_AUDIO_THREAD(Create);
275 RUN_ON_AUDIO_THREAD(Start);
276 RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream);
277 WaitForDataToFlow();
278 RUN_ON_AUDIO_THREAD(StopFirstOutputStream);
279 RUN_ON_AUDIO_THREAD(RestartAllStoppedOutputStreams);
280 WaitForDataToFlow();
281 RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream);
282 RUN_ON_AUDIO_THREAD(Stop);
283 RUN_ON_AUDIO_THREAD(Close);
284 WaitUntilClosed();
287 TEST_P(VirtualAudioInputStreamTest, MultipleOutputs) {
288 RUN_ON_AUDIO_THREAD(Create);
289 RUN_ON_AUDIO_THREAD(Start);
290 RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream);
291 WaitForDataToFlow();
292 RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream);
293 RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream);
294 WaitForDataToFlow();
295 RUN_ON_AUDIO_THREAD(StopFirstOutputStream);
296 RUN_ON_AUDIO_THREAD(StopFirstOutputStream);
297 WaitForDataToFlow();
298 RUN_ON_AUDIO_THREAD(StopFirstOutputStream);
299 RUN_ON_AUDIO_THREAD(RestartAllStoppedOutputStreams);
300 WaitForDataToFlow();
301 RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream);
302 RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream);
303 RUN_ON_AUDIO_THREAD(Stop);
304 RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream);
305 RUN_ON_AUDIO_THREAD(Close);
306 WaitUntilClosed();
309 // A combination of all of the above tests with many output streams.
310 TEST_P(VirtualAudioInputStreamTest, ComprehensiveTest) {
311 static const int kNumOutputs = 8;
312 static const int kHalfNumOutputs = kNumOutputs / 2;
313 static const int kPauseIterations = 5;
315 RUN_ON_AUDIO_THREAD(Create);
316 for (int i = 0; i < kHalfNumOutputs; ++i) {
317 RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream);
319 RUN_ON_AUDIO_THREAD(Start);
320 WaitForDataToFlow();
321 for (int i = 0; i < kHalfNumOutputs; ++i) {
322 RUN_ON_AUDIO_THREAD(CreateAndStartOneOutputStream);
324 WaitForDataToFlow();
325 for (int i = 0; i < kPauseIterations; ++i) {
326 RUN_ON_AUDIO_THREAD(StopSomeOutputStreams);
327 WaitForDataToFlow();
328 RUN_ON_AUDIO_THREAD(RestartAllStoppedOutputStreams);
329 WaitForDataToFlow();
331 for (int i = 0; i < kHalfNumOutputs; ++i) {
332 RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream);
334 RUN_ON_AUDIO_THREAD(Stop);
335 for (int i = 0; i < kHalfNumOutputs; ++i) {
336 RUN_ON_AUDIO_THREAD(StopAndCloseOneOutputStream);
338 RUN_ON_AUDIO_THREAD(Close);
339 WaitUntilClosed();
342 INSTANTIATE_TEST_CASE_P(SingleVersusMultithreaded,
343 VirtualAudioInputStreamTest,
344 ::testing::Values(false, true));
346 } // namespace media