1/* 2 * libjingle 3 * Copyright 2012 Google Inc. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28#include <vector> 29 30#include "talk/p2p/base/basicpacketsocketfactory.h" 31#include "talk/p2p/base/portallocatorsessionproxy.h" 32#include "talk/p2p/client/basicportallocator.h" 33#include "talk/p2p/client/fakeportallocator.h" 34#include "webrtc/base/fakenetwork.h" 35#include "webrtc/base/gunit.h" 36#include "webrtc/base/thread.h" 37 38using cricket::Candidate; 39using cricket::PortAllocatorSession; 40using cricket::PortAllocatorSessionMuxer; 41using cricket::PortAllocatorSessionProxy; 42 43// Based on ICE_UFRAG_LENGTH 44static const char kIceUfrag0[] = "TESTICEUFRAG0000"; 45// Based on ICE_PWD_LENGTH 46static const char kIcePwd0[] = "TESTICEPWD00000000000000"; 47 48class TestSessionChannel : public sigslot::has_slots<> { 49 public: 50 explicit TestSessionChannel(PortAllocatorSessionProxy* proxy) 51 : proxy_session_(proxy), 52 candidates_count_(0), 53 allocation_complete_(false), 54 ports_count_(0) { 55 proxy_session_->SignalCandidatesAllocationDone.connect( 56 this, &TestSessionChannel::OnCandidatesAllocationDone); 57 proxy_session_->SignalCandidatesReady.connect( 58 this, &TestSessionChannel::OnCandidatesReady); 59 proxy_session_->SignalPortReady.connect( 60 this, &TestSessionChannel::OnPortReady); 61 } 62 virtual ~TestSessionChannel() { 63 delete proxy_session_; 64 } 65 void OnCandidatesReady(PortAllocatorSession* session, 66 const std::vector<Candidate>& candidates) { 67 EXPECT_EQ(proxy_session_, session); 68 candidates_count_ += static_cast<int>(candidates.size()); 69 } 70 void OnCandidatesAllocationDone(PortAllocatorSession* session) { 71 EXPECT_EQ(proxy_session_, session); 72 allocation_complete_ = true; 73 } 74 void OnPortReady(PortAllocatorSession* session, 75 cricket::PortInterface* port) { 76 EXPECT_EQ(proxy_session_, session); 77 ++ports_count_; 78 } 79 int candidates_count() { return candidates_count_; } 80 bool allocation_complete() { return allocation_complete_; } 81 int ports_count() { return ports_count_; } 82 83 void StartGettingPorts() { 84 proxy_session_->StartGettingPorts(); 85 } 86 87 void StopGettingPorts() { 88 proxy_session_->StopGettingPorts(); 89 } 90 91 bool IsGettingPorts() { 92 return proxy_session_->IsGettingPorts(); 93 } 94 95 private: 96 PortAllocatorSessionProxy* proxy_session_; 97 int candidates_count_; 98 bool allocation_complete_; 99 int ports_count_; 100}; 101 102class PortAllocatorSessionProxyTest : public testing::Test { 103 public: 104 PortAllocatorSessionProxyTest() 105 : socket_factory_(rtc::Thread::Current()), 106 allocator_(rtc::Thread::Current(), NULL), 107 session_(new cricket::FakePortAllocatorSession( 108 rtc::Thread::Current(), &socket_factory_, 109 "test content", 1, 110 kIceUfrag0, kIcePwd0)), 111 session_muxer_(new PortAllocatorSessionMuxer(session_)) { 112 } 113 virtual ~PortAllocatorSessionProxyTest() {} 114 void RegisterSessionProxy(PortAllocatorSessionProxy* proxy) { 115 session_muxer_->RegisterSessionProxy(proxy); 116 } 117 118 TestSessionChannel* CreateChannel() { 119 PortAllocatorSessionProxy* proxy = 120 new PortAllocatorSessionProxy("test content", 1, 0); 121 TestSessionChannel* channel = new TestSessionChannel(proxy); 122 session_muxer_->RegisterSessionProxy(proxy); 123 channel->StartGettingPorts(); 124 return channel; 125 } 126 127 protected: 128 rtc::BasicPacketSocketFactory socket_factory_; 129 cricket::FakePortAllocator allocator_; 130 cricket::FakePortAllocatorSession* session_; 131 // Muxer object will be delete itself after all registered session proxies 132 // are deleted. 133 PortAllocatorSessionMuxer* session_muxer_; 134}; 135 136TEST_F(PortAllocatorSessionProxyTest, TestBasic) { 137 TestSessionChannel* channel = CreateChannel(); 138 EXPECT_EQ_WAIT(1, channel->candidates_count(), 1000); 139 EXPECT_EQ(1, channel->ports_count()); 140 EXPECT_TRUE(channel->allocation_complete()); 141 delete channel; 142} 143 144TEST_F(PortAllocatorSessionProxyTest, TestLateBinding) { 145 TestSessionChannel* channel1 = CreateChannel(); 146 EXPECT_EQ_WAIT(1, channel1->candidates_count(), 1000); 147 EXPECT_EQ(1, channel1->ports_count()); 148 EXPECT_TRUE(channel1->allocation_complete()); 149 EXPECT_EQ(1, session_->port_config_count()); 150 // Creating another PortAllocatorSessionProxy and it also should receive 151 // already happened events. 152 PortAllocatorSessionProxy* proxy = 153 new PortAllocatorSessionProxy("test content", 2, 0); 154 TestSessionChannel* channel2 = new TestSessionChannel(proxy); 155 session_muxer_->RegisterSessionProxy(proxy); 156 EXPECT_TRUE(channel2->IsGettingPorts()); 157 EXPECT_EQ_WAIT(1, channel2->candidates_count(), 1000); 158 EXPECT_EQ(1, channel2->ports_count()); 159 EXPECT_TRUE_WAIT(channel2->allocation_complete(), 1000); 160 EXPECT_EQ(1, session_->port_config_count()); 161 delete channel1; 162 delete channel2; 163} 164