Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2019 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 | |
Jonas Olsson | a4d8737 | 2019-07-05 19:08:33 +0200 | [diff] [blame] | 11 | #include "test/network/network_emulation.h" |
| 12 | |
Artem Titov | ff39312 | 2019-04-05 11:19:52 +0200 | [diff] [blame] | 13 | #include <atomic> |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 14 | #include <memory> |
Artem Titov | 386802e | 2019-07-05 10:48:17 +0200 | [diff] [blame] | 15 | #include <set> |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 16 | |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 17 | #include "api/test/simulated_network.h" |
Artem Titov | a768345 | 2019-05-15 12:26:38 +0200 | [diff] [blame] | 18 | #include "api/units/time_delta.h" |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 19 | #include "call/simulated_network.h" |
| 20 | #include "rtc_base/event.h" |
Artem Titov | ff39312 | 2019-04-05 11:19:52 +0200 | [diff] [blame] | 21 | #include "rtc_base/gunit.h" |
Markus Handell | 4ab7dde | 2020-07-10 13:23:25 +0200 | [diff] [blame] | 22 | #include "rtc_base/synchronization/mutex.h" |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 23 | #include "test/gmock.h" |
| 24 | #include "test/gtest.h" |
Artem Titov | 386802e | 2019-07-05 10:48:17 +0200 | [diff] [blame] | 25 | #include "test/network/network_emulation_manager.h" |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 26 | |
| 27 | namespace webrtc { |
| 28 | namespace test { |
Artem Titov | ff39312 | 2019-04-05 11:19:52 +0200 | [diff] [blame] | 29 | namespace { |
| 30 | |
Artem Titov | 1062cfe | 2020-07-21 15:46:08 +0200 | [diff] [blame] | 31 | using ::testing::ElementsAreArray; |
| 32 | |
Danil Chapovalov | 0c626af | 2020-02-10 11:16:00 +0100 | [diff] [blame] | 33 | constexpr TimeDelta kNetworkPacketWaitTimeout = TimeDelta::Millis(100); |
| 34 | constexpr TimeDelta kStatsWaitTimeout = TimeDelta::Seconds(1); |
Niels Möller | 7536bc5 | 2019-10-04 13:54:39 +0200 | [diff] [blame] | 35 | constexpr int kOverheadIpv4Udp = 20 + 8; |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 36 | |
| 37 | class SocketReader : public sigslot::has_slots<> { |
| 38 | public: |
Niels Möller | d0b8879 | 2021-08-12 10:32:30 +0200 | [diff] [blame] | 39 | explicit SocketReader(rtc::Socket* socket, rtc::Thread* network_thread) |
Artem Titov | 519d74a | 2019-05-17 12:01:00 +0200 | [diff] [blame] | 40 | : socket_(socket), network_thread_(network_thread) { |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 41 | socket_->SignalReadEvent.connect(this, &SocketReader::OnReadEvent); |
| 42 | size_ = 128 * 1024; |
| 43 | buf_ = new char[size_]; |
| 44 | } |
| 45 | ~SocketReader() override { delete[] buf_; } |
| 46 | |
Niels Möller | d0b8879 | 2021-08-12 10:32:30 +0200 | [diff] [blame] | 47 | void OnReadEvent(rtc::Socket* socket) { |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 48 | RTC_DCHECK(socket_ == socket); |
Sebastian Jansson | 9d4bbc2 | 2020-01-10 20:03:56 +0100 | [diff] [blame] | 49 | RTC_DCHECK(network_thread_->IsCurrent()); |
| 50 | int64_t timestamp; |
| 51 | len_ = socket_->Recv(buf_, size_, ×tamp); |
Artem Titov | 519d74a | 2019-05-17 12:01:00 +0200 | [diff] [blame] | 52 | |
Markus Handell | 4ab7dde | 2020-07-10 13:23:25 +0200 | [diff] [blame] | 53 | MutexLock lock(&lock_); |
Sebastian Jansson | 9d4bbc2 | 2020-01-10 20:03:56 +0100 | [diff] [blame] | 54 | received_count_++; |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 55 | } |
| 56 | |
| 57 | int ReceivedCount() { |
Markus Handell | 4ab7dde | 2020-07-10 13:23:25 +0200 | [diff] [blame] | 58 | MutexLock lock(&lock_); |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 59 | return received_count_; |
| 60 | } |
| 61 | |
| 62 | private: |
Niels Möller | d0b8879 | 2021-08-12 10:32:30 +0200 | [diff] [blame] | 63 | rtc::Socket* const socket_; |
Artem Titov | 519d74a | 2019-05-17 12:01:00 +0200 | [diff] [blame] | 64 | rtc::Thread* const network_thread_; |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 65 | char* buf_; |
| 66 | size_t size_; |
| 67 | int len_; |
| 68 | |
Markus Handell | 4ab7dde | 2020-07-10 13:23:25 +0200 | [diff] [blame] | 69 | Mutex lock_; |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 70 | int received_count_ RTC_GUARDED_BY(lock_) = 0; |
| 71 | }; |
| 72 | |
Artem Titov | ff39312 | 2019-04-05 11:19:52 +0200 | [diff] [blame] | 73 | class MockReceiver : public EmulatedNetworkReceiverInterface { |
| 74 | public: |
Danil Chapovalov | 54706d6 | 2020-05-14 19:50:01 +0200 | [diff] [blame] | 75 | MOCK_METHOD(void, OnPacketReceived, (EmulatedIpPacket packet), (override)); |
Artem Titov | ff39312 | 2019-04-05 11:19:52 +0200 | [diff] [blame] | 76 | }; |
| 77 | |
| 78 | class NetworkEmulationManagerThreeNodesRoutingTest : public ::testing::Test { |
| 79 | public: |
| 80 | NetworkEmulationManagerThreeNodesRoutingTest() { |
| 81 | e1_ = emulation_.CreateEndpoint(EmulatedEndpointConfig()); |
| 82 | e2_ = emulation_.CreateEndpoint(EmulatedEndpointConfig()); |
| 83 | e3_ = emulation_.CreateEndpoint(EmulatedEndpointConfig()); |
| 84 | } |
| 85 | |
| 86 | void SetupRouting( |
| 87 | std::function<void(EmulatedEndpoint*, |
| 88 | EmulatedEndpoint*, |
| 89 | EmulatedEndpoint*, |
| 90 | NetworkEmulationManager*)> create_routing_func) { |
| 91 | create_routing_func(e1_, e2_, e3_, &emulation_); |
| 92 | } |
| 93 | |
| 94 | void SendPacketsAndValidateDelivery() { |
Mirko Bonadei | 6a489f2 | 2019-04-09 15:11:12 +0200 | [diff] [blame] | 95 | EXPECT_CALL(r_e1_e2_, OnPacketReceived(::testing::_)).Times(1); |
| 96 | EXPECT_CALL(r_e2_e1_, OnPacketReceived(::testing::_)).Times(1); |
| 97 | EXPECT_CALL(r_e1_e3_, OnPacketReceived(::testing::_)).Times(1); |
| 98 | EXPECT_CALL(r_e3_e1_, OnPacketReceived(::testing::_)).Times(1); |
Artem Titov | ff39312 | 2019-04-05 11:19:52 +0200 | [diff] [blame] | 99 | |
| 100 | uint16_t common_send_port = 80; |
| 101 | uint16_t r_e1_e2_port = e2_->BindReceiver(0, &r_e1_e2_).value(); |
| 102 | uint16_t r_e2_e1_port = e1_->BindReceiver(0, &r_e2_e1_).value(); |
| 103 | uint16_t r_e1_e3_port = e3_->BindReceiver(0, &r_e1_e3_).value(); |
| 104 | uint16_t r_e3_e1_port = e1_->BindReceiver(0, &r_e3_e1_).value(); |
| 105 | |
| 106 | // Next code is using API of EmulatedEndpoint, that is visible only for |
| 107 | // internals of network emulation layer. Don't use this API in other tests. |
| 108 | // Send packet from e1 to e2. |
| 109 | e1_->SendPacket( |
| 110 | rtc::SocketAddress(e1_->GetPeerLocalAddress(), common_send_port), |
| 111 | rtc::SocketAddress(e2_->GetPeerLocalAddress(), r_e1_e2_port), |
| 112 | rtc::CopyOnWriteBuffer(10)); |
| 113 | |
| 114 | // Send packet from e2 to e1. |
| 115 | e2_->SendPacket( |
| 116 | rtc::SocketAddress(e2_->GetPeerLocalAddress(), common_send_port), |
| 117 | rtc::SocketAddress(e1_->GetPeerLocalAddress(), r_e2_e1_port), |
| 118 | rtc::CopyOnWriteBuffer(10)); |
| 119 | |
| 120 | // Send packet from e1 to e3. |
| 121 | e1_->SendPacket( |
| 122 | rtc::SocketAddress(e1_->GetPeerLocalAddress(), common_send_port), |
| 123 | rtc::SocketAddress(e3_->GetPeerLocalAddress(), r_e1_e3_port), |
| 124 | rtc::CopyOnWriteBuffer(10)); |
| 125 | |
| 126 | // Send packet from e3 to e1. |
| 127 | e3_->SendPacket( |
| 128 | rtc::SocketAddress(e3_->GetPeerLocalAddress(), common_send_port), |
| 129 | rtc::SocketAddress(e1_->GetPeerLocalAddress(), r_e3_e1_port), |
| 130 | rtc::CopyOnWriteBuffer(10)); |
| 131 | |
| 132 | // Sleep at the end to wait for async packets delivery. |
Sebastian Jansson | 6ce033a | 2020-01-22 10:12:56 +0100 | [diff] [blame] | 133 | emulation_.time_controller()->AdvanceTime(kNetworkPacketWaitTimeout); |
Artem Titov | ff39312 | 2019-04-05 11:19:52 +0200 | [diff] [blame] | 134 | } |
| 135 | |
| 136 | private: |
| 137 | // Receivers: r_<source endpoint>_<destination endpoint> |
| 138 | // They must be destroyed after emulation, so they should be declared before. |
| 139 | MockReceiver r_e1_e2_; |
| 140 | MockReceiver r_e2_e1_; |
| 141 | MockReceiver r_e1_e3_; |
| 142 | MockReceiver r_e3_e1_; |
| 143 | |
Sebastian Jansson | 6ce033a | 2020-01-22 10:12:56 +0100 | [diff] [blame] | 144 | NetworkEmulationManagerImpl emulation_{TimeMode::kRealTime}; |
Artem Titov | ff39312 | 2019-04-05 11:19:52 +0200 | [diff] [blame] | 145 | EmulatedEndpoint* e1_; |
| 146 | EmulatedEndpoint* e2_; |
| 147 | EmulatedEndpoint* e3_; |
| 148 | }; |
| 149 | |
| 150 | EmulatedNetworkNode* CreateEmulatedNodeWithDefaultBuiltInConfig( |
| 151 | NetworkEmulationManager* emulation) { |
| 152 | return emulation->CreateEmulatedNode( |
Mirko Bonadei | 317a1f0 | 2019-09-17 17:06:18 +0200 | [diff] [blame] | 153 | std::make_unique<SimulatedNetwork>(BuiltInNetworkBehaviorConfig())); |
Artem Titov | ff39312 | 2019-04-05 11:19:52 +0200 | [diff] [blame] | 154 | } |
| 155 | |
| 156 | } // namespace |
| 157 | |
Mirko Bonadei | 6a489f2 | 2019-04-09 15:11:12 +0200 | [diff] [blame] | 158 | using ::testing::_; |
Artem Titov | ff39312 | 2019-04-05 11:19:52 +0200 | [diff] [blame] | 159 | |
Artem Titov | 0bf4c29 | 2019-02-26 10:00:07 +0100 | [diff] [blame] | 160 | TEST(NetworkEmulationManagerTest, GeneratedIpv4AddressDoesNotCollide) { |
Sebastian Jansson | 6ce033a | 2020-01-22 10:12:56 +0100 | [diff] [blame] | 161 | NetworkEmulationManagerImpl network_manager(TimeMode::kRealTime); |
Artem Titov | 0bf4c29 | 2019-02-26 10:00:07 +0100 | [diff] [blame] | 162 | std::set<rtc::IPAddress> ips; |
Artem Titov | a268b69 | 2019-03-12 13:37:28 +0100 | [diff] [blame] | 163 | EmulatedEndpointConfig config; |
| 164 | config.generated_ip_family = EmulatedEndpointConfig::IpAddressFamily::kIpv4; |
Artem Titov | 0bf4c29 | 2019-02-26 10:00:07 +0100 | [diff] [blame] | 165 | for (int i = 0; i < 1000; i++) { |
Artem Titov | aba8dc2 | 2019-03-11 10:08:40 +0100 | [diff] [blame] | 166 | EmulatedEndpoint* endpoint = network_manager.CreateEndpoint(config); |
Artem Titov | 0bf4c29 | 2019-02-26 10:00:07 +0100 | [diff] [blame] | 167 | ASSERT_EQ(endpoint->GetPeerLocalAddress().family(), AF_INET); |
| 168 | bool result = ips.insert(endpoint->GetPeerLocalAddress()).second; |
| 169 | ASSERT_TRUE(result); |
| 170 | } |
| 171 | } |
| 172 | |
| 173 | TEST(NetworkEmulationManagerTest, GeneratedIpv6AddressDoesNotCollide) { |
Sebastian Jansson | 6ce033a | 2020-01-22 10:12:56 +0100 | [diff] [blame] | 174 | NetworkEmulationManagerImpl network_manager(TimeMode::kRealTime); |
Artem Titov | 0bf4c29 | 2019-02-26 10:00:07 +0100 | [diff] [blame] | 175 | std::set<rtc::IPAddress> ips; |
Artem Titov | a268b69 | 2019-03-12 13:37:28 +0100 | [diff] [blame] | 176 | EmulatedEndpointConfig config; |
| 177 | config.generated_ip_family = EmulatedEndpointConfig::IpAddressFamily::kIpv6; |
Artem Titov | 0bf4c29 | 2019-02-26 10:00:07 +0100 | [diff] [blame] | 178 | for (int i = 0; i < 1000; i++) { |
Artem Titov | aba8dc2 | 2019-03-11 10:08:40 +0100 | [diff] [blame] | 179 | EmulatedEndpoint* endpoint = network_manager.CreateEndpoint(config); |
Artem Titov | 0bf4c29 | 2019-02-26 10:00:07 +0100 | [diff] [blame] | 180 | ASSERT_EQ(endpoint->GetPeerLocalAddress().family(), AF_INET6); |
| 181 | bool result = ips.insert(endpoint->GetPeerLocalAddress()).second; |
| 182 | ASSERT_TRUE(result); |
| 183 | } |
| 184 | } |
| 185 | |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 186 | TEST(NetworkEmulationManagerTest, Run) { |
Sebastian Jansson | 6ce033a | 2020-01-22 10:12:56 +0100 | [diff] [blame] | 187 | NetworkEmulationManagerImpl network_manager(TimeMode::kRealTime); |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 188 | |
| 189 | EmulatedNetworkNode* alice_node = network_manager.CreateEmulatedNode( |
Mirko Bonadei | 317a1f0 | 2019-09-17 17:06:18 +0200 | [diff] [blame] | 190 | std::make_unique<SimulatedNetwork>(BuiltInNetworkBehaviorConfig())); |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 191 | EmulatedNetworkNode* bob_node = network_manager.CreateEmulatedNode( |
Mirko Bonadei | 317a1f0 | 2019-09-17 17:06:18 +0200 | [diff] [blame] | 192 | std::make_unique<SimulatedNetwork>(BuiltInNetworkBehaviorConfig())); |
Artem Titov | aba8dc2 | 2019-03-11 10:08:40 +0100 | [diff] [blame] | 193 | EmulatedEndpoint* alice_endpoint = |
Artem Titov | a268b69 | 2019-03-12 13:37:28 +0100 | [diff] [blame] | 194 | network_manager.CreateEndpoint(EmulatedEndpointConfig()); |
Artem Titov | aba8dc2 | 2019-03-11 10:08:40 +0100 | [diff] [blame] | 195 | EmulatedEndpoint* bob_endpoint = |
Artem Titov | a268b69 | 2019-03-12 13:37:28 +0100 | [diff] [blame] | 196 | network_manager.CreateEndpoint(EmulatedEndpointConfig()); |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 197 | network_manager.CreateRoute(alice_endpoint, {alice_node}, bob_endpoint); |
| 198 | network_manager.CreateRoute(bob_endpoint, {bob_node}, alice_endpoint); |
| 199 | |
Artem Titov | e5cc85b | 2019-03-28 12:11:09 +0100 | [diff] [blame] | 200 | EmulatedNetworkManagerInterface* nt1 = |
| 201 | network_manager.CreateEmulatedNetworkManagerInterface({alice_endpoint}); |
| 202 | EmulatedNetworkManagerInterface* nt2 = |
| 203 | network_manager.CreateEmulatedNetworkManagerInterface({bob_endpoint}); |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 204 | |
Sebastian Jansson | 9d4bbc2 | 2020-01-10 20:03:56 +0100 | [diff] [blame] | 205 | rtc::Thread* t1 = nt1->network_thread(); |
| 206 | rtc::Thread* t2 = nt2->network_thread(); |
| 207 | |
Artem Titov | 806299e | 2019-04-12 12:17:19 +0200 | [diff] [blame] | 208 | rtc::CopyOnWriteBuffer data("Hello"); |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 209 | for (uint64_t j = 0; j < 2; j++) { |
Niels Möller | d0b8879 | 2021-08-12 10:32:30 +0200 | [diff] [blame] | 210 | rtc::Socket* s1 = nullptr; |
| 211 | rtc::Socket* s2 = nullptr; |
Danil Chapovalov | 7358b40 | 2021-02-01 20:43:19 +0100 | [diff] [blame] | 212 | t1->Invoke<void>(RTC_FROM_HERE, [&] { |
Niels Möller | d0b8879 | 2021-08-12 10:32:30 +0200 | [diff] [blame] | 213 | s1 = t1->socketserver()->CreateSocket(AF_INET, SOCK_DGRAM); |
Danil Chapovalov | 7358b40 | 2021-02-01 20:43:19 +0100 | [diff] [blame] | 214 | }); |
| 215 | t2->Invoke<void>(RTC_FROM_HERE, [&] { |
Niels Möller | d0b8879 | 2021-08-12 10:32:30 +0200 | [diff] [blame] | 216 | s2 = t2->socketserver()->CreateSocket(AF_INET, SOCK_DGRAM); |
Danil Chapovalov | 7358b40 | 2021-02-01 20:43:19 +0100 | [diff] [blame] | 217 | }); |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 218 | |
Sebastian Jansson | 9d4bbc2 | 2020-01-10 20:03:56 +0100 | [diff] [blame] | 219 | SocketReader r1(s1, t1); |
| 220 | SocketReader r2(s2, t2); |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 221 | |
| 222 | rtc::SocketAddress a1(alice_endpoint->GetPeerLocalAddress(), 0); |
| 223 | rtc::SocketAddress a2(bob_endpoint->GetPeerLocalAddress(), 0); |
| 224 | |
Sebastian Jansson | 9d4bbc2 | 2020-01-10 20:03:56 +0100 | [diff] [blame] | 225 | t1->Invoke<void>(RTC_FROM_HERE, [&] { |
| 226 | s1->Bind(a1); |
| 227 | a1 = s1->GetLocalAddress(); |
| 228 | }); |
| 229 | t2->Invoke<void>(RTC_FROM_HERE, [&] { |
| 230 | s2->Bind(a2); |
| 231 | a2 = s2->GetLocalAddress(); |
| 232 | }); |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 233 | |
Sebastian Jansson | 9d4bbc2 | 2020-01-10 20:03:56 +0100 | [diff] [blame] | 234 | t1->Invoke<void>(RTC_FROM_HERE, [&] { s1->Connect(a2); }); |
| 235 | t2->Invoke<void>(RTC_FROM_HERE, [&] { s2->Connect(a1); }); |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 236 | |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 237 | for (uint64_t i = 0; i < 1000; i++) { |
Henrik Boström | 2deee4b | 2022-01-20 11:58:05 +0100 | [diff] [blame] | 238 | t1->PostTask([&]() { s1->Send(data.data(), data.size()); }); |
| 239 | t2->PostTask([&]() { s2->Send(data.data(), data.size()); }); |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 240 | } |
| 241 | |
Danil Chapovalov | 0c626af | 2020-02-10 11:16:00 +0100 | [diff] [blame] | 242 | network_manager.time_controller()->AdvanceTime(TimeDelta::Seconds(1)); |
Sebastian Jansson | 6ce033a | 2020-01-22 10:12:56 +0100 | [diff] [blame] | 243 | |
Artem Titov | 806299e | 2019-04-12 12:17:19 +0200 | [diff] [blame] | 244 | EXPECT_EQ(r1.ReceivedCount(), 1000); |
| 245 | EXPECT_EQ(r2.ReceivedCount(), 1000); |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 246 | |
Sebastian Jansson | 9d4bbc2 | 2020-01-10 20:03:56 +0100 | [diff] [blame] | 247 | t1->Invoke<void>(RTC_FROM_HERE, [&] { delete s1; }); |
| 248 | t2->Invoke<void>(RTC_FROM_HERE, [&] { delete s2; }); |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 249 | } |
Artem Titov | 806299e | 2019-04-12 12:17:19 +0200 | [diff] [blame] | 250 | |
Niels Möller | 7536bc5 | 2019-10-04 13:54:39 +0200 | [diff] [blame] | 251 | const int64_t single_packet_size = data.size() + kOverheadIpv4Udp; |
Artem Titov | 806299e | 2019-04-12 12:17:19 +0200 | [diff] [blame] | 252 | std::atomic<int> received_stats_count{0}; |
Artem Titov | 3e0b65d | 2020-07-23 02:19:02 +0200 | [diff] [blame] | 253 | nt1->GetStats([&](std::unique_ptr<EmulatedNetworkStats> st) { |
| 254 | EXPECT_EQ(st->PacketsSent(), 2000l); |
| 255 | EXPECT_EQ(st->BytesSent().bytes(), single_packet_size * 2000l); |
| 256 | EXPECT_THAT(st->LocalAddresses(), |
Artem Titov | 1062cfe | 2020-07-21 15:46:08 +0200 | [diff] [blame] | 257 | ElementsAreArray({alice_endpoint->GetPeerLocalAddress()})); |
Artem Titov | 3e0b65d | 2020-07-23 02:19:02 +0200 | [diff] [blame] | 258 | EXPECT_EQ(st->PacketsReceived(), 2000l); |
| 259 | EXPECT_EQ(st->BytesReceived().bytes(), single_packet_size * 2000l); |
| 260 | EXPECT_EQ(st->PacketsDropped(), 0l); |
| 261 | EXPECT_EQ(st->BytesDropped().bytes(), 0l); |
Artem Titov | c1a0737 | 2020-07-21 09:50:11 +0200 | [diff] [blame] | 262 | |
Artem Titov | 14b46a7 | 2020-07-31 12:57:24 +0200 | [diff] [blame] | 263 | rtc::IPAddress bob_ip = bob_endpoint->GetPeerLocalAddress(); |
| 264 | std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkIncomingStats>> |
| 265 | source_st = st->IncomingStatsPerSource(); |
Artem Titov | 3e0b65d | 2020-07-23 02:19:02 +0200 | [diff] [blame] | 266 | ASSERT_EQ(source_st.size(), 1lu); |
Artem Titov | 14b46a7 | 2020-07-31 12:57:24 +0200 | [diff] [blame] | 267 | EXPECT_EQ(source_st.at(bob_ip)->PacketsReceived(), 2000l); |
| 268 | EXPECT_EQ(source_st.at(bob_ip)->BytesReceived().bytes(), |
Artem Titov | c1a0737 | 2020-07-21 09:50:11 +0200 | [diff] [blame] | 269 | single_packet_size * 2000l); |
Artem Titov | 14b46a7 | 2020-07-31 12:57:24 +0200 | [diff] [blame] | 270 | EXPECT_EQ(source_st.at(bob_ip)->PacketsDropped(), 0l); |
| 271 | EXPECT_EQ(source_st.at(bob_ip)->BytesDropped().bytes(), 0l); |
| 272 | |
| 273 | std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkOutgoingStats>> |
| 274 | dest_st = st->OutgoingStatsPerDestination(); |
| 275 | ASSERT_EQ(dest_st.size(), 1lu); |
| 276 | EXPECT_EQ(dest_st.at(bob_ip)->PacketsSent(), 2000l); |
| 277 | EXPECT_EQ(dest_st.at(bob_ip)->BytesSent().bytes(), |
| 278 | single_packet_size * 2000l); |
Artem Titov | cbe6e8a | 2020-09-22 15:45:00 +0200 | [diff] [blame] | 279 | |
| 280 | // No debug stats are collected by default. |
| 281 | EXPECT_TRUE(st->SentPacketsSizeCounter().IsEmpty()); |
| 282 | EXPECT_TRUE(st->SentPacketsQueueWaitTimeUs().IsEmpty()); |
| 283 | EXPECT_TRUE(st->ReceivedPacketsSizeCounter().IsEmpty()); |
| 284 | EXPECT_TRUE(st->DroppedPacketsSizeCounter().IsEmpty()); |
| 285 | EXPECT_TRUE(dest_st.at(bob_ip)->SentPacketsSizeCounter().IsEmpty()); |
| 286 | EXPECT_TRUE(source_st.at(bob_ip)->ReceivedPacketsSizeCounter().IsEmpty()); |
| 287 | EXPECT_TRUE(source_st.at(bob_ip)->DroppedPacketsSizeCounter().IsEmpty()); |
| 288 | |
Artem Titov | 806299e | 2019-04-12 12:17:19 +0200 | [diff] [blame] | 289 | received_stats_count++; |
| 290 | }); |
Artem Titov | 3e0b65d | 2020-07-23 02:19:02 +0200 | [diff] [blame] | 291 | nt2->GetStats([&](std::unique_ptr<EmulatedNetworkStats> st) { |
| 292 | EXPECT_EQ(st->PacketsSent(), 2000l); |
| 293 | EXPECT_EQ(st->BytesSent().bytes(), single_packet_size * 2000l); |
| 294 | EXPECT_THAT(st->LocalAddresses(), |
Artem Titov | 1062cfe | 2020-07-21 15:46:08 +0200 | [diff] [blame] | 295 | ElementsAreArray({bob_endpoint->GetPeerLocalAddress()})); |
Artem Titov | 3e0b65d | 2020-07-23 02:19:02 +0200 | [diff] [blame] | 296 | EXPECT_EQ(st->PacketsReceived(), 2000l); |
| 297 | EXPECT_EQ(st->BytesReceived().bytes(), single_packet_size * 2000l); |
| 298 | EXPECT_EQ(st->PacketsDropped(), 0l); |
| 299 | EXPECT_EQ(st->BytesDropped().bytes(), 0l); |
| 300 | EXPECT_GT(st->FirstReceivedPacketSize(), DataSize::Zero()); |
| 301 | EXPECT_TRUE(st->FirstPacketReceivedTime().IsFinite()); |
| 302 | EXPECT_TRUE(st->LastPacketReceivedTime().IsFinite()); |
Artem Titov | c1a0737 | 2020-07-21 09:50:11 +0200 | [diff] [blame] | 303 | |
Artem Titov | 14b46a7 | 2020-07-31 12:57:24 +0200 | [diff] [blame] | 304 | rtc::IPAddress alice_ip = alice_endpoint->GetPeerLocalAddress(); |
| 305 | std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkIncomingStats>> |
| 306 | source_st = st->IncomingStatsPerSource(); |
Artem Titov | 3e0b65d | 2020-07-23 02:19:02 +0200 | [diff] [blame] | 307 | ASSERT_EQ(source_st.size(), 1lu); |
Artem Titov | 14b46a7 | 2020-07-31 12:57:24 +0200 | [diff] [blame] | 308 | EXPECT_EQ(source_st.at(alice_ip)->PacketsReceived(), 2000l); |
| 309 | EXPECT_EQ(source_st.at(alice_ip)->BytesReceived().bytes(), |
Artem Titov | 3e0b65d | 2020-07-23 02:19:02 +0200 | [diff] [blame] | 310 | single_packet_size * 2000l); |
Artem Titov | 14b46a7 | 2020-07-31 12:57:24 +0200 | [diff] [blame] | 311 | EXPECT_EQ(source_st.at(alice_ip)->PacketsDropped(), 0l); |
| 312 | EXPECT_EQ(source_st.at(alice_ip)->BytesDropped().bytes(), 0l); |
| 313 | |
| 314 | std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkOutgoingStats>> |
| 315 | dest_st = st->OutgoingStatsPerDestination(); |
| 316 | ASSERT_EQ(dest_st.size(), 1lu); |
| 317 | EXPECT_EQ(dest_st.at(alice_ip)->PacketsSent(), 2000l); |
| 318 | EXPECT_EQ(dest_st.at(alice_ip)->BytesSent().bytes(), |
| 319 | single_packet_size * 2000l); |
Artem Titov | cbe6e8a | 2020-09-22 15:45:00 +0200 | [diff] [blame] | 320 | |
| 321 | // No debug stats are collected by default. |
| 322 | EXPECT_TRUE(st->SentPacketsSizeCounter().IsEmpty()); |
| 323 | EXPECT_TRUE(st->SentPacketsQueueWaitTimeUs().IsEmpty()); |
| 324 | EXPECT_TRUE(st->ReceivedPacketsSizeCounter().IsEmpty()); |
| 325 | EXPECT_TRUE(st->DroppedPacketsSizeCounter().IsEmpty()); |
| 326 | EXPECT_TRUE(dest_st.at(alice_ip)->SentPacketsSizeCounter().IsEmpty()); |
| 327 | EXPECT_TRUE(source_st.at(alice_ip)->ReceivedPacketsSizeCounter().IsEmpty()); |
| 328 | EXPECT_TRUE(source_st.at(alice_ip)->DroppedPacketsSizeCounter().IsEmpty()); |
| 329 | |
Artem Titov | 806299e | 2019-04-12 12:17:19 +0200 | [diff] [blame] | 330 | received_stats_count++; |
| 331 | }); |
Sebastian Jansson | 6ce033a | 2020-01-22 10:12:56 +0100 | [diff] [blame] | 332 | ASSERT_EQ_SIMULATED_WAIT(received_stats_count.load(), 2, |
| 333 | kStatsWaitTimeout.ms(), |
| 334 | *network_manager.time_controller()); |
Artem Titov | 806299e | 2019-04-12 12:17:19 +0200 | [diff] [blame] | 335 | } |
| 336 | |
Artem Titov | cbe6e8a | 2020-09-22 15:45:00 +0200 | [diff] [blame] | 337 | TEST(NetworkEmulationManagerTest, DebugStatsCollectedInDebugMode) { |
| 338 | NetworkEmulationManagerImpl network_manager(TimeMode::kSimulated); |
| 339 | |
| 340 | EmulatedNetworkNode* alice_node = network_manager.CreateEmulatedNode( |
| 341 | std::make_unique<SimulatedNetwork>(BuiltInNetworkBehaviorConfig())); |
| 342 | EmulatedNetworkNode* bob_node = network_manager.CreateEmulatedNode( |
| 343 | std::make_unique<SimulatedNetwork>(BuiltInNetworkBehaviorConfig())); |
| 344 | EmulatedEndpointConfig debug_config; |
| 345 | debug_config.stats_gathering_mode = |
| 346 | EmulatedEndpointConfig::StatsGatheringMode::kDebug; |
| 347 | EmulatedEndpoint* alice_endpoint = |
| 348 | network_manager.CreateEndpoint(debug_config); |
| 349 | EmulatedEndpoint* bob_endpoint = |
| 350 | network_manager.CreateEndpoint(EmulatedEndpointConfig()); |
| 351 | network_manager.CreateRoute(alice_endpoint, {alice_node}, bob_endpoint); |
| 352 | network_manager.CreateRoute(bob_endpoint, {bob_node}, alice_endpoint); |
| 353 | |
| 354 | EmulatedNetworkManagerInterface* nt1 = |
| 355 | network_manager.CreateEmulatedNetworkManagerInterface({alice_endpoint}); |
| 356 | EmulatedNetworkManagerInterface* nt2 = |
| 357 | network_manager.CreateEmulatedNetworkManagerInterface({bob_endpoint}); |
| 358 | |
| 359 | rtc::Thread* t1 = nt1->network_thread(); |
| 360 | rtc::Thread* t2 = nt2->network_thread(); |
| 361 | |
| 362 | rtc::CopyOnWriteBuffer data("Hello"); |
| 363 | for (uint64_t j = 0; j < 2; j++) { |
Niels Möller | d0b8879 | 2021-08-12 10:32:30 +0200 | [diff] [blame] | 364 | rtc::Socket* s1 = nullptr; |
| 365 | rtc::Socket* s2 = nullptr; |
Danil Chapovalov | 7358b40 | 2021-02-01 20:43:19 +0100 | [diff] [blame] | 366 | t1->Invoke<void>(RTC_FROM_HERE, [&] { |
Niels Möller | d0b8879 | 2021-08-12 10:32:30 +0200 | [diff] [blame] | 367 | s1 = t1->socketserver()->CreateSocket(AF_INET, SOCK_DGRAM); |
Danil Chapovalov | 7358b40 | 2021-02-01 20:43:19 +0100 | [diff] [blame] | 368 | }); |
| 369 | t2->Invoke<void>(RTC_FROM_HERE, [&] { |
Niels Möller | d0b8879 | 2021-08-12 10:32:30 +0200 | [diff] [blame] | 370 | s2 = t2->socketserver()->CreateSocket(AF_INET, SOCK_DGRAM); |
Danil Chapovalov | 7358b40 | 2021-02-01 20:43:19 +0100 | [diff] [blame] | 371 | }); |
Artem Titov | cbe6e8a | 2020-09-22 15:45:00 +0200 | [diff] [blame] | 372 | |
| 373 | SocketReader r1(s1, t1); |
| 374 | SocketReader r2(s2, t2); |
| 375 | |
| 376 | rtc::SocketAddress a1(alice_endpoint->GetPeerLocalAddress(), 0); |
| 377 | rtc::SocketAddress a2(bob_endpoint->GetPeerLocalAddress(), 0); |
| 378 | |
| 379 | t1->Invoke<void>(RTC_FROM_HERE, [&] { |
| 380 | s1->Bind(a1); |
| 381 | a1 = s1->GetLocalAddress(); |
| 382 | }); |
| 383 | t2->Invoke<void>(RTC_FROM_HERE, [&] { |
| 384 | s2->Bind(a2); |
| 385 | a2 = s2->GetLocalAddress(); |
| 386 | }); |
| 387 | |
| 388 | t1->Invoke<void>(RTC_FROM_HERE, [&] { s1->Connect(a2); }); |
| 389 | t2->Invoke<void>(RTC_FROM_HERE, [&] { s2->Connect(a1); }); |
| 390 | |
| 391 | for (uint64_t i = 0; i < 1000; i++) { |
Henrik Boström | 2deee4b | 2022-01-20 11:58:05 +0100 | [diff] [blame] | 392 | t1->PostTask([&]() { s1->Send(data.data(), data.size()); }); |
| 393 | t2->PostTask([&]() { s2->Send(data.data(), data.size()); }); |
Artem Titov | cbe6e8a | 2020-09-22 15:45:00 +0200 | [diff] [blame] | 394 | } |
| 395 | |
| 396 | network_manager.time_controller()->AdvanceTime(TimeDelta::Seconds(1)); |
| 397 | |
| 398 | EXPECT_EQ(r1.ReceivedCount(), 1000); |
| 399 | EXPECT_EQ(r2.ReceivedCount(), 1000); |
| 400 | |
| 401 | t1->Invoke<void>(RTC_FROM_HERE, [&] { delete s1; }); |
| 402 | t2->Invoke<void>(RTC_FROM_HERE, [&] { delete s2; }); |
| 403 | } |
| 404 | |
| 405 | const int64_t single_packet_size = data.size() + kOverheadIpv4Udp; |
| 406 | std::atomic<int> received_stats_count{0}; |
| 407 | nt1->GetStats([&](std::unique_ptr<EmulatedNetworkStats> st) { |
| 408 | rtc::IPAddress bob_ip = bob_endpoint->GetPeerLocalAddress(); |
| 409 | std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkIncomingStats>> |
| 410 | source_st = st->IncomingStatsPerSource(); |
| 411 | ASSERT_EQ(source_st.size(), 1lu); |
| 412 | |
| 413 | std::map<rtc::IPAddress, std::unique_ptr<EmulatedNetworkOutgoingStats>> |
| 414 | dest_st = st->OutgoingStatsPerDestination(); |
| 415 | ASSERT_EQ(dest_st.size(), 1lu); |
| 416 | |
| 417 | // No debug stats are collected by default. |
| 418 | EXPECT_EQ(st->SentPacketsSizeCounter().NumSamples(), 2000l); |
| 419 | EXPECT_EQ(st->ReceivedPacketsSizeCounter().GetAverage(), |
| 420 | single_packet_size); |
| 421 | EXPECT_EQ(st->SentPacketsQueueWaitTimeUs().NumSamples(), 2000l); |
| 422 | EXPECT_LT(st->SentPacketsQueueWaitTimeUs().GetMax(), 1); |
| 423 | EXPECT_TRUE(st->DroppedPacketsSizeCounter().IsEmpty()); |
| 424 | EXPECT_EQ(dest_st.at(bob_ip)->SentPacketsSizeCounter().NumSamples(), 2000l); |
| 425 | EXPECT_EQ(dest_st.at(bob_ip)->SentPacketsSizeCounter().GetAverage(), |
| 426 | single_packet_size); |
| 427 | EXPECT_EQ(source_st.at(bob_ip)->ReceivedPacketsSizeCounter().NumSamples(), |
| 428 | 2000l); |
| 429 | EXPECT_EQ(source_st.at(bob_ip)->ReceivedPacketsSizeCounter().GetAverage(), |
| 430 | single_packet_size); |
| 431 | EXPECT_TRUE(source_st.at(bob_ip)->DroppedPacketsSizeCounter().IsEmpty()); |
| 432 | |
| 433 | received_stats_count++; |
| 434 | }); |
| 435 | ASSERT_EQ_SIMULATED_WAIT(received_stats_count.load(), 1, |
| 436 | kStatsWaitTimeout.ms(), |
| 437 | *network_manager.time_controller()); |
| 438 | } |
| 439 | |
Artem Titov | a768345 | 2019-05-15 12:26:38 +0200 | [diff] [blame] | 440 | TEST(NetworkEmulationManagerTest, ThroughputStats) { |
Sebastian Jansson | 6ce033a | 2020-01-22 10:12:56 +0100 | [diff] [blame] | 441 | NetworkEmulationManagerImpl network_manager(TimeMode::kRealTime); |
Artem Titov | 806299e | 2019-04-12 12:17:19 +0200 | [diff] [blame] | 442 | |
| 443 | EmulatedNetworkNode* alice_node = network_manager.CreateEmulatedNode( |
Mirko Bonadei | 317a1f0 | 2019-09-17 17:06:18 +0200 | [diff] [blame] | 444 | std::make_unique<SimulatedNetwork>(BuiltInNetworkBehaviorConfig())); |
Artem Titov | 806299e | 2019-04-12 12:17:19 +0200 | [diff] [blame] | 445 | EmulatedNetworkNode* bob_node = network_manager.CreateEmulatedNode( |
Mirko Bonadei | 317a1f0 | 2019-09-17 17:06:18 +0200 | [diff] [blame] | 446 | std::make_unique<SimulatedNetwork>(BuiltInNetworkBehaviorConfig())); |
Artem Titov | 806299e | 2019-04-12 12:17:19 +0200 | [diff] [blame] | 447 | EmulatedEndpoint* alice_endpoint = |
| 448 | network_manager.CreateEndpoint(EmulatedEndpointConfig()); |
| 449 | EmulatedEndpoint* bob_endpoint = |
| 450 | network_manager.CreateEndpoint(EmulatedEndpointConfig()); |
| 451 | network_manager.CreateRoute(alice_endpoint, {alice_node}, bob_endpoint); |
| 452 | network_manager.CreateRoute(bob_endpoint, {bob_node}, alice_endpoint); |
| 453 | |
| 454 | EmulatedNetworkManagerInterface* nt1 = |
| 455 | network_manager.CreateEmulatedNetworkManagerInterface({alice_endpoint}); |
| 456 | EmulatedNetworkManagerInterface* nt2 = |
| 457 | network_manager.CreateEmulatedNetworkManagerInterface({bob_endpoint}); |
| 458 | |
Sebastian Jansson | 9d4bbc2 | 2020-01-10 20:03:56 +0100 | [diff] [blame] | 459 | rtc::Thread* t1 = nt1->network_thread(); |
| 460 | rtc::Thread* t2 = nt2->network_thread(); |
| 461 | |
Niels Möller | 7536bc5 | 2019-10-04 13:54:39 +0200 | [diff] [blame] | 462 | constexpr int64_t kUdpPayloadSize = 100; |
| 463 | constexpr int64_t kSinglePacketSize = kUdpPayloadSize + kOverheadIpv4Udp; |
| 464 | rtc::CopyOnWriteBuffer data(kUdpPayloadSize); |
Danil Chapovalov | 7358b40 | 2021-02-01 20:43:19 +0100 | [diff] [blame] | 465 | |
Niels Möller | d0b8879 | 2021-08-12 10:32:30 +0200 | [diff] [blame] | 466 | rtc::Socket* s1 = nullptr; |
| 467 | rtc::Socket* s2 = nullptr; |
Danil Chapovalov | 7358b40 | 2021-02-01 20:43:19 +0100 | [diff] [blame] | 468 | t1->Invoke<void>(RTC_FROM_HERE, [&] { |
Niels Möller | d0b8879 | 2021-08-12 10:32:30 +0200 | [diff] [blame] | 469 | s1 = t1->socketserver()->CreateSocket(AF_INET, SOCK_DGRAM); |
Danil Chapovalov | 7358b40 | 2021-02-01 20:43:19 +0100 | [diff] [blame] | 470 | }); |
| 471 | t2->Invoke<void>(RTC_FROM_HERE, [&] { |
Niels Möller | d0b8879 | 2021-08-12 10:32:30 +0200 | [diff] [blame] | 472 | s2 = t2->socketserver()->CreateSocket(AF_INET, SOCK_DGRAM); |
Danil Chapovalov | 7358b40 | 2021-02-01 20:43:19 +0100 | [diff] [blame] | 473 | }); |
Artem Titov | 806299e | 2019-04-12 12:17:19 +0200 | [diff] [blame] | 474 | |
Sebastian Jansson | 9d4bbc2 | 2020-01-10 20:03:56 +0100 | [diff] [blame] | 475 | SocketReader r1(s1, t1); |
| 476 | SocketReader r2(s2, t2); |
Artem Titov | 806299e | 2019-04-12 12:17:19 +0200 | [diff] [blame] | 477 | |
| 478 | rtc::SocketAddress a1(alice_endpoint->GetPeerLocalAddress(), 0); |
| 479 | rtc::SocketAddress a2(bob_endpoint->GetPeerLocalAddress(), 0); |
| 480 | |
Sebastian Jansson | 9d4bbc2 | 2020-01-10 20:03:56 +0100 | [diff] [blame] | 481 | t1->Invoke<void>(RTC_FROM_HERE, [&] { |
| 482 | s1->Bind(a1); |
| 483 | a1 = s1->GetLocalAddress(); |
| 484 | }); |
| 485 | t2->Invoke<void>(RTC_FROM_HERE, [&] { |
| 486 | s2->Bind(a2); |
| 487 | a2 = s2->GetLocalAddress(); |
| 488 | }); |
Artem Titov | 806299e | 2019-04-12 12:17:19 +0200 | [diff] [blame] | 489 | |
Sebastian Jansson | 9d4bbc2 | 2020-01-10 20:03:56 +0100 | [diff] [blame] | 490 | t1->Invoke<void>(RTC_FROM_HERE, [&] { s1->Connect(a2); }); |
| 491 | t2->Invoke<void>(RTC_FROM_HERE, [&] { s2->Connect(a1); }); |
Artem Titov | 806299e | 2019-04-12 12:17:19 +0200 | [diff] [blame] | 492 | |
Yves Gerey | b64d65e | 2019-09-06 16:35:20 +0200 | [diff] [blame] | 493 | // Send 11 packets, totalizing 1 second between the first and the last. |
| 494 | const int kNumPacketsSent = 11; |
Danil Chapovalov | 0c626af | 2020-02-10 11:16:00 +0100 | [diff] [blame] | 495 | const TimeDelta kDelay = TimeDelta::Millis(100); |
Yves Gerey | b64d65e | 2019-09-06 16:35:20 +0200 | [diff] [blame] | 496 | for (int i = 0; i < kNumPacketsSent; i++) { |
Henrik Boström | 2deee4b | 2022-01-20 11:58:05 +0100 | [diff] [blame] | 497 | t1->PostTask([&]() { s1->Send(data.data(), data.size()); }); |
| 498 | t2->PostTask([&]() { s2->Send(data.data(), data.size()); }); |
Sebastian Jansson | 6ce033a | 2020-01-22 10:12:56 +0100 | [diff] [blame] | 499 | network_manager.time_controller()->AdvanceTime(kDelay); |
Artem Titov | 806299e | 2019-04-12 12:17:19 +0200 | [diff] [blame] | 500 | } |
Artem Titov | 806299e | 2019-04-12 12:17:19 +0200 | [diff] [blame] | 501 | |
Artem Titov | 806299e | 2019-04-12 12:17:19 +0200 | [diff] [blame] | 502 | std::atomic<int> received_stats_count{0}; |
Artem Titov | 3e0b65d | 2020-07-23 02:19:02 +0200 | [diff] [blame] | 503 | nt1->GetStats([&](std::unique_ptr<EmulatedNetworkStats> st) { |
| 504 | EXPECT_EQ(st->PacketsSent(), kNumPacketsSent); |
| 505 | EXPECT_EQ(st->BytesSent().bytes(), kSinglePacketSize * kNumPacketsSent); |
Yves Gerey | b64d65e | 2019-09-06 16:35:20 +0200 | [diff] [blame] | 506 | |
Yves Gerey | c65de42 | 2019-11-08 20:29:04 +0100 | [diff] [blame] | 507 | const double tolerance = 0.95; // Accept 5% tolerance for timing. |
Artem Titov | 3e0b65d | 2020-07-23 02:19:02 +0200 | [diff] [blame] | 508 | EXPECT_GE(st->LastPacketSentTime() - st->FirstPacketSentTime(), |
Sebastian Jansson | 6ce033a | 2020-01-22 10:12:56 +0100 | [diff] [blame] | 509 | (kNumPacketsSent - 1) * kDelay * tolerance); |
Artem Titov | 3e0b65d | 2020-07-23 02:19:02 +0200 | [diff] [blame] | 510 | EXPECT_GT(st->AverageSendRate().bps(), 0); |
Artem Titov | 806299e | 2019-04-12 12:17:19 +0200 | [diff] [blame] | 511 | received_stats_count++; |
| 512 | }); |
Sebastian Jansson | 6ce033a | 2020-01-22 10:12:56 +0100 | [diff] [blame] | 513 | |
| 514 | ASSERT_EQ_SIMULATED_WAIT(received_stats_count.load(), 1, |
| 515 | kStatsWaitTimeout.ms(), |
| 516 | *network_manager.time_controller()); |
| 517 | |
Artem Titov | a768345 | 2019-05-15 12:26:38 +0200 | [diff] [blame] | 518 | EXPECT_EQ(r1.ReceivedCount(), 11); |
| 519 | EXPECT_EQ(r2.ReceivedCount(), 11); |
Artem Titov | 519d74a | 2019-05-17 12:01:00 +0200 | [diff] [blame] | 520 | |
Sebastian Jansson | 9d4bbc2 | 2020-01-10 20:03:56 +0100 | [diff] [blame] | 521 | t1->Invoke<void>(RTC_FROM_HERE, [&] { delete s1; }); |
| 522 | t2->Invoke<void>(RTC_FROM_HERE, [&] { delete s2; }); |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 523 | } |
| 524 | |
Artem Titov | ff39312 | 2019-04-05 11:19:52 +0200 | [diff] [blame] | 525 | // Testing that packets are delivered via all routes using a routing scheme as |
| 526 | // follows: |
| 527 | // * e1 -> n1 -> e2 |
| 528 | // * e2 -> n2 -> e1 |
| 529 | // * e1 -> n3 -> e3 |
| 530 | // * e3 -> n4 -> e1 |
| 531 | TEST_F(NetworkEmulationManagerThreeNodesRoutingTest, |
| 532 | PacketsAreDeliveredInBothWaysWhenConnectedToTwoPeers) { |
| 533 | SetupRouting([](EmulatedEndpoint* e1, EmulatedEndpoint* e2, |
| 534 | EmulatedEndpoint* e3, NetworkEmulationManager* emulation) { |
| 535 | auto* node1 = CreateEmulatedNodeWithDefaultBuiltInConfig(emulation); |
| 536 | auto* node2 = CreateEmulatedNodeWithDefaultBuiltInConfig(emulation); |
| 537 | auto* node3 = CreateEmulatedNodeWithDefaultBuiltInConfig(emulation); |
| 538 | auto* node4 = CreateEmulatedNodeWithDefaultBuiltInConfig(emulation); |
| 539 | |
| 540 | emulation->CreateRoute(e1, {node1}, e2); |
| 541 | emulation->CreateRoute(e2, {node2}, e1); |
| 542 | |
| 543 | emulation->CreateRoute(e1, {node3}, e3); |
| 544 | emulation->CreateRoute(e3, {node4}, e1); |
| 545 | }); |
| 546 | SendPacketsAndValidateDelivery(); |
| 547 | } |
| 548 | |
| 549 | // Testing that packets are delivered via all routes using a routing scheme as |
| 550 | // follows: |
| 551 | // * e1 -> n1 -> e2 |
| 552 | // * e2 -> n2 -> e1 |
| 553 | // * e1 -> n1 -> e3 |
| 554 | // * e3 -> n4 -> e1 |
| 555 | TEST_F(NetworkEmulationManagerThreeNodesRoutingTest, |
| 556 | PacketsAreDeliveredInBothWaysWhenConnectedToTwoPeersOverSameSendLink) { |
| 557 | SetupRouting([](EmulatedEndpoint* e1, EmulatedEndpoint* e2, |
| 558 | EmulatedEndpoint* e3, NetworkEmulationManager* emulation) { |
| 559 | auto* node1 = CreateEmulatedNodeWithDefaultBuiltInConfig(emulation); |
| 560 | auto* node2 = CreateEmulatedNodeWithDefaultBuiltInConfig(emulation); |
| 561 | auto* node3 = CreateEmulatedNodeWithDefaultBuiltInConfig(emulation); |
| 562 | |
| 563 | emulation->CreateRoute(e1, {node1}, e2); |
| 564 | emulation->CreateRoute(e2, {node2}, e1); |
| 565 | |
| 566 | emulation->CreateRoute(e1, {node1}, e3); |
| 567 | emulation->CreateRoute(e3, {node3}, e1); |
| 568 | }); |
| 569 | SendPacketsAndValidateDelivery(); |
| 570 | } |
| 571 | |
Artem Titov | 5d55597 | 2020-11-12 16:15:44 +0100 | [diff] [blame] | 572 | TEST(NetworkEmulationManagerTest, EndpointLoopback) { |
| 573 | NetworkEmulationManagerImpl network_manager(TimeMode::kSimulated); |
| 574 | auto endpoint = network_manager.CreateEndpoint(EmulatedEndpointConfig()); |
| 575 | |
| 576 | MockReceiver receiver; |
| 577 | EXPECT_CALL(receiver, OnPacketReceived(::testing::_)).Times(1); |
| 578 | ASSERT_EQ(endpoint->BindReceiver(80, &receiver), 80); |
| 579 | |
| 580 | endpoint->SendPacket(rtc::SocketAddress(endpoint->GetPeerLocalAddress(), 80), |
| 581 | rtc::SocketAddress(endpoint->GetPeerLocalAddress(), 80), |
| 582 | "Hello"); |
| 583 | network_manager.time_controller()->AdvanceTime(TimeDelta::Seconds(1)); |
| 584 | } |
| 585 | |
Artem Titov | 3d37e06 | 2021-02-19 20:26:32 +0100 | [diff] [blame] | 586 | TEST(NetworkEmulationManagerTest, EndpointCanSendWithDifferentSourceIp) { |
| 587 | constexpr uint32_t kEndpointIp = 0xC0A80011; // 192.168.0.17 |
| 588 | constexpr uint32_t kSourceIp = 0xC0A80012; // 192.168.0.18 |
| 589 | NetworkEmulationManagerImpl network_manager(TimeMode::kSimulated); |
| 590 | EmulatedEndpointConfig endpoint_config; |
| 591 | endpoint_config.ip = rtc::IPAddress(kEndpointIp); |
| 592 | endpoint_config.allow_send_packet_with_different_source_ip = true; |
| 593 | auto endpoint = network_manager.CreateEndpoint(endpoint_config); |
| 594 | |
| 595 | MockReceiver receiver; |
| 596 | EXPECT_CALL(receiver, OnPacketReceived(::testing::_)).Times(1); |
| 597 | ASSERT_EQ(endpoint->BindReceiver(80, &receiver), 80); |
| 598 | |
| 599 | endpoint->SendPacket(rtc::SocketAddress(kSourceIp, 80), |
| 600 | rtc::SocketAddress(endpoint->GetPeerLocalAddress(), 80), |
| 601 | "Hello"); |
| 602 | network_manager.time_controller()->AdvanceTime(TimeDelta::Seconds(1)); |
| 603 | } |
| 604 | |
| 605 | TEST(NetworkEmulationManagerTest, |
| 606 | EndpointCanReceiveWithDifferentDestIpThroughDefaultRoute) { |
| 607 | constexpr uint32_t kDestEndpointIp = 0xC0A80011; // 192.168.0.17 |
| 608 | constexpr uint32_t kDestIp = 0xC0A80012; // 192.168.0.18 |
| 609 | NetworkEmulationManagerImpl network_manager(TimeMode::kSimulated); |
| 610 | auto sender_endpoint = |
| 611 | network_manager.CreateEndpoint(EmulatedEndpointConfig()); |
| 612 | EmulatedEndpointConfig endpoint_config; |
| 613 | endpoint_config.ip = rtc::IPAddress(kDestEndpointIp); |
| 614 | endpoint_config.allow_receive_packets_with_different_dest_ip = true; |
| 615 | auto receiver_endpoint = network_manager.CreateEndpoint(endpoint_config); |
| 616 | |
| 617 | MockReceiver receiver; |
| 618 | EXPECT_CALL(receiver, OnPacketReceived(::testing::_)).Times(1); |
| 619 | ASSERT_EQ(receiver_endpoint->BindReceiver(80, &receiver), 80); |
| 620 | |
| 621 | network_manager.CreateDefaultRoute( |
| 622 | sender_endpoint, {network_manager.NodeBuilder().Build().node}, |
| 623 | receiver_endpoint); |
| 624 | |
| 625 | sender_endpoint->SendPacket( |
| 626 | rtc::SocketAddress(sender_endpoint->GetPeerLocalAddress(), 80), |
| 627 | rtc::SocketAddress(kDestIp, 80), "Hello"); |
| 628 | network_manager.time_controller()->AdvanceTime(TimeDelta::Seconds(1)); |
| 629 | } |
| 630 | |
Jonas Oreland | 9705011 | 2020-11-17 21:30:33 +0100 | [diff] [blame] | 631 | TEST(NetworkEmulationManagerTURNTest, GetIceServerConfig) { |
| 632 | NetworkEmulationManagerImpl network_manager(TimeMode::kRealTime); |
| 633 | auto turn = network_manager.CreateTURNServer(EmulatedTURNServerConfig()); |
| 634 | |
| 635 | EXPECT_GT(turn->GetIceServerConfig().username.size(), 0u); |
| 636 | EXPECT_GT(turn->GetIceServerConfig().password.size(), 0u); |
| 637 | EXPECT_NE(turn->GetIceServerConfig().url.find( |
| 638 | turn->GetClientEndpoint()->GetPeerLocalAddress().ToString()), |
| 639 | std::string::npos); |
| 640 | } |
| 641 | |
| 642 | TEST(NetworkEmulationManagerTURNTest, ClientTraffic) { |
| 643 | NetworkEmulationManagerImpl emulation(TimeMode::kSimulated); |
| 644 | auto* ep = emulation.CreateEndpoint(EmulatedEndpointConfig()); |
| 645 | auto* turn = emulation.CreateTURNServer(EmulatedTURNServerConfig()); |
| 646 | auto* node = CreateEmulatedNodeWithDefaultBuiltInConfig(&emulation); |
| 647 | emulation.CreateRoute(ep, {node}, turn->GetClientEndpoint()); |
| 648 | emulation.CreateRoute(turn->GetClientEndpoint(), {node}, ep); |
| 649 | |
| 650 | MockReceiver recv; |
| 651 | int port = ep->BindReceiver(0, &recv).value(); |
| 652 | |
| 653 | // Construct a STUN BINDING. |
| 654 | cricket::StunMessage ping; |
| 655 | ping.SetType(cricket::STUN_BINDING_REQUEST); |
| 656 | rtc::ByteBufferWriter buf; |
| 657 | ping.Write(&buf); |
| 658 | rtc::CopyOnWriteBuffer packet(buf.Data(), buf.Length()); |
| 659 | |
| 660 | // We expect to get a ping reply. |
| 661 | EXPECT_CALL(recv, OnPacketReceived(::testing::_)).Times(1); |
| 662 | |
| 663 | ep->SendPacket(rtc::SocketAddress(ep->GetPeerLocalAddress(), port), |
| 664 | turn->GetClientEndpointAddress(), packet); |
| 665 | emulation.time_controller()->AdvanceTime(TimeDelta::Seconds(1)); |
| 666 | } |
| 667 | |
Artem Titov | 0774bd9 | 2019-01-30 15:26:05 +0100 | [diff] [blame] | 668 | } // namespace test |
| 669 | } // namespace webrtc |