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