Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(79)

Side by Side Diff: webrtc/api/quicdatatransport_unittest.cc

Issue 1886623002: Add QuicDataChannel and QuicDataTransport classes (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Make QuicDataChannel::Message public so QuicDataTransport can use it for handling messages Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * Copyright 2016 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 "webrtc/api/quicdatatransport.h"
12
13 #include <set>
14 #include <string>
15 #include <unordered_map>
16 #include <vector>
17
18 #include "webrtc/api/quicdatachannel.h"
19 #include "webrtc/base/bytebuffer.h"
20 #include "webrtc/base/gunit.h"
21 #include "webrtc/p2p/base/faketransportcontroller.h"
22 #include "webrtc/p2p/quic/quictransportchannel.h"
23 #include "webrtc/p2p/quic/reliablequicstream.h"
24
25 using webrtc::DataBuffer;
26 using webrtc::DataChannelInit;
27 using webrtc::DataChannelInterface;
28 using webrtc::DataChannelObserver;
29 using webrtc::QuicDataChannel;
30 using webrtc::QuicDataTransport;
31 using cricket::FakeTransportChannel;
32 using cricket::QuicTransportChannel;
33 using cricket::ReliableQuicStream;
34
35 namespace {
36
37 // Timeout for asynchronous operations.
38 static const int kTimeoutMs = 1000; // milliseconds
39
40 // FakeObserver receives messages from the data channel.
41 class FakeObserver : public DataChannelObserver {
42 public:
43 FakeObserver() {}
44
45 void OnStateChange() override {}
46
47 void OnBufferedAmountChange(uint64_t previous_amount) override {}
48
49 void OnMessage(const webrtc::DataBuffer& buffer) override {
50 messages_.push_back(std::string(buffer.data.data<char>(), buffer.size()));
51 }
52
53 const std::vector<std::string>& messages() const { return messages_; }
54
55 size_t messages_received() const { return messages_.size(); }
56
57 private:
58 std::vector<std::string> messages_;
59 };
60
61 // A peer who uses a QUIC transport channel and fake ICE transport channel to
62 // send or receive data.
63 class QuicDataTransportPeer {
64 public:
65 QuicDataTransportPeer()
66 : quic_data_transport_(rtc::Thread::Current(), rtc::Thread::Current()),
67 ice_transport_channel_("data", 0),
68 quic_transport_channel_(&ice_transport_channel_) {
69 ice_transport_channel_.SetAsync(true);
70 }
71
72 void GenerateCertificateAndFingerprint() {
73 rtc::scoped_refptr<rtc::RTCCertificate> local_cert =
74 rtc::RTCCertificate::Create(rtc::scoped_ptr<rtc::SSLIdentity>(
75 rtc::SSLIdentity::Generate("cert_name", rtc::KT_DEFAULT)));
76 quic_transport_channel_.SetLocalCertificate(local_cert);
77 local_fingerprint_.reset(CreateFingerprint(local_cert.get()));
78 }
79
80 // Connects |ice_transport_channel_| to that of the other peer.
81 void Connect(QuicDataTransportPeer* other_peer) {
82 ice_transport_channel_.Connect();
83 other_peer->ice_transport_channel_.Connect();
84 ice_transport_channel_.SetDestination(&other_peer->ice_transport_channel_);
85 }
86
87 rtc::scoped_ptr<rtc::SSLFingerprint>& local_fingerprint() {
88 return local_fingerprint_;
89 }
90
91 QuicTransportChannel* quic_transport_channel() {
92 return &quic_transport_channel_;
93 }
94
95 // Write a messge directly to the ReliableQuicStream.
96 void WriteMessage(int data_channel_id,
97 uint64_t message_id,
98 const std::string& message) {
99 ReliableQuicStream* stream = quic_transport_channel_.CreateQuicStream();
100 rtc::CopyOnWriteBuffer payload;
101 webrtc::EncodeQuicHeader(data_channel_id, message_id, &payload);
102 stream->Write(payload.data<char>(), payload.size(), false);
103 stream->Write(message.data(), message.size(), true);
104 }
105
106 rtc::scoped_refptr<DataChannelInterface> CreateDataChannel(
107 const DataChannelInit* config) {
108 return quic_data_transport_.CreateDataChannel("testing", config);
109 }
110
111 QuicDataTransport* quic_data_transport() { return &quic_data_transport_; }
112
113 private:
114 // Creates a fingerprint from a certificate.
115 rtc::SSLFingerprint* CreateFingerprint(rtc::RTCCertificate* cert) {
116 std::string digest_algorithm;
117 cert->ssl_certificate().GetSignatureDigestAlgorithm(&digest_algorithm);
118 rtc::scoped_ptr<rtc::SSLFingerprint> fingerprint(
119 rtc::SSLFingerprint::Create(digest_algorithm, cert->identity()));
120 return fingerprint.release();
121 }
122
123 QuicDataTransport quic_data_transport_;
124 FakeTransportChannel ice_transport_channel_;
125 QuicTransportChannel quic_transport_channel_;
126 rtc::scoped_ptr<rtc::SSLFingerprint> local_fingerprint_;
127 };
128
129 class QuicDataTransportTest : public testing::Test {
130 public:
131 QuicDataTransportTest() {}
132
133 void ConnectTransportChannels() {
134 SetCryptoParameters();
135 peer1_.Connect(&peer2_);
136 ASSERT_TRUE_WAIT(peer1_.quic_transport_channel()->writable() &&
137 peer2_.quic_transport_channel()->writable(),
138 kTimeoutMs);
139 }
140
141 void SetTransportChannels() {
142 ASSERT_TRUE(peer1_.quic_data_transport()->SetTransportChannel(
143 peer1_.quic_transport_channel()));
144 ASSERT_TRUE(peer2_.quic_data_transport()->SetTransportChannel(
145 peer2_.quic_transport_channel()));
146 }
147
148 // Sets crypto parameters required for the QUIC handshake.
149 void SetCryptoParameters() {
150 peer1_.GenerateCertificateAndFingerprint();
151 peer2_.GenerateCertificateAndFingerprint();
152
153 peer1_.quic_transport_channel()->SetSslRole(rtc::SSL_CLIENT);
154 peer2_.quic_transport_channel()->SetSslRole(rtc::SSL_SERVER);
155
156 rtc::scoped_ptr<rtc::SSLFingerprint>& peer1_fingerprint =
157 peer1_.local_fingerprint();
158 rtc::scoped_ptr<rtc::SSLFingerprint>& peer2_fingerprint =
159 peer2_.local_fingerprint();
160
161 peer1_.quic_transport_channel()->SetRemoteFingerprint(
162 peer2_fingerprint->algorithm,
163 reinterpret_cast<const uint8_t*>(peer2_fingerprint->digest.data()),
164 peer2_fingerprint->digest.size());
165 peer2_.quic_transport_channel()->SetRemoteFingerprint(
166 peer1_fingerprint->algorithm,
167 reinterpret_cast<const uint8_t*>(peer1_fingerprint->digest.data()),
168 peer1_fingerprint->digest.size());
169 }
170
171 protected:
172 QuicDataTransportPeer peer1_;
173 QuicDataTransportPeer peer2_;
174 };
175
176 // Tests creation and destruction of data channels.
177 TEST_F(QuicDataTransportTest, CreateAndDestroyDataChannels) {
178 QuicDataTransport* quic_data_transport = peer2_.quic_data_transport();
179 EXPECT_FALSE(quic_data_transport->HasDataChannels());
180 for (int data_channel_id = 0; data_channel_id < 5; ++data_channel_id) {
181 EXPECT_FALSE(quic_data_transport->HasDataChannel(data_channel_id));
182 webrtc::DataChannelInit config;
183 config.id = data_channel_id;
184 rtc::scoped_refptr<DataChannelInterface> data_channel =
185 peer2_.CreateDataChannel(&config);
186 EXPECT_NE(nullptr, data_channel);
187 EXPECT_EQ(data_channel_id, data_channel->id());
188 EXPECT_TRUE(quic_data_transport->HasDataChannel(data_channel_id));
189 }
190 EXPECT_TRUE(quic_data_transport->HasDataChannels());
191 for (int data_channel_id = 0; data_channel_id < 5; ++data_channel_id) {
192 quic_data_transport->DestroyDataChannel(data_channel_id);
193 EXPECT_FALSE(quic_data_transport->HasDataChannel(data_channel_id));
194 }
195 EXPECT_FALSE(quic_data_transport->HasDataChannels());
196 }
197
198 // Tests that the QuicDataTransport does not allow creating multiple
199 // QuicDataChannels with the same id.
200 TEST_F(QuicDataTransportTest, CannotCreateDataChannelsWithSameId) {
201 webrtc::DataChannelInit config;
202 config.id = 2;
203 EXPECT_NE(nullptr, peer2_.CreateDataChannel(&config));
204 EXPECT_EQ(nullptr, peer2_.CreateDataChannel(&config));
205 }
206
207 // Tests that any data channels created by the QuicDataTransport are in state
208 // kConnecting before the QuicTransportChannel is set, then transiton to state
209 // kOpen when the transport channel becomes writable.
210 TEST_F(QuicDataTransportTest, DataChannelsOpenWhenTransportChannelWritable) {
211 webrtc::DataChannelInit config1;
212 config1.id = 7;
213 rtc::scoped_refptr<DataChannelInterface> data_channel1 =
214 peer2_.CreateDataChannel(&config1);
215 EXPECT_EQ(webrtc::DataChannelInterface::kConnecting, data_channel1->state());
216 SetTransportChannels();
217 EXPECT_EQ(webrtc::DataChannelInterface::kConnecting, data_channel1->state());
218 webrtc::DataChannelInit config2;
219 config2.id = 14;
220 rtc::scoped_refptr<DataChannelInterface> data_channel2 =
221 peer2_.CreateDataChannel(&config2);
222 EXPECT_EQ(webrtc::DataChannelInterface::kConnecting, data_channel2->state());
223 // Existing data channels should open once the transport channel is writable.
224 ConnectTransportChannels();
225 EXPECT_EQ_WAIT(webrtc::DataChannelInterface::kOpen, data_channel1->state(),
226 kTimeoutMs);
227 EXPECT_EQ_WAIT(webrtc::DataChannelInterface::kOpen, data_channel2->state(),
228 kTimeoutMs);
229 // Any data channels created afterwards should start in state kOpen.
230 webrtc::DataChannelInit config3;
231 config3.id = 21;
232 rtc::scoped_refptr<DataChannelInterface> data_channel3 =
233 peer2_.CreateDataChannel(&config3);
234 EXPECT_EQ(webrtc::DataChannelInterface::kOpen, data_channel3->state());
235 }
236
237 // Tests that the QuicTransport dispatches messages for one QuicDataChannel.
238 TEST_F(QuicDataTransportTest, ReceiveMessagesForSingleDataChannel) {
239 ConnectTransportChannels();
240 SetTransportChannels();
241
242 int data_channel_id = 1337;
243 webrtc::DataChannelInit config;
244 config.id = data_channel_id;
245 rtc::scoped_refptr<DataChannelInterface> peer2_data_channel =
246 peer2_.CreateDataChannel(&config);
247 FakeObserver observer;
248 peer2_data_channel->RegisterObserver(&observer);
249
250 uint64_t message1_id = 26u;
251 peer1_.WriteMessage(data_channel_id, message1_id, "Testing");
252 ASSERT_EQ_WAIT(1, observer.messages_received(), kTimeoutMs);
253 EXPECT_EQ("Testing", observer.messages()[0]);
254
255 uint64_t message2_id = 402u;
256 peer1_.WriteMessage(data_channel_id, message2_id, "Hello, World!");
257 ASSERT_EQ_WAIT(2, observer.messages_received(), kTimeoutMs);
258 EXPECT_EQ("Hello, World!", observer.messages()[1]);
259
260 uint64_t message3_id = 100260415u;
261 peer1_.WriteMessage(data_channel_id, message3_id, "Third message");
262 ASSERT_EQ_WAIT(3, observer.messages_received(), kTimeoutMs);
263 EXPECT_EQ("Third message", observer.messages()[2]);
264 }
265
266 // Tests that the QuicTransport dispatches messages to the correct data channel
267 // when multiple are in use.
268 TEST_F(QuicDataTransportTest, ReceiveMessagesForMultipleDataChannels) {
269 ConnectTransportChannels();
270 SetTransportChannels();
271
272 std::vector<rtc::scoped_refptr<DataChannelInterface>> data_channels;
273 for (int data_channel_id = 0; data_channel_id < 5; ++data_channel_id) {
274 webrtc::DataChannelInit config;
275 config.id = data_channel_id;
276 data_channels.push_back(peer2_.CreateDataChannel(&config));
277 }
278
279 for (int data_channel_id = 0; data_channel_id < 5; ++data_channel_id) {
280 uint64_t message1_id = 48023u;
281 FakeObserver observer;
282 DataChannelInterface* peer2_data_channel =
283 data_channels[data_channel_id].get();
284 peer2_data_channel->RegisterObserver(&observer);
285 peer1_.WriteMessage(data_channel_id, message1_id, "Testing");
286 ASSERT_EQ_WAIT(1, observer.messages_received(), kTimeoutMs);
287 EXPECT_EQ("Testing", observer.messages()[0]);
288
289 uint64_t message2_id = 1372643095u;
290 peer1_.WriteMessage(data_channel_id, message2_id, "Hello, World!");
291 ASSERT_EQ_WAIT(2, observer.messages_received(), kTimeoutMs);
292 EXPECT_EQ("Hello, World!", observer.messages()[1]);
293 }
294 }
295
296 // Tests end-to-end that both peers can use multiple QuicDataChannels to
297 // send/receive messages using a QuicDataTransport.
298 TEST_F(QuicDataTransportTest, EndToEndSendReceiveMessages) {
299 ConnectTransportChannels();
300 SetTransportChannels();
301
302 std::vector<rtc::scoped_refptr<DataChannelInterface>> peer1_data_channels;
303 std::vector<rtc::scoped_refptr<DataChannelInterface>> peer2_data_channels;
304
305 for (int data_channel_id = 0; data_channel_id < 5; ++data_channel_id) {
306 webrtc::DataChannelInit config;
307 config.id = data_channel_id;
308 peer1_data_channels.push_back(peer1_.CreateDataChannel(&config));
309 peer2_data_channels.push_back(peer2_.CreateDataChannel(&config));
310 }
311
312 for (int data_channel_id = 0; data_channel_id < 5; ++data_channel_id) {
313 DataChannelInterface* peer1_data_channel =
314 peer1_data_channels[data_channel_id].get();
315 FakeObserver observer1;
316 peer1_data_channel->RegisterObserver(&observer1);
317 DataChannelInterface* peer2_data_channel =
318 peer2_data_channels[data_channel_id].get();
319 FakeObserver observer2;
320 peer2_data_channel->RegisterObserver(&observer2);
321
322 peer1_data_channel->Send(webrtc::DataBuffer("Peer 1 message 1"));
323 ASSERT_EQ_WAIT(1, observer2.messages_received(), kTimeoutMs);
324 EXPECT_EQ("Peer 1 message 1", observer2.messages()[0]);
325
326 peer1_data_channel->Send(webrtc::DataBuffer("Peer 1 message 2"));
327 ASSERT_EQ_WAIT(2, observer2.messages_received(), kTimeoutMs);
328 EXPECT_EQ("Peer 1 message 2", observer2.messages()[1]);
329
330 peer2_data_channel->Send(webrtc::DataBuffer("Peer 2 message 1"));
331 ASSERT_EQ_WAIT(1, observer1.messages_received(), kTimeoutMs);
332 EXPECT_EQ("Peer 2 message 1", observer1.messages()[0]);
333
334 peer2_data_channel->Send(webrtc::DataBuffer("Peer 2 message 2"));
335 ASSERT_EQ_WAIT(2, observer1.messages_received(), kTimeoutMs);
336 EXPECT_EQ("Peer 2 message 2", observer1.messages()[1]);
337 }
338 }
339
340 // Tests that SetTransportChannel returns false when setting a NULL transport
341 // channel or a transport channel that is not equivalent to the one already set.
342 TEST_F(QuicDataTransportTest, SetTransportChannelReturnValue) {
343 QuicDataTransport* quic_data_transport = peer1_.quic_data_transport();
344 EXPECT_FALSE(quic_data_transport->SetTransportChannel(nullptr));
345 QuicTransportChannel* transport_channel = peer1_.quic_transport_channel();
346 EXPECT_TRUE(quic_data_transport->SetTransportChannel(transport_channel));
347 EXPECT_TRUE(quic_data_transport->SetTransportChannel(transport_channel));
348 QuicTransportChannel* other_transport_channel =
349 peer2_.quic_transport_channel();
350 EXPECT_FALSE(
351 quic_data_transport->SetTransportChannel(other_transport_channel));
352 }
353
354 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698