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.
6 #include "base/message_loop/message_loop.h"
7 #include "base/time/time.h"
8 #include "media/audio/audio_buffers_state.h"
9 #include "media/audio/audio_parameters.h"
10 #include "media/audio/fake_audio_consumer.h"
11 #include "media/audio/simple_sources.h"
12 #include "testing/gtest/include/gtest/gtest.h"
16 static const int kTestCallbacks
= 5;
18 class FakeAudioConsumerTest
: public testing::Test
{
20 FakeAudioConsumerTest()
22 AudioParameters::AUDIO_FAKE
, CHANNEL_LAYOUT_STEREO
, 44100, 8, 128),
23 fake_consumer_(message_loop_
.message_loop_proxy(), params_
),
24 source_(params_
.channels(), 200.0, params_
.sample_rate()) {
25 time_between_callbacks_
= base::TimeDelta::FromMicroseconds(
26 params_
.frames_per_buffer() * base::Time::kMicrosecondsPerSecond
/
27 static_cast<float>(params_
.sample_rate()));
30 virtual ~FakeAudioConsumerTest() {}
32 void ConsumeData(AudioBus
* audio_bus
) {
33 source_
.OnMoreData(audio_bus
, AudioBuffersState());
36 void RunOnAudioThread() {
37 ASSERT_TRUE(message_loop_
.message_loop_proxy()->BelongsToCurrentThread());
38 fake_consumer_
.Start(base::Bind(
39 &FakeAudioConsumerTest::ConsumeData
, base::Unretained(this)));
42 void RunOnceOnAudioThread() {
43 ASSERT_TRUE(message_loop_
.message_loop_proxy()->BelongsToCurrentThread());
45 // Start() should immediately post a task to run the source callback, so we
46 // should end up with only a single callback being run.
47 message_loop_
.PostTask(FROM_HERE
, base::Bind(
48 &FakeAudioConsumerTest::EndTest
, base::Unretained(this), 1));
51 void StopStartOnAudioThread() {
52 ASSERT_TRUE(message_loop_
.message_loop_proxy()->BelongsToCurrentThread());
53 fake_consumer_
.Stop();
57 void TimeCallbacksOnAudioThread(int callbacks
) {
58 ASSERT_TRUE(message_loop_
.message_loop_proxy()->BelongsToCurrentThread());
60 if (source_
.callbacks() == 0) {
62 start_time_
= base::TimeTicks::Now();
65 // Keep going until we've seen the requested number of callbacks.
66 if (source_
.callbacks() < callbacks
) {
67 message_loop_
.PostDelayedTask(FROM_HERE
, base::Bind(
68 &FakeAudioConsumerTest::TimeCallbacksOnAudioThread
,
69 base::Unretained(this), callbacks
), time_between_callbacks_
/ 2);
71 end_time_
= base::TimeTicks::Now();
76 void EndTest(int callbacks
) {
77 ASSERT_TRUE(message_loop_
.message_loop_proxy()->BelongsToCurrentThread());
78 fake_consumer_
.Stop();
79 EXPECT_LE(callbacks
, source_
.callbacks());
80 message_loop_
.PostTask(FROM_HERE
, base::MessageLoop::QuitClosure());
84 base::MessageLoop message_loop_
;
85 AudioParameters params_
;
86 FakeAudioConsumer fake_consumer_
;
87 SineWaveAudioSource source_
;
88 base::TimeTicks start_time_
;
89 base::TimeTicks end_time_
;
90 base::TimeDelta time_between_callbacks_
;
93 DISALLOW_COPY_AND_ASSIGN(FakeAudioConsumerTest
);
96 // Ensure the fake audio stream runs on the audio thread and handles fires
97 // callbacks to the AudioSourceCallback.
98 TEST_F(FakeAudioConsumerTest
, FakeStreamBasicCallback
) {
99 message_loop_
.PostTask(FROM_HERE
, base::Bind(
100 &FakeAudioConsumerTest::RunOnceOnAudioThread
,
101 base::Unretained(this)));
105 // Ensure the time between callbacks is sane.
106 TEST_F(FakeAudioConsumerTest
, TimeBetweenCallbacks
) {
107 message_loop_
.PostTask(FROM_HERE
, base::Bind(
108 &FakeAudioConsumerTest::TimeCallbacksOnAudioThread
,
109 base::Unretained(this), kTestCallbacks
));
112 // There are only (kTestCallbacks - 1) intervals between kTestCallbacks.
113 base::TimeDelta actual_time_between_callbacks
=
114 (end_time_
- start_time_
) / (source_
.callbacks() - 1);
116 // Ensure callback time is no faster than the expected time between callbacks.
117 EXPECT_TRUE(actual_time_between_callbacks
>= time_between_callbacks_
);
119 // Softly check if the callback time is no slower than twice the expected time
120 // between callbacks. Since this test runs on the bots we can't be too strict
122 if (actual_time_between_callbacks
> 2 * time_between_callbacks_
)
123 LOG(ERROR
) << "Time between fake audio callbacks is too large!";
126 // Ensure Start()/Stop() on the stream doesn't generate too many callbacks. See
127 // http://crbug.com/159049
128 TEST_F(FakeAudioConsumerTest
, StartStopClearsCallbacks
) {
129 message_loop_
.PostTask(FROM_HERE
, base::Bind(
130 &FakeAudioConsumerTest::TimeCallbacksOnAudioThread
,
131 base::Unretained(this), kTestCallbacks
));
133 // Issue a Stop() / Start() in between expected callbacks to maximize the
134 // chance of catching the FakeAudioOutputStream doing the wrong thing.
135 message_loop_
.PostDelayedTask(FROM_HERE
, base::Bind(
136 &FakeAudioConsumerTest::StopStartOnAudioThread
,
137 base::Unretained(this)), time_between_callbacks_
/ 2);
139 // EndTest() will ensure the proper number of callbacks have occurred.