| /* |
| * libjingle |
| * Copyright 2012 Google Inc. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright notice, |
| * this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright notice, |
| * this list of conditions and the following disclaimer in the documentation |
| * and/or other materials provided with the distribution. |
| * 3. The name of the author may not be used to endorse or promote products |
| * derived from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO |
| * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
| * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |
| * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
| * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include <vector> |
| |
| #include "talk/base/fakenetwork.h" |
| #include "talk/base/gunit.h" |
| #include "talk/base/thread.h" |
| #include "talk/p2p/base/basicpacketsocketfactory.h" |
| #include "talk/p2p/base/portallocatorsessionproxy.h" |
| #include "talk/p2p/client/basicportallocator.h" |
| #include "talk/p2p/client/fakeportallocator.h" |
| |
| using cricket::Candidate; |
| using cricket::PortAllocatorSession; |
| using cricket::PortAllocatorSessionMuxer; |
| using cricket::PortAllocatorSessionProxy; |
| |
| // Based on ICE_UFRAG_LENGTH |
| static const char kIceUfrag0[] = "TESTICEUFRAG0000"; |
| // Based on ICE_PWD_LENGTH |
| static const char kIcePwd0[] = "TESTICEPWD00000000000000"; |
| |
| class TestSessionChannel : public sigslot::has_slots<> { |
| public: |
| explicit TestSessionChannel(PortAllocatorSessionProxy* proxy) |
| : proxy_session_(proxy), |
| candidates_count_(0), |
| allocation_complete_(false), |
| ports_count_(0) { |
| proxy_session_->SignalCandidatesAllocationDone.connect( |
| this, &TestSessionChannel::OnCandidatesAllocationDone); |
| proxy_session_->SignalCandidatesReady.connect( |
| this, &TestSessionChannel::OnCandidatesReady); |
| proxy_session_->SignalPortReady.connect( |
| this, &TestSessionChannel::OnPortReady); |
| } |
| virtual ~TestSessionChannel() { |
| delete proxy_session_; |
| } |
| void OnCandidatesReady(PortAllocatorSession* session, |
| const std::vector<Candidate>& candidates) { |
| EXPECT_EQ(proxy_session_, session); |
| candidates_count_ += static_cast<int>(candidates.size()); |
| } |
| void OnCandidatesAllocationDone(PortAllocatorSession* session) { |
| EXPECT_EQ(proxy_session_, session); |
| allocation_complete_ = true; |
| } |
| void OnPortReady(PortAllocatorSession* session, |
| cricket::PortInterface* port) { |
| EXPECT_EQ(proxy_session_, session); |
| ++ports_count_; |
| } |
| int candidates_count() { return candidates_count_; } |
| bool allocation_complete() { return allocation_complete_; } |
| int ports_count() { return ports_count_; } |
| |
| void StartGettingPorts() { |
| proxy_session_->StartGettingPorts(); |
| } |
| |
| void StopGettingPorts() { |
| proxy_session_->StopGettingPorts(); |
| } |
| |
| bool IsGettingPorts() { |
| return proxy_session_->IsGettingPorts(); |
| } |
| |
| private: |
| PortAllocatorSessionProxy* proxy_session_; |
| int candidates_count_; |
| bool allocation_complete_; |
| int ports_count_; |
| }; |
| |
| class PortAllocatorSessionProxyTest : public testing::Test { |
| public: |
| PortAllocatorSessionProxyTest() |
| : socket_factory_(talk_base::Thread::Current()), |
| allocator_(talk_base::Thread::Current(), NULL), |
| session_(new cricket::FakePortAllocatorSession( |
| talk_base::Thread::Current(), &socket_factory_, |
| "test content", 1, |
| kIceUfrag0, kIcePwd0)), |
| session_muxer_(new PortAllocatorSessionMuxer(session_)) { |
| } |
| virtual ~PortAllocatorSessionProxyTest() {} |
| void RegisterSessionProxy(PortAllocatorSessionProxy* proxy) { |
| session_muxer_->RegisterSessionProxy(proxy); |
| } |
| |
| TestSessionChannel* CreateChannel() { |
| PortAllocatorSessionProxy* proxy = |
| new PortAllocatorSessionProxy("test content", 1, 0); |
| TestSessionChannel* channel = new TestSessionChannel(proxy); |
| session_muxer_->RegisterSessionProxy(proxy); |
| channel->StartGettingPorts(); |
| return channel; |
| } |
| |
| protected: |
| talk_base::BasicPacketSocketFactory socket_factory_; |
| cricket::FakePortAllocator allocator_; |
| cricket::FakePortAllocatorSession* session_; |
| // Muxer object will be delete itself after all registered session proxies |
| // are deleted. |
| PortAllocatorSessionMuxer* session_muxer_; |
| }; |
| |
| TEST_F(PortAllocatorSessionProxyTest, TestBasic) { |
| TestSessionChannel* channel = CreateChannel(); |
| EXPECT_EQ_WAIT(1, channel->candidates_count(), 1000); |
| EXPECT_EQ(1, channel->ports_count()); |
| EXPECT_TRUE(channel->allocation_complete()); |
| delete channel; |
| } |
| |
| TEST_F(PortAllocatorSessionProxyTest, TestLateBinding) { |
| TestSessionChannel* channel1 = CreateChannel(); |
| EXPECT_EQ_WAIT(1, channel1->candidates_count(), 1000); |
| EXPECT_EQ(1, channel1->ports_count()); |
| EXPECT_TRUE(channel1->allocation_complete()); |
| EXPECT_EQ(1, session_->port_config_count()); |
| // Creating another PortAllocatorSessionProxy and it also should receive |
| // already happened events. |
| PortAllocatorSessionProxy* proxy = |
| new PortAllocatorSessionProxy("test content", 2, 0); |
| TestSessionChannel* channel2 = new TestSessionChannel(proxy); |
| session_muxer_->RegisterSessionProxy(proxy); |
| EXPECT_TRUE(channel2->IsGettingPorts()); |
| EXPECT_EQ_WAIT(1, channel2->candidates_count(), 1000); |
| EXPECT_EQ(1, channel2->ports_count()); |
| EXPECT_TRUE_WAIT(channel2->allocation_complete(), 1000); |
| EXPECT_EQ(1, session_->port_config_count()); |
| delete channel1; |
| delete channel2; |
| } |