1 /*
2 * Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "audio/voip/voip_core.h"
12
13 #include "api/audio_codecs/builtin_audio_decoder_factory.h"
14 #include "api/audio_codecs/builtin_audio_encoder_factory.h"
15 #include "api/task_queue/default_task_queue_factory.h"
16 #include "modules/audio_device/include/mock_audio_device.h"
17 #include "modules/audio_processing/include/mock_audio_processing.h"
18 #include "test/gtest.h"
19 #include "test/mock_transport.h"
20 #include "test/run_loop.h"
21
22 namespace webrtc {
23 namespace {
24
25 using ::testing::NiceMock;
26 using ::testing::Return;
27
28 constexpr int kPcmuPayload = 0;
29 constexpr int kPcmuSampleRateHz = 8000;
30 constexpr int kDtmfEventDurationMs = 1000;
31 constexpr DtmfEvent kDtmfEventCode = DtmfEvent::kDigitZero;
32
33 class VoipCoreTest : public ::testing::Test {
34 public:
35 const SdpAudioFormat kPcmuFormat = {"pcmu", 8000, 1};
36
VoipCoreTest()37 VoipCoreTest() { audio_device_ = test::MockAudioDeviceModule::CreateNice(); }
38
SetUp()39 void SetUp() override {
40 auto encoder_factory = CreateBuiltinAudioEncoderFactory();
41 auto decoder_factory = CreateBuiltinAudioDecoderFactory();
42 rtc::scoped_refptr<AudioProcessing> audio_processing =
43 rtc::make_ref_counted<NiceMock<test::MockAudioProcessing>>();
44
45 voip_core_ = std::make_unique<VoipCore>(
46 std::move(encoder_factory), std::move(decoder_factory),
47 CreateDefaultTaskQueueFactory(), audio_device_,
48 std::move(audio_processing));
49 }
50
51 test::RunLoop run_loop_;
52 std::unique_ptr<VoipCore> voip_core_;
53 NiceMock<MockTransport> transport_;
54 rtc::scoped_refptr<test::MockAudioDeviceModule> audio_device_;
55 };
56
57 // Validate expected API calls that involves with VoipCore. Some verification is
58 // involved with checking mock audio device.
TEST_F(VoipCoreTest,BasicVoipCoreOperation)59 TEST_F(VoipCoreTest, BasicVoipCoreOperation) {
60 // Program mock as non-operational and ready to start.
61 EXPECT_CALL(*audio_device_, Recording()).WillOnce(Return(false));
62 EXPECT_CALL(*audio_device_, Playing()).WillOnce(Return(false));
63 EXPECT_CALL(*audio_device_, InitRecording()).WillOnce(Return(0));
64 EXPECT_CALL(*audio_device_, InitPlayout()).WillOnce(Return(0));
65 EXPECT_CALL(*audio_device_, StartRecording()).WillOnce(Return(0));
66 EXPECT_CALL(*audio_device_, StartPlayout()).WillOnce(Return(0));
67
68 auto channel = voip_core_->CreateChannel(&transport_, 0xdeadc0de);
69
70 EXPECT_EQ(voip_core_->SetSendCodec(channel, kPcmuPayload, kPcmuFormat),
71 VoipResult::kOk);
72 EXPECT_EQ(
73 voip_core_->SetReceiveCodecs(channel, {{kPcmuPayload, kPcmuFormat}}),
74 VoipResult::kOk);
75
76 EXPECT_EQ(voip_core_->StartSend(channel), VoipResult::kOk);
77 EXPECT_EQ(voip_core_->StartPlayout(channel), VoipResult::kOk);
78
79 EXPECT_EQ(voip_core_->RegisterTelephoneEventType(channel, kPcmuPayload,
80 kPcmuSampleRateHz),
81 VoipResult::kOk);
82
83 EXPECT_EQ(
84 voip_core_->SendDtmfEvent(channel, kDtmfEventCode, kDtmfEventDurationMs),
85 VoipResult::kOk);
86
87 // Program mock as operational that is ready to be stopped.
88 EXPECT_CALL(*audio_device_, Recording()).WillOnce(Return(true));
89 EXPECT_CALL(*audio_device_, Playing()).WillOnce(Return(true));
90 EXPECT_CALL(*audio_device_, StopRecording()).WillOnce(Return(0));
91 EXPECT_CALL(*audio_device_, StopPlayout()).WillOnce(Return(0));
92
93 EXPECT_EQ(voip_core_->StopSend(channel), VoipResult::kOk);
94 EXPECT_EQ(voip_core_->StopPlayout(channel), VoipResult::kOk);
95 EXPECT_EQ(voip_core_->ReleaseChannel(channel), VoipResult::kOk);
96 }
97
TEST_F(VoipCoreTest,ExpectFailToUseReleasedChannelId)98 TEST_F(VoipCoreTest, ExpectFailToUseReleasedChannelId) {
99 auto channel = voip_core_->CreateChannel(&transport_, 0xdeadc0de);
100
101 // Release right after creation.
102 EXPECT_EQ(voip_core_->ReleaseChannel(channel), VoipResult::kOk);
103
104 // Now use released channel.
105
106 EXPECT_EQ(voip_core_->SetSendCodec(channel, kPcmuPayload, kPcmuFormat),
107 VoipResult::kInvalidArgument);
108 EXPECT_EQ(
109 voip_core_->SetReceiveCodecs(channel, {{kPcmuPayload, kPcmuFormat}}),
110 VoipResult::kInvalidArgument);
111 EXPECT_EQ(voip_core_->RegisterTelephoneEventType(channel, kPcmuPayload,
112 kPcmuSampleRateHz),
113 VoipResult::kInvalidArgument);
114 EXPECT_EQ(voip_core_->StartSend(channel), VoipResult::kInvalidArgument);
115 EXPECT_EQ(voip_core_->StartPlayout(channel), VoipResult::kInvalidArgument);
116 EXPECT_EQ(
117 voip_core_->SendDtmfEvent(channel, kDtmfEventCode, kDtmfEventDurationMs),
118 VoipResult::kInvalidArgument);
119 }
120
TEST_F(VoipCoreTest,SendDtmfEventWithoutRegistering)121 TEST_F(VoipCoreTest, SendDtmfEventWithoutRegistering) {
122 // Program mock as non-operational and ready to start send.
123 EXPECT_CALL(*audio_device_, Recording()).WillOnce(Return(false));
124 EXPECT_CALL(*audio_device_, InitRecording()).WillOnce(Return(0));
125 EXPECT_CALL(*audio_device_, StartRecording()).WillOnce(Return(0));
126
127 auto channel = voip_core_->CreateChannel(&transport_, 0xdeadc0de);
128
129 EXPECT_EQ(voip_core_->SetSendCodec(channel, kPcmuPayload, kPcmuFormat),
130 VoipResult::kOk);
131
132 EXPECT_EQ(voip_core_->StartSend(channel), VoipResult::kOk);
133 // Send Dtmf event without registering beforehand, thus payload
134 // type is not set and kFailedPrecondition is expected.
135 EXPECT_EQ(
136 voip_core_->SendDtmfEvent(channel, kDtmfEventCode, kDtmfEventDurationMs),
137 VoipResult::kFailedPrecondition);
138
139 // Program mock as sending and is ready to be stopped.
140 EXPECT_CALL(*audio_device_, Recording()).WillOnce(Return(true));
141 EXPECT_CALL(*audio_device_, StopRecording()).WillOnce(Return(0));
142
143 EXPECT_EQ(voip_core_->StopSend(channel), VoipResult::kOk);
144 EXPECT_EQ(voip_core_->ReleaseChannel(channel), VoipResult::kOk);
145 }
146
TEST_F(VoipCoreTest,SendDtmfEventWithoutStartSend)147 TEST_F(VoipCoreTest, SendDtmfEventWithoutStartSend) {
148 auto channel = voip_core_->CreateChannel(&transport_, 0xdeadc0de);
149
150 EXPECT_EQ(voip_core_->RegisterTelephoneEventType(channel, kPcmuPayload,
151 kPcmuSampleRateHz),
152 VoipResult::kOk);
153
154 // Send Dtmf event without calling StartSend beforehand, thus
155 // Dtmf events cannot be sent and kFailedPrecondition is expected.
156 EXPECT_EQ(
157 voip_core_->SendDtmfEvent(channel, kDtmfEventCode, kDtmfEventDurationMs),
158 VoipResult::kFailedPrecondition);
159
160 EXPECT_EQ(voip_core_->ReleaseChannel(channel), VoipResult::kOk);
161 }
162
TEST_F(VoipCoreTest,StartSendAndPlayoutWithoutSettingCodec)163 TEST_F(VoipCoreTest, StartSendAndPlayoutWithoutSettingCodec) {
164 auto channel = voip_core_->CreateChannel(&transport_, 0xdeadc0de);
165
166 // Call StartSend and StartPlayout without setting send/receive
167 // codec. Code should see that codecs aren't set and return false.
168 EXPECT_EQ(voip_core_->StartSend(channel), VoipResult::kFailedPrecondition);
169 EXPECT_EQ(voip_core_->StartPlayout(channel), VoipResult::kFailedPrecondition);
170
171 EXPECT_EQ(voip_core_->ReleaseChannel(channel), VoipResult::kOk);
172 }
173
TEST_F(VoipCoreTest,StopSendAndPlayoutWithoutStarting)174 TEST_F(VoipCoreTest, StopSendAndPlayoutWithoutStarting) {
175 auto channel = voip_core_->CreateChannel(&transport_, 0xdeadc0de);
176
177 EXPECT_EQ(voip_core_->SetSendCodec(channel, kPcmuPayload, kPcmuFormat),
178 VoipResult::kOk);
179 EXPECT_EQ(
180 voip_core_->SetReceiveCodecs(channel, {{kPcmuPayload, kPcmuFormat}}),
181 VoipResult::kOk);
182
183 // Call StopSend and StopPlayout without starting them in
184 // the first place. Should see that it is already in the
185 // stopped state and return true.
186 EXPECT_EQ(voip_core_->StopSend(channel), VoipResult::kOk);
187 EXPECT_EQ(voip_core_->StopPlayout(channel), VoipResult::kOk);
188
189 EXPECT_EQ(voip_core_->ReleaseChannel(channel), VoipResult::kOk);
190 }
191
192 } // namespace
193 } // namespace webrtc
194