128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org/* 228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * libjingle 35f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org * Copyright 2012 Google Inc. 428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * 528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * Redistribution and use in source and binary forms, with or without 628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * modification, are permitted provided that the following conditions are met: 728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * 828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * 1. Redistributions of source code must retain the above copyright notice, 928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * this list of conditions and the following disclaimer. 1028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * 2. Redistributions in binary form must reproduce the above copyright notice, 1128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * this list of conditions and the following disclaimer in the documentation 1228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * and/or other materials provided with the distribution. 1328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * 3. The name of the author may not be used to endorse or promote products 1428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * derived from this software without specific prior written permission. 1528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * 1628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 1728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 1828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 1928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 2128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 2228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 2328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 2428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 2528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org */ 2728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 2828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#include "talk/app/webrtc/dtmfsender.h" 2928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 3028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#include <set> 3128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#include <string> 3228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#include <vector> 3328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 3428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#include "talk/app/webrtc/audiotrack.h" 35d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org#include "webrtc/base/gunit.h" 36d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org#include "webrtc/base/logging.h" 37d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org#include "webrtc/base/timeutils.h" 3828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 3928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgusing webrtc::AudioTrackInterface; 4028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgusing webrtc::AudioTrack; 4128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgusing webrtc::DtmfProviderInterface; 4228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgusing webrtc::DtmfSender; 4328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgusing webrtc::DtmfSenderObserverInterface; 4428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 4528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgstatic const char kTestAudioLabel[] = "test_audio_track"; 4628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgstatic const int kMaxWaitMs = 3000; 4728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 48fc950848e39c5627c9af3e3a44e5177843b03d09Magnus Jedvertclass FakeDtmfObserver : public DtmfSenderObserverInterface { 4928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org public: 5028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org FakeDtmfObserver() : completed_(false) {} 5128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 5228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Implements DtmfSenderObserverInterface. 5314665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org void OnToneChange(const std::string& tone) override { 5428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_VERBOSE) << "FakeDtmfObserver::OnToneChange '" << tone << "'."; 5528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org tones_.push_back(tone); 5628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (tone.empty()) { 5728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org completed_ = true; 5828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 5928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 6028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 6128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // getters 6228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org const std::vector<std::string>& tones() const { 6328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return tones_; 6428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 6528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org bool completed() const { 6628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return completed_; 6728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 6828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 6928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org private: 7028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org std::vector<std::string> tones_; 7128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org bool completed_; 7228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}; 7328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 7428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgclass FakeDtmfProvider : public DtmfProviderInterface { 7528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org public: 7628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org struct DtmfInfo { 7728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org DtmfInfo(int code, int duration, int gap) 7828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org : code(code), 7928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org duration(duration), 8028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org gap(gap) {} 8128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org int code; 8228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org int duration; 8328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org int gap; 8428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org }; 8528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 8628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org FakeDtmfProvider() : last_insert_dtmf_call_(0) {} 8728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 8828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org ~FakeDtmfProvider() { 8928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org SignalDestroyed(); 9028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 9128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 9228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Implements DtmfProviderInterface. 9314665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org bool CanInsertDtmf(const std::string& track_label) override { 9428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return (can_insert_dtmf_tracks_.count(track_label) != 0); 9528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 9628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 9714665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org bool InsertDtmf(const std::string& track_label, 9814665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org int code, 9914665ff7d4024d07e58622f498b23fd980001871kjellander@webrtc.org int duration) override { 10028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org int gap = 0; 101d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org // TODO(ronghuawu): Make the timer (basically the rtc::TimeNanos) 10228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // mockable and use a fake timer in the unit tests. 10328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (last_insert_dtmf_call_ > 0) { 104d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org gap = static_cast<int>(rtc::Time() - last_insert_dtmf_call_); 10528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 106d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org last_insert_dtmf_call_ = rtc::Time(); 10728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 10828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_VERBOSE) << "FakeDtmfProvider::InsertDtmf code=" << code 10928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << " duration=" << duration 11028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << " gap=" << gap << "."; 11128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org dtmf_info_queue_.push_back(DtmfInfo(code, duration, gap)); 11228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return true; 11328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 11428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 11528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org virtual sigslot::signal0<>* GetOnDestroyedSignal() { 11628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return &SignalDestroyed; 11728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 11828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 11928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // getter and setter 12028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org const std::vector<DtmfInfo>& dtmf_info_queue() const { 12128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return dtmf_info_queue_; 12228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 12328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 12428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // helper functions 12528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org void AddCanInsertDtmfTrack(const std::string& label) { 12628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org can_insert_dtmf_tracks_.insert(label); 12728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 12828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org void RemoveCanInsertDtmfTrack(const std::string& label) { 12928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org can_insert_dtmf_tracks_.erase(label); 13028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 13128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 13228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org private: 13328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org std::set<std::string> can_insert_dtmf_tracks_; 13428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org std::vector<DtmfInfo> dtmf_info_queue_; 1350c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström int64_t last_insert_dtmf_call_; 13628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org sigslot::signal0<> SignalDestroyed; 13728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}; 13828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 13928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgclass DtmfSenderTest : public testing::Test { 14028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org protected: 14128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org DtmfSenderTest() 14228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org : track_(AudioTrack::Create(kTestAudioLabel, NULL)), 143d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org observer_(new rtc::RefCountedObject<FakeDtmfObserver>()), 14428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org provider_(new FakeDtmfProvider()) { 14528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org provider_->AddCanInsertDtmfTrack(kTestAudioLabel); 146d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org dtmf_ = DtmfSender::Create(track_, rtc::Thread::Current(), 14728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org provider_.get()); 14828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org dtmf_->RegisterObserver(observer_.get()); 14928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 15028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 15128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org ~DtmfSenderTest() { 15228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (dtmf_.get()) { 15328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org dtmf_->UnregisterObserver(); 15428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 15528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 15628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 15728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Constructs a list of DtmfInfo from |tones|, |duration| and 15828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // |inter_tone_gap|. 15928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org void GetDtmfInfoFromString(const std::string& tones, int duration, 16028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org int inter_tone_gap, 16128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org std::vector<FakeDtmfProvider::DtmfInfo>* dtmfs) { 16228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Init extra_delay as -inter_tone_gap - duration to ensure the first 16328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // DtmfInfo's gap field will be 0. 16428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org int extra_delay = -1 * (inter_tone_gap + duration); 16528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 16628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org std::string::const_iterator it = tones.begin(); 16728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org for (; it != tones.end(); ++it) { 16828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org char tone = *it; 16928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org int code = 0; 17028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org webrtc::GetDtmfCode(tone, &code); 17128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (tone == ',') { 17228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org extra_delay = 2000; // 2 seconds 17328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } else { 17428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org dtmfs->push_back(FakeDtmfProvider::DtmfInfo(code, duration, 17528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org duration + inter_tone_gap + extra_delay)); 17628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org extra_delay = 0; 17728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 17828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 17928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 18028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 18128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org void VerifyExpectedState(AudioTrackInterface* track, 18228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org const std::string& tones, 18328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org int duration, int inter_tone_gap) { 18428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org EXPECT_EQ(track, dtmf_->track()); 18528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org EXPECT_EQ(tones, dtmf_->tones()); 18628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org EXPECT_EQ(duration, dtmf_->duration()); 18728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org EXPECT_EQ(inter_tone_gap, dtmf_->inter_tone_gap()); 18828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 18928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 19028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Verify the provider got all the expected calls. 19128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org void VerifyOnProvider(const std::string& tones, int duration, 19228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org int inter_tone_gap) { 19328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org std::vector<FakeDtmfProvider::DtmfInfo> dtmf_queue_ref; 19428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org GetDtmfInfoFromString(tones, duration, inter_tone_gap, &dtmf_queue_ref); 19528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org VerifyOnProvider(dtmf_queue_ref); 19628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 19728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 19828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org void VerifyOnProvider( 19928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org const std::vector<FakeDtmfProvider::DtmfInfo>& dtmf_queue_ref) { 20028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org const std::vector<FakeDtmfProvider::DtmfInfo>& dtmf_queue = 20128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org provider_->dtmf_info_queue(); 20228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org ASSERT_EQ(dtmf_queue_ref.size(), dtmf_queue.size()); 20328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org std::vector<FakeDtmfProvider::DtmfInfo>::const_iterator it_ref = 20428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org dtmf_queue_ref.begin(); 20528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org std::vector<FakeDtmfProvider::DtmfInfo>::const_iterator it = 20628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org dtmf_queue.begin(); 20728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org while (it_ref != dtmf_queue_ref.end() && it != dtmf_queue.end()) { 20828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org EXPECT_EQ(it_ref->code, it->code); 20928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org EXPECT_EQ(it_ref->duration, it->duration); 2108d1e4d61497a47dcfe4ef5a10f17008de4690351wu@webrtc.org // Allow ~100ms error. 2118d1e4d61497a47dcfe4ef5a10f17008de4690351wu@webrtc.org EXPECT_GE(it_ref->gap, it->gap - 100); 2128d1e4d61497a47dcfe4ef5a10f17008de4690351wu@webrtc.org EXPECT_LE(it_ref->gap, it->gap + 100); 21328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org ++it_ref; 21428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org ++it; 21528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 21628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 21728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 21828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Verify the observer got all the expected callbacks. 21928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org void VerifyOnObserver(const std::string& tones_ref) { 22028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org const std::vector<std::string>& tones = observer_->tones(); 22128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // The observer will get an empty string at the end. 22228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org EXPECT_EQ(tones_ref.size() + 1, tones.size()); 22328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org EXPECT_TRUE(tones.back().empty()); 22428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org std::string::const_iterator it_ref = tones_ref.begin(); 22528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org std::vector<std::string>::const_iterator it = tones.begin(); 22628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org while (it_ref != tones_ref.end() && it != tones.end()) { 22728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org EXPECT_EQ(*it_ref, it->at(0)); 22828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org ++it_ref; 22928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org ++it; 23028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 23128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 23228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 233d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org rtc::scoped_refptr<AudioTrackInterface> track_; 234d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org rtc::scoped_ptr<FakeDtmfObserver> observer_; 235d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org rtc::scoped_ptr<FakeDtmfProvider> provider_; 236d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org rtc::scoped_refptr<DtmfSender> dtmf_; 23728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}; 23828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 23928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgTEST_F(DtmfSenderTest, CanInsertDtmf) { 24028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org EXPECT_TRUE(dtmf_->CanInsertDtmf()); 24128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org provider_->RemoveCanInsertDtmfTrack(kTestAudioLabel); 24228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org EXPECT_FALSE(dtmf_->CanInsertDtmf()); 24328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 24428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 24528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgTEST_F(DtmfSenderTest, InsertDtmf) { 24628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org std::string tones = "@1%a&*$"; 24728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org int duration = 100; 24828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org int inter_tone_gap = 50; 24928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org EXPECT_TRUE(dtmf_->InsertDtmf(tones, duration, inter_tone_gap)); 25028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org EXPECT_TRUE_WAIT(observer_->completed(), kMaxWaitMs); 25128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 25228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // The unrecognized characters should be ignored. 25328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org std::string known_tones = "1a*"; 25428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org VerifyOnProvider(known_tones, duration, inter_tone_gap); 25528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org VerifyOnObserver(known_tones); 25628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 25728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 25828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgTEST_F(DtmfSenderTest, InsertDtmfTwice) { 25928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org std::string tones1 = "12"; 26028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org std::string tones2 = "ab"; 26128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org int duration = 100; 26228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org int inter_tone_gap = 50; 26328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org EXPECT_TRUE(dtmf_->InsertDtmf(tones1, duration, inter_tone_gap)); 26428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org VerifyExpectedState(track_, tones1, duration, inter_tone_gap); 26528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Wait until the first tone got sent. 26628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org EXPECT_TRUE_WAIT(observer_->tones().size() == 1, kMaxWaitMs); 26728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org VerifyExpectedState(track_, "2", duration, inter_tone_gap); 26828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Insert with another tone buffer. 26928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org EXPECT_TRUE(dtmf_->InsertDtmf(tones2, duration, inter_tone_gap)); 27028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org VerifyExpectedState(track_, tones2, duration, inter_tone_gap); 27128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Wait until it's completed. 27228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org EXPECT_TRUE_WAIT(observer_->completed(), kMaxWaitMs); 27328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 27428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org std::vector<FakeDtmfProvider::DtmfInfo> dtmf_queue_ref; 27528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org GetDtmfInfoFromString("1", duration, inter_tone_gap, &dtmf_queue_ref); 27628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org GetDtmfInfoFromString("ab", duration, inter_tone_gap, &dtmf_queue_ref); 27728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org VerifyOnProvider(dtmf_queue_ref); 27828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org VerifyOnObserver("1ab"); 27928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 28028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 28128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgTEST_F(DtmfSenderTest, InsertDtmfWhileProviderIsDeleted) { 28228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org std::string tones = "@1%a&*$"; 28328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org int duration = 100; 28428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org int inter_tone_gap = 50; 28528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org EXPECT_TRUE(dtmf_->InsertDtmf(tones, duration, inter_tone_gap)); 28628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Wait until the first tone got sent. 28728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org EXPECT_TRUE_WAIT(observer_->tones().size() == 1, kMaxWaitMs); 28828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Delete provider. 28928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org provider_.reset(); 29028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // The queue should be discontinued so no more tone callbacks. 29128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org WAIT(false, 200); 29228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org EXPECT_EQ(1U, observer_->tones().size()); 29328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 29428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 29528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgTEST_F(DtmfSenderTest, InsertDtmfWhileSenderIsDeleted) { 29628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org std::string tones = "@1%a&*$"; 29728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org int duration = 100; 29828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org int inter_tone_gap = 50; 29928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org EXPECT_TRUE(dtmf_->InsertDtmf(tones, duration, inter_tone_gap)); 30028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Wait until the first tone got sent. 30128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org EXPECT_TRUE_WAIT(observer_->tones().size() == 1, kMaxWaitMs); 30228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Delete the sender. 30328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org dtmf_ = NULL; 30428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // The queue should be discontinued so no more tone callbacks. 30528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org WAIT(false, 200); 30628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org EXPECT_EQ(1U, observer_->tones().size()); 30728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 30828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 30928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgTEST_F(DtmfSenderTest, InsertEmptyTonesToCancelPreviousTask) { 31028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org std::string tones1 = "12"; 31128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org std::string tones2 = ""; 31228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org int duration = 100; 31328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org int inter_tone_gap = 50; 31428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org EXPECT_TRUE(dtmf_->InsertDtmf(tones1, duration, inter_tone_gap)); 31528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Wait until the first tone got sent. 31628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org EXPECT_TRUE_WAIT(observer_->tones().size() == 1, kMaxWaitMs); 31728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Insert with another tone buffer. 31828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org EXPECT_TRUE(dtmf_->InsertDtmf(tones2, duration, inter_tone_gap)); 31928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Wait until it's completed. 32028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org EXPECT_TRUE_WAIT(observer_->completed(), kMaxWaitMs); 32128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 32228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org std::vector<FakeDtmfProvider::DtmfInfo> dtmf_queue_ref; 32328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org GetDtmfInfoFromString("1", duration, inter_tone_gap, &dtmf_queue_ref); 32428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org VerifyOnProvider(dtmf_queue_ref); 32528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org VerifyOnObserver("1"); 32628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 32728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 328a02d76845f266ec692af0854aca433e8246d7715kjellander@webrtc.org// Flaky when run in parallel. 329a02d76845f266ec692af0854aca433e8246d7715kjellander@webrtc.org// See https://code.google.com/p/webrtc/issues/detail?id=4219. 330a02d76845f266ec692af0854aca433e8246d7715kjellander@webrtc.orgTEST_F(DtmfSenderTest, DISABLED_InsertDtmfWithCommaAsDelay) { 33128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org std::string tones = "3,4"; 33228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org int duration = 100; 33328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org int inter_tone_gap = 50; 33428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org EXPECT_TRUE(dtmf_->InsertDtmf(tones, duration, inter_tone_gap)); 33528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org EXPECT_TRUE_WAIT(observer_->completed(), kMaxWaitMs); 33628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 33728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org VerifyOnProvider(tones, duration, inter_tone_gap); 33828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org VerifyOnObserver(tones); 33928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 34028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 34128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgTEST_F(DtmfSenderTest, TryInsertDtmfWhenItDoesNotWork) { 34228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org std::string tones = "3,4"; 34328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org int duration = 100; 34428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org int inter_tone_gap = 50; 34528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org provider_->RemoveCanInsertDtmfTrack(kTestAudioLabel); 34628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org EXPECT_FALSE(dtmf_->InsertDtmf(tones, duration, inter_tone_gap)); 34728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 34828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 34928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgTEST_F(DtmfSenderTest, InsertDtmfWithInvalidDurationOrGap) { 35028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org std::string tones = "3,4"; 35128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org int duration = 100; 35228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org int inter_tone_gap = 50; 35328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 35428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org EXPECT_FALSE(dtmf_->InsertDtmf(tones, 6001, inter_tone_gap)); 35528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org EXPECT_FALSE(dtmf_->InsertDtmf(tones, 69, inter_tone_gap)); 35628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org EXPECT_FALSE(dtmf_->InsertDtmf(tones, duration, 49)); 35728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 35828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org EXPECT_TRUE(dtmf_->InsertDtmf(tones, duration, inter_tone_gap)); 35928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 360