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/base/fakenetwork.h" 31#include "talk/base/gunit.h" 32#include "talk/base/thread.h" 33#include "talk/p2p/base/basicpacketsocketfactory.h" 34#include "talk/p2p/base/portallocatorsessionproxy.h" 35#include "talk/p2p/client/basicportallocator.h" 36#include "talk/p2p/client/fakeportallocator.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 void OnCandidatesReady(PortAllocatorSession* session, 64 const std::vector<Candidate>& candidates) { 65 EXPECT_EQ(proxy_session_, session); 66 candidates_count_ += static_cast<int>(candidates.size()); 67 } 68 void OnCandidatesAllocationDone(PortAllocatorSession* session) { 69 EXPECT_EQ(proxy_session_, session); 70 allocation_complete_ = true; 71 } 72 void OnPortReady(PortAllocatorSession* session, 73 cricket::PortInterface* port) { 74 EXPECT_EQ(proxy_session_, session); 75 ++ports_count_; 76 } 77 int candidates_count() { return candidates_count_; } 78 bool allocation_complete() { return allocation_complete_; } 79 int ports_count() { return ports_count_; } 80 81 void StartGettingPorts() { 82 proxy_session_->StartGettingPorts(); 83 } 84 85 void StopGettingPorts() { 86 proxy_session_->StopGettingPorts(); 87 } 88 89 bool IsGettingPorts() { 90 return proxy_session_->IsGettingPorts(); 91 } 92 93 private: 94 PortAllocatorSessionProxy* proxy_session_; 95 int candidates_count_; 96 bool allocation_complete_; 97 int ports_count_; 98}; 99 100class PortAllocatorSessionProxyTest : public testing::Test { 101 public: 102 PortAllocatorSessionProxyTest() 103 : socket_factory_(talk_base::Thread::Current()), 104 allocator_(talk_base::Thread::Current(), NULL), 105 session_(talk_base::Thread::Current(), &socket_factory_, 106 "test content", 1, 107 kIceUfrag0, kIcePwd0), 108 session_muxer_(new PortAllocatorSessionMuxer(&session_)) { 109 } 110 virtual ~PortAllocatorSessionProxyTest() {} 111 void RegisterSessionProxy(PortAllocatorSessionProxy* proxy) { 112 session_muxer_->RegisterSessionProxy(proxy); 113 } 114 115 TestSessionChannel* CreateChannel() { 116 PortAllocatorSessionProxy* proxy = 117 new PortAllocatorSessionProxy("test content", 1, 0); 118 TestSessionChannel* channel = new TestSessionChannel(proxy); 119 session_muxer_->RegisterSessionProxy(proxy); 120 channel->StartGettingPorts(); 121 return channel; 122 } 123 124 protected: 125 talk_base::BasicPacketSocketFactory socket_factory_; 126 cricket::FakePortAllocator allocator_; 127 cricket::FakePortAllocatorSession session_; 128 // Muxer object will be delete itself after all registered session proxies 129 // are deleted. 130 PortAllocatorSessionMuxer* session_muxer_; 131}; 132 133TEST_F(PortAllocatorSessionProxyTest, TestBasic) { 134 TestSessionChannel* channel = CreateChannel(); 135 EXPECT_EQ_WAIT(1, channel->candidates_count(), 1000); 136 EXPECT_EQ(1, channel->ports_count()); 137 EXPECT_TRUE(channel->allocation_complete()); 138 delete channel; 139} 140 141TEST_F(PortAllocatorSessionProxyTest, TestLateBinding) { 142 TestSessionChannel* channel1 = CreateChannel(); 143 EXPECT_EQ_WAIT(1, channel1->candidates_count(), 1000); 144 EXPECT_EQ(1, channel1->ports_count()); 145 EXPECT_TRUE(channel1->allocation_complete()); 146 EXPECT_EQ(1, session_.port_config_count()); 147 // Creating another PortAllocatorSessionProxy and it also should receive 148 // already happened events. 149 PortAllocatorSessionProxy* proxy = 150 new PortAllocatorSessionProxy("test content", 2, 0); 151 TestSessionChannel* channel2 = new TestSessionChannel(proxy); 152 session_muxer_->RegisterSessionProxy(proxy); 153 EXPECT_TRUE(channel2->IsGettingPorts()); 154 EXPECT_EQ_WAIT(1, channel2->candidates_count(), 1000); 155 EXPECT_EQ(1, channel2->ports_count()); 156 EXPECT_TRUE_WAIT(channel2->allocation_complete(), 1000); 157 EXPECT_EQ(1, session_.port_config_count()); 158 delete channel1; 159 delete channel2; 160} 161