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