|
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* vim: set ts=2 et sw=2 tw=80: */ |
|
3 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file, |
|
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
6 |
|
7 // Original author: ekr@rtfm.com |
|
8 |
|
9 #include <iostream> |
|
10 #include <string> |
|
11 #include <map> |
|
12 |
|
13 #include "sigslot.h" |
|
14 |
|
15 #include "logging.h" |
|
16 #include "nspr.h" |
|
17 #include "nss.h" |
|
18 #include "ssl.h" |
|
19 |
|
20 #include "nsThreadUtils.h" |
|
21 #include "nsXPCOM.h" |
|
22 |
|
23 #include "dtlsidentity.h" |
|
24 #include "nricectx.h" |
|
25 #include "nricemediastream.h" |
|
26 #include "transportflow.h" |
|
27 #include "transportlayer.h" |
|
28 #include "transportlayerdtls.h" |
|
29 #include "transportlayerice.h" |
|
30 #include "transportlayerlog.h" |
|
31 #include "transportlayerloopback.h" |
|
32 |
|
33 #include "mtransport_test_utils.h" |
|
34 #include "runnable_utils.h" |
|
35 |
|
36 #define GTEST_HAS_RTTI 0 |
|
37 #include "gtest/gtest.h" |
|
38 #include "gtest_utils.h" |
|
39 |
|
40 using namespace mozilla; |
|
41 MOZ_MTLOG_MODULE("mtransport") |
|
42 |
|
43 MtransportTestUtils *test_utils; |
|
44 |
|
45 // Layer class which can't be initialized. |
|
46 class TransportLayerDummy : public TransportLayer { |
|
47 public: |
|
48 TransportLayerDummy(bool allow_init, bool *destroyed) |
|
49 : allow_init_(allow_init), |
|
50 destroyed_(destroyed) { |
|
51 *destroyed_ = false; |
|
52 } |
|
53 |
|
54 virtual ~TransportLayerDummy() { |
|
55 *destroyed_ = true; |
|
56 } |
|
57 |
|
58 virtual nsresult InitInternal() { |
|
59 return allow_init_ ? NS_OK : NS_ERROR_FAILURE; |
|
60 } |
|
61 |
|
62 virtual TransportResult SendPacket(const unsigned char *data, size_t len) { |
|
63 MOZ_CRASH(); // Should never be called. |
|
64 return 0; |
|
65 } |
|
66 |
|
67 TRANSPORT_LAYER_ID("lossy") |
|
68 |
|
69 private: |
|
70 bool allow_init_; |
|
71 bool *destroyed_; |
|
72 }; |
|
73 |
|
74 // Class to simulate various kinds of network lossage |
|
75 class TransportLayerLossy : public TransportLayer { |
|
76 public: |
|
77 TransportLayerLossy() : loss_mask_(0), packet_(0) {} |
|
78 ~TransportLayerLossy () {} |
|
79 |
|
80 virtual TransportResult SendPacket(const unsigned char *data, size_t len) { |
|
81 MOZ_MTLOG(ML_NOTICE, LAYER_INFO << "SendPacket(" << len << ")"); |
|
82 |
|
83 if (loss_mask_ & (1 << (packet_ % 32))) { |
|
84 MOZ_MTLOG(ML_NOTICE, "Dropping packet"); |
|
85 ++packet_; |
|
86 return len; |
|
87 } |
|
88 |
|
89 ++packet_; |
|
90 |
|
91 return downward_->SendPacket(data, len); |
|
92 } |
|
93 |
|
94 void SetLoss(uint32_t packet) { |
|
95 loss_mask_ |= (1 << (packet & 32)); |
|
96 } |
|
97 |
|
98 void StateChange(TransportLayer *layer, State state) { |
|
99 TL_SET_STATE(state); |
|
100 } |
|
101 |
|
102 void PacketReceived(TransportLayer *layer, const unsigned char *data, |
|
103 size_t len) { |
|
104 SignalPacketReceived(this, data, len); |
|
105 } |
|
106 |
|
107 TRANSPORT_LAYER_ID("lossy") |
|
108 |
|
109 protected: |
|
110 virtual void WasInserted() { |
|
111 downward_->SignalPacketReceived. |
|
112 connect(this, |
|
113 &TransportLayerLossy::PacketReceived); |
|
114 downward_->SignalStateChange. |
|
115 connect(this, |
|
116 &TransportLayerLossy::StateChange); |
|
117 |
|
118 TL_SET_STATE(downward_->state()); |
|
119 } |
|
120 |
|
121 private: |
|
122 uint32_t loss_mask_; |
|
123 uint32_t packet_; |
|
124 }; |
|
125 |
|
126 namespace { |
|
127 class TransportTestPeer : public sigslot::has_slots<> { |
|
128 public: |
|
129 TransportTestPeer(nsCOMPtr<nsIEventTarget> target, std::string name) |
|
130 : name_(name), target_(target), |
|
131 received_(0), flow_(new TransportFlow(name)), |
|
132 loopback_(new TransportLayerLoopback()), |
|
133 logging_(new TransportLayerLogging()), |
|
134 lossy_(new TransportLayerLossy()), |
|
135 dtls_(new TransportLayerDtls()), |
|
136 identity_(DtlsIdentity::Generate()), |
|
137 ice_ctx_(NrIceCtx::Create(name, |
|
138 name == "P2" ? |
|
139 TransportLayerDtls::CLIENT : |
|
140 TransportLayerDtls::SERVER)), |
|
141 streams_(), candidates_(), |
|
142 peer_(nullptr), |
|
143 gathering_complete_(false) |
|
144 { |
|
145 std::vector<NrIceStunServer> stun_servers; |
|
146 ScopedDeletePtr<NrIceStunServer> server(NrIceStunServer::Create( |
|
147 std::string((char *)"216.93.246.14"), 3478)); |
|
148 stun_servers.push_back(*server); |
|
149 EXPECT_TRUE(NS_SUCCEEDED(ice_ctx_->SetStunServers(stun_servers))); |
|
150 |
|
151 dtls_->SetIdentity(identity_); |
|
152 dtls_->SetRole(name == "P2" ? |
|
153 TransportLayerDtls::CLIENT : |
|
154 TransportLayerDtls::SERVER); |
|
155 |
|
156 nsresult res = identity_->ComputeFingerprint("sha-1", |
|
157 fingerprint_, |
|
158 sizeof(fingerprint_), |
|
159 &fingerprint_len_); |
|
160 EXPECT_TRUE(NS_SUCCEEDED(res)); |
|
161 EXPECT_EQ(20u, fingerprint_len_); |
|
162 } |
|
163 |
|
164 ~TransportTestPeer() { |
|
165 test_utils->sts_target()->Dispatch( |
|
166 WrapRunnable(this, &TransportTestPeer::DestroyFlow), |
|
167 NS_DISPATCH_SYNC); |
|
168 } |
|
169 |
|
170 |
|
171 void DestroyFlow() { |
|
172 if (flow_) { |
|
173 loopback_->Disconnect(); |
|
174 flow_ = nullptr; |
|
175 } |
|
176 ice_ctx_ = nullptr; |
|
177 } |
|
178 |
|
179 void DisconnectDestroyFlow() { |
|
180 loopback_->Disconnect(); |
|
181 disconnect_all(); // Disconnect from the signals; |
|
182 flow_ = nullptr; |
|
183 } |
|
184 |
|
185 void SetDtlsAllowAll() { |
|
186 nsresult res = dtls_->SetVerificationAllowAll(); |
|
187 ASSERT_TRUE(NS_SUCCEEDED(res)); |
|
188 } |
|
189 |
|
190 void SetDtlsPeer(TransportTestPeer *peer, int digests, unsigned int damage) { |
|
191 unsigned int mask = 1; |
|
192 |
|
193 for (int i=0; i<digests; i++) { |
|
194 unsigned char fingerprint_to_set[TransportLayerDtls::kMaxDigestLength]; |
|
195 |
|
196 memcpy(fingerprint_to_set, |
|
197 peer->fingerprint_, |
|
198 peer->fingerprint_len_); |
|
199 if (damage & mask) |
|
200 fingerprint_to_set[0]++; |
|
201 |
|
202 nsresult res = dtls_->SetVerificationDigest( |
|
203 "sha-1", |
|
204 fingerprint_to_set, |
|
205 peer->fingerprint_len_); |
|
206 |
|
207 ASSERT_TRUE(NS_SUCCEEDED(res)); |
|
208 |
|
209 mask <<= 1; |
|
210 } |
|
211 } |
|
212 |
|
213 |
|
214 void ConnectSocket_s(TransportTestPeer *peer) { |
|
215 nsresult res; |
|
216 res = loopback_->Init(); |
|
217 ASSERT_EQ((nsresult)NS_OK, res); |
|
218 |
|
219 loopback_->Connect(peer->loopback_); |
|
220 |
|
221 ASSERT_EQ((nsresult)NS_OK, flow_->PushLayer(loopback_)); |
|
222 ASSERT_EQ((nsresult)NS_OK, flow_->PushLayer(logging_)); |
|
223 ASSERT_EQ((nsresult)NS_OK, flow_->PushLayer(lossy_)); |
|
224 ASSERT_EQ((nsresult)NS_OK, flow_->PushLayer(dtls_)); |
|
225 |
|
226 flow_->SignalPacketReceived.connect(this, &TransportTestPeer::PacketReceived); |
|
227 } |
|
228 |
|
229 void ConnectSocket(TransportTestPeer *peer) { |
|
230 RUN_ON_THREAD(test_utils->sts_target(), |
|
231 WrapRunnable(this, & TransportTestPeer::ConnectSocket_s, |
|
232 peer), |
|
233 NS_DISPATCH_SYNC); |
|
234 } |
|
235 |
|
236 void InitIce() { |
|
237 nsresult res; |
|
238 |
|
239 // Attach our slots |
|
240 ice_ctx_->SignalGatheringStateChange. |
|
241 connect(this, &TransportTestPeer::GatheringStateChange); |
|
242 |
|
243 char name[100]; |
|
244 snprintf(name, sizeof(name), "%s:stream%d", name_.c_str(), |
|
245 (int)streams_.size()); |
|
246 |
|
247 // Create the media stream |
|
248 mozilla::RefPtr<NrIceMediaStream> stream = |
|
249 ice_ctx_->CreateStream(static_cast<char *>(name), 1); |
|
250 ASSERT_TRUE(stream != nullptr); |
|
251 streams_.push_back(stream); |
|
252 |
|
253 // Listen for candidates |
|
254 stream->SignalCandidate. |
|
255 connect(this, &TransportTestPeer::GotCandidate); |
|
256 |
|
257 // Create the transport layer |
|
258 ice_ = new TransportLayerIce(name, ice_ctx_, stream, 1); |
|
259 |
|
260 // Assemble the stack |
|
261 nsAutoPtr<std::queue<mozilla::TransportLayer *> > layers( |
|
262 new std::queue<mozilla::TransportLayer *>); |
|
263 layers->push(ice_); |
|
264 layers->push(dtls_); |
|
265 |
|
266 test_utils->sts_target()->Dispatch( |
|
267 WrapRunnableRet(flow_, &TransportFlow::PushLayers, layers, &res), |
|
268 NS_DISPATCH_SYNC); |
|
269 |
|
270 ASSERT_EQ((nsresult)NS_OK, res); |
|
271 |
|
272 // Listen for media events |
|
273 flow_->SignalPacketReceived.connect(this, &TransportTestPeer::PacketReceived); |
|
274 flow_->SignalStateChange.connect(this, &TransportTestPeer::StateChanged); |
|
275 |
|
276 // Start gathering |
|
277 test_utils->sts_target()->Dispatch( |
|
278 WrapRunnableRet(ice_ctx_, &NrIceCtx::StartGathering, &res), |
|
279 NS_DISPATCH_SYNC); |
|
280 ASSERT_TRUE(NS_SUCCEEDED(res)); |
|
281 } |
|
282 |
|
283 void ConnectIce(TransportTestPeer *peer) { |
|
284 peer_ = peer; |
|
285 |
|
286 // If gathering is already complete, push the candidates over |
|
287 if (gathering_complete_) |
|
288 GatheringComplete(); |
|
289 } |
|
290 |
|
291 // New candidate |
|
292 void GotCandidate(NrIceMediaStream *stream, const std::string &candidate) { |
|
293 std::cerr << "Got candidate " << candidate << std::endl; |
|
294 candidates_[stream->name()].push_back(candidate); |
|
295 } |
|
296 |
|
297 void GatheringStateChange(NrIceCtx* ctx, |
|
298 NrIceCtx::GatheringState state) { |
|
299 (void)ctx; |
|
300 if (state == NrIceCtx::ICE_CTX_GATHER_COMPLETE) { |
|
301 GatheringComplete(); |
|
302 } |
|
303 } |
|
304 |
|
305 // Gathering complete, so send our candidates and start |
|
306 // connecting on the other peer. |
|
307 void GatheringComplete() { |
|
308 nsresult res; |
|
309 |
|
310 // Don't send to the other side |
|
311 if (!peer_) { |
|
312 gathering_complete_ = true; |
|
313 return; |
|
314 } |
|
315 |
|
316 // First send attributes |
|
317 test_utils->sts_target()->Dispatch( |
|
318 WrapRunnableRet(peer_->ice_ctx_, |
|
319 &NrIceCtx::ParseGlobalAttributes, |
|
320 ice_ctx_->GetGlobalAttributes(), &res), |
|
321 NS_DISPATCH_SYNC); |
|
322 ASSERT_TRUE(NS_SUCCEEDED(res)); |
|
323 |
|
324 for (size_t i=0; i<streams_.size(); ++i) { |
|
325 test_utils->sts_target()->Dispatch( |
|
326 WrapRunnableRet(peer_->streams_[i], &NrIceMediaStream::ParseAttributes, |
|
327 candidates_[streams_[i]->name()], &res), NS_DISPATCH_SYNC); |
|
328 |
|
329 ASSERT_TRUE(NS_SUCCEEDED(res)); |
|
330 } |
|
331 |
|
332 // Start checks on the other peer. |
|
333 test_utils->sts_target()->Dispatch( |
|
334 WrapRunnableRet(peer_->ice_ctx_, &NrIceCtx::StartChecks, &res), |
|
335 NS_DISPATCH_SYNC); |
|
336 ASSERT_TRUE(NS_SUCCEEDED(res)); |
|
337 } |
|
338 |
|
339 TransportResult SendPacket(const unsigned char* data, size_t len) { |
|
340 TransportResult ret; |
|
341 test_utils->sts_target()->Dispatch( |
|
342 WrapRunnableRet(flow_, &TransportFlow::SendPacket, data, len, &ret), |
|
343 NS_DISPATCH_SYNC); |
|
344 |
|
345 return ret; |
|
346 } |
|
347 |
|
348 |
|
349 void StateChanged(TransportFlow *flow, TransportLayer::State state) { |
|
350 if (state == TransportLayer::TS_OPEN) { |
|
351 std::cerr << "Now connected" << std::endl; |
|
352 } |
|
353 } |
|
354 |
|
355 void PacketReceived(TransportFlow * flow, const unsigned char* data, |
|
356 size_t len) { |
|
357 std::cerr << "Received " << len << " bytes" << std::endl; |
|
358 ++received_; |
|
359 } |
|
360 |
|
361 void SetLoss(uint32_t loss) { |
|
362 lossy_->SetLoss(loss); |
|
363 } |
|
364 |
|
365 TransportLayer::State state() { |
|
366 TransportLayer::State tstate; |
|
367 |
|
368 RUN_ON_THREAD(test_utils->sts_target(), |
|
369 WrapRunnableRet(flow_, &TransportFlow::state, &tstate), |
|
370 NS_DISPATCH_SYNC); |
|
371 |
|
372 return tstate; |
|
373 } |
|
374 |
|
375 bool connected() { |
|
376 return state() == TransportLayer::TS_OPEN; |
|
377 } |
|
378 |
|
379 bool failed() { |
|
380 return state() == TransportLayer::TS_ERROR; |
|
381 } |
|
382 |
|
383 size_t received() { return received_; } |
|
384 |
|
385 private: |
|
386 std::string name_; |
|
387 nsCOMPtr<nsIEventTarget> target_; |
|
388 size_t received_; |
|
389 mozilla::RefPtr<TransportFlow> flow_; |
|
390 TransportLayerLoopback *loopback_; |
|
391 TransportLayerLogging *logging_; |
|
392 TransportLayerLossy *lossy_; |
|
393 TransportLayerDtls *dtls_; |
|
394 TransportLayerIce *ice_; |
|
395 mozilla::RefPtr<DtlsIdentity> identity_; |
|
396 mozilla::RefPtr<NrIceCtx> ice_ctx_; |
|
397 std::vector<mozilla::RefPtr<NrIceMediaStream> > streams_; |
|
398 std::map<std::string, std::vector<std::string> > candidates_; |
|
399 TransportTestPeer *peer_; |
|
400 bool gathering_complete_; |
|
401 unsigned char fingerprint_[TransportLayerDtls::kMaxDigestLength]; |
|
402 size_t fingerprint_len_; |
|
403 }; |
|
404 |
|
405 |
|
406 class TransportTest : public ::testing::Test { |
|
407 public: |
|
408 TransportTest() { |
|
409 fds_[0] = nullptr; |
|
410 fds_[1] = nullptr; |
|
411 } |
|
412 |
|
413 ~TransportTest() { |
|
414 delete p1_; |
|
415 delete p2_; |
|
416 |
|
417 // Can't detach these |
|
418 // PR_Close(fds_[0]); |
|
419 // PR_Close(fds_[1]); |
|
420 } |
|
421 |
|
422 void DestroyPeerFlows() { |
|
423 p1_->DisconnectDestroyFlow(); |
|
424 p2_->DisconnectDestroyFlow(); |
|
425 } |
|
426 |
|
427 void SetUp() { |
|
428 nsresult rv; |
|
429 target_ = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv); |
|
430 ASSERT_TRUE(NS_SUCCEEDED(rv)); |
|
431 |
|
432 p1_ = new TransportTestPeer(target_, "P1"); |
|
433 p2_ = new TransportTestPeer(target_, "P2"); |
|
434 } |
|
435 |
|
436 void SetDtlsPeer(int digests = 1, unsigned int damage = 0) { |
|
437 p1_->SetDtlsPeer(p2_, digests, damage); |
|
438 p2_->SetDtlsPeer(p1_, digests, damage); |
|
439 } |
|
440 |
|
441 void SetDtlsAllowAll() { |
|
442 p1_->SetDtlsAllowAll(); |
|
443 p2_->SetDtlsAllowAll(); |
|
444 } |
|
445 |
|
446 void ConnectSocket() { |
|
447 test_utils->sts_target()->Dispatch( |
|
448 WrapRunnable(p1_, &TransportTestPeer::ConnectSocket, p2_), |
|
449 NS_DISPATCH_SYNC); |
|
450 test_utils->sts_target()->Dispatch( |
|
451 WrapRunnable(p2_, &TransportTestPeer::ConnectSocket, p1_), |
|
452 NS_DISPATCH_SYNC); |
|
453 |
|
454 ASSERT_TRUE_WAIT(p1_->connected(), 10000); |
|
455 ASSERT_TRUE_WAIT(p2_->connected(), 10000); |
|
456 } |
|
457 |
|
458 void ConnectSocketExpectFail() { |
|
459 test_utils->sts_target()->Dispatch( |
|
460 WrapRunnable(p1_, &TransportTestPeer::ConnectSocket, p2_), |
|
461 NS_DISPATCH_SYNC); |
|
462 test_utils->sts_target()->Dispatch( |
|
463 WrapRunnable(p2_, &TransportTestPeer::ConnectSocket, p1_), |
|
464 NS_DISPATCH_SYNC); |
|
465 ASSERT_TRUE_WAIT(p1_->failed(), 10000); |
|
466 ASSERT_TRUE_WAIT(p2_->failed(), 10000); |
|
467 } |
|
468 |
|
469 void InitIce() { |
|
470 p1_->InitIce(); |
|
471 p2_->InitIce(); |
|
472 } |
|
473 |
|
474 void ConnectIce() { |
|
475 p1_->InitIce(); |
|
476 p2_->InitIce(); |
|
477 p1_->ConnectIce(p2_); |
|
478 p2_->ConnectIce(p1_); |
|
479 ASSERT_TRUE_WAIT(p1_->connected(), 10000); |
|
480 ASSERT_TRUE_WAIT(p2_->connected(), 10000); |
|
481 } |
|
482 |
|
483 void TransferTest(size_t count) { |
|
484 unsigned char buf[1000]; |
|
485 |
|
486 for (size_t i= 0; i<count; ++i) { |
|
487 memset(buf, count & 0xff, sizeof(buf)); |
|
488 TransportResult rv = p1_->SendPacket(buf, sizeof(buf)); |
|
489 ASSERT_TRUE(rv > 0); |
|
490 } |
|
491 |
|
492 std::cerr << "Received == " << p2_->received() << std::endl; |
|
493 ASSERT_TRUE_WAIT(count == p2_->received(), 10000); |
|
494 } |
|
495 |
|
496 protected: |
|
497 PRFileDesc *fds_[2]; |
|
498 TransportTestPeer *p1_; |
|
499 TransportTestPeer *p2_; |
|
500 nsCOMPtr<nsIEventTarget> target_; |
|
501 }; |
|
502 |
|
503 |
|
504 TEST_F(TransportTest, TestNoDtlsVerificationSettings) { |
|
505 ConnectSocketExpectFail(); |
|
506 } |
|
507 |
|
508 TEST_F(TransportTest, TestConnect) { |
|
509 SetDtlsPeer(); |
|
510 ConnectSocket(); |
|
511 } |
|
512 |
|
513 TEST_F(TransportTest, TestConnectDestroyFlowsMainThread) { |
|
514 SetDtlsPeer(); |
|
515 ConnectSocket(); |
|
516 DestroyPeerFlows(); |
|
517 } |
|
518 |
|
519 TEST_F(TransportTest, TestConnectAllowAll) { |
|
520 SetDtlsAllowAll(); |
|
521 ConnectSocket(); |
|
522 } |
|
523 |
|
524 TEST_F(TransportTest, TestConnectBadDigest) { |
|
525 SetDtlsPeer(1, 1); |
|
526 |
|
527 ConnectSocketExpectFail(); |
|
528 } |
|
529 |
|
530 TEST_F(TransportTest, TestConnectTwoDigests) { |
|
531 SetDtlsPeer(2, 0); |
|
532 |
|
533 ConnectSocket(); |
|
534 } |
|
535 |
|
536 TEST_F(TransportTest, TestConnectTwoDigestsFirstBad) { |
|
537 SetDtlsPeer(2, 1); |
|
538 |
|
539 ConnectSocketExpectFail(); |
|
540 } |
|
541 |
|
542 TEST_F(TransportTest, TestConnectTwoDigestsSecondBad) { |
|
543 SetDtlsPeer(2, 2); |
|
544 |
|
545 ConnectSocketExpectFail(); |
|
546 } |
|
547 |
|
548 TEST_F(TransportTest, TestConnectTwoDigestsBothBad) { |
|
549 SetDtlsPeer(2, 3); |
|
550 |
|
551 ConnectSocketExpectFail(); |
|
552 } |
|
553 |
|
554 TEST_F(TransportTest, TestTransfer) { |
|
555 SetDtlsPeer(); |
|
556 ConnectSocket(); |
|
557 TransferTest(1); |
|
558 } |
|
559 |
|
560 TEST_F(TransportTest, TestConnectLoseFirst) { |
|
561 SetDtlsPeer(); |
|
562 p1_->SetLoss(0); |
|
563 ConnectSocket(); |
|
564 TransferTest(1); |
|
565 } |
|
566 |
|
567 TEST_F(TransportTest, TestConnectIce) { |
|
568 SetDtlsPeer(); |
|
569 ConnectIce(); |
|
570 } |
|
571 |
|
572 TEST_F(TransportTest, TestTransferIce) { |
|
573 SetDtlsPeer(); |
|
574 ConnectIce(); |
|
575 TransferTest(1); |
|
576 } |
|
577 |
|
578 TEST(PushTests, LayerFail) { |
|
579 TransportFlow flow; |
|
580 nsresult rv; |
|
581 bool destroyed1, destroyed2; |
|
582 |
|
583 rv = flow.PushLayer(new TransportLayerDummy(true, &destroyed1)); |
|
584 ASSERT_TRUE(NS_SUCCEEDED(rv)); |
|
585 |
|
586 rv = flow.PushLayer(new TransportLayerDummy(false, &destroyed2)); |
|
587 ASSERT_TRUE(NS_FAILED(rv)); |
|
588 |
|
589 ASSERT_EQ(TransportLayer::TS_ERROR, flow.state()); |
|
590 ASSERT_EQ(true, destroyed1); |
|
591 ASSERT_EQ(true, destroyed2); |
|
592 |
|
593 rv = flow.PushLayer(new TransportLayerDummy(true, &destroyed1)); |
|
594 ASSERT_TRUE(NS_FAILED(rv)); |
|
595 ASSERT_EQ(true, destroyed1); |
|
596 } |
|
597 |
|
598 |
|
599 TEST(PushTests, LayersFail) { |
|
600 TransportFlow flow; |
|
601 nsresult rv; |
|
602 bool destroyed1, destroyed2, destroyed3; |
|
603 |
|
604 rv = flow.PushLayer(new TransportLayerDummy(true, &destroyed1)); |
|
605 ASSERT_TRUE(NS_SUCCEEDED(rv)); |
|
606 |
|
607 nsAutoPtr<std::queue<TransportLayer *> > layers( |
|
608 new std::queue<TransportLayer *>()); |
|
609 |
|
610 layers->push(new TransportLayerDummy(true, &destroyed2)); |
|
611 layers->push(new TransportLayerDummy(false, &destroyed3)); |
|
612 |
|
613 rv = flow.PushLayers(layers); |
|
614 ASSERT_TRUE(NS_FAILED(rv)); |
|
615 |
|
616 ASSERT_EQ(TransportLayer::TS_ERROR, flow.state()); |
|
617 ASSERT_EQ(true, destroyed1); |
|
618 ASSERT_EQ(true, destroyed2); |
|
619 ASSERT_EQ(true, destroyed3); |
|
620 |
|
621 layers = new std::queue<TransportLayer *>(); |
|
622 layers->push(new TransportLayerDummy(true, &destroyed2)); |
|
623 layers->push(new TransportLayerDummy(true, &destroyed3)); |
|
624 rv = flow.PushLayers(layers); |
|
625 |
|
626 ASSERT_TRUE(NS_FAILED(rv)); |
|
627 ASSERT_EQ(true, destroyed2); |
|
628 ASSERT_EQ(true, destroyed3); |
|
629 } |
|
630 |
|
631 } // end namespace |
|
632 |
|
633 int main(int argc, char **argv) |
|
634 { |
|
635 test_utils = new MtransportTestUtils(); |
|
636 |
|
637 NSS_NoDB_Init(nullptr); |
|
638 NSS_SetDomesticPolicy(); |
|
639 // Start the tests |
|
640 ::testing::InitGoogleTest(&argc, argv); |
|
641 |
|
642 int rv = RUN_ALL_TESTS(); |
|
643 delete test_utils; |
|
644 return rv; |
|
645 } |