| OLD | NEW |
| 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. |
| 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 Loading... |
| 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 SIMULATED_WAIT(false, 200, fake_clock_); |
| 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 SIMULATED_WAIT(false, 200, fake_clock_); |
| 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 } |
| OLD | NEW |