1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker * Copyright 2012 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker *
4*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker */
10*d9f75844SAndroid Build Coastguard Worker
11*d9f75844SAndroid Build Coastguard Worker #include "pc/dtmf_sender.h"
12*d9f75844SAndroid Build Coastguard Worker
13*d9f75844SAndroid Build Coastguard Worker #include <stddef.h>
14*d9f75844SAndroid Build Coastguard Worker
15*d9f75844SAndroid Build Coastguard Worker #include <memory>
16*d9f75844SAndroid Build Coastguard Worker #include <string>
17*d9f75844SAndroid Build Coastguard Worker #include <vector>
18*d9f75844SAndroid Build Coastguard Worker
19*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/fake_clock.h"
20*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/gunit.h"
21*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/time_utils.h"
22*d9f75844SAndroid Build Coastguard Worker #include "test/gtest.h"
23*d9f75844SAndroid Build Coastguard Worker
24*d9f75844SAndroid Build Coastguard Worker using webrtc::DtmfProviderInterface;
25*d9f75844SAndroid Build Coastguard Worker using webrtc::DtmfSender;
26*d9f75844SAndroid Build Coastguard Worker using webrtc::DtmfSenderObserverInterface;
27*d9f75844SAndroid Build Coastguard Worker
28*d9f75844SAndroid Build Coastguard Worker // TODO(deadbeef): Even though this test now uses a fake clock, it has a
29*d9f75844SAndroid Build Coastguard Worker // generous 3-second timeout for every test case. The timeout could be tuned
30*d9f75844SAndroid Build Coastguard Worker // to each test based on the tones sent, instead.
31*d9f75844SAndroid Build Coastguard Worker static const int kMaxWaitMs = 3000;
32*d9f75844SAndroid Build Coastguard Worker
33*d9f75844SAndroid Build Coastguard Worker class FakeDtmfObserver : public DtmfSenderObserverInterface {
34*d9f75844SAndroid Build Coastguard Worker public:
FakeDtmfObserver()35*d9f75844SAndroid Build Coastguard Worker FakeDtmfObserver() : completed_(false) {}
36*d9f75844SAndroid Build Coastguard Worker
37*d9f75844SAndroid Build Coastguard Worker // Implements DtmfSenderObserverInterface.
OnToneChange(const std::string & tone)38*d9f75844SAndroid Build Coastguard Worker void OnToneChange(const std::string& tone) override {
39*d9f75844SAndroid Build Coastguard Worker tones_from_single_argument_callback_.push_back(tone);
40*d9f75844SAndroid Build Coastguard Worker if (tone.empty()) {
41*d9f75844SAndroid Build Coastguard Worker completed_ = true;
42*d9f75844SAndroid Build Coastguard Worker }
43*d9f75844SAndroid Build Coastguard Worker }
OnToneChange(const std::string & tone,const std::string & tone_buffer)44*d9f75844SAndroid Build Coastguard Worker void OnToneChange(const std::string& tone,
45*d9f75844SAndroid Build Coastguard Worker const std::string& tone_buffer) override {
46*d9f75844SAndroid Build Coastguard Worker tones_.push_back(tone);
47*d9f75844SAndroid Build Coastguard Worker tones_remaining_ = tone_buffer;
48*d9f75844SAndroid Build Coastguard Worker if (tone.empty()) {
49*d9f75844SAndroid Build Coastguard Worker completed_ = true;
50*d9f75844SAndroid Build Coastguard Worker }
51*d9f75844SAndroid Build Coastguard Worker }
52*d9f75844SAndroid Build Coastguard Worker
53*d9f75844SAndroid Build Coastguard Worker // getters
tones() const54*d9f75844SAndroid Build Coastguard Worker const std::vector<std::string>& tones() const { return tones_; }
tones_from_single_argument_callback() const55*d9f75844SAndroid Build Coastguard Worker const std::vector<std::string>& tones_from_single_argument_callback() const {
56*d9f75844SAndroid Build Coastguard Worker return tones_from_single_argument_callback_;
57*d9f75844SAndroid Build Coastguard Worker }
tones_remaining()58*d9f75844SAndroid Build Coastguard Worker const std::string tones_remaining() { return tones_remaining_; }
completed() const59*d9f75844SAndroid Build Coastguard Worker bool completed() const { return completed_; }
60*d9f75844SAndroid Build Coastguard Worker
61*d9f75844SAndroid Build Coastguard Worker private:
62*d9f75844SAndroid Build Coastguard Worker std::vector<std::string> tones_;
63*d9f75844SAndroid Build Coastguard Worker std::vector<std::string> tones_from_single_argument_callback_;
64*d9f75844SAndroid Build Coastguard Worker std::string tones_remaining_;
65*d9f75844SAndroid Build Coastguard Worker bool completed_;
66*d9f75844SAndroid Build Coastguard Worker };
67*d9f75844SAndroid Build Coastguard Worker
68*d9f75844SAndroid Build Coastguard Worker class FakeDtmfProvider : public DtmfProviderInterface {
69*d9f75844SAndroid Build Coastguard Worker public:
70*d9f75844SAndroid Build Coastguard Worker struct DtmfInfo {
DtmfInfoFakeDtmfProvider::DtmfInfo71*d9f75844SAndroid Build Coastguard Worker DtmfInfo(int code, int duration, int gap)
72*d9f75844SAndroid Build Coastguard Worker : code(code), duration(duration), gap(gap) {}
73*d9f75844SAndroid Build Coastguard Worker int code;
74*d9f75844SAndroid Build Coastguard Worker int duration;
75*d9f75844SAndroid Build Coastguard Worker int gap;
76*d9f75844SAndroid Build Coastguard Worker };
77*d9f75844SAndroid Build Coastguard Worker
FakeDtmfProvider()78*d9f75844SAndroid Build Coastguard Worker FakeDtmfProvider() : last_insert_dtmf_call_(0) {}
79*d9f75844SAndroid Build Coastguard Worker
80*d9f75844SAndroid Build Coastguard Worker // Implements DtmfProviderInterface.
CanInsertDtmf()81*d9f75844SAndroid Build Coastguard Worker bool CanInsertDtmf() override { return can_insert_; }
82*d9f75844SAndroid Build Coastguard Worker
InsertDtmf(int code,int duration)83*d9f75844SAndroid Build Coastguard Worker bool InsertDtmf(int code, int duration) override {
84*d9f75844SAndroid Build Coastguard Worker int gap = 0;
85*d9f75844SAndroid Build Coastguard Worker // TODO(ronghuawu): Make the timer (basically the rtc::TimeNanos)
86*d9f75844SAndroid Build Coastguard Worker // mockable and use a fake timer in the unit tests.
87*d9f75844SAndroid Build Coastguard Worker if (last_insert_dtmf_call_ > 0) {
88*d9f75844SAndroid Build Coastguard Worker gap = static_cast<int>(rtc::TimeMillis() - last_insert_dtmf_call_);
89*d9f75844SAndroid Build Coastguard Worker }
90*d9f75844SAndroid Build Coastguard Worker last_insert_dtmf_call_ = rtc::TimeMillis();
91*d9f75844SAndroid Build Coastguard Worker
92*d9f75844SAndroid Build Coastguard Worker dtmf_info_queue_.push_back(DtmfInfo(code, duration, gap));
93*d9f75844SAndroid Build Coastguard Worker return true;
94*d9f75844SAndroid Build Coastguard Worker }
95*d9f75844SAndroid Build Coastguard Worker
96*d9f75844SAndroid Build Coastguard Worker // getter and setter
dtmf_info_queue() const97*d9f75844SAndroid Build Coastguard Worker const std::vector<DtmfInfo>& dtmf_info_queue() const {
98*d9f75844SAndroid Build Coastguard Worker return dtmf_info_queue_;
99*d9f75844SAndroid Build Coastguard Worker }
100*d9f75844SAndroid Build Coastguard Worker
101*d9f75844SAndroid Build Coastguard Worker // helper functions
SetCanInsertDtmf(bool can_insert)102*d9f75844SAndroid Build Coastguard Worker void SetCanInsertDtmf(bool can_insert) { can_insert_ = can_insert; }
103*d9f75844SAndroid Build Coastguard Worker
104*d9f75844SAndroid Build Coastguard Worker private:
105*d9f75844SAndroid Build Coastguard Worker bool can_insert_ = false;
106*d9f75844SAndroid Build Coastguard Worker std::vector<DtmfInfo> dtmf_info_queue_;
107*d9f75844SAndroid Build Coastguard Worker int64_t last_insert_dtmf_call_;
108*d9f75844SAndroid Build Coastguard Worker };
109*d9f75844SAndroid Build Coastguard Worker
110*d9f75844SAndroid Build Coastguard Worker class DtmfSenderTest : public ::testing::Test {
111*d9f75844SAndroid Build Coastguard Worker protected:
DtmfSenderTest()112*d9f75844SAndroid Build Coastguard Worker DtmfSenderTest()
113*d9f75844SAndroid Build Coastguard Worker : observer_(new FakeDtmfObserver()), provider_(new FakeDtmfProvider()) {
114*d9f75844SAndroid Build Coastguard Worker provider_->SetCanInsertDtmf(true);
115*d9f75844SAndroid Build Coastguard Worker dtmf_ = DtmfSender::Create(rtc::Thread::Current(), provider_.get());
116*d9f75844SAndroid Build Coastguard Worker dtmf_->RegisterObserver(observer_.get());
117*d9f75844SAndroid Build Coastguard Worker }
118*d9f75844SAndroid Build Coastguard Worker
~DtmfSenderTest()119*d9f75844SAndroid Build Coastguard Worker ~DtmfSenderTest() {
120*d9f75844SAndroid Build Coastguard Worker if (dtmf_.get()) {
121*d9f75844SAndroid Build Coastguard Worker dtmf_->UnregisterObserver();
122*d9f75844SAndroid Build Coastguard Worker }
123*d9f75844SAndroid Build Coastguard Worker }
124*d9f75844SAndroid Build Coastguard Worker
125*d9f75844SAndroid Build Coastguard Worker // Constructs a list of DtmfInfo from `tones`, `duration` and
126*d9f75844SAndroid Build Coastguard Worker // `inter_tone_gap`.
GetDtmfInfoFromString(const std::string & tones,int duration,int inter_tone_gap,std::vector<FakeDtmfProvider::DtmfInfo> * dtmfs,int comma_delay=webrtc::DtmfSender::kDtmfDefaultCommaDelayMs)127*d9f75844SAndroid Build Coastguard Worker void GetDtmfInfoFromString(
128*d9f75844SAndroid Build Coastguard Worker const std::string& tones,
129*d9f75844SAndroid Build Coastguard Worker int duration,
130*d9f75844SAndroid Build Coastguard Worker int inter_tone_gap,
131*d9f75844SAndroid Build Coastguard Worker std::vector<FakeDtmfProvider::DtmfInfo>* dtmfs,
132*d9f75844SAndroid Build Coastguard Worker int comma_delay = webrtc::DtmfSender::kDtmfDefaultCommaDelayMs) {
133*d9f75844SAndroid Build Coastguard Worker // Init extra_delay as -inter_tone_gap - duration to ensure the first
134*d9f75844SAndroid Build Coastguard Worker // DtmfInfo's gap field will be 0.
135*d9f75844SAndroid Build Coastguard Worker int extra_delay = -1 * (inter_tone_gap + duration);
136*d9f75844SAndroid Build Coastguard Worker
137*d9f75844SAndroid Build Coastguard Worker std::string::const_iterator it = tones.begin();
138*d9f75844SAndroid Build Coastguard Worker for (; it != tones.end(); ++it) {
139*d9f75844SAndroid Build Coastguard Worker char tone = *it;
140*d9f75844SAndroid Build Coastguard Worker int code = 0;
141*d9f75844SAndroid Build Coastguard Worker webrtc::GetDtmfCode(tone, &code);
142*d9f75844SAndroid Build Coastguard Worker if (tone == ',') {
143*d9f75844SAndroid Build Coastguard Worker extra_delay = comma_delay;
144*d9f75844SAndroid Build Coastguard Worker } else {
145*d9f75844SAndroid Build Coastguard Worker dtmfs->push_back(FakeDtmfProvider::DtmfInfo(
146*d9f75844SAndroid Build Coastguard Worker code, duration, duration + inter_tone_gap + extra_delay));
147*d9f75844SAndroid Build Coastguard Worker extra_delay = 0;
148*d9f75844SAndroid Build Coastguard Worker }
149*d9f75844SAndroid Build Coastguard Worker }
150*d9f75844SAndroid Build Coastguard Worker }
151*d9f75844SAndroid Build Coastguard Worker
VerifyExpectedState(const std::string & tones,int duration,int inter_tone_gap)152*d9f75844SAndroid Build Coastguard Worker void VerifyExpectedState(const std::string& tones,
153*d9f75844SAndroid Build Coastguard Worker int duration,
154*d9f75844SAndroid Build Coastguard Worker int inter_tone_gap) {
155*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(tones, dtmf_->tones());
156*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(duration, dtmf_->duration());
157*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(inter_tone_gap, dtmf_->inter_tone_gap());
158*d9f75844SAndroid Build Coastguard Worker }
159*d9f75844SAndroid Build Coastguard Worker
160*d9f75844SAndroid Build Coastguard Worker // Verify the provider got all the expected calls.
VerifyOnProvider(const std::string & tones,int duration,int inter_tone_gap,int comma_delay=webrtc::DtmfSender::kDtmfDefaultCommaDelayMs)161*d9f75844SAndroid Build Coastguard Worker void VerifyOnProvider(
162*d9f75844SAndroid Build Coastguard Worker const std::string& tones,
163*d9f75844SAndroid Build Coastguard Worker int duration,
164*d9f75844SAndroid Build Coastguard Worker int inter_tone_gap,
165*d9f75844SAndroid Build Coastguard Worker int comma_delay = webrtc::DtmfSender::kDtmfDefaultCommaDelayMs) {
166*d9f75844SAndroid Build Coastguard Worker std::vector<FakeDtmfProvider::DtmfInfo> dtmf_queue_ref;
167*d9f75844SAndroid Build Coastguard Worker GetDtmfInfoFromString(tones, duration, inter_tone_gap, &dtmf_queue_ref,
168*d9f75844SAndroid Build Coastguard Worker comma_delay);
169*d9f75844SAndroid Build Coastguard Worker VerifyOnProvider(dtmf_queue_ref);
170*d9f75844SAndroid Build Coastguard Worker }
171*d9f75844SAndroid Build Coastguard Worker
VerifyOnProvider(const std::vector<FakeDtmfProvider::DtmfInfo> & dtmf_queue_ref)172*d9f75844SAndroid Build Coastguard Worker void VerifyOnProvider(
173*d9f75844SAndroid Build Coastguard Worker const std::vector<FakeDtmfProvider::DtmfInfo>& dtmf_queue_ref) {
174*d9f75844SAndroid Build Coastguard Worker const std::vector<FakeDtmfProvider::DtmfInfo>& dtmf_queue =
175*d9f75844SAndroid Build Coastguard Worker provider_->dtmf_info_queue();
176*d9f75844SAndroid Build Coastguard Worker ASSERT_EQ(dtmf_queue_ref.size(), dtmf_queue.size());
177*d9f75844SAndroid Build Coastguard Worker std::vector<FakeDtmfProvider::DtmfInfo>::const_iterator it_ref =
178*d9f75844SAndroid Build Coastguard Worker dtmf_queue_ref.begin();
179*d9f75844SAndroid Build Coastguard Worker std::vector<FakeDtmfProvider::DtmfInfo>::const_iterator it =
180*d9f75844SAndroid Build Coastguard Worker dtmf_queue.begin();
181*d9f75844SAndroid Build Coastguard Worker while (it_ref != dtmf_queue_ref.end() && it != dtmf_queue.end()) {
182*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(it_ref->code, it->code);
183*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(it_ref->duration, it->duration);
184*d9f75844SAndroid Build Coastguard Worker // Allow ~10ms error (can be small since we're using a fake clock).
185*d9f75844SAndroid Build Coastguard Worker EXPECT_GE(it_ref->gap, it->gap - 10);
186*d9f75844SAndroid Build Coastguard Worker EXPECT_LE(it_ref->gap, it->gap + 10);
187*d9f75844SAndroid Build Coastguard Worker ++it_ref;
188*d9f75844SAndroid Build Coastguard Worker ++it;
189*d9f75844SAndroid Build Coastguard Worker }
190*d9f75844SAndroid Build Coastguard Worker }
191*d9f75844SAndroid Build Coastguard Worker
192*d9f75844SAndroid Build Coastguard Worker // Verify the observer got all the expected callbacks.
VerifyOnObserver(const std::string & tones_ref)193*d9f75844SAndroid Build Coastguard Worker void VerifyOnObserver(const std::string& tones_ref) {
194*d9f75844SAndroid Build Coastguard Worker const std::vector<std::string>& tones = observer_->tones();
195*d9f75844SAndroid Build Coastguard Worker // The observer will get an empty string at the end.
196*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(tones_ref.size() + 1, tones.size());
197*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(observer_->tones(),
198*d9f75844SAndroid Build Coastguard Worker observer_->tones_from_single_argument_callback());
199*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(tones.back().empty());
200*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(observer_->tones_remaining().empty());
201*d9f75844SAndroid Build Coastguard Worker std::string::const_iterator it_ref = tones_ref.begin();
202*d9f75844SAndroid Build Coastguard Worker std::vector<std::string>::const_iterator it = tones.begin();
203*d9f75844SAndroid Build Coastguard Worker while (it_ref != tones_ref.end() && it != tones.end()) {
204*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(*it_ref, it->at(0));
205*d9f75844SAndroid Build Coastguard Worker ++it_ref;
206*d9f75844SAndroid Build Coastguard Worker ++it;
207*d9f75844SAndroid Build Coastguard Worker }
208*d9f75844SAndroid Build Coastguard Worker }
209*d9f75844SAndroid Build Coastguard Worker
210*d9f75844SAndroid Build Coastguard Worker rtc::AutoThread main_thread_;
211*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<FakeDtmfObserver> observer_;
212*d9f75844SAndroid Build Coastguard Worker std::unique_ptr<FakeDtmfProvider> provider_;
213*d9f75844SAndroid Build Coastguard Worker rtc::scoped_refptr<DtmfSender> dtmf_;
214*d9f75844SAndroid Build Coastguard Worker rtc::ScopedFakeClock fake_clock_;
215*d9f75844SAndroid Build Coastguard Worker };
216*d9f75844SAndroid Build Coastguard Worker
TEST_F(DtmfSenderTest,CanInsertDtmf)217*d9f75844SAndroid Build Coastguard Worker TEST_F(DtmfSenderTest, CanInsertDtmf) {
218*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(dtmf_->CanInsertDtmf());
219*d9f75844SAndroid Build Coastguard Worker provider_->SetCanInsertDtmf(false);
220*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(dtmf_->CanInsertDtmf());
221*d9f75844SAndroid Build Coastguard Worker }
222*d9f75844SAndroid Build Coastguard Worker
TEST_F(DtmfSenderTest,InsertDtmf)223*d9f75844SAndroid Build Coastguard Worker TEST_F(DtmfSenderTest, InsertDtmf) {
224*d9f75844SAndroid Build Coastguard Worker std::string tones = "@1%a&*$";
225*d9f75844SAndroid Build Coastguard Worker int duration = 100;
226*d9f75844SAndroid Build Coastguard Worker int inter_tone_gap = 50;
227*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(dtmf_->InsertDtmf(tones, duration, inter_tone_gap));
228*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_SIMULATED_WAIT(observer_->completed(), kMaxWaitMs, fake_clock_);
229*d9f75844SAndroid Build Coastguard Worker
230*d9f75844SAndroid Build Coastguard Worker // The unrecognized characters should be ignored.
231*d9f75844SAndroid Build Coastguard Worker std::string known_tones = "1a*";
232*d9f75844SAndroid Build Coastguard Worker VerifyOnProvider(known_tones, duration, inter_tone_gap);
233*d9f75844SAndroid Build Coastguard Worker VerifyOnObserver(known_tones);
234*d9f75844SAndroid Build Coastguard Worker }
235*d9f75844SAndroid Build Coastguard Worker
TEST_F(DtmfSenderTest,InsertDtmfTwice)236*d9f75844SAndroid Build Coastguard Worker TEST_F(DtmfSenderTest, InsertDtmfTwice) {
237*d9f75844SAndroid Build Coastguard Worker std::string tones1 = "12";
238*d9f75844SAndroid Build Coastguard Worker std::string tones2 = "ab";
239*d9f75844SAndroid Build Coastguard Worker int duration = 100;
240*d9f75844SAndroid Build Coastguard Worker int inter_tone_gap = 50;
241*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(dtmf_->InsertDtmf(tones1, duration, inter_tone_gap));
242*d9f75844SAndroid Build Coastguard Worker VerifyExpectedState(tones1, duration, inter_tone_gap);
243*d9f75844SAndroid Build Coastguard Worker // Wait until the first tone got sent.
244*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_SIMULATED_WAIT(observer_->tones().size() == 1, kMaxWaitMs,
245*d9f75844SAndroid Build Coastguard Worker fake_clock_);
246*d9f75844SAndroid Build Coastguard Worker VerifyExpectedState("2", duration, inter_tone_gap);
247*d9f75844SAndroid Build Coastguard Worker // Insert with another tone buffer.
248*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(dtmf_->InsertDtmf(tones2, duration, inter_tone_gap));
249*d9f75844SAndroid Build Coastguard Worker VerifyExpectedState(tones2, duration, inter_tone_gap);
250*d9f75844SAndroid Build Coastguard Worker // Wait until it's completed.
251*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_SIMULATED_WAIT(observer_->completed(), kMaxWaitMs, fake_clock_);
252*d9f75844SAndroid Build Coastguard Worker
253*d9f75844SAndroid Build Coastguard Worker std::vector<FakeDtmfProvider::DtmfInfo> dtmf_queue_ref;
254*d9f75844SAndroid Build Coastguard Worker GetDtmfInfoFromString("1", duration, inter_tone_gap, &dtmf_queue_ref);
255*d9f75844SAndroid Build Coastguard Worker GetDtmfInfoFromString("ab", duration, inter_tone_gap, &dtmf_queue_ref);
256*d9f75844SAndroid Build Coastguard Worker VerifyOnProvider(dtmf_queue_ref);
257*d9f75844SAndroid Build Coastguard Worker VerifyOnObserver("1ab");
258*d9f75844SAndroid Build Coastguard Worker }
259*d9f75844SAndroid Build Coastguard Worker
TEST_F(DtmfSenderTest,InsertDtmfWhileProviderIsDeleted)260*d9f75844SAndroid Build Coastguard Worker TEST_F(DtmfSenderTest, InsertDtmfWhileProviderIsDeleted) {
261*d9f75844SAndroid Build Coastguard Worker std::string tones = "@1%a&*$";
262*d9f75844SAndroid Build Coastguard Worker int duration = 100;
263*d9f75844SAndroid Build Coastguard Worker int inter_tone_gap = 50;
264*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(dtmf_->InsertDtmf(tones, duration, inter_tone_gap));
265*d9f75844SAndroid Build Coastguard Worker // Wait until the first tone got sent.
266*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_SIMULATED_WAIT(observer_->tones().size() == 1, kMaxWaitMs,
267*d9f75844SAndroid Build Coastguard Worker fake_clock_);
268*d9f75844SAndroid Build Coastguard Worker // Delete provider.
269*d9f75844SAndroid Build Coastguard Worker dtmf_->OnDtmfProviderDestroyed();
270*d9f75844SAndroid Build Coastguard Worker provider_.reset();
271*d9f75844SAndroid Build Coastguard Worker // The queue should be discontinued so no more tone callbacks.
272*d9f75844SAndroid Build Coastguard Worker SIMULATED_WAIT(false, 200, fake_clock_);
273*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1U, observer_->tones().size());
274*d9f75844SAndroid Build Coastguard Worker }
275*d9f75844SAndroid Build Coastguard Worker
TEST_F(DtmfSenderTest,InsertDtmfWhileSenderIsDeleted)276*d9f75844SAndroid Build Coastguard Worker TEST_F(DtmfSenderTest, InsertDtmfWhileSenderIsDeleted) {
277*d9f75844SAndroid Build Coastguard Worker std::string tones = "@1%a&*$";
278*d9f75844SAndroid Build Coastguard Worker int duration = 100;
279*d9f75844SAndroid Build Coastguard Worker int inter_tone_gap = 50;
280*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(dtmf_->InsertDtmf(tones, duration, inter_tone_gap));
281*d9f75844SAndroid Build Coastguard Worker // Wait until the first tone got sent.
282*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_SIMULATED_WAIT(observer_->tones().size() == 1, kMaxWaitMs,
283*d9f75844SAndroid Build Coastguard Worker fake_clock_);
284*d9f75844SAndroid Build Coastguard Worker // Delete the sender.
285*d9f75844SAndroid Build Coastguard Worker dtmf_ = NULL;
286*d9f75844SAndroid Build Coastguard Worker // The queue should be discontinued so no more tone callbacks.
287*d9f75844SAndroid Build Coastguard Worker SIMULATED_WAIT(false, 200, fake_clock_);
288*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1U, observer_->tones().size());
289*d9f75844SAndroid Build Coastguard Worker }
290*d9f75844SAndroid Build Coastguard Worker
TEST_F(DtmfSenderTest,InsertEmptyTonesToCancelPreviousTask)291*d9f75844SAndroid Build Coastguard Worker TEST_F(DtmfSenderTest, InsertEmptyTonesToCancelPreviousTask) {
292*d9f75844SAndroid Build Coastguard Worker std::string tones1 = "12";
293*d9f75844SAndroid Build Coastguard Worker std::string tones2 = "";
294*d9f75844SAndroid Build Coastguard Worker int duration = 100;
295*d9f75844SAndroid Build Coastguard Worker int inter_tone_gap = 50;
296*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(dtmf_->InsertDtmf(tones1, duration, inter_tone_gap));
297*d9f75844SAndroid Build Coastguard Worker // Wait until the first tone got sent.
298*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_SIMULATED_WAIT(observer_->tones().size() == 1, kMaxWaitMs,
299*d9f75844SAndroid Build Coastguard Worker fake_clock_);
300*d9f75844SAndroid Build Coastguard Worker // Insert with another tone buffer.
301*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(dtmf_->InsertDtmf(tones2, duration, inter_tone_gap));
302*d9f75844SAndroid Build Coastguard Worker // Wait until it's completed.
303*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_SIMULATED_WAIT(observer_->completed(), kMaxWaitMs, fake_clock_);
304*d9f75844SAndroid Build Coastguard Worker
305*d9f75844SAndroid Build Coastguard Worker std::vector<FakeDtmfProvider::DtmfInfo> dtmf_queue_ref;
306*d9f75844SAndroid Build Coastguard Worker GetDtmfInfoFromString("1", duration, inter_tone_gap, &dtmf_queue_ref);
307*d9f75844SAndroid Build Coastguard Worker VerifyOnProvider(dtmf_queue_ref);
308*d9f75844SAndroid Build Coastguard Worker VerifyOnObserver("1");
309*d9f75844SAndroid Build Coastguard Worker }
310*d9f75844SAndroid Build Coastguard Worker
TEST_F(DtmfSenderTest,InsertDtmfWithDefaultCommaDelay)311*d9f75844SAndroid Build Coastguard Worker TEST_F(DtmfSenderTest, InsertDtmfWithDefaultCommaDelay) {
312*d9f75844SAndroid Build Coastguard Worker std::string tones = "3,4";
313*d9f75844SAndroid Build Coastguard Worker int duration = 100;
314*d9f75844SAndroid Build Coastguard Worker int inter_tone_gap = 50;
315*d9f75844SAndroid Build Coastguard Worker int default_comma_delay = webrtc::DtmfSender::kDtmfDefaultCommaDelayMs;
316*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(dtmf_->comma_delay(), default_comma_delay);
317*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(dtmf_->InsertDtmf(tones, duration, inter_tone_gap));
318*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_SIMULATED_WAIT(observer_->completed(), kMaxWaitMs, fake_clock_);
319*d9f75844SAndroid Build Coastguard Worker
320*d9f75844SAndroid Build Coastguard Worker VerifyOnProvider(tones, duration, inter_tone_gap);
321*d9f75844SAndroid Build Coastguard Worker VerifyOnObserver(tones);
322*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(dtmf_->comma_delay(), default_comma_delay);
323*d9f75844SAndroid Build Coastguard Worker }
324*d9f75844SAndroid Build Coastguard Worker
TEST_F(DtmfSenderTest,InsertDtmfWithNonDefaultCommaDelay)325*d9f75844SAndroid Build Coastguard Worker TEST_F(DtmfSenderTest, InsertDtmfWithNonDefaultCommaDelay) {
326*d9f75844SAndroid Build Coastguard Worker std::string tones = "3,4";
327*d9f75844SAndroid Build Coastguard Worker int duration = 100;
328*d9f75844SAndroid Build Coastguard Worker int inter_tone_gap = 50;
329*d9f75844SAndroid Build Coastguard Worker int default_comma_delay = webrtc::DtmfSender::kDtmfDefaultCommaDelayMs;
330*d9f75844SAndroid Build Coastguard Worker int comma_delay = 500;
331*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(dtmf_->comma_delay(), default_comma_delay);
332*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(dtmf_->InsertDtmf(tones, duration, inter_tone_gap, comma_delay));
333*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_SIMULATED_WAIT(observer_->completed(), kMaxWaitMs, fake_clock_);
334*d9f75844SAndroid Build Coastguard Worker
335*d9f75844SAndroid Build Coastguard Worker VerifyOnProvider(tones, duration, inter_tone_gap, comma_delay);
336*d9f75844SAndroid Build Coastguard Worker VerifyOnObserver(tones);
337*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(dtmf_->comma_delay(), comma_delay);
338*d9f75844SAndroid Build Coastguard Worker }
339*d9f75844SAndroid Build Coastguard Worker
TEST_F(DtmfSenderTest,TryInsertDtmfWhenItDoesNotWork)340*d9f75844SAndroid Build Coastguard Worker TEST_F(DtmfSenderTest, TryInsertDtmfWhenItDoesNotWork) {
341*d9f75844SAndroid Build Coastguard Worker std::string tones = "3,4";
342*d9f75844SAndroid Build Coastguard Worker int duration = 100;
343*d9f75844SAndroid Build Coastguard Worker int inter_tone_gap = 50;
344*d9f75844SAndroid Build Coastguard Worker provider_->SetCanInsertDtmf(false);
345*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(dtmf_->InsertDtmf(tones, duration, inter_tone_gap));
346*d9f75844SAndroid Build Coastguard Worker }
347*d9f75844SAndroid Build Coastguard Worker
TEST_F(DtmfSenderTest,InsertDtmfWithInvalidDurationOrGap)348*d9f75844SAndroid Build Coastguard Worker TEST_F(DtmfSenderTest, InsertDtmfWithInvalidDurationOrGap) {
349*d9f75844SAndroid Build Coastguard Worker std::string tones = "3,4";
350*d9f75844SAndroid Build Coastguard Worker int duration = 40;
351*d9f75844SAndroid Build Coastguard Worker int inter_tone_gap = 50;
352*d9f75844SAndroid Build Coastguard Worker
353*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(dtmf_->InsertDtmf(tones, 6001, inter_tone_gap));
354*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(dtmf_->InsertDtmf(tones, 39, inter_tone_gap));
355*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(dtmf_->InsertDtmf(tones, duration, 29));
356*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(dtmf_->InsertDtmf(tones, duration, inter_tone_gap, 29));
357*d9f75844SAndroid Build Coastguard Worker
358*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(dtmf_->InsertDtmf(tones, duration, inter_tone_gap));
359*d9f75844SAndroid Build Coastguard Worker }
360*d9f75844SAndroid Build Coastguard Worker
TEST_F(DtmfSenderTest,InsertDtmfSendsAfterWait)361*d9f75844SAndroid Build Coastguard Worker TEST_F(DtmfSenderTest, InsertDtmfSendsAfterWait) {
362*d9f75844SAndroid Build Coastguard Worker std::string tones = "ABC";
363*d9f75844SAndroid Build Coastguard Worker int duration = 100;
364*d9f75844SAndroid Build Coastguard Worker int inter_tone_gap = 50;
365*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(dtmf_->InsertDtmf(tones, duration, inter_tone_gap));
366*d9f75844SAndroid Build Coastguard Worker VerifyExpectedState("ABC", duration, inter_tone_gap);
367*d9f75844SAndroid Build Coastguard Worker // Wait until the first tone got sent.
368*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_SIMULATED_WAIT(observer_->tones().size() == 1, kMaxWaitMs,
369*d9f75844SAndroid Build Coastguard Worker fake_clock_);
370*d9f75844SAndroid Build Coastguard Worker VerifyExpectedState("BC", duration, inter_tone_gap);
371*d9f75844SAndroid Build Coastguard Worker }
372