using webrtc::DtmfProviderInterface; using webrtc::DtmfSender; using webrtc::DtmfSenderObserverInterface;
// TODO(deadbeef): Even though this test now uses a fake clock, it has a // generous 3-second timeout for every test case. The timeout could be tuned // to each test based on the tones sent, instead. staticconst int kMaxWaitMs = 3000;
class FakeDtmfObserver : public DtmfSenderObserverInterface { public:
FakeDtmfObserver() : completed_(false) {}
class FakeDtmfProvider : public DtmfProviderInterface { public: struct DtmfInfo {
DtmfInfo(int code, int duration, int gap)
: code(code), duration(duration), gap(gap) {}
int code;
int duration;
int gap;
};
bool InsertDtmf(int code, int duration) override {
int gap = 0; // TODO(ronghuawu): Make the timer (basically the webrtc::TimeNanos) // mockable and use a fake timer in the unit tests.
if (last_insert_dtmf_call_ > 0) {
gap = static_cast<int>(webrtc::TimeMillis() - last_insert_dtmf_call_);
}
last_insert_dtmf_call_ = webrtc::TimeMillis();
~DtmfSenderTest() override {
if (dtmf_) {
dtmf_->UnregisterObserver();
}
}
// Constructs a list of DtmfInfo from `tones`, `duration` and // `inter_tone_gap`. void GetDtmfInfoFromString( const std::string& tones,
int duration,
int inter_tone_gap,
std::vector<FakeDtmfProvider::DtmfInfo>* dtmfs,
int comma_delay = webrtc::DtmfSender::kDtmfDefaultCommaDelayMs) { // Init extra_delay as -inter_tone_gap - duration to ensure the first // DtmfInfo's gap field will be 0.
int extra_delay = -1 * (inter_tone_gap + duration);
std::string::const_iterator it = tones.begin();
for (; it != tones.end(); ++it) {
char tone = *it;
int code = 0;
webrtc::GetDtmfCode(tone, &code);
if (tone == ',') {
extra_delay = comma_delay;
} else {
dtmfs->push_back(FakeDtmfProvider::DtmfInfo(
code, duration, duration + inter_tone_gap + extra_delay));
extra_delay = 0;
}
}
}
void VerifyExpectedState(const std::string& tones,
int duration,
int inter_tone_gap) {
EXPECT_EQ(tones, dtmf_->tones());
EXPECT_EQ(duration, dtmf_->duration());
EXPECT_EQ(inter_tone_gap, dtmf_->inter_tone_gap());
}
// Verify the provider got all the expected calls. void VerifyOnProvider( const std::string& tones,
int duration,
int inter_tone_gap,
int comma_delay = webrtc::DtmfSender::kDtmfDefaultCommaDelayMs) {
std::vector<FakeDtmfProvider::DtmfInfo> dtmf_queue_ref;
GetDtmfInfoFromString(tones, duration, inter_tone_gap, &dtmf_queue_ref,
comma_delay);
VerifyOnProvider(dtmf_queue_ref);
}
void VerifyOnProvider( const std::vector<FakeDtmfProvider::DtmfInfo>& dtmf_queue_ref) { const std::vector<FakeDtmfProvider::DtmfInfo>& dtmf_queue =
provider_->dtmf_info_queue();
ASSERT_EQ(dtmf_queue_ref.size(), dtmf_queue.size());
std::vector<FakeDtmfProvider::DtmfInfo>::const_iterator it_ref =
dtmf_queue_ref.begin();
std::vector<FakeDtmfProvider::DtmfInfo>::const_iterator it =
dtmf_queue.begin(); while (it_ref != dtmf_queue_ref.end() && it != dtmf_queue.end()) {
EXPECT_EQ(it_ref->code, it->code);
EXPECT_EQ(it_ref->duration, it->duration); // Allow ~10ms error (can be small since we're using a fake clock).
EXPECT_GE(it_ref->gap, it->gap - 10);
EXPECT_LE(it_ref->gap, it->gap + 10);
++it_ref;
++it;
}
}
// Verify the observer got all the expected callbacks. void VerifyOnObserver(const std::string& tones_ref) { const std::vector<std::string>& tones = observer_->tones(); // The observer will get an empty string at the end.
EXPECT_EQ(tones_ref.size() + 1, tones.size());
EXPECT_TRUE(tones.back().empty());
EXPECT_TRUE(observer_->tones_remaining().empty());
std::string::const_iterator it_ref = tones_ref.begin();
std::vector<std::string>::const_iterator it = tones.begin(); while (it_ref != tones_ref.end() && it != tones.end()) {
EXPECT_EQ(*it_ref, it->at(0));
++it_ref;
++it;
}
}
TEST_F(DtmfSenderTest, InsertDtmfWhileProviderIsDeleted) {
std::string tones = "@1%a&*$";
int duration = 100;
int inter_tone_gap = 50;
EXPECT_TRUE(dtmf_->InsertDtmf(tones, duration, inter_tone_gap)); // Wait until the first tone got sent.
EXPECT_THAT(webrtc::WaitUntil(
[&] { return observer_->tones().size(); }, ::testing::Eq(1),
{.timeout = webrtc::TimeDelta::Millis(kMaxWaitMs),
.clock = &time_controller_}),
webrtc::IsRtcOk()); // Delete provider.
dtmf_->OnDtmfProviderDestroyed();
provider_.reset(); // The queue should be discontinued so no more tone callbacks.
time_controller_.AdvanceTime(webrtc::TimeDelta::Millis(200));
EXPECT_EQ(1U, observer_->tones().size());
}
TEST_F(DtmfSenderTest, InsertDtmfWhileSenderIsDeleted) {
std::string tones = "@1%a&*$";
int duration = 100;
int inter_tone_gap = 50;
EXPECT_TRUE(dtmf_->InsertDtmf(tones, duration, inter_tone_gap)); // Wait until the first tone got sent.
EXPECT_THAT(webrtc::WaitUntil(
[&] { return observer_->tones().size(); }, ::testing::Eq(1),
{.timeout = webrtc::TimeDelta::Millis(kMaxWaitMs),
.clock = &time_controller_}),
webrtc::IsRtcOk()); // Delete the sender.
dtmf_ = nullptr; // The queue should be discontinued so no more tone callbacks.
time_controller_.AdvanceTime(webrtc::TimeDelta::Millis(200));
EXPECT_EQ(1U, observer_->tones().size());
}
TEST_F(DtmfSenderTest, InsertEmptyTonesToCancelPreviousTask) {
std::string tones1 = "12";
std::string tones2 = "";
int duration = 100;
int inter_tone_gap = 50;
EXPECT_TRUE(dtmf_->InsertDtmf(tones1, duration, inter_tone_gap)); // Wait until the first tone got sent.
EXPECT_THAT(webrtc::WaitUntil(
[&] { return observer_->tones().size(); }, ::testing::Eq(1),
{.timeout = webrtc::TimeDelta::Millis(kMaxWaitMs),
.clock = &time_controller_}),
webrtc::IsRtcOk()); // Insert with another tone buffer.
EXPECT_TRUE(dtmf_->InsertDtmf(tones2, duration, inter_tone_gap)); // Wait until it's completed.
EXPECT_THAT(webrtc::WaitUntil(
[&] { return observer_->completed(); }, ::testing::IsTrue(),
{.timeout = webrtc::TimeDelta::Millis(kMaxWaitMs),
.clock = &time_controller_}),
webrtc::IsRtcOk());
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.