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
38 using cricket::Candidate;
39 using cricket::PortAllocatorSession;
40 using cricket::PortAllocatorSessionMuxer;
41 using cricket::PortAllocatorSessionProxy;
42
43 // Based on ICE_UFRAG_LENGTH
44 static const char kIceUfrag0[] = "TESTICEUFRAG0000";
45 // Based on ICE_PWD_LENGTH
46 static const char kIcePwd0[] = "TESTICEPWD00000000000000";
47
48 class TestSessionChannel : public sigslot::has_slots<> {
49 public:
TestSessionChannel(PortAllocatorSessionProxy * proxy)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 }
~TestSessionChannel()62 virtual ~TestSessionChannel() {
63 delete proxy_session_;
64 }
OnCandidatesReady(PortAllocatorSession * session,const std::vector<Candidate> & candidates)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 }
OnCandidatesAllocationDone(PortAllocatorSession * session)70 void OnCandidatesAllocationDone(PortAllocatorSession* session) {
71 EXPECT_EQ(proxy_session_, session);
72 allocation_complete_ = true;
73 }
OnPortReady(PortAllocatorSession * session,cricket::PortInterface * port)74 void OnPortReady(PortAllocatorSession* session,
75 cricket::PortInterface* port) {
76 EXPECT_EQ(proxy_session_, session);
77 ++ports_count_;
78 }
candidates_count()79 int candidates_count() { return candidates_count_; }
allocation_complete()80 bool allocation_complete() { return allocation_complete_; }
ports_count()81 int ports_count() { return ports_count_; }
82
StartGettingPorts()83 void StartGettingPorts() {
84 proxy_session_->StartGettingPorts();
85 }
86
StopGettingPorts()87 void StopGettingPorts() {
88 proxy_session_->StopGettingPorts();
89 }
90
IsGettingPorts()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
102 class PortAllocatorSessionProxyTest : public testing::Test {
103 public:
PortAllocatorSessionProxyTest()104 PortAllocatorSessionProxyTest()
105 : socket_factory_(talk_base::Thread::Current()),
106 allocator_(talk_base::Thread::Current(), NULL),
107 session_(new cricket::FakePortAllocatorSession(
108 talk_base::Thread::Current(), &socket_factory_,
109 "test content", 1,
110 kIceUfrag0, kIcePwd0)),
111 session_muxer_(new PortAllocatorSessionMuxer(session_)) {
112 }
~PortAllocatorSessionProxyTest()113 virtual ~PortAllocatorSessionProxyTest() {}
RegisterSessionProxy(PortAllocatorSessionProxy * proxy)114 void RegisterSessionProxy(PortAllocatorSessionProxy* proxy) {
115 session_muxer_->RegisterSessionProxy(proxy);
116 }
117
CreateChannel()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 talk_base::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
TEST_F(PortAllocatorSessionProxyTest,TestBasic)136 TEST_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
TEST_F(PortAllocatorSessionProxyTest,TestLateBinding)144 TEST_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