Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(732)

Side by Side Diff: webrtc/api/dtmfsender_unittest.cc

Issue 2447013007: Fixing flaky DtmfSenderTest by using fake clock. (Closed)
Patch Set: Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2012 The WebRTC project authors. All Rights Reserved. 2 * Copyright 2012 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include "webrtc/api/dtmfsender.h" 11 #include "webrtc/api/dtmfsender.h"
12 12
13 #include <memory> 13 #include <memory>
14 #include <set> 14 #include <set>
15 #include <string> 15 #include <string>
16 #include <vector> 16 #include <vector>
17 17
18 #include "webrtc/api/audiotrack.h" 18 #include "webrtc/api/audiotrack.h"
19 #include "webrtc/base/fakeclock.h"
19 #include "webrtc/base/gunit.h" 20 #include "webrtc/base/gunit.h"
20 #include "webrtc/base/logging.h" 21 #include "webrtc/base/logging.h"
21 #include "webrtc/base/timeutils.h" 22 #include "webrtc/base/timeutils.h"
22 23
23 using webrtc::AudioTrackInterface; 24 using webrtc::AudioTrackInterface;
24 using webrtc::AudioTrack; 25 using webrtc::AudioTrack;
25 using webrtc::DtmfProviderInterface; 26 using webrtc::DtmfProviderInterface;
26 using webrtc::DtmfSender; 27 using webrtc::DtmfSender;
27 using webrtc::DtmfSenderObserverInterface; 28 using webrtc::DtmfSenderObserverInterface;
28 29
29 static const char kTestAudioLabel[] = "test_audio_track"; 30 static const char kTestAudioLabel[] = "test_audio_track";
31 // TODO(deadbeef): Even though this test now uses a fake clock, it has a
32 // generous 3-second timeout for every test case. The timeout could be tuned
33 // to each test based on the tones sent, instead.
honghaiz3 2016/10/28 17:23:26 Is there a problem if we change it in this CL?
Taylor Brandstetter 2016/10/28 20:31:23 It just seemed like more work than necessary at th
30 static const int kMaxWaitMs = 3000; 34 static const int kMaxWaitMs = 3000;
31 35
32 class FakeDtmfObserver : public DtmfSenderObserverInterface { 36 class FakeDtmfObserver : public DtmfSenderObserverInterface {
33 public: 37 public:
34 FakeDtmfObserver() : completed_(false) {} 38 FakeDtmfObserver() : completed_(false) {}
35 39
36 // Implements DtmfSenderObserverInterface. 40 // Implements DtmfSenderObserverInterface.
37 void OnToneChange(const std::string& tone) override { 41 void OnToneChange(const std::string& tone) override {
38 LOG(LS_VERBOSE) << "FakeDtmfObserver::OnToneChange '" << tone << "'."; 42 LOG(LS_VERBOSE) << "FakeDtmfObserver::OnToneChange '" << tone << "'.";
39 tones_.push_back(tone); 43 tones_.push_back(tone);
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
184 const std::vector<FakeDtmfProvider::DtmfInfo>& dtmf_queue = 188 const std::vector<FakeDtmfProvider::DtmfInfo>& dtmf_queue =
185 provider_->dtmf_info_queue(); 189 provider_->dtmf_info_queue();
186 ASSERT_EQ(dtmf_queue_ref.size(), dtmf_queue.size()); 190 ASSERT_EQ(dtmf_queue_ref.size(), dtmf_queue.size());
187 std::vector<FakeDtmfProvider::DtmfInfo>::const_iterator it_ref = 191 std::vector<FakeDtmfProvider::DtmfInfo>::const_iterator it_ref =
188 dtmf_queue_ref.begin(); 192 dtmf_queue_ref.begin();
189 std::vector<FakeDtmfProvider::DtmfInfo>::const_iterator it = 193 std::vector<FakeDtmfProvider::DtmfInfo>::const_iterator it =
190 dtmf_queue.begin(); 194 dtmf_queue.begin();
191 while (it_ref != dtmf_queue_ref.end() && it != dtmf_queue.end()) { 195 while (it_ref != dtmf_queue_ref.end() && it != dtmf_queue.end()) {
192 EXPECT_EQ(it_ref->code, it->code); 196 EXPECT_EQ(it_ref->code, it->code);
193 EXPECT_EQ(it_ref->duration, it->duration); 197 EXPECT_EQ(it_ref->duration, it->duration);
194 // Allow ~100ms error. 198 // Allow ~10ms error (can be small since we're using a fake clock).
195 EXPECT_GE(it_ref->gap, it->gap - 100); 199 EXPECT_GE(it_ref->gap, it->gap - 10);
196 EXPECT_LE(it_ref->gap, it->gap + 100); 200 EXPECT_LE(it_ref->gap, it->gap + 10);
197 ++it_ref; 201 ++it_ref;
198 ++it; 202 ++it;
199 } 203 }
200 } 204 }
201 205
202 // Verify the observer got all the expected callbacks. 206 // Verify the observer got all the expected callbacks.
203 void VerifyOnObserver(const std::string& tones_ref) { 207 void VerifyOnObserver(const std::string& tones_ref) {
204 const std::vector<std::string>& tones = observer_->tones(); 208 const std::vector<std::string>& tones = observer_->tones();
205 // The observer will get an empty string at the end. 209 // The observer will get an empty string at the end.
206 EXPECT_EQ(tones_ref.size() + 1, tones.size()); 210 EXPECT_EQ(tones_ref.size() + 1, tones.size());
207 EXPECT_TRUE(tones.back().empty()); 211 EXPECT_TRUE(tones.back().empty());
208 std::string::const_iterator it_ref = tones_ref.begin(); 212 std::string::const_iterator it_ref = tones_ref.begin();
209 std::vector<std::string>::const_iterator it = tones.begin(); 213 std::vector<std::string>::const_iterator it = tones.begin();
210 while (it_ref != tones_ref.end() && it != tones.end()) { 214 while (it_ref != tones_ref.end() && it != tones.end()) {
211 EXPECT_EQ(*it_ref, it->at(0)); 215 EXPECT_EQ(*it_ref, it->at(0));
212 ++it_ref; 216 ++it_ref;
213 ++it; 217 ++it;
214 } 218 }
215 } 219 }
216 220
217 rtc::scoped_refptr<AudioTrackInterface> track_; 221 rtc::scoped_refptr<AudioTrackInterface> track_;
218 std::unique_ptr<FakeDtmfObserver> observer_; 222 std::unique_ptr<FakeDtmfObserver> observer_;
219 std::unique_ptr<FakeDtmfProvider> provider_; 223 std::unique_ptr<FakeDtmfProvider> provider_;
220 rtc::scoped_refptr<DtmfSender> dtmf_; 224 rtc::scoped_refptr<DtmfSender> dtmf_;
225 rtc::ScopedFakeClock fake_clock_;
221 }; 226 };
222 227
223 TEST_F(DtmfSenderTest, CanInsertDtmf) { 228 TEST_F(DtmfSenderTest, CanInsertDtmf) {
224 EXPECT_TRUE(dtmf_->CanInsertDtmf()); 229 EXPECT_TRUE(dtmf_->CanInsertDtmf());
225 provider_->RemoveCanInsertDtmfTrack(kTestAudioLabel); 230 provider_->RemoveCanInsertDtmfTrack(kTestAudioLabel);
226 EXPECT_FALSE(dtmf_->CanInsertDtmf()); 231 EXPECT_FALSE(dtmf_->CanInsertDtmf());
227 } 232 }
228 233
229 TEST_F(DtmfSenderTest, InsertDtmf) { 234 TEST_F(DtmfSenderTest, InsertDtmf) {
230 std::string tones = "@1%a&*$"; 235 std::string tones = "@1%a&*$";
231 int duration = 100; 236 int duration = 100;
232 int inter_tone_gap = 50; 237 int inter_tone_gap = 50;
233 EXPECT_TRUE(dtmf_->InsertDtmf(tones, duration, inter_tone_gap)); 238 EXPECT_TRUE(dtmf_->InsertDtmf(tones, duration, inter_tone_gap));
234 EXPECT_TRUE_WAIT(observer_->completed(), kMaxWaitMs); 239 EXPECT_TRUE_SIMULATED_WAIT(observer_->completed(), kMaxWaitMs, fake_clock_);
235 240
236 // The unrecognized characters should be ignored. 241 // The unrecognized characters should be ignored.
237 std::string known_tones = "1a*"; 242 std::string known_tones = "1a*";
238 VerifyOnProvider(known_tones, duration, inter_tone_gap); 243 VerifyOnProvider(known_tones, duration, inter_tone_gap);
239 VerifyOnObserver(known_tones); 244 VerifyOnObserver(known_tones);
240 } 245 }
241 246
242 TEST_F(DtmfSenderTest, InsertDtmfTwice) { 247 TEST_F(DtmfSenderTest, InsertDtmfTwice) {
243 std::string tones1 = "12"; 248 std::string tones1 = "12";
244 std::string tones2 = "ab"; 249 std::string tones2 = "ab";
245 int duration = 100; 250 int duration = 100;
246 int inter_tone_gap = 50; 251 int inter_tone_gap = 50;
247 EXPECT_TRUE(dtmf_->InsertDtmf(tones1, duration, inter_tone_gap)); 252 EXPECT_TRUE(dtmf_->InsertDtmf(tones1, duration, inter_tone_gap));
248 VerifyExpectedState(track_, tones1, duration, inter_tone_gap); 253 VerifyExpectedState(track_, tones1, duration, inter_tone_gap);
249 // Wait until the first tone got sent. 254 // Wait until the first tone got sent.
250 EXPECT_TRUE_WAIT(observer_->tones().size() == 1, kMaxWaitMs); 255 EXPECT_TRUE_SIMULATED_WAIT(observer_->tones().size() == 1, kMaxWaitMs,
256 fake_clock_);
251 VerifyExpectedState(track_, "2", duration, inter_tone_gap); 257 VerifyExpectedState(track_, "2", duration, inter_tone_gap);
252 // Insert with another tone buffer. 258 // Insert with another tone buffer.
253 EXPECT_TRUE(dtmf_->InsertDtmf(tones2, duration, inter_tone_gap)); 259 EXPECT_TRUE(dtmf_->InsertDtmf(tones2, duration, inter_tone_gap));
254 VerifyExpectedState(track_, tones2, duration, inter_tone_gap); 260 VerifyExpectedState(track_, tones2, duration, inter_tone_gap);
255 // Wait until it's completed. 261 // Wait until it's completed.
256 EXPECT_TRUE_WAIT(observer_->completed(), kMaxWaitMs); 262 EXPECT_TRUE_SIMULATED_WAIT(observer_->completed(), kMaxWaitMs, fake_clock_);
257 263
258 std::vector<FakeDtmfProvider::DtmfInfo> dtmf_queue_ref; 264 std::vector<FakeDtmfProvider::DtmfInfo> dtmf_queue_ref;
259 GetDtmfInfoFromString("1", duration, inter_tone_gap, &dtmf_queue_ref); 265 GetDtmfInfoFromString("1", duration, inter_tone_gap, &dtmf_queue_ref);
260 GetDtmfInfoFromString("ab", duration, inter_tone_gap, &dtmf_queue_ref); 266 GetDtmfInfoFromString("ab", duration, inter_tone_gap, &dtmf_queue_ref);
261 VerifyOnProvider(dtmf_queue_ref); 267 VerifyOnProvider(dtmf_queue_ref);
262 VerifyOnObserver("1ab"); 268 VerifyOnObserver("1ab");
263 } 269 }
264 270
265 TEST_F(DtmfSenderTest, InsertDtmfWhileProviderIsDeleted) { 271 TEST_F(DtmfSenderTest, InsertDtmfWhileProviderIsDeleted) {
266 std::string tones = "@1%a&*$"; 272 std::string tones = "@1%a&*$";
267 int duration = 100; 273 int duration = 100;
268 int inter_tone_gap = 50; 274 int inter_tone_gap = 50;
269 EXPECT_TRUE(dtmf_->InsertDtmf(tones, duration, inter_tone_gap)); 275 EXPECT_TRUE(dtmf_->InsertDtmf(tones, duration, inter_tone_gap));
270 // Wait until the first tone got sent. 276 // Wait until the first tone got sent.
271 EXPECT_TRUE_WAIT(observer_->tones().size() == 1, kMaxWaitMs); 277 EXPECT_TRUE_SIMULATED_WAIT(observer_->tones().size() == 1, kMaxWaitMs,
278 fake_clock_);
272 // Delete provider. 279 // Delete provider.
273 provider_.reset(); 280 provider_.reset();
274 // The queue should be discontinued so no more tone callbacks. 281 // The queue should be discontinued so no more tone callbacks.
275 WAIT(false, 200); 282 WAIT(false, 200);
276 EXPECT_EQ(1U, observer_->tones().size()); 283 EXPECT_EQ(1U, observer_->tones().size());
277 } 284 }
278 285
279 TEST_F(DtmfSenderTest, InsertDtmfWhileSenderIsDeleted) { 286 TEST_F(DtmfSenderTest, InsertDtmfWhileSenderIsDeleted) {
280 std::string tones = "@1%a&*$"; 287 std::string tones = "@1%a&*$";
281 int duration = 100; 288 int duration = 100;
282 int inter_tone_gap = 50; 289 int inter_tone_gap = 50;
283 EXPECT_TRUE(dtmf_->InsertDtmf(tones, duration, inter_tone_gap)); 290 EXPECT_TRUE(dtmf_->InsertDtmf(tones, duration, inter_tone_gap));
284 // Wait until the first tone got sent. 291 // Wait until the first tone got sent.
285 EXPECT_TRUE_WAIT(observer_->tones().size() == 1, kMaxWaitMs); 292 EXPECT_TRUE_SIMULATED_WAIT(observer_->tones().size() == 1, kMaxWaitMs,
293 fake_clock_);
286 // Delete the sender. 294 // Delete the sender.
287 dtmf_ = NULL; 295 dtmf_ = NULL;
288 // The queue should be discontinued so no more tone callbacks. 296 // The queue should be discontinued so no more tone callbacks.
289 WAIT(false, 200); 297 WAIT(false, 200);
honghaiz3 2016/10/28 17:23:26 Change this and another one below to to SIMULATED_
Taylor Brandstetter 2016/10/28 20:31:23 Good catch, done.
290 EXPECT_EQ(1U, observer_->tones().size()); 298 EXPECT_EQ(1U, observer_->tones().size());
291 } 299 }
292 300
293 TEST_F(DtmfSenderTest, InsertEmptyTonesToCancelPreviousTask) { 301 TEST_F(DtmfSenderTest, InsertEmptyTonesToCancelPreviousTask) {
294 std::string tones1 = "12"; 302 std::string tones1 = "12";
295 std::string tones2 = ""; 303 std::string tones2 = "";
296 int duration = 100; 304 int duration = 100;
297 int inter_tone_gap = 50; 305 int inter_tone_gap = 50;
298 EXPECT_TRUE(dtmf_->InsertDtmf(tones1, duration, inter_tone_gap)); 306 EXPECT_TRUE(dtmf_->InsertDtmf(tones1, duration, inter_tone_gap));
299 // Wait until the first tone got sent. 307 // Wait until the first tone got sent.
300 EXPECT_TRUE_WAIT(observer_->tones().size() == 1, kMaxWaitMs); 308 EXPECT_TRUE_SIMULATED_WAIT(observer_->tones().size() == 1, kMaxWaitMs,
309 fake_clock_);
301 // Insert with another tone buffer. 310 // Insert with another tone buffer.
302 EXPECT_TRUE(dtmf_->InsertDtmf(tones2, duration, inter_tone_gap)); 311 EXPECT_TRUE(dtmf_->InsertDtmf(tones2, duration, inter_tone_gap));
303 // Wait until it's completed. 312 // Wait until it's completed.
304 EXPECT_TRUE_WAIT(observer_->completed(), kMaxWaitMs); 313 EXPECT_TRUE_SIMULATED_WAIT(observer_->completed(), kMaxWaitMs, fake_clock_);
305 314
306 std::vector<FakeDtmfProvider::DtmfInfo> dtmf_queue_ref; 315 std::vector<FakeDtmfProvider::DtmfInfo> dtmf_queue_ref;
307 GetDtmfInfoFromString("1", duration, inter_tone_gap, &dtmf_queue_ref); 316 GetDtmfInfoFromString("1", duration, inter_tone_gap, &dtmf_queue_ref);
308 VerifyOnProvider(dtmf_queue_ref); 317 VerifyOnProvider(dtmf_queue_ref);
309 VerifyOnObserver("1"); 318 VerifyOnObserver("1");
310 } 319 }
311 320
312 // Flaky when run in parallel. 321 TEST_F(DtmfSenderTest, InsertDtmfWithCommaAsDelay) {
313 // See https://code.google.com/p/webrtc/issues/detail?id=4219.
314 TEST_F(DtmfSenderTest, DISABLED_InsertDtmfWithCommaAsDelay) {
315 std::string tones = "3,4"; 322 std::string tones = "3,4";
316 int duration = 100; 323 int duration = 100;
317 int inter_tone_gap = 50; 324 int inter_tone_gap = 50;
318 EXPECT_TRUE(dtmf_->InsertDtmf(tones, duration, inter_tone_gap)); 325 EXPECT_TRUE(dtmf_->InsertDtmf(tones, duration, inter_tone_gap));
319 EXPECT_TRUE_WAIT(observer_->completed(), kMaxWaitMs); 326 EXPECT_TRUE_SIMULATED_WAIT(observer_->completed(), kMaxWaitMs, fake_clock_);
320 327
321 VerifyOnProvider(tones, duration, inter_tone_gap); 328 VerifyOnProvider(tones, duration, inter_tone_gap);
322 VerifyOnObserver(tones); 329 VerifyOnObserver(tones);
323 } 330 }
324 331
325 TEST_F(DtmfSenderTest, TryInsertDtmfWhenItDoesNotWork) { 332 TEST_F(DtmfSenderTest, TryInsertDtmfWhenItDoesNotWork) {
326 std::string tones = "3,4"; 333 std::string tones = "3,4";
327 int duration = 100; 334 int duration = 100;
328 int inter_tone_gap = 50; 335 int inter_tone_gap = 50;
329 provider_->RemoveCanInsertDtmfTrack(kTestAudioLabel); 336 provider_->RemoveCanInsertDtmfTrack(kTestAudioLabel);
330 EXPECT_FALSE(dtmf_->InsertDtmf(tones, duration, inter_tone_gap)); 337 EXPECT_FALSE(dtmf_->InsertDtmf(tones, duration, inter_tone_gap));
331 } 338 }
332 339
333 TEST_F(DtmfSenderTest, InsertDtmfWithInvalidDurationOrGap) { 340 TEST_F(DtmfSenderTest, InsertDtmfWithInvalidDurationOrGap) {
334 std::string tones = "3,4"; 341 std::string tones = "3,4";
335 int duration = 100; 342 int duration = 100;
336 int inter_tone_gap = 50; 343 int inter_tone_gap = 50;
337 344
338 EXPECT_FALSE(dtmf_->InsertDtmf(tones, 6001, inter_tone_gap)); 345 EXPECT_FALSE(dtmf_->InsertDtmf(tones, 6001, inter_tone_gap));
339 EXPECT_FALSE(dtmf_->InsertDtmf(tones, 69, inter_tone_gap)); 346 EXPECT_FALSE(dtmf_->InsertDtmf(tones, 69, inter_tone_gap));
340 EXPECT_FALSE(dtmf_->InsertDtmf(tones, duration, 49)); 347 EXPECT_FALSE(dtmf_->InsertDtmf(tones, duration, 49));
341 348
342 EXPECT_TRUE(dtmf_->InsertDtmf(tones, duration, inter_tone_gap)); 349 EXPECT_TRUE(dtmf_->InsertDtmf(tones, duration, inter_tone_gap));
343 } 350 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698