OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * Copyright 2016 The WebRTC Project Authors. All rights reserved. |
| 3 * |
| 4 * Use of this source code is governed by a BSD-style license |
| 5 * that can be found in the LICENSE file in the root of the source |
| 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ |
| 10 |
| 11 #include <algorithm> |
| 12 #include <list> |
| 13 #include <memory> |
| 14 #include <utility> |
| 15 #include <vector> |
| 16 |
| 17 #include "webrtc/base/gunit.h" |
| 18 #include "webrtc/base/thread.h" |
| 19 #include "webrtc/base/socketserver.h" |
| 20 #include "webrtc/p2p/base/transportchannelimpl.h" |
| 21 #include "webrtc/p2p/rawudp/rawudptransportchannel.h" |
| 22 |
| 23 namespace cricket { |
| 24 |
| 25 class RawUdpTransPortChannelTest : public testing::Test, |
| 26 public sigslot::has_slots<> { |
| 27 public: |
| 28 void SetUp() { |
| 29 // TODO(johan) investigate whether an AutoThread should be instantiated. |
| 30 network_thread_ = rtc::Thread::Current(); |
| 31 ASSERT_NE(nullptr, network_thread_); |
| 32 network_thread_->set_socketserver( |
| 33 rtc::SocketServer::CreateDefault().release()); |
| 34 ep1_.Init("name1", 1); |
| 35 ep2_.Init("name2", 2); |
| 36 } |
| 37 |
| 38 void TearDown() { |
| 39 ep1_.Reset(); |
| 40 ep2_.Reset(); |
| 41 network_thread_ = nullptr; |
| 42 } |
| 43 |
| 44 struct Endpoint : public sigslot::has_slots<> { |
| 45 void Init(std::string tch_name, int component) { |
| 46 ch_.reset(new RawUdpTransportChannel(std::move(tch_name), component)); |
| 47 ch_->SignalReadPacket.connect(this, &Endpoint::OnReadPacket); |
| 48 ch_->SignalCandidateGathered.connect(this, |
| 49 &Endpoint::OnCandidateGathered); |
| 50 ch_->SignalGatheringState.connect(this, |
| 51 &Endpoint::OnGatheringStateChanged); |
| 52 ResetStats(); |
| 53 } |
| 54 |
| 55 void Reset() { |
| 56 ch_.reset(); |
| 57 local_candidates_.clear(); |
| 58 remote_candidates_.clear(); |
| 59 gathering_state_changes_.clear(); |
| 60 } |
| 61 |
| 62 bool CheckData(const char* data, int len) { |
| 63 bool ret = false; |
| 64 if (!ch_packets_.empty()) { |
| 65 std::string packet = ch_packets_.front(); |
| 66 ret = (packet == std::string(data, len)); |
| 67 ch_packets_.pop_front(); |
| 68 } |
| 69 return ret; |
| 70 } |
| 71 |
| 72 void ResetStats() { |
| 73 num_received_packets_ = 0; |
| 74 num_send_packets_ = 0; |
| 75 count_signal_tch_state_changed_ = 0; |
| 76 } |
| 77 |
| 78 void OnReadPacket(TransportChannel* channel, |
| 79 const char* data, |
| 80 size_t len, |
| 81 const rtc::PacketTime& packet_time, |
| 82 int flags) { |
| 83 num_received_packets_++; |
| 84 LOG(LS_VERBOSE) << "OnReadPacket (unittest)"; |
| 85 ch_packets_.push_front(std::string(data, len)); |
| 86 } |
| 87 |
| 88 int SendData(const char* data, size_t len) { |
| 89 rtc::PacketOptions options; |
| 90 return ch_->SendPacket(data, len, options, 0); |
| 91 } |
| 92 |
| 93 void OnCandidateGathered(TransportChannelImpl* channel, |
| 94 const Candidate& cand) { |
| 95 ASSERT_EQ(ch_.get(), channel); |
| 96 local_candidates_.push_back(cand); |
| 97 } |
| 98 |
| 99 // for now this function is only well defined, if there is exact one local |
| 100 // candidate. |
| 101 void GetLocalPort(uint16_t* local_port) { |
| 102 ASSERT_EQ(1u, local_candidates_.size()); |
| 103 const cricket::Candidate& cand = local_candidates_[0]; |
| 104 const rtc::SocketAddress& addr = cand.address(); |
| 105 *local_port = addr.port(); |
| 106 } |
| 107 |
| 108 void OnGatheringStateChanged(TransportChannelImpl* channel) { |
| 109 ASSERT_EQ(ch_.get(), channel); |
| 110 IceGatheringState gathering_state = channel->gathering_state(); |
| 111 gathering_state_changes_.push_back(gathering_state); |
| 112 } |
| 113 |
| 114 std::list<std::string> ch_packets_; |
| 115 std::unique_ptr<RawUdpTransportChannel> ch_; |
| 116 uint32_t num_received_packets_; // increases on SignalReadPacket. |
| 117 uint32_t num_send_packets_; |
| 118 std::vector<IceGatheringState> gathering_state_changes_; |
| 119 uint32_t count_signal_tch_state_changed_; |
| 120 // TODO(johan) check if it makes sense to have a vector of |
| 121 // std::shared<cricket::Candidate> to simplify memory cleanup. |
| 122 Candidates local_candidates_; |
| 123 Candidates remote_candidates_; |
| 124 }; |
| 125 |
| 126 Endpoint ep1_; |
| 127 Endpoint ep2_; |
| 128 rtc::Thread* network_thread_; |
| 129 |
| 130 void TestSendRecv() { |
| 131 for (uint32_t i = 0; i < 5; ++i) { |
| 132 static const char* data = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; |
| 133 int len = static_cast<int>(strlen(data)); |
| 134 // local_channel1 <==> remote_chanel1 |
| 135 EXPECT_EQ_WAIT(len, ep1_.SendData(data, len), 1000); |
| 136 // rtc::Thread::Current()->ProcessMessages(1000); |
| 137 EXPECT_TRUE_WAIT(ep2_.CheckData(data, len), 1000); |
| 138 EXPECT_EQ_WAIT(i + 1u, ep2_.num_received_packets_, 100); |
| 139 EXPECT_EQ_WAIT(len, ep2_.SendData(data, len), 1000); |
| 140 // rtc::Thread::Current()->ProcessMessages(1000); |
| 141 EXPECT_TRUE_WAIT(ep1_.CheckData(data, len), 1000); |
| 142 EXPECT_EQ_WAIT(i + 1u, ep1_.num_received_packets_, 100); |
| 143 } |
| 144 } |
| 145 }; |
| 146 |
| 147 TEST_F(RawUdpTransPortChannelTest, SendRecvBasic) { |
| 148 ep1_.ch_->MaybeStartGathering(); |
| 149 ep2_.ch_->MaybeStartGathering(); |
| 150 uint16_t port; |
| 151 ep2_.GetLocalPort(&port); |
| 152 rtc::SocketAddress addr2 = rtc::SocketAddress("127.0.0.1", port); |
| 153 cricket::Candidate cand; |
| 154 cand.set_address(addr2); |
| 155 ep1_.ch_->AddRemoteCandidate(cand); |
| 156 ep1_.GetLocalPort(&port); |
| 157 rtc::SocketAddress addr1 = rtc::SocketAddress("127.0.0.1", port); |
| 158 cand.set_address(addr1); |
| 159 ep2_.ch_->AddRemoteCandidate(cand); |
| 160 TestSendRecv(); |
| 161 } |
| 162 |
| 163 TEST_F(RawUdpTransPortChannelTest, MaybeStartGatheringTwice) { |
| 164 ep1_.ch_->MaybeStartGathering(); |
| 165 ep1_.ch_->MaybeStartGathering(); |
| 166 EXPECT_EQ_WAIT(1u, ep1_.local_candidates_.size(), 1000); |
| 167 } |
| 168 |
| 169 TEST_F(RawUdpTransPortChannelTest, StatusAndSignals) { |
| 170 // TransportController connects to several signals of a TransportChannel. |
| 171 // RawUdpTransportChannel should emit all this signals. |
| 172 // Exception to this rule is SignalDtlsHandshakeError. |
| 173 EXPECT_EQ(kIceGatheringNew, ep1_.ch_->gathering_state()); |
| 174 ep1_.ch_->MaybeStartGathering(); |
| 175 ASSERT_EQ_WAIT(2u, ep1_.gathering_state_changes_.size(), 100); |
| 176 EXPECT_EQ(kIceGatheringGathering, ep1_.gathering_state_changes_[0]); |
| 177 EXPECT_EQ(kIceGatheringComplete, ep1_.gathering_state_changes_[1]); |
| 178 // Loopback |
| 179 EXPECT_EQ_WAIT(1u, ep1_.local_candidates_.size(), 100); |
| 180 Candidate cand = ep1_.local_candidates_[0]; |
| 181 EXPECT_TRUE(!ep1_.ch_->writable()); |
| 182 rtc::SocketAddress cand_addr = cand.address(); |
| 183 // keep port, but explicit set IP. |
| 184 cand_addr.SetIP("127.0.0.1"); |
| 185 cand.set_address(cand_addr); |
| 186 ep1_.ch_->AddRemoteCandidate(cand); |
| 187 EXPECT_TRUE(ep1_.ch_->writable()); |
| 188 // TODO(johan): test for SignalWritableState. |
| 189 const char data[] = "abc"; |
| 190 ep1_.SendData(data, sizeof(data)); |
| 191 EXPECT_EQ_WAIT(1u, ep1_.ch_packets_.size(), 100); |
| 192 } |
| 193 } // namespace cricket |
OLD | NEW |