[safe-browsing] Database full hash matches like prefix match.
[chromium-blink-merge.git] / chrome / browser / media / audio_stream_monitor_unittest.cc
blob51ac58f45899e8e3cda1f4edaa370558148d21c3
1 // Copyright 2014 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 "chrome/browser/media/audio_stream_monitor.h"
7 #include <map>
8 #include <utility>
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/test/simple_test_tick_clock.h"
14 #include "chrome/test/base/testing_profile.h"
15 #include "content/public/browser/invalidate_type.h"
16 #include "content/public/browser/web_contents.h"
17 #include "content/public/browser/web_contents_delegate.h"
18 #include "content/public/test/test_browser_thread_bundle.h"
19 #include "media/audio/audio_power_monitor.h"
20 #include "testing/gmock/include/gmock/gmock.h"
21 #include "testing/gtest/include/gtest/gtest.h"
23 using ::testing::InvokeWithoutArgs;
25 namespace {
27 const int kStreamId = 3;
28 const int kAnotherStreamId = 6;
30 // Used to confirm audio indicator state changes occur at the correct times.
31 class MockWebContentsDelegate : public content::WebContentsDelegate {
32 public:
33 MOCK_METHOD2(NavigationStateChanged,
34 void(const content::WebContents* source,
35 unsigned changed_flags));
38 } // namespace
40 class AudioStreamMonitorTest : public testing::Test {
41 public:
42 AudioStreamMonitorTest() {
43 // Start |clock_| at non-zero.
44 clock_.Advance(base::TimeDelta::FromSeconds(1000000));
46 // Create a WebContents instance and set it to use our mock delegate.
47 web_contents_.reset(content::WebContents::Create(
48 content::WebContents::CreateParams(&profile_, NULL)));
49 web_contents_->SetDelegate(&mock_web_contents_delegate_);
51 // Create an AudioStreamMonitor instance whose lifecycle is tied to that of
52 // |web_contents_|, and override its clock with the test clock.
53 AudioStreamMonitor::CreateForWebContents(web_contents_.get());
54 CHECK(audio_stream_monitor());
55 const_cast<base::TickClock*&>(audio_stream_monitor()->clock_) = &clock_;
58 AudioStreamMonitor* audio_stream_monitor() {
59 return AudioStreamMonitor::FromWebContents(web_contents_.get());
62 base::TimeTicks GetTestClockTime() { return clock_.NowTicks(); }
64 void AdvanceClock(const base::TimeDelta& delta) { clock_.Advance(delta); }
66 AudioStreamMonitor::ReadPowerAndClipCallback CreatePollCallback(
67 int stream_id) {
68 return base::Bind(
69 &AudioStreamMonitorTest::ReadPower, base::Unretained(this), stream_id);
72 void SetStreamPower(int stream_id, float power) {
73 current_power_[stream_id] = power;
76 void SimulatePollTimerFired() { audio_stream_monitor()->Poll(); }
78 void SimulateOffTimerFired() { audio_stream_monitor()->MaybeToggle(); }
80 void ExpectIsPolling(int stream_id, bool is_polling) {
81 AudioStreamMonitor* const monitor = audio_stream_monitor();
82 EXPECT_EQ(is_polling,
83 monitor->poll_callbacks_.find(stream_id) !=
84 monitor->poll_callbacks_.end());
85 EXPECT_EQ(!monitor->poll_callbacks_.empty(),
86 monitor->poll_timer_.IsRunning());
89 void ExpectTabWasRecentlyAudible(bool was_audible,
90 const base::TimeTicks& last_blurt_time) {
91 AudioStreamMonitor* const monitor = audio_stream_monitor();
92 EXPECT_EQ(was_audible, monitor->was_recently_audible_);
93 EXPECT_EQ(last_blurt_time, monitor->last_blurt_time_);
94 EXPECT_EQ(monitor->was_recently_audible_, monitor->off_timer_.IsRunning());
97 void ExpectWebContentsWillBeNotifiedOnce(bool should_be_audible) {
98 EXPECT_CALL(mock_web_contents_delegate_,
99 NavigationStateChanged(web_contents_.get(),
100 content::INVALIDATE_TYPE_TAB))
101 .WillOnce(InvokeWithoutArgs(
102 this,
103 should_be_audible
104 ? &AudioStreamMonitorTest::ExpectIsNotifyingForToggleOn
105 : &AudioStreamMonitorTest::ExpectIsNotifyingForToggleOff))
106 .RetiresOnSaturation();
109 static base::TimeDelta one_polling_interval() {
110 return base::TimeDelta::FromSeconds(1) /
111 AudioStreamMonitor::kPowerMeasurementsPerSecond;
114 static base::TimeDelta holding_period() {
115 return base::TimeDelta::FromMilliseconds(
116 AudioStreamMonitor::kHoldOnMilliseconds);
119 private:
120 std::pair<float, bool> ReadPower(int stream_id) {
121 return std::make_pair(current_power_[stream_id], false);
124 void ExpectIsNotifyingForToggleOn() {
125 EXPECT_TRUE(audio_stream_monitor()->WasRecentlyAudible());
128 void ExpectIsNotifyingForToggleOff() {
129 EXPECT_FALSE(audio_stream_monitor()->WasRecentlyAudible());
132 content::TestBrowserThreadBundle browser_thread_bundle_;
133 TestingProfile profile_;
134 MockWebContentsDelegate mock_web_contents_delegate_;
135 base::SimpleTestTickClock clock_;
136 std::map<int, float> current_power_;
137 scoped_ptr<content::WebContents> web_contents_;
139 DISALLOW_COPY_AND_ASSIGN(AudioStreamMonitorTest);
142 // Tests that AudioStreamMonitor is polling while it has a
143 // ReadPowerAndClipCallback, and is not polling at other times.
144 TEST_F(AudioStreamMonitorTest, PollsWhenProvidedACallback) {
145 EXPECT_FALSE(audio_stream_monitor()->WasRecentlyAudible());
146 ExpectIsPolling(kStreamId, false);
148 audio_stream_monitor()->StartMonitoringStream(kStreamId,
149 CreatePollCallback(kStreamId));
150 EXPECT_FALSE(audio_stream_monitor()->WasRecentlyAudible());
151 ExpectIsPolling(kStreamId, true);
153 audio_stream_monitor()->StopMonitoringStream(kStreamId);
154 EXPECT_FALSE(audio_stream_monitor()->WasRecentlyAudible());
155 ExpectIsPolling(kStreamId, false);
158 // Tests that AudioStreamMonitor debounces the power level readings it's taking,
159 // which could be fluctuating rapidly between the audible versus silence
160 // threshold. See comments in audio_stream_monitor.h for expected behavior.
161 TEST_F(AudioStreamMonitorTest,
162 ImpulsesKeepIndicatorOnUntilHoldingPeriodHasPassed) {
163 audio_stream_monitor()->StartMonitoringStream(kStreamId,
164 CreatePollCallback(kStreamId));
166 // Expect WebContents will get one call form AudioStreamMonitor to toggle the
167 // indicator on upon the very first poll.
168 ExpectWebContentsWillBeNotifiedOnce(true);
170 // Loop, each time testing a slightly longer period of polled silence. The
171 // indicator should remain on throughout.
172 int num_silence_polls = 0;
173 base::TimeTicks last_blurt_time;
174 do {
175 // Poll an audible signal, and expect tab indicator state is on.
176 SetStreamPower(kStreamId, media::AudioPowerMonitor::max_power());
177 last_blurt_time = GetTestClockTime();
178 SimulatePollTimerFired();
179 ExpectTabWasRecentlyAudible(true, last_blurt_time);
180 AdvanceClock(one_polling_interval());
182 // Poll a silent signal repeatedly, ensuring that the indicator is being
183 // held on during the holding period.
184 SetStreamPower(kStreamId, media::AudioPowerMonitor::zero_power());
185 for (int i = 0; i < num_silence_polls; ++i) {
186 SimulatePollTimerFired();
187 ExpectTabWasRecentlyAudible(true, last_blurt_time);
188 // Note: Redundant off timer firings should not have any effect.
189 SimulateOffTimerFired();
190 ExpectTabWasRecentlyAudible(true, last_blurt_time);
191 AdvanceClock(one_polling_interval());
194 ++num_silence_polls;
195 } while (GetTestClockTime() < last_blurt_time + holding_period());
197 // At this point, the clock has just advanced to beyond the holding period, so
198 // the next firing of the off timer should turn off the tab indicator. Also,
199 // make sure it stays off for several cycles thereafter.
200 ExpectWebContentsWillBeNotifiedOnce(false);
201 for (int i = 0; i < 10; ++i) {
202 SimulateOffTimerFired();
203 ExpectTabWasRecentlyAudible(false, last_blurt_time);
204 AdvanceClock(one_polling_interval());
208 // Tests that the AudioStreamMonitor correctly processes the blurts from two
209 // different streams in the same tab.
210 TEST_F(AudioStreamMonitorTest, HandlesMultipleStreamsBlurting) {
211 audio_stream_monitor()->StartMonitoringStream(kStreamId,
212 CreatePollCallback(kStreamId));
213 audio_stream_monitor()->StartMonitoringStream(
214 kAnotherStreamId,
215 CreatePollCallback(kAnotherStreamId));
217 base::TimeTicks last_blurt_time;
218 ExpectTabWasRecentlyAudible(false, last_blurt_time);
220 // Measure audible sound from the first stream and silence from the second.
221 // The indicator turns on (i.e., tab was recently audible).
222 ExpectWebContentsWillBeNotifiedOnce(true);
223 SetStreamPower(kStreamId, media::AudioPowerMonitor::max_power());
224 SetStreamPower(kAnotherStreamId, media::AudioPowerMonitor::zero_power());
225 last_blurt_time = GetTestClockTime();
226 SimulatePollTimerFired();
227 ExpectTabWasRecentlyAudible(true, last_blurt_time);
229 // Halfway through the holding period, the second stream joins in. The
230 // indicator stays on.
231 AdvanceClock(holding_period() / 2);
232 SimulateOffTimerFired();
233 SetStreamPower(kAnotherStreamId, media::AudioPowerMonitor::max_power());
234 last_blurt_time = GetTestClockTime();
235 SimulatePollTimerFired(); // Restarts holding period.
236 ExpectTabWasRecentlyAudible(true, last_blurt_time);
238 // Now, measure silence from both streams. After an entire holding period
239 // has passed (since the second stream joined in), the indicator should turn
240 // off.
241 ExpectWebContentsWillBeNotifiedOnce(false);
242 AdvanceClock(holding_period());
243 SimulateOffTimerFired();
244 SetStreamPower(kStreamId, media::AudioPowerMonitor::zero_power());
245 SetStreamPower(kAnotherStreamId, media::AudioPowerMonitor::zero_power());
246 SimulatePollTimerFired();
247 ExpectTabWasRecentlyAudible(false, last_blurt_time);
249 // Now, measure silence from the first stream and audible sound from the
250 // second. The indicator turns back on.
251 ExpectWebContentsWillBeNotifiedOnce(true);
252 SetStreamPower(kAnotherStreamId, media::AudioPowerMonitor::max_power());
253 last_blurt_time = GetTestClockTime();
254 SimulatePollTimerFired();
255 ExpectTabWasRecentlyAudible(true, last_blurt_time);
257 // From here onwards, both streams are silent. Halfway through the holding
258 // period, the indicator should not have changed.
259 SetStreamPower(kAnotherStreamId, media::AudioPowerMonitor::zero_power());
260 AdvanceClock(holding_period() / 2);
261 SimulatePollTimerFired();
262 SimulateOffTimerFired();
263 ExpectTabWasRecentlyAudible(true, last_blurt_time);
265 // Just past the holding period, the indicator should be turned off.
266 ExpectWebContentsWillBeNotifiedOnce(false);
267 AdvanceClock(holding_period() - (GetTestClockTime() - last_blurt_time));
268 SimulateOffTimerFired();
269 ExpectTabWasRecentlyAudible(false, last_blurt_time);
271 // Polling should not turn the indicator back while both streams are remaining
272 // silent.
273 for (int i = 0; i < 100; ++i) {
274 AdvanceClock(one_polling_interval());
275 SimulatePollTimerFired();
276 ExpectTabWasRecentlyAudible(false, last_blurt_time);