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 | |
18 #include "webrtc/base/gunit.h" | |
19 #include "webrtc/base/thread.h" | |
20 #include "webrtc/base/socketserver.h" | |
21 #include "webrtc/p2p/base/transportchannelimpl.h" | |
22 #include "webrtc/p2p/rawudp/rawudptransportchannel.h" | |
23 | |
24 namespace cricket { | |
25 | |
26 class RawUdpTransPortChannelTest : public testing::Test, | |
27 public sigslot::has_slots<> { | |
28 public: | |
29 void SetUp() { | |
30 // TODO(johan) investigate whether an AutoThread should be instantiated. | |
31 network_thread_ = rtc::Thread::Current(); | |
32 ASSERT_NE(nullptr, network_thread_); | |
33 network_thread_->set_socketserver( | |
34 rtc::SocketServer::CreateDefault().release()); | |
35 ep1_.Init("name1", 1); | |
36 ep2_.Init("name2", 2); | |
37 } | |
sprang_webrtc
2016/10/07 09:56:22
nit: empty line between methods. here and elsewher
| |
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 void Reset() { | |
55 ch_.reset(); | |
56 local_candidates_.clear(); | |
57 remote_candidates_.clear(); | |
58 gathering_state_changes_.clear(); | |
59 } | |
60 bool CheckData(const char* data, int len) { | |
61 bool ret = false; | |
62 if (!ch_packets_.empty()) { | |
63 std::string packet = ch_packets_.front(); | |
64 ret = (packet == std::string(data, len)); | |
65 ch_packets_.pop_front(); | |
66 } | |
67 return ret; | |
68 } | |
69 | |
70 void ResetStats() { | |
71 num_received_packets_ = 0; | |
72 num_send_packets_ = 0; | |
73 count_signal_tch_state_changed_ = 0; | |
74 } | |
75 | |
76 void OnReadPacket(TransportChannel* channel, | |
77 const char* data, | |
78 size_t len, | |
79 const rtc::PacketTime& packet_time, | |
80 int flags) { | |
81 num_received_packets_++; | |
82 LOG(LS_VERBOSE) << "OnReadPacket (unittest)"; | |
83 ch_packets_.push_front(std::string(data, len)); | |
84 } | |
85 | |
86 int SendData(const char* data, size_t len) { | |
87 rtc::PacketOptions options; | |
88 return ch_->SendPacket(data, len, options, 0); | |
89 } | |
90 | |
91 void OnCandidateGathered(TransportChannelImpl* channel, | |
92 const Candidate& cand) { | |
93 ASSERT_EQ(ch_.get(), channel); | |
94 local_candidates_.push_back(cand); | |
95 } | |
96 | |
97 // for now this function is only well defined, if there is exact one local | |
98 // candidate | |
99 void GetLocalPort(uint16_t* local_port) { | |
100 ASSERT_EQ(1u, local_candidates_.size()); | |
101 const cricket::Candidate& cand = local_candidates_[0]; | |
102 const rtc::SocketAddress& addr = cand.address(); | |
103 *local_port = addr.port(); | |
104 } | |
105 | |
106 void OnGatheringStateChanged(TransportChannelImpl* channel) { | |
107 ASSERT_EQ(ch_.get(), channel); | |
108 IceGatheringState gathering_state = channel->gathering_state(); | |
109 gathering_state_changes_.push_back(gathering_state); | |
110 } | |
111 | |
112 std::list<std::string> ch_packets_; | |
113 std::unique_ptr<RawUdpTransportChannel> ch_; | |
114 uint32_t num_received_packets_; // increases on SignalReadPacket | |
115 uint32_t num_send_packets_; | |
116 std::vector<IceGatheringState> gathering_state_changes_; | |
117 uint32_t count_signal_tch_state_changed_; | |
118 // TODO(johan) check if it makes sense to have a vector of | |
119 // std::shared<cricket::Candidate> to simplify memory cleanup | |
120 Candidates local_candidates_; | |
121 Candidates remote_candidates_; | |
122 }; | |
123 Endpoint ep1_; | |
124 Endpoint ep2_; | |
125 rtc::Thread* network_thread_; | |
126 | |
127 void TestSendRecv() { | |
128 for (uint32_t i = 0; i < 5; ++i) { | |
129 static const char* data = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; | |
130 int len = static_cast<int>(strlen(data)); | |
131 // local_channel1 <==> remote_chanel1 | |
132 EXPECT_EQ_WAIT(len, ep1_.SendData(data, len), 1000); | |
133 // rtc::Thread::Current()->ProcessMessages(1000); | |
134 EXPECT_TRUE_WAIT(ep2_.CheckData(data, len), 1000); | |
135 EXPECT_EQ_WAIT(i + 1u, ep2_.num_received_packets_, 100); | |
136 EXPECT_EQ_WAIT(len, ep2_.SendData(data, len), 1000); | |
137 // rtc::Thread::Current()->ProcessMessages(1000); | |
138 EXPECT_TRUE_WAIT(ep1_.CheckData(data, len), 1000); | |
139 EXPECT_EQ_WAIT(i + 1u, ep1_.num_received_packets_, 100); | |
140 } | |
141 } | |
142 }; | |
143 | |
144 TEST_F(RawUdpTransPortChannelTest, SendRecvBasic) { | |
145 ep1_.ch_->MaybeStartGathering(); | |
146 ep2_.ch_->MaybeStartGathering(); | |
147 uint16_t port; | |
148 ep2_.GetLocalPort(&port); | |
149 rtc::SocketAddress addr2 = rtc::SocketAddress("127.0.0.1", port); | |
150 cricket::Candidate cand; | |
151 cand.set_address(addr2); | |
152 ep1_.ch_->AddRemoteCandidate(cand); | |
153 ep1_.GetLocalPort(&port); | |
154 rtc::SocketAddress addr1 = rtc::SocketAddress("127.0.0.1", port); | |
155 cand.set_address(addr1); | |
156 ep2_.ch_->AddRemoteCandidate(cand); | |
157 TestSendRecv(); | |
158 } | |
159 | |
160 TEST_F(RawUdpTransPortChannelTest, MaybeStartGatheringTwice) { | |
161 ep1_.ch_->MaybeStartGathering(); | |
162 ep1_.ch_->MaybeStartGathering(); | |
163 EXPECT_EQ_WAIT(1u, ep1_.local_candidates_.size(), 1000); | |
164 } | |
165 | |
166 TEST_F(RawUdpTransPortChannelTest, StatusAndSignals) { | |
167 /* TransportController connects to several signals of a TransportChannel. | |
168 RawUdpTransportChannel should emit all this signals. | |
169 Exception to this rule is SignalDtlsHandshakeError. | |
170 */ | |
sprang_webrtc
2016/10/07 09:56:21
Avoid /* */ blocks in favor of //-prefix for all l
johan
2016/10/07 12:24:26
Acknowledged.
| |
171 EXPECT_EQ(kIceGatheringNew, ep1_.ch_->gathering_state()); | |
172 ep1_.ch_->MaybeStartGathering(); | |
173 ASSERT_EQ_WAIT(2u, ep1_.gathering_state_changes_.size(), 100); | |
174 EXPECT_EQ(kIceGatheringGathering, ep1_.gathering_state_changes_[0]); | |
175 EXPECT_EQ(kIceGatheringComplete, ep1_.gathering_state_changes_[1]); | |
176 // Loopback | |
177 EXPECT_EQ_WAIT(1u, ep1_.local_candidates_.size(), 100); | |
178 Candidate& cand = ep1_.local_candidates_[0]; | |
sprang_webrtc
2016/10/07 09:56:21
Please use only const references, or pointer types
johan
2016/10/07 12:24:26
Good one. Actually I should have a copy in this pl
| |
179 EXPECT_TRUE(!ep1_.ch_->writable()); | |
180 rtc::SocketAddress cand_addr = cand.address(); | |
181 // keep port, but explicit set IP | |
182 cand_addr.SetIP("127.0.0.1"); | |
183 cand.set_address(cand_addr); | |
184 ep1_.ch_->AddRemoteCandidate(cand); | |
185 EXPECT_TRUE(ep1_.ch_->writable()); | |
186 // TODO(johan): test for SignalWritableState | |
187 const char data[] = "abc"; | |
188 ep1_.SendData(data, sizeof(data)); | |
189 EXPECT_EQ_WAIT(1u, ep1_.ch_packets_.size(), 100); | |
190 } | |
191 } // namespace cricket | |
OLD | NEW |