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

Side by Side Diff: webrtc/p2p/quic/quictransportchannel_unittest.cc

Issue 1721673004: Create QuicTransportChannel (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Modify WritePacket() and respond to comments Created 4 years, 9 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
« no previous file with comments | « webrtc/p2p/quic/quictransportchannel.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/p2p/quic/quictransportchannel.h"
12
13 #include <set>
14 #include <string>
15 #include <vector>
16
17 #include "webrtc/base/common.h"
18 #include "webrtc/base/gunit.h"
19 #include "webrtc/base/scoped_ptr.h"
20 #include "webrtc/base/sslidentity.h"
21 #include "webrtc/p2p/base/faketransportcontroller.h"
22
23 using cricket::ConnectionRole;
24 using cricket::IceRole;
25 using cricket::QuicTransportChannel;
26 using cricket::TransportChannel;
27 using cricket::TransportDescription;
28
29 // Timeout in milliseconds for asynchronous operations in unit tests.
30 const int kTimeoutMs = 1000;
31
32 // Export keying material parameters.
33 const char kExporterLabel[] = "label";
34 const uint8_t kExporterContext[] = "context";
35 const size_t kExporterContextLength = sizeof(kExporterContext);
36 const size_t kOutputKeyLength = 20;
37
38 // Packet size for SRTP.
39 const size_t kPacketSize = 100;
40
41 // Indicates channel has no write error.
42 const int kNoWriteError = 0;
43
44 // ICE parameters.
45 const char kIceUfrag[] = "TESTICEUFRAG0001";
46 const char kIcePwd[] = "TESTICEPWD00000000000001";
47
48 // QUIC packet parameters.
49 const net::IPAddressNumber kIpAddress(net::kIPv4AddressSize, 0);
50 const net::IPEndPoint kIpEndpoint(kIpAddress, 0);
51
52 // Detects incoming RTP packets.
53 bool IsRtpLeadByte(uint8_t b) {
54 return (b & 0xC0) == 0x80;
55 }
56 // Detects incoming QUIC packets.
57 bool IsQuicLeadByte(uint8_t b) {
58 return (b & 0x80) == 0;
59 }
60
61 // Maps SSL role to ICE connection role. The peer with a client role is assumed
62 // to be the one who initiates the connection.
63 ConnectionRole SslRoleToConnectionRole(rtc::SSLRole ssl_role) {
64 return (ssl_role == rtc::SSL_CLIENT) ? cricket::CONNECTIONROLE_ACTIVE
65 : cricket::CONNECTIONROLE_PASSIVE;
66 }
67
68 // Allows cricket::FakeTransportChannel to simulate write blocked
69 // and write error states.
70 // TODO(mikescarlett): Add this functionality to cricket::FakeTransportChannel.
71 class FakeTransportChannel : public cricket::FakeTransportChannel {
72 public:
73 FakeTransportChannel(const std::string& name, int component)
74 : cricket::FakeTransportChannel(name, component), error_(kNoWriteError) {}
75 int GetError() override { return error_; }
76 void SetError(int error) { error_ = error; }
77 int SendPacket(const char* data,
78 size_t len,
79 const rtc::PacketOptions& options,
80 int flags) override {
81 if (error_ == kNoWriteError) {
82 return cricket::FakeTransportChannel::SendPacket(data, len, options,
83 flags);
84 }
85 return -1;
86 }
87
88 private:
89 int error_;
90 };
91
92 // Peer who establishes a handshake using a QuicTransportChannel, which wraps
93 // a FakeTransportChannel to simulate network connectivity and ICE negotiation.
94 class QuicTestPeer : public sigslot::has_slots<> {
95 public:
96 explicit QuicTestPeer(const std::string& name)
97 : name_(name),
98 bytes_sent_(0),
99 fake_channel_(name_, 0),
100 quic_channel_(&fake_channel_) {
101 quic_channel_.SignalReadPacket.connect(
102 this, &QuicTestPeer::OnTransportChannelReadPacket);
103 fake_channel_.SetAsync(true);
104 SetLocalCertificate();
105 }
106
107 // Connects |fake_channel_| to that of the other peer.
108 void Connect(QuicTestPeer* peer) {
109 fake_channel_.Connect();
110 peer->fake_channel_.Connect();
111 fake_channel_.SetDestination(&peer->fake_channel_);
112 }
113
114 // Disconnects |fake_channel_|.
115 void Disconnect() { fake_channel_.SetDestination(nullptr); }
116
117 // Simulates the fingerprint exchange and ICE parameter negotiation
118 // which is done before QUIC handshake is started. Peer certificates must be
119 // set first.
120 void NegotiateBeforeQuic(QuicTestPeer* peer,
121 IceRole ice_role,
122 rtc::SSLRole local_ssl_role,
123 rtc::SSLRole remote_ssl_role) {
pthatcher1 2016/03/01 22:46:52 Should this be called SetIceAndCryptoParameters?
mikescarlett 2016/03/02 02:34:19 I moved the crypto-related stuff outside and put I
124 rtc::scoped_refptr<rtc::RTCCertificate> local_cert =
125 quic_channel()->GetLocalCertificate();
126 ASSERT_TRUE(local_cert);
127 rtc::scoped_refptr<rtc::RTCCertificate> remote_cert =
128 peer->quic_channel()->GetLocalCertificate();
129 ASSERT_TRUE(remote_cert);
130 // Create fingerprints from certificates.
131 rtc::scoped_ptr<rtc::SSLFingerprint> local_fingerprint;
132 rtc::scoped_ptr<rtc::SSLFingerprint> remote_fingerprint;
133 local_fingerprint.reset(CreateFingerprint(local_cert.get()));
134 ASSERT_NE(local_fingerprint, nullptr);
135 remote_fingerprint.reset(CreateFingerprint(remote_cert.get()));
136 ASSERT_NE(remote_fingerprint, nullptr);
137 // Pass the ICE credentials to the underlying channel.
138 SetIceCredentials(ice_role, local_fingerprint.get(),
139 remote_fingerprint.get(), local_ssl_role,
140 remote_ssl_role);
141 // Set SSL and fingerprint parameters for QUIC channel.
142 quic_channel_.SetSslRole(local_ssl_role);
143 quic_channel_.SetRemoteFingerprint(
144 remote_fingerprint->algorithm,
145 reinterpret_cast<const uint8_t*>(remote_fingerprint->digest.data()),
146 remote_fingerprint->digest.size());
147 }
148
149 // Generates ICE credentials and passes them to |quic_channel_|.
150 void SetIceCredentials(IceRole ice_role,
pthatcher1 2016/03/01 22:46:52 Since this is only called once, I'd suggest just i
mikescarlett 2016/03/02 02:34:19 I merged them into SetIceParameters.
151 rtc::SSLFingerprint* local_fingerprint,
152 rtc::SSLFingerprint* remote_fingerprint,
153 rtc::SSLRole local_ssl_role,
154 rtc::SSLRole remote_ssl_role) {
155 quic_channel_.SetIceRole(ice_role);
156 quic_channel_.SetIceTiebreaker(
157 (ice_role == cricket::ICEROLE_CONTROLLING) ? 1 : 2);
158
159 ConnectionRole local_connection_role =
160 SslRoleToConnectionRole(local_ssl_role);
161 ConnectionRole remote_connection_role =
162 SslRoleToConnectionRole(remote_ssl_role);
163
164 TransportDescription local_desc(std::vector<std::string>(), kIceUfrag,
165 kIcePwd, cricket::ICEMODE_FULL,
166 local_connection_role, local_fingerprint);
167 TransportDescription remote_desc(
168 std::vector<std::string>(), kIceUfrag, kIcePwd, cricket::ICEMODE_FULL,
169 remote_connection_role, remote_fingerprint);
170
171 quic_channel_.SetIceCredentials(local_desc.ice_ufrag, local_desc.ice_pwd);
172 quic_channel_.SetRemoteIceCredentials(remote_desc.ice_ufrag,
173 remote_desc.ice_pwd);
174 }
175
176 // Sets certificate for |quic_channel_|.
177 void SetLocalCertificate() {
178 quic_channel_.SetLocalCertificate(
179 rtc::RTCCertificate::Create(rtc::scoped_ptr<rtc::SSLIdentity>(
180 rtc::SSLIdentity::Generate(name_, rtc::KT_DEFAULT))));
181 }
182
183 // Creates fingerprint from certificate.
184 rtc::SSLFingerprint* CreateFingerprint(rtc::RTCCertificate* cert) {
185 std::string digest_algorithm;
186 bool get_digest_algorithm =
187 cert->ssl_certificate().GetSignatureDigestAlgorithm(&digest_algorithm);
188 if (!get_digest_algorithm || digest_algorithm.empty()) {
189 return nullptr;
190 }
191 scoped_ptr<rtc::SSLFingerprint> fingerprint(
192 rtc::SSLFingerprint::Create(digest_algorithm, cert->identity()));
193 if (digest_algorithm != rtc::DIGEST_SHA_256) {
194 return nullptr;
195 }
196 return fingerprint.release();
197 }
198
199 // Send packets to the other peer via |quic_channel_|.
200 void SendPackets(size_t count, bool srtp, bool expect_success) {
pthatcher1 2016/03/01 22:46:52 This method is only called once, so it seems like
mikescarlett 2016/03/02 02:34:19 Done. Split this and moved asserts like you sugges
201 char packet[kPacketSize];
202 for (size_t sent = 0; sent < count; ++sent) {
203 // If |srtp| is true, make this packet look like SRTP.
204 packet[0] = (srtp) ? 0x80 : 0x00;
205 // Set the bypass flag if we're sending SRTP.
206 int flags = srtp ? cricket::PF_SRTP_BYPASS : 0;
207 rtc::PacketOptions packet_options;
208 int rv = quic_channel_.SendPacket(&packet[0], kPacketSize, packet_options,
209 flags);
210 if (rv > 0) {
211 ASSERT_TRUE(expect_success);
212 ASSERT_EQ(kPacketSize, static_cast<size_t>(rv));
213 bytes_sent_ += rv;
214 } else {
215 ASSERT_FALSE(expect_success);
216 ASSERT_EQ(-1, rv);
217 }
218 }
219 }
220
221 // Sends a non-SRTP packet with the PF_SRTP_BYPASS flag.
222 int SendInvalidSrtpPacket() {
pthatcher1 2016/03/01 22:46:52 Ah, well now it looks like you should have three m
mikescarlett 2016/03/02 02:34:19 Done.
223 char packet[kPacketSize];
224 // Fill the packet with 0 to form an invalid SRTP packet.
225 memset(packet, 0, kPacketSize);
226 rtc::PacketOptions packet_options;
227 return quic_channel_.SendPacket(&packet[0], kPacketSize, packet_options,
228 cricket::PF_SRTP_BYPASS);
229 }
230
231 net::WriteResult WriteQuicPacket(std::string packet) {
232 return quic_channel_.WritePacket(packet.data(), packet.size(), kIpAddress,
233 kIpEndpoint);
234 }
235
236 bool handshake_confirmed() const {
pthatcher1 2016/03/01 22:46:52 Would a more correct name be quic_connected()?
mikescarlett 2016/03/02 02:34:19 That's fine. Done.
237 return quic_channel_.quic_state() == cricket::QUIC_TRANSPORT_CONNECTED;
238 }
239
240 void ClearBytesSent() { bytes_sent_ = 0; }
241
242 void ClearBytesReceived() { bytes_received_ = 0; }
243
244 void SetWriteError(int error) { fake_channel_.SetError(error); }
245
246 size_t bytes_received() const { return bytes_received_; }
247
248 size_t bytes_sent() const { return bytes_sent_; }
249
250 FakeTransportChannel* fake_channel() { return &fake_channel_; }
pthatcher1 2016/03/01 22:46:52 I would call this ice_channel(), even though it's
mikescarlett 2016/03/02 02:34:19 Done.
251
252 QuicTransportChannel* quic_channel() { return &quic_channel_; }
253
254 private:
255 // QUIC channel callback.
256 void OnTransportChannelReadPacket(TransportChannel* channel,
257 const char* data,
258 size_t size,
259 const rtc::PacketTime& packet_time,
260 int flags) {
261 bytes_received_ += size;
262 // Only SRTP packets should have the bypass flag set.
263 int expected_flags = IsRtpLeadByte(data[0]) ? cricket::PF_SRTP_BYPASS : 0;
264 ASSERT_EQ(expected_flags, flags);
265 }
266
267 std::string name_; // Channel name.
268 size_t bytes_sent_; // Bytes sent by QUIC channel.
269 size_t bytes_received_; // Bytes received by fake channel.
270 FakeTransportChannel fake_channel_;
271 QuicTransportChannel quic_channel_;
272 };
273
274 class QuicTransportChannelTest : public testing::Test {
275 public:
276 QuicTransportChannelTest() : peer1_("P1"), peer2_("P2") {}
277
278 // Performs negotiation before QUIC handshake, then connects the fake
279 // transport channels of each peer. As a side effect, the QUIC channels
280 // start sending handshake messages.
281 void Connect(rtc::SSLRole peer1_ssl_role, rtc::SSLRole peer2_ssl_role) {
282 ASSERT_NE(peer1_ssl_role, peer2_ssl_role);
283 NegotiateBeforeQuic(peer1_ssl_role, peer2_ssl_role);
284 peer1_.Connect(&peer2_);
285 }
286
287 // By default, |peer1_| has client role and |peer2_| has server role in the
288 // QUIC handshake.
289 void Connect() { Connect(rtc::SSL_CLIENT, rtc::SSL_SERVER); }
290
291 // Disconnects the fake transport channels.
292 void Disconnect() {
293 peer1_.Disconnect();
294 peer2_.Disconnect();
295 }
296
297 // Sets up ICE parameters and exchanges fingerprints before QUIC handshake.
298 void NegotiateBeforeQuic(rtc::SSLRole peer1_ssl_role,
299 rtc::SSLRole peer2_ssl_role) {
300 peer1_.NegotiateBeforeQuic(&peer2_, cricket::ICEROLE_CONTROLLED,
301 peer1_ssl_role, peer2_ssl_role);
302 peer2_.NegotiateBeforeQuic(&peer1_, cricket::ICEROLE_CONTROLLING,
303 peer2_ssl_role, peer1_ssl_role);
304 }
pthatcher1 2016/03/01 22:46:52 You have 4 methods that basically do a given opera
mikescarlett 2016/03/02 02:34:19 I merged this into one method and will revisit whe
305
306 // Check whether |peer2_| receives packets sent by |peer1_|.
307 void TestTransfer(size_t count, bool srtp, bool expect_success) {
pthatcher1 2016/03/01 22:46:52 I'd suggest to just inline this code into the test
mikescarlett 2016/03/02 02:34:19 Inlined.
308 peer1_.ClearBytesSent();
309 peer2_.ClearBytesReceived();
310 peer1_.SendPackets(count, srtp, expect_success);
311
312 if (expect_success) {
313 size_t total_bytes = kPacketSize * count;
314 EXPECT_EQ_WAIT(total_bytes, peer2_.bytes_received(), kTimeoutMs);
315 EXPECT_EQ(total_bytes, peer1_.bytes_sent());
316 } else {
317 EXPECT_EQ(0u, peer1_.bytes_sent());
318 }
319 }
320
321 // Check that non-SRTP is not sent with the SRTP_BYPASS flag.
322 void TestTransferInvalidSrtp() {
323 peer1_.ClearBytesSent();
324 peer2_.ClearBytesReceived();
325 EXPECT_EQ(-1, peer1_.SendInvalidSrtpPacket());
326 EXPECT_EQ(0u, peer2_.bytes_received());
327 }
328
329 // Check that peers export identical keying material after the QUIC handshake.
330 void TestExportKeyingMaterial() {
pthatcher1 2016/03/01 22:46:52 Same here: Just put this in the test case.
mikescarlett 2016/03/02 02:34:19 Inlined.
331 uint8_t key1[kOutputKeyLength];
332 uint8_t key2[kOutputKeyLength];
333
334 bool from_success = peer1_.quic_channel()->ExportKeyingMaterial(
335 kExporterLabel, kExporterContext, kExporterContextLength, true, key1,
336 kOutputKeyLength);
337 ASSERT_TRUE(from_success);
338 bool to_success = peer2_.quic_channel()->ExportKeyingMaterial(
339 kExporterLabel, kExporterContext, kExporterContextLength, true, key2,
340 kOutputKeyLength);
341 ASSERT_TRUE(to_success);
342
343 EXPECT_EQ(0, memcmp(key1, key2, sizeof(key1)));
344 }
345
346 // Checks if QUIC handshake is done.
347 bool handshake_confirmed() const {
348 return peer1_.handshake_confirmed() && peer2_.handshake_confirmed();
349 }
350
351 // Checks if QUIC channels are writable.
352 bool quic_writable() {
353 return peer1_.quic_channel()->writable() &&
354 peer2_.quic_channel()->writable();
355 }
356
357 protected:
358 // QUIC peer with a client role, who initiates the QUIC handshake.
359 QuicTestPeer peer1_;
360 // QUIC peer with a server role, who responds to the client peer.
361 QuicTestPeer peer2_;
362 };
363
364 // Test that the QUIC channel passes down ICE parameters to the underlying ICE
365 // channel.
366 TEST_F(QuicTransportChannelTest, ChannelSetupIce) {
367 NegotiateBeforeQuic(rtc::SSL_CLIENT, rtc::SSL_SERVER);
368 FakeTransportChannel* channel1 = peer1_.fake_channel();
369 FakeTransportChannel* channel2 = peer2_.fake_channel();
370 EXPECT_EQ(cricket::ICEROLE_CONTROLLED, channel1->GetIceRole());
371 EXPECT_EQ(2u, channel1->IceTiebreaker());
372 EXPECT_EQ(kIceUfrag, channel1->ice_ufrag());
373 EXPECT_EQ(kIcePwd, channel1->ice_pwd());
374 EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel2->GetIceRole());
375 EXPECT_EQ(1u, channel2->IceTiebreaker());
376 }
377
378 // Test export keying material after QUIC handshake.
379 TEST_F(QuicTransportChannelTest, ExportKeyingMaterial) {
380 Connect();
381 ASSERT_TRUE_WAIT(handshake_confirmed(), kTimeoutMs);
382 TestExportKeyingMaterial();
383 }
384
385 // Test that QUIC channel is not writable before the QUIC handshake.
386 TEST_F(QuicTransportChannelTest, NotWritableBeforeHandshake) {
387 Connect();
388 EXPECT_FALSE(quic_writable());
389 Disconnect();
390 EXPECT_FALSE(quic_writable());
391 Connect();
392 EXPECT_FALSE(quic_writable());
393 }
394
395 // Test that once handshake begins, QUIC is not writable until its completion.
396 TEST_F(QuicTransportChannelTest, QuicHandshake) {
397 Connect();
398 EXPECT_FALSE(quic_writable());
399 ASSERT_TRUE_WAIT(handshake_confirmed(), kTimeoutMs);
400 EXPECT_TRUE(quic_writable());
401 }
402
403 // Non-SRTP data should not be sent using SendPacket(), regardless of QUIC
404 // channel state.
405 TEST_F(QuicTransportChannelTest, TransferNonSrtp) {
406 TestTransfer(1, false, false);
407 TestTransfer(1, true, false);
408 Connect();
409 TestTransfer(1, false, false);
410 ASSERT_TRUE_WAIT(handshake_confirmed(), kTimeoutMs);
411 TestTransfer(1, false, false);
412 }
413
414 // SRTP data should always be sent, regardless of QUIC channel state.
415 TEST_F(QuicTransportChannelTest, TransferSrtp) {
416 Connect();
417 TestTransfer(10, true, true);
418 ASSERT_TRUE_WAIT(handshake_confirmed(), kTimeoutMs);
419 TestTransfer(10, true, true);
420 }
421
422 // Test that invalid SRTP (non-SRTP data with
423 // PF_SRTP_BYPASS flag) fails to send with return value -1.
424 TEST_F(QuicTransportChannelTest, TransferInvalidSrtp) {
425 TestTransferInvalidSrtp();
426 Connect();
427 TestTransferInvalidSrtp();
428 }
429
430 // Test that QuicTransportChannel::WritePacket blocks when underlying channel
pthatcher1 2016/03/01 22:46:52 when underlying => when the underlying
mikescarlett 2016/03/02 02:34:19 Done.
431 // is not writable, and otherwise succeeds.
432 TEST_F(QuicTransportChannelTest, QuicWritePacket) {
433 peer1_.fake_channel()->Connect();
434 peer2_.fake_channel()->Connect();
435 peer1_.fake_channel()->SetDestination(peer2_.fake_channel());
436 std::string packet = "FAKEQUICPACKET";
437
438 // QUIC should be write blocked when the underlying channel is not writable.
439 peer1_.fake_channel()->SetWritable(false);
440 EXPECT_TRUE(peer1_.quic_channel()->IsWriteBlocked());
441 net::WriteResult write_blocked_result = peer1_.WriteQuicPacket(packet);
442 EXPECT_EQ(net::WRITE_STATUS_BLOCKED, write_blocked_result.status);
443 EXPECT_EQ(EWOULDBLOCK, write_blocked_result.error_code);
444
445 // QUIC should ignore errors when the underlying channel is writable.
446 peer1_.fake_channel()->SetWritable(true);
447 EXPECT_FALSE(peer1_.quic_channel()->IsWriteBlocked());
448 peer1_.SetWriteError(EWOULDBLOCK);
449 net::WriteResult ignore_error_result = peer1_.WriteQuicPacket(packet);
450 EXPECT_EQ(net::WRITE_STATUS_OK, ignore_error_result.status);
451 EXPECT_EQ(0, ignore_error_result.bytes_written);
452
453 peer1_.SetWriteError(kNoWriteError);
454 net::WriteResult no_error_result = peer1_.WriteQuicPacket(packet);
455 EXPECT_EQ(net::WRITE_STATUS_OK, no_error_result.status);
456 EXPECT_EQ(static_cast<int>(packet.size()), no_error_result.bytes_written);
457 }
458
459 // Test that SSL roles can be reversed before QUIC handshake.
460 TEST_F(QuicTransportChannelTest, QuicRoleReversalBeforeQuic) {
461 EXPECT_TRUE(peer1_.quic_channel()->SetSslRole(rtc::SSL_SERVER));
462 EXPECT_TRUE(peer1_.quic_channel()->SetSslRole(rtc::SSL_CLIENT));
463 EXPECT_TRUE(peer1_.quic_channel()->SetSslRole(rtc::SSL_SERVER));
464 }
465
466 // Test that SSL roles cannot be reversed after QUIC handshake. SetSslRole
467 // returns true if the current SSL role equals the proposed SSL role.
468 TEST_F(QuicTransportChannelTest, QuicRoleReversalAfterQuic) {
469 Connect();
470 ASSERT_TRUE_WAIT(handshake_confirmed(), kTimeoutMs);
471 EXPECT_FALSE(peer1_.quic_channel()->SetSslRole(rtc::SSL_SERVER));
472 EXPECT_TRUE(peer1_.quic_channel()->SetSslRole(rtc::SSL_CLIENT));
473 EXPECT_FALSE(peer2_.quic_channel()->SetSslRole(rtc::SSL_CLIENT));
474 EXPECT_TRUE(peer2_.quic_channel()->SetSslRole(rtc::SSL_SERVER));
475 }
476
477 // Set SSL role, then check that GetSslRole returns the same value.
478 TEST_F(QuicTransportChannelTest, SetGetSslRole) {
479 ASSERT_TRUE(peer1_.quic_channel()->SetSslRole(rtc::SSL_SERVER));
480 rtc::scoped_ptr<rtc::SSLRole> role(new rtc::SSLRole());
481 ASSERT_TRUE(peer1_.quic_channel()->GetSslRole(role.get()));
482 EXPECT_EQ(rtc::SSL_SERVER, *role);
483 }
484
485 // Test that after QUIC handshake is complete, QUIC handshake remains confirmed
486 // even if underlying channel reconnects.
487 TEST_F(QuicTransportChannelTest, HandshakeConfirmedAfterReconnect) {
488 Connect();
489 ASSERT_TRUE_WAIT(handshake_confirmed(), kTimeoutMs);
490 Disconnect();
491 EXPECT_TRUE(handshake_confirmed());
492 Connect();
493 EXPECT_TRUE(handshake_confirmed());
494 }
OLDNEW
« no previous file with comments | « webrtc/p2p/quic/quictransportchannel.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698