1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/mtransport/test/transport_unittests.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,645 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set ts=2 et sw=2 tw=80: */ 1.6 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this file, 1.8 + * You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +// Original author: ekr@rtfm.com 1.11 + 1.12 +#include <iostream> 1.13 +#include <string> 1.14 +#include <map> 1.15 + 1.16 +#include "sigslot.h" 1.17 + 1.18 +#include "logging.h" 1.19 +#include "nspr.h" 1.20 +#include "nss.h" 1.21 +#include "ssl.h" 1.22 + 1.23 +#include "nsThreadUtils.h" 1.24 +#include "nsXPCOM.h" 1.25 + 1.26 +#include "dtlsidentity.h" 1.27 +#include "nricectx.h" 1.28 +#include "nricemediastream.h" 1.29 +#include "transportflow.h" 1.30 +#include "transportlayer.h" 1.31 +#include "transportlayerdtls.h" 1.32 +#include "transportlayerice.h" 1.33 +#include "transportlayerlog.h" 1.34 +#include "transportlayerloopback.h" 1.35 + 1.36 +#include "mtransport_test_utils.h" 1.37 +#include "runnable_utils.h" 1.38 + 1.39 +#define GTEST_HAS_RTTI 0 1.40 +#include "gtest/gtest.h" 1.41 +#include "gtest_utils.h" 1.42 + 1.43 +using namespace mozilla; 1.44 +MOZ_MTLOG_MODULE("mtransport") 1.45 + 1.46 +MtransportTestUtils *test_utils; 1.47 + 1.48 +// Layer class which can't be initialized. 1.49 +class TransportLayerDummy : public TransportLayer { 1.50 + public: 1.51 + TransportLayerDummy(bool allow_init, bool *destroyed) 1.52 + : allow_init_(allow_init), 1.53 + destroyed_(destroyed) { 1.54 + *destroyed_ = false; 1.55 + } 1.56 + 1.57 + virtual ~TransportLayerDummy() { 1.58 + *destroyed_ = true; 1.59 + } 1.60 + 1.61 + virtual nsresult InitInternal() { 1.62 + return allow_init_ ? NS_OK : NS_ERROR_FAILURE; 1.63 + } 1.64 + 1.65 + virtual TransportResult SendPacket(const unsigned char *data, size_t len) { 1.66 + MOZ_CRASH(); // Should never be called. 1.67 + return 0; 1.68 + } 1.69 + 1.70 + TRANSPORT_LAYER_ID("lossy") 1.71 + 1.72 + private: 1.73 + bool allow_init_; 1.74 + bool *destroyed_; 1.75 +}; 1.76 + 1.77 +// Class to simulate various kinds of network lossage 1.78 +class TransportLayerLossy : public TransportLayer { 1.79 + public: 1.80 + TransportLayerLossy() : loss_mask_(0), packet_(0) {} 1.81 + ~TransportLayerLossy () {} 1.82 + 1.83 + virtual TransportResult SendPacket(const unsigned char *data, size_t len) { 1.84 + MOZ_MTLOG(ML_NOTICE, LAYER_INFO << "SendPacket(" << len << ")"); 1.85 + 1.86 + if (loss_mask_ & (1 << (packet_ % 32))) { 1.87 + MOZ_MTLOG(ML_NOTICE, "Dropping packet"); 1.88 + ++packet_; 1.89 + return len; 1.90 + } 1.91 + 1.92 + ++packet_; 1.93 + 1.94 + return downward_->SendPacket(data, len); 1.95 + } 1.96 + 1.97 + void SetLoss(uint32_t packet) { 1.98 + loss_mask_ |= (1 << (packet & 32)); 1.99 + } 1.100 + 1.101 + void StateChange(TransportLayer *layer, State state) { 1.102 + TL_SET_STATE(state); 1.103 + } 1.104 + 1.105 + void PacketReceived(TransportLayer *layer, const unsigned char *data, 1.106 + size_t len) { 1.107 + SignalPacketReceived(this, data, len); 1.108 + } 1.109 + 1.110 + TRANSPORT_LAYER_ID("lossy") 1.111 + 1.112 + protected: 1.113 + virtual void WasInserted() { 1.114 + downward_->SignalPacketReceived. 1.115 + connect(this, 1.116 + &TransportLayerLossy::PacketReceived); 1.117 + downward_->SignalStateChange. 1.118 + connect(this, 1.119 + &TransportLayerLossy::StateChange); 1.120 + 1.121 + TL_SET_STATE(downward_->state()); 1.122 + } 1.123 + 1.124 + private: 1.125 + uint32_t loss_mask_; 1.126 + uint32_t packet_; 1.127 +}; 1.128 + 1.129 +namespace { 1.130 +class TransportTestPeer : public sigslot::has_slots<> { 1.131 + public: 1.132 + TransportTestPeer(nsCOMPtr<nsIEventTarget> target, std::string name) 1.133 + : name_(name), target_(target), 1.134 + received_(0), flow_(new TransportFlow(name)), 1.135 + loopback_(new TransportLayerLoopback()), 1.136 + logging_(new TransportLayerLogging()), 1.137 + lossy_(new TransportLayerLossy()), 1.138 + dtls_(new TransportLayerDtls()), 1.139 + identity_(DtlsIdentity::Generate()), 1.140 + ice_ctx_(NrIceCtx::Create(name, 1.141 + name == "P2" ? 1.142 + TransportLayerDtls::CLIENT : 1.143 + TransportLayerDtls::SERVER)), 1.144 + streams_(), candidates_(), 1.145 + peer_(nullptr), 1.146 + gathering_complete_(false) 1.147 + { 1.148 + std::vector<NrIceStunServer> stun_servers; 1.149 + ScopedDeletePtr<NrIceStunServer> server(NrIceStunServer::Create( 1.150 + std::string((char *)"216.93.246.14"), 3478)); 1.151 + stun_servers.push_back(*server); 1.152 + EXPECT_TRUE(NS_SUCCEEDED(ice_ctx_->SetStunServers(stun_servers))); 1.153 + 1.154 + dtls_->SetIdentity(identity_); 1.155 + dtls_->SetRole(name == "P2" ? 1.156 + TransportLayerDtls::CLIENT : 1.157 + TransportLayerDtls::SERVER); 1.158 + 1.159 + nsresult res = identity_->ComputeFingerprint("sha-1", 1.160 + fingerprint_, 1.161 + sizeof(fingerprint_), 1.162 + &fingerprint_len_); 1.163 + EXPECT_TRUE(NS_SUCCEEDED(res)); 1.164 + EXPECT_EQ(20u, fingerprint_len_); 1.165 + } 1.166 + 1.167 + ~TransportTestPeer() { 1.168 + test_utils->sts_target()->Dispatch( 1.169 + WrapRunnable(this, &TransportTestPeer::DestroyFlow), 1.170 + NS_DISPATCH_SYNC); 1.171 + } 1.172 + 1.173 + 1.174 + void DestroyFlow() { 1.175 + if (flow_) { 1.176 + loopback_->Disconnect(); 1.177 + flow_ = nullptr; 1.178 + } 1.179 + ice_ctx_ = nullptr; 1.180 + } 1.181 + 1.182 + void DisconnectDestroyFlow() { 1.183 + loopback_->Disconnect(); 1.184 + disconnect_all(); // Disconnect from the signals; 1.185 + flow_ = nullptr; 1.186 + } 1.187 + 1.188 + void SetDtlsAllowAll() { 1.189 + nsresult res = dtls_->SetVerificationAllowAll(); 1.190 + ASSERT_TRUE(NS_SUCCEEDED(res)); 1.191 + } 1.192 + 1.193 + void SetDtlsPeer(TransportTestPeer *peer, int digests, unsigned int damage) { 1.194 + unsigned int mask = 1; 1.195 + 1.196 + for (int i=0; i<digests; i++) { 1.197 + unsigned char fingerprint_to_set[TransportLayerDtls::kMaxDigestLength]; 1.198 + 1.199 + memcpy(fingerprint_to_set, 1.200 + peer->fingerprint_, 1.201 + peer->fingerprint_len_); 1.202 + if (damage & mask) 1.203 + fingerprint_to_set[0]++; 1.204 + 1.205 + nsresult res = dtls_->SetVerificationDigest( 1.206 + "sha-1", 1.207 + fingerprint_to_set, 1.208 + peer->fingerprint_len_); 1.209 + 1.210 + ASSERT_TRUE(NS_SUCCEEDED(res)); 1.211 + 1.212 + mask <<= 1; 1.213 + } 1.214 + } 1.215 + 1.216 + 1.217 + void ConnectSocket_s(TransportTestPeer *peer) { 1.218 + nsresult res; 1.219 + res = loopback_->Init(); 1.220 + ASSERT_EQ((nsresult)NS_OK, res); 1.221 + 1.222 + loopback_->Connect(peer->loopback_); 1.223 + 1.224 + ASSERT_EQ((nsresult)NS_OK, flow_->PushLayer(loopback_)); 1.225 + ASSERT_EQ((nsresult)NS_OK, flow_->PushLayer(logging_)); 1.226 + ASSERT_EQ((nsresult)NS_OK, flow_->PushLayer(lossy_)); 1.227 + ASSERT_EQ((nsresult)NS_OK, flow_->PushLayer(dtls_)); 1.228 + 1.229 + flow_->SignalPacketReceived.connect(this, &TransportTestPeer::PacketReceived); 1.230 + } 1.231 + 1.232 + void ConnectSocket(TransportTestPeer *peer) { 1.233 + RUN_ON_THREAD(test_utils->sts_target(), 1.234 + WrapRunnable(this, & TransportTestPeer::ConnectSocket_s, 1.235 + peer), 1.236 + NS_DISPATCH_SYNC); 1.237 + } 1.238 + 1.239 + void InitIce() { 1.240 + nsresult res; 1.241 + 1.242 + // Attach our slots 1.243 + ice_ctx_->SignalGatheringStateChange. 1.244 + connect(this, &TransportTestPeer::GatheringStateChange); 1.245 + 1.246 + char name[100]; 1.247 + snprintf(name, sizeof(name), "%s:stream%d", name_.c_str(), 1.248 + (int)streams_.size()); 1.249 + 1.250 + // Create the media stream 1.251 + mozilla::RefPtr<NrIceMediaStream> stream = 1.252 + ice_ctx_->CreateStream(static_cast<char *>(name), 1); 1.253 + ASSERT_TRUE(stream != nullptr); 1.254 + streams_.push_back(stream); 1.255 + 1.256 + // Listen for candidates 1.257 + stream->SignalCandidate. 1.258 + connect(this, &TransportTestPeer::GotCandidate); 1.259 + 1.260 + // Create the transport layer 1.261 + ice_ = new TransportLayerIce(name, ice_ctx_, stream, 1); 1.262 + 1.263 + // Assemble the stack 1.264 + nsAutoPtr<std::queue<mozilla::TransportLayer *> > layers( 1.265 + new std::queue<mozilla::TransportLayer *>); 1.266 + layers->push(ice_); 1.267 + layers->push(dtls_); 1.268 + 1.269 + test_utils->sts_target()->Dispatch( 1.270 + WrapRunnableRet(flow_, &TransportFlow::PushLayers, layers, &res), 1.271 + NS_DISPATCH_SYNC); 1.272 + 1.273 + ASSERT_EQ((nsresult)NS_OK, res); 1.274 + 1.275 + // Listen for media events 1.276 + flow_->SignalPacketReceived.connect(this, &TransportTestPeer::PacketReceived); 1.277 + flow_->SignalStateChange.connect(this, &TransportTestPeer::StateChanged); 1.278 + 1.279 + // Start gathering 1.280 + test_utils->sts_target()->Dispatch( 1.281 + WrapRunnableRet(ice_ctx_, &NrIceCtx::StartGathering, &res), 1.282 + NS_DISPATCH_SYNC); 1.283 + ASSERT_TRUE(NS_SUCCEEDED(res)); 1.284 + } 1.285 + 1.286 + void ConnectIce(TransportTestPeer *peer) { 1.287 + peer_ = peer; 1.288 + 1.289 + // If gathering is already complete, push the candidates over 1.290 + if (gathering_complete_) 1.291 + GatheringComplete(); 1.292 + } 1.293 + 1.294 + // New candidate 1.295 + void GotCandidate(NrIceMediaStream *stream, const std::string &candidate) { 1.296 + std::cerr << "Got candidate " << candidate << std::endl; 1.297 + candidates_[stream->name()].push_back(candidate); 1.298 + } 1.299 + 1.300 + void GatheringStateChange(NrIceCtx* ctx, 1.301 + NrIceCtx::GatheringState state) { 1.302 + (void)ctx; 1.303 + if (state == NrIceCtx::ICE_CTX_GATHER_COMPLETE) { 1.304 + GatheringComplete(); 1.305 + } 1.306 + } 1.307 + 1.308 + // Gathering complete, so send our candidates and start 1.309 + // connecting on the other peer. 1.310 + void GatheringComplete() { 1.311 + nsresult res; 1.312 + 1.313 + // Don't send to the other side 1.314 + if (!peer_) { 1.315 + gathering_complete_ = true; 1.316 + return; 1.317 + } 1.318 + 1.319 + // First send attributes 1.320 + test_utils->sts_target()->Dispatch( 1.321 + WrapRunnableRet(peer_->ice_ctx_, 1.322 + &NrIceCtx::ParseGlobalAttributes, 1.323 + ice_ctx_->GetGlobalAttributes(), &res), 1.324 + NS_DISPATCH_SYNC); 1.325 + ASSERT_TRUE(NS_SUCCEEDED(res)); 1.326 + 1.327 + for (size_t i=0; i<streams_.size(); ++i) { 1.328 + test_utils->sts_target()->Dispatch( 1.329 + WrapRunnableRet(peer_->streams_[i], &NrIceMediaStream::ParseAttributes, 1.330 + candidates_[streams_[i]->name()], &res), NS_DISPATCH_SYNC); 1.331 + 1.332 + ASSERT_TRUE(NS_SUCCEEDED(res)); 1.333 + } 1.334 + 1.335 + // Start checks on the other peer. 1.336 + test_utils->sts_target()->Dispatch( 1.337 + WrapRunnableRet(peer_->ice_ctx_, &NrIceCtx::StartChecks, &res), 1.338 + NS_DISPATCH_SYNC); 1.339 + ASSERT_TRUE(NS_SUCCEEDED(res)); 1.340 + } 1.341 + 1.342 + TransportResult SendPacket(const unsigned char* data, size_t len) { 1.343 + TransportResult ret; 1.344 + test_utils->sts_target()->Dispatch( 1.345 + WrapRunnableRet(flow_, &TransportFlow::SendPacket, data, len, &ret), 1.346 + NS_DISPATCH_SYNC); 1.347 + 1.348 + return ret; 1.349 + } 1.350 + 1.351 + 1.352 + void StateChanged(TransportFlow *flow, TransportLayer::State state) { 1.353 + if (state == TransportLayer::TS_OPEN) { 1.354 + std::cerr << "Now connected" << std::endl; 1.355 + } 1.356 + } 1.357 + 1.358 + void PacketReceived(TransportFlow * flow, const unsigned char* data, 1.359 + size_t len) { 1.360 + std::cerr << "Received " << len << " bytes" << std::endl; 1.361 + ++received_; 1.362 + } 1.363 + 1.364 + void SetLoss(uint32_t loss) { 1.365 + lossy_->SetLoss(loss); 1.366 + } 1.367 + 1.368 + TransportLayer::State state() { 1.369 + TransportLayer::State tstate; 1.370 + 1.371 + RUN_ON_THREAD(test_utils->sts_target(), 1.372 + WrapRunnableRet(flow_, &TransportFlow::state, &tstate), 1.373 + NS_DISPATCH_SYNC); 1.374 + 1.375 + return tstate; 1.376 + } 1.377 + 1.378 + bool connected() { 1.379 + return state() == TransportLayer::TS_OPEN; 1.380 + } 1.381 + 1.382 + bool failed() { 1.383 + return state() == TransportLayer::TS_ERROR; 1.384 + } 1.385 + 1.386 + size_t received() { return received_; } 1.387 + 1.388 + private: 1.389 + std::string name_; 1.390 + nsCOMPtr<nsIEventTarget> target_; 1.391 + size_t received_; 1.392 + mozilla::RefPtr<TransportFlow> flow_; 1.393 + TransportLayerLoopback *loopback_; 1.394 + TransportLayerLogging *logging_; 1.395 + TransportLayerLossy *lossy_; 1.396 + TransportLayerDtls *dtls_; 1.397 + TransportLayerIce *ice_; 1.398 + mozilla::RefPtr<DtlsIdentity> identity_; 1.399 + mozilla::RefPtr<NrIceCtx> ice_ctx_; 1.400 + std::vector<mozilla::RefPtr<NrIceMediaStream> > streams_; 1.401 + std::map<std::string, std::vector<std::string> > candidates_; 1.402 + TransportTestPeer *peer_; 1.403 + bool gathering_complete_; 1.404 + unsigned char fingerprint_[TransportLayerDtls::kMaxDigestLength]; 1.405 + size_t fingerprint_len_; 1.406 +}; 1.407 + 1.408 + 1.409 +class TransportTest : public ::testing::Test { 1.410 + public: 1.411 + TransportTest() { 1.412 + fds_[0] = nullptr; 1.413 + fds_[1] = nullptr; 1.414 + } 1.415 + 1.416 + ~TransportTest() { 1.417 + delete p1_; 1.418 + delete p2_; 1.419 + 1.420 + // Can't detach these 1.421 + // PR_Close(fds_[0]); 1.422 + // PR_Close(fds_[1]); 1.423 + } 1.424 + 1.425 + void DestroyPeerFlows() { 1.426 + p1_->DisconnectDestroyFlow(); 1.427 + p2_->DisconnectDestroyFlow(); 1.428 + } 1.429 + 1.430 + void SetUp() { 1.431 + nsresult rv; 1.432 + target_ = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv); 1.433 + ASSERT_TRUE(NS_SUCCEEDED(rv)); 1.434 + 1.435 + p1_ = new TransportTestPeer(target_, "P1"); 1.436 + p2_ = new TransportTestPeer(target_, "P2"); 1.437 + } 1.438 + 1.439 + void SetDtlsPeer(int digests = 1, unsigned int damage = 0) { 1.440 + p1_->SetDtlsPeer(p2_, digests, damage); 1.441 + p2_->SetDtlsPeer(p1_, digests, damage); 1.442 + } 1.443 + 1.444 + void SetDtlsAllowAll() { 1.445 + p1_->SetDtlsAllowAll(); 1.446 + p2_->SetDtlsAllowAll(); 1.447 + } 1.448 + 1.449 + void ConnectSocket() { 1.450 + test_utils->sts_target()->Dispatch( 1.451 + WrapRunnable(p1_, &TransportTestPeer::ConnectSocket, p2_), 1.452 + NS_DISPATCH_SYNC); 1.453 + test_utils->sts_target()->Dispatch( 1.454 + WrapRunnable(p2_, &TransportTestPeer::ConnectSocket, p1_), 1.455 + NS_DISPATCH_SYNC); 1.456 + 1.457 + ASSERT_TRUE_WAIT(p1_->connected(), 10000); 1.458 + ASSERT_TRUE_WAIT(p2_->connected(), 10000); 1.459 + } 1.460 + 1.461 + void ConnectSocketExpectFail() { 1.462 + test_utils->sts_target()->Dispatch( 1.463 + WrapRunnable(p1_, &TransportTestPeer::ConnectSocket, p2_), 1.464 + NS_DISPATCH_SYNC); 1.465 + test_utils->sts_target()->Dispatch( 1.466 + WrapRunnable(p2_, &TransportTestPeer::ConnectSocket, p1_), 1.467 + NS_DISPATCH_SYNC); 1.468 + ASSERT_TRUE_WAIT(p1_->failed(), 10000); 1.469 + ASSERT_TRUE_WAIT(p2_->failed(), 10000); 1.470 + } 1.471 + 1.472 + void InitIce() { 1.473 + p1_->InitIce(); 1.474 + p2_->InitIce(); 1.475 + } 1.476 + 1.477 + void ConnectIce() { 1.478 + p1_->InitIce(); 1.479 + p2_->InitIce(); 1.480 + p1_->ConnectIce(p2_); 1.481 + p2_->ConnectIce(p1_); 1.482 + ASSERT_TRUE_WAIT(p1_->connected(), 10000); 1.483 + ASSERT_TRUE_WAIT(p2_->connected(), 10000); 1.484 + } 1.485 + 1.486 + void TransferTest(size_t count) { 1.487 + unsigned char buf[1000]; 1.488 + 1.489 + for (size_t i= 0; i<count; ++i) { 1.490 + memset(buf, count & 0xff, sizeof(buf)); 1.491 + TransportResult rv = p1_->SendPacket(buf, sizeof(buf)); 1.492 + ASSERT_TRUE(rv > 0); 1.493 + } 1.494 + 1.495 + std::cerr << "Received == " << p2_->received() << std::endl; 1.496 + ASSERT_TRUE_WAIT(count == p2_->received(), 10000); 1.497 + } 1.498 + 1.499 + protected: 1.500 + PRFileDesc *fds_[2]; 1.501 + TransportTestPeer *p1_; 1.502 + TransportTestPeer *p2_; 1.503 + nsCOMPtr<nsIEventTarget> target_; 1.504 +}; 1.505 + 1.506 + 1.507 +TEST_F(TransportTest, TestNoDtlsVerificationSettings) { 1.508 + ConnectSocketExpectFail(); 1.509 +} 1.510 + 1.511 +TEST_F(TransportTest, TestConnect) { 1.512 + SetDtlsPeer(); 1.513 + ConnectSocket(); 1.514 +} 1.515 + 1.516 +TEST_F(TransportTest, TestConnectDestroyFlowsMainThread) { 1.517 + SetDtlsPeer(); 1.518 + ConnectSocket(); 1.519 + DestroyPeerFlows(); 1.520 +} 1.521 + 1.522 +TEST_F(TransportTest, TestConnectAllowAll) { 1.523 + SetDtlsAllowAll(); 1.524 + ConnectSocket(); 1.525 +} 1.526 + 1.527 +TEST_F(TransportTest, TestConnectBadDigest) { 1.528 + SetDtlsPeer(1, 1); 1.529 + 1.530 + ConnectSocketExpectFail(); 1.531 +} 1.532 + 1.533 +TEST_F(TransportTest, TestConnectTwoDigests) { 1.534 + SetDtlsPeer(2, 0); 1.535 + 1.536 + ConnectSocket(); 1.537 +} 1.538 + 1.539 +TEST_F(TransportTest, TestConnectTwoDigestsFirstBad) { 1.540 + SetDtlsPeer(2, 1); 1.541 + 1.542 + ConnectSocketExpectFail(); 1.543 +} 1.544 + 1.545 +TEST_F(TransportTest, TestConnectTwoDigestsSecondBad) { 1.546 + SetDtlsPeer(2, 2); 1.547 + 1.548 + ConnectSocketExpectFail(); 1.549 +} 1.550 + 1.551 +TEST_F(TransportTest, TestConnectTwoDigestsBothBad) { 1.552 + SetDtlsPeer(2, 3); 1.553 + 1.554 + ConnectSocketExpectFail(); 1.555 +} 1.556 + 1.557 +TEST_F(TransportTest, TestTransfer) { 1.558 + SetDtlsPeer(); 1.559 + ConnectSocket(); 1.560 + TransferTest(1); 1.561 +} 1.562 + 1.563 +TEST_F(TransportTest, TestConnectLoseFirst) { 1.564 + SetDtlsPeer(); 1.565 + p1_->SetLoss(0); 1.566 + ConnectSocket(); 1.567 + TransferTest(1); 1.568 +} 1.569 + 1.570 +TEST_F(TransportTest, TestConnectIce) { 1.571 + SetDtlsPeer(); 1.572 + ConnectIce(); 1.573 +} 1.574 + 1.575 +TEST_F(TransportTest, TestTransferIce) { 1.576 + SetDtlsPeer(); 1.577 + ConnectIce(); 1.578 + TransferTest(1); 1.579 +} 1.580 + 1.581 +TEST(PushTests, LayerFail) { 1.582 + TransportFlow flow; 1.583 + nsresult rv; 1.584 + bool destroyed1, destroyed2; 1.585 + 1.586 + rv = flow.PushLayer(new TransportLayerDummy(true, &destroyed1)); 1.587 + ASSERT_TRUE(NS_SUCCEEDED(rv)); 1.588 + 1.589 + rv = flow.PushLayer(new TransportLayerDummy(false, &destroyed2)); 1.590 + ASSERT_TRUE(NS_FAILED(rv)); 1.591 + 1.592 + ASSERT_EQ(TransportLayer::TS_ERROR, flow.state()); 1.593 + ASSERT_EQ(true, destroyed1); 1.594 + ASSERT_EQ(true, destroyed2); 1.595 + 1.596 + rv = flow.PushLayer(new TransportLayerDummy(true, &destroyed1)); 1.597 + ASSERT_TRUE(NS_FAILED(rv)); 1.598 + ASSERT_EQ(true, destroyed1); 1.599 +} 1.600 + 1.601 + 1.602 +TEST(PushTests, LayersFail) { 1.603 + TransportFlow flow; 1.604 + nsresult rv; 1.605 + bool destroyed1, destroyed2, destroyed3; 1.606 + 1.607 + rv = flow.PushLayer(new TransportLayerDummy(true, &destroyed1)); 1.608 + ASSERT_TRUE(NS_SUCCEEDED(rv)); 1.609 + 1.610 + nsAutoPtr<std::queue<TransportLayer *> > layers( 1.611 + new std::queue<TransportLayer *>()); 1.612 + 1.613 + layers->push(new TransportLayerDummy(true, &destroyed2)); 1.614 + layers->push(new TransportLayerDummy(false, &destroyed3)); 1.615 + 1.616 + rv = flow.PushLayers(layers); 1.617 + ASSERT_TRUE(NS_FAILED(rv)); 1.618 + 1.619 + ASSERT_EQ(TransportLayer::TS_ERROR, flow.state()); 1.620 + ASSERT_EQ(true, destroyed1); 1.621 + ASSERT_EQ(true, destroyed2); 1.622 + ASSERT_EQ(true, destroyed3); 1.623 + 1.624 + layers = new std::queue<TransportLayer *>(); 1.625 + layers->push(new TransportLayerDummy(true, &destroyed2)); 1.626 + layers->push(new TransportLayerDummy(true, &destroyed3)); 1.627 + rv = flow.PushLayers(layers); 1.628 + 1.629 + ASSERT_TRUE(NS_FAILED(rv)); 1.630 + ASSERT_EQ(true, destroyed2); 1.631 + ASSERT_EQ(true, destroyed3); 1.632 +} 1.633 + 1.634 +} // end namespace 1.635 + 1.636 +int main(int argc, char **argv) 1.637 +{ 1.638 + test_utils = new MtransportTestUtils(); 1.639 + 1.640 + NSS_NoDB_Init(nullptr); 1.641 + NSS_SetDomesticPolicy(); 1.642 + // Start the tests 1.643 + ::testing::InitGoogleTest(&argc, argv); 1.644 + 1.645 + int rv = RUN_ALL_TESTS(); 1.646 + delete test_utils; 1.647 + return rv; 1.648 +}