blob: ee0f0aa09ea75ffe38837e4d53753ddf4ae9a545 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
2 * libjingle
3 * Copyright 2004--2011, 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 "talk/base/network.h"
29
30#include <vector>
31#if defined(POSIX)
32#include <sys/types.h>
33#ifndef ANDROID
34#include <ifaddrs.h>
35#else
36#include "talk/base/ifaddrs-android.h"
37#endif
38#endif
39#include "talk/base/gunit.h"
40
41namespace talk_base {
42
43class NetworkTest : public testing::Test, public sigslot::has_slots<> {
44 public:
45 NetworkTest() : callback_called_(false) {}
46
47 void OnNetworksChanged() {
48 callback_called_ = true;
49 }
50
51 void MergeNetworkList(BasicNetworkManager& network_manager,
52 const NetworkManager::NetworkList& list,
53 bool* changed ) {
54 network_manager.MergeNetworkList(list, changed);
55 }
56
57 bool IsIgnoredNetwork(const Network& network) {
58 return BasicNetworkManager::IsIgnoredNetwork(network);
59 }
60
61 NetworkManager::NetworkList GetNetworks(
62 const BasicNetworkManager& network_manager, bool include_ignored) {
63 NetworkManager::NetworkList list;
64 network_manager.CreateNetworks(include_ignored, &list);
65 return list;
66 }
67
68#if defined(POSIX)
69 // Separated from CreateNetworks for tests.
70 static void CallConvertIfAddrs(const BasicNetworkManager& network_manager,
71 struct ifaddrs* interfaces,
72 bool include_ignored,
73 NetworkManager::NetworkList* networks) {
74 network_manager.ConvertIfAddrs(interfaces, include_ignored, networks);
75 }
76#endif // defined(POSIX)
77
78 protected:
79 bool callback_called_;
80};
81
82// Test that the Network ctor works properly.
83TEST_F(NetworkTest, TestNetworkConstruct) {
84 Network ipv4_network1("test_eth0", "Test Network Adapter 1",
85 IPAddress(0x12345600U), 24);
86 EXPECT_EQ("test_eth0", ipv4_network1.name());
87 EXPECT_EQ("Test Network Adapter 1", ipv4_network1.description());
88 EXPECT_EQ(IPAddress(0x12345600U), ipv4_network1.prefix());
89 EXPECT_EQ(24, ipv4_network1.prefix_length());
90 EXPECT_FALSE(ipv4_network1.ignored());
91}
92
93// Tests that our ignore function works properly.
94TEST_F(NetworkTest, TestNetworkIgnore) {
95 Network ipv4_network1("test_eth0", "Test Network Adapter 1",
96 IPAddress(0x12345600U), 24);
97 Network ipv4_network2("test_eth1", "Test Network Adapter 2",
98 IPAddress(0x00010000U), 16);
99 EXPECT_FALSE(IsIgnoredNetwork(ipv4_network1));
100 EXPECT_TRUE(IsIgnoredNetwork(ipv4_network2));
101}
102
103TEST_F(NetworkTest, TestCreateNetworks) {
104 BasicNetworkManager manager;
105 NetworkManager::NetworkList result = GetNetworks(manager, true);
106 // We should be able to bind to any addresses we find.
107 NetworkManager::NetworkList::iterator it;
108 for (it = result.begin();
109 it != result.end();
110 ++it) {
111 sockaddr_storage storage;
112 memset(&storage, 0, sizeof(storage));
113 IPAddress ip = (*it)->ip();
114 SocketAddress bindaddress(ip, 0);
115 bindaddress.SetScopeID((*it)->scope_id());
116 // TODO: Make this use talk_base::AsyncSocket once it supports IPv6.
117 int fd = static_cast<int>(socket(ip.family(), SOCK_STREAM, IPPROTO_TCP));
118 if (fd > 0) {
119 size_t ipsize = bindaddress.ToSockAddrStorage(&storage);
120 EXPECT_GE(ipsize, 0U);
121 int success = ::bind(fd,
122 reinterpret_cast<sockaddr*>(&storage),
123 static_cast<int>(ipsize));
124 EXPECT_EQ(0, success);
125#ifdef WIN32
126 closesocket(fd);
127#else
128 close(fd);
129#endif
130 }
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000131 delete (*it);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000132 }
133}
134
135// Test that UpdateNetworks succeeds.
136TEST_F(NetworkTest, TestUpdateNetworks) {
137 BasicNetworkManager manager;
138 manager.SignalNetworksChanged.connect(
139 static_cast<NetworkTest*>(this), &NetworkTest::OnNetworksChanged);
140 manager.StartUpdating();
141 Thread::Current()->ProcessMessages(0);
142 EXPECT_TRUE(callback_called_);
143 callback_called_ = false;
144 // Callback should be triggered immediately when StartUpdating
145 // is called, after network update signal is already sent.
146 manager.StartUpdating();
147 EXPECT_TRUE(manager.started());
148 Thread::Current()->ProcessMessages(0);
149 EXPECT_TRUE(callback_called_);
150 manager.StopUpdating();
151 EXPECT_TRUE(manager.started());
152 manager.StopUpdating();
153 EXPECT_FALSE(manager.started());
154 manager.StopUpdating();
155 EXPECT_FALSE(manager.started());
156 callback_called_ = false;
157 // Callback should be triggered immediately after StartUpdating is called
158 // when start_count_ is reset to 0.
159 manager.StartUpdating();
160 Thread::Current()->ProcessMessages(0);
161 EXPECT_TRUE(callback_called_);
162}
163
164// Verify that MergeNetworkList() merges network lists properly.
165TEST_F(NetworkTest, TestBasicMergeNetworkList) {
166 Network ipv4_network1("test_eth0", "Test Network Adapter 1",
167 IPAddress(0x12345600U), 24);
168 Network ipv4_network2("test_eth1", "Test Network Adapter 2",
169 IPAddress(0x00010000U), 16);
170 ipv4_network1.AddIP(IPAddress(0x12345678));
171 ipv4_network2.AddIP(IPAddress(0x00010004));
172 BasicNetworkManager manager;
173
174 // Add ipv4_network1 to the list of networks.
175 NetworkManager::NetworkList list;
176 list.push_back(new Network(ipv4_network1));
177 bool changed;
178 MergeNetworkList(manager, list, &changed);
179 EXPECT_TRUE(changed);
180 list.clear();
181
182 manager.GetNetworks(&list);
183 EXPECT_EQ(1U, list.size());
184 EXPECT_EQ(ipv4_network1.ToString(), list[0]->ToString());
185 Network* net1 = list[0];
186 list.clear();
187
188 // Replace ipv4_network1 with ipv4_network2.
189 list.push_back(new Network(ipv4_network2));
190 MergeNetworkList(manager, list, &changed);
191 EXPECT_TRUE(changed);
192 list.clear();
193
194 manager.GetNetworks(&list);
195 EXPECT_EQ(1U, list.size());
196 EXPECT_EQ(ipv4_network2.ToString(), list[0]->ToString());
197 Network* net2 = list[0];
198 list.clear();
199
200 // Add Network2 back.
201 list.push_back(new Network(ipv4_network1));
202 list.push_back(new Network(ipv4_network2));
203 MergeNetworkList(manager, list, &changed);
204 EXPECT_TRUE(changed);
205 list.clear();
206
207 // Verify that we get previous instances of Network objects.
208 manager.GetNetworks(&list);
209 EXPECT_EQ(2U, list.size());
210 EXPECT_TRUE((net1 == list[0] && net2 == list[1]) ||
211 (net1 == list[1] && net2 == list[0]));
212 list.clear();
213
214 // Call MergeNetworkList() again and verify that we don't get update
215 // notification.
216 list.push_back(new Network(ipv4_network2));
217 list.push_back(new Network(ipv4_network1));
218 MergeNetworkList(manager, list, &changed);
219 EXPECT_FALSE(changed);
220 list.clear();
221
222 // Verify that we get previous instances of Network objects.
223 manager.GetNetworks(&list);
224 EXPECT_EQ(2U, list.size());
225 EXPECT_TRUE((net1 == list[0] && net2 == list[1]) ||
226 (net1 == list[1] && net2 == list[0]));
227 list.clear();
228}
229
230// Sets up some test IPv6 networks and appends them to list.
231// Four networks are added - public and link local, for two interfaces.
232void SetupNetworks(NetworkManager::NetworkList* list) {
233 IPAddress ip;
234 IPAddress prefix;
235 EXPECT_TRUE(IPFromString("fe80::1234:5678:abcd:ef12", &ip));
236 EXPECT_TRUE(IPFromString("fe80::", &prefix));
237 // First, fake link-locals.
238 Network ipv6_eth0_linklocalnetwork("test_eth0", "Test NetworkAdapter 1",
239 prefix, 64);
240 ipv6_eth0_linklocalnetwork.AddIP(ip);
241 EXPECT_TRUE(IPFromString("fe80::5678:abcd:ef12:3456", &ip));
242 Network ipv6_eth1_linklocalnetwork("test_eth1", "Test NetworkAdapter 2",
243 prefix, 64);
244 ipv6_eth1_linklocalnetwork.AddIP(ip);
245 // Public networks:
246 EXPECT_TRUE(IPFromString("2401:fa00:4:1000:be30:5bff:fee5:c3", &ip));
247 prefix = TruncateIP(ip, 64);
248 Network ipv6_eth0_publicnetwork1_ip1("test_eth0", "Test NetworkAdapter 1",
249 prefix, 64);
250 ipv6_eth0_publicnetwork1_ip1.AddIP(ip);
251 EXPECT_TRUE(IPFromString("2400:4030:1:2c00:be30:abcd:efab:cdef", &ip));
252 prefix = TruncateIP(ip, 64);
253 Network ipv6_eth1_publicnetwork1_ip1("test_eth1", "Test NetworkAdapter 1",
254 prefix, 64);
255 ipv6_eth1_publicnetwork1_ip1.AddIP(ip);
256 list->push_back(new Network(ipv6_eth0_linklocalnetwork));
257 list->push_back(new Network(ipv6_eth1_linklocalnetwork));
258 list->push_back(new Network(ipv6_eth0_publicnetwork1_ip1));
259 list->push_back(new Network(ipv6_eth1_publicnetwork1_ip1));
260}
261
262// Test that the basic network merging case works.
263TEST_F(NetworkTest, TestIPv6MergeNetworkList) {
264 BasicNetworkManager manager;
265 manager.SignalNetworksChanged.connect(
266 static_cast<NetworkTest*>(this), &NetworkTest::OnNetworksChanged);
267 NetworkManager::NetworkList original_list;
268 SetupNetworks(&original_list);
269 bool changed = false;
270 MergeNetworkList(manager, original_list, &changed);
271 EXPECT_TRUE(changed);
272 NetworkManager::NetworkList list;
273 manager.GetNetworks(&list);
274 EXPECT_EQ(original_list.size(), list.size());
275 // Verify that the original members are in the merged list.
276 for (NetworkManager::NetworkList::iterator it = original_list.begin();
277 it != original_list.end(); ++it) {
278 EXPECT_NE(list.end(), std::find(list.begin(), list.end(), *it));
279 }
280}
281
282// Tests that when two network lists that describe the same set of networks are
283// merged, that the changed callback is not called, and that the original
284// objects remain in the result list.
285TEST_F(NetworkTest, TestNoChangeMerge) {
286 BasicNetworkManager manager;
287 manager.SignalNetworksChanged.connect(
288 static_cast<NetworkTest*>(this), &NetworkTest::OnNetworksChanged);
289 NetworkManager::NetworkList original_list;
290 SetupNetworks(&original_list);
291 bool changed = false;
292 MergeNetworkList(manager, original_list, &changed);
293 EXPECT_TRUE(changed);
294 // Second list that describes the same networks but with new objects.
295 NetworkManager::NetworkList second_list;
296 SetupNetworks(&second_list);
297 changed = false;
298 MergeNetworkList(manager, second_list, &changed);
299 EXPECT_FALSE(changed);
300 NetworkManager::NetworkList resulting_list;
301 manager.GetNetworks(&resulting_list);
302 EXPECT_EQ(original_list.size(), resulting_list.size());
303 // Verify that the original members are in the merged list.
304 for (NetworkManager::NetworkList::iterator it = original_list.begin();
305 it != original_list.end(); ++it) {
306 EXPECT_NE(resulting_list.end(),
307 std::find(resulting_list.begin(), resulting_list.end(), *it));
308 }
309 // Doublecheck that the new networks aren't in the list.
310 for (NetworkManager::NetworkList::iterator it = second_list.begin();
311 it != second_list.end(); ++it) {
312 EXPECT_EQ(resulting_list.end(),
313 std::find(resulting_list.begin(), resulting_list.end(), *it));
314 }
315}
316
317// Test that we can merge a network that is the same as another network but with
318// a different IP. The original network should remain in the list, but have its
319// IP changed.
320TEST_F(NetworkTest, MergeWithChangedIP) {
321 BasicNetworkManager manager;
322 manager.SignalNetworksChanged.connect(
323 static_cast<NetworkTest*>(this), &NetworkTest::OnNetworksChanged);
324 NetworkManager::NetworkList original_list;
325 SetupNetworks(&original_list);
326 // Make a network that we're going to change.
327 IPAddress ip;
328 EXPECT_TRUE(IPFromString("2401:fa01:4:1000:be30:faa:fee:faa", &ip));
329 IPAddress prefix = TruncateIP(ip, 64);
330 Network* network_to_change = new Network("test_eth0",
331 "Test Network Adapter 1",
332 prefix, 64);
333 Network* changed_network = new Network(*network_to_change);
334 network_to_change->AddIP(ip);
335 IPAddress changed_ip;
336 EXPECT_TRUE(IPFromString("2401:fa01:4:1000:be30:f00:f00:f00", &changed_ip));
337 changed_network->AddIP(changed_ip);
338 original_list.push_back(network_to_change);
339 bool changed = false;
340 MergeNetworkList(manager, original_list, &changed);
341 NetworkManager::NetworkList second_list;
342 SetupNetworks(&second_list);
343 second_list.push_back(changed_network);
344 changed = false;
345 MergeNetworkList(manager, second_list, &changed);
346 EXPECT_TRUE(changed);
347 NetworkManager::NetworkList list;
348 manager.GetNetworks(&list);
349 EXPECT_EQ(original_list.size(), list.size());
350 // Make sure the original network is still in the merged list.
351 EXPECT_NE(list.end(),
352 std::find(list.begin(), list.end(), network_to_change));
353 EXPECT_EQ(changed_ip, network_to_change->GetIPs().at(0));
354}
355
356// Testing a similar case to above, but checking that a network can be updated
357// with additional IPs (not just a replacement).
358TEST_F(NetworkTest, TestMultipleIPMergeNetworkList) {
359 BasicNetworkManager manager;
360 manager.SignalNetworksChanged.connect(
361 static_cast<NetworkTest*>(this), &NetworkTest::OnNetworksChanged);
362 NetworkManager::NetworkList original_list;
363 SetupNetworks(&original_list);
364 bool changed = false;
365 MergeNetworkList(manager, original_list, &changed);
366 EXPECT_TRUE(changed);
367 IPAddress ip;
368 IPAddress check_ip;
369 IPAddress prefix;
370 // Add a second IP to the public network on eth0 (2401:fa00:4:1000/64).
371 EXPECT_TRUE(IPFromString("2401:fa00:4:1000:be30:5bff:fee5:c6", &ip));
372 prefix = TruncateIP(ip, 64);
373 Network ipv6_eth0_publicnetwork1_ip2("test_eth0", "Test NetworkAdapter 1",
374 prefix, 64);
375 // This is the IP that already existed in the public network on eth0.
376 EXPECT_TRUE(IPFromString("2401:fa00:4:1000:be30:5bff:fee5:c3", &check_ip));
377 ipv6_eth0_publicnetwork1_ip2.AddIP(ip);
378 original_list.push_back(new Network(ipv6_eth0_publicnetwork1_ip2));
379 changed = false;
380 MergeNetworkList(manager, original_list, &changed);
381 EXPECT_TRUE(changed);
382 // There should still be four networks.
383 NetworkManager::NetworkList list;
384 manager.GetNetworks(&list);
385 EXPECT_EQ(4U, list.size());
386 // Check the gathered IPs.
387 int matchcount = 0;
388 for (NetworkManager::NetworkList::iterator it = list.begin();
389 it != list.end(); ++it) {
390 if ((*it)->ToString() == original_list[2]->ToString()) {
391 ++matchcount;
392 EXPECT_EQ(1, matchcount);
393 // This should be the same network object as before.
394 EXPECT_EQ((*it), original_list[2]);
395 // But with two addresses now.
396 EXPECT_EQ(2U, (*it)->GetIPs().size());
397 EXPECT_NE((*it)->GetIPs().end(),
398 std::find((*it)->GetIPs().begin(),
399 (*it)->GetIPs().end(),
400 check_ip));
401 EXPECT_NE((*it)->GetIPs().end(),
402 std::find((*it)->GetIPs().begin(),
403 (*it)->GetIPs().end(),
404 ip));
405 } else {
406 // Check the IP didn't get added anywhere it wasn't supposed to.
407 EXPECT_EQ((*it)->GetIPs().end(),
408 std::find((*it)->GetIPs().begin(),
409 (*it)->GetIPs().end(),
410 ip));
411 }
412 }
413}
414
415// Test that merge correctly distinguishes multiple networks on an interface.
416TEST_F(NetworkTest, TestMultiplePublicNetworksOnOneInterfaceMerge) {
417 BasicNetworkManager manager;
418 manager.SignalNetworksChanged.connect(
419 static_cast<NetworkTest*>(this), &NetworkTest::OnNetworksChanged);
420 NetworkManager::NetworkList original_list;
421 SetupNetworks(&original_list);
422 bool changed = false;
423 MergeNetworkList(manager, original_list, &changed);
424 EXPECT_TRUE(changed);
425 IPAddress ip;
426 IPAddress prefix;
427 // A second network for eth0.
428 EXPECT_TRUE(IPFromString("2400:4030:1:2c00:be30:5bff:fee5:c3", &ip));
429 prefix = TruncateIP(ip, 64);
430 Network ipv6_eth0_publicnetwork2_ip1("test_eth0", "Test NetworkAdapter 1",
431 prefix, 64);
432 ipv6_eth0_publicnetwork2_ip1.AddIP(ip);
433 original_list.push_back(new Network(ipv6_eth0_publicnetwork2_ip1));
434 changed = false;
435 MergeNetworkList(manager, original_list, &changed);
436 EXPECT_TRUE(changed);
437 // There should be five networks now.
438 NetworkManager::NetworkList list;
439 manager.GetNetworks(&list);
440 EXPECT_EQ(5U, list.size());
441 // Check the resulting addresses.
442 for (NetworkManager::NetworkList::iterator it = list.begin();
443 it != list.end(); ++it) {
444 if ((*it)->prefix() == ipv6_eth0_publicnetwork2_ip1.prefix() &&
445 (*it)->name() == ipv6_eth0_publicnetwork2_ip1.name()) {
446 // Check the new network has 1 IP and that it's the correct one.
447 EXPECT_EQ(1U, (*it)->GetIPs().size());
448 EXPECT_EQ(ip, (*it)->GetIPs().at(0));
449 } else {
450 // Check the IP didn't get added anywhere it wasn't supposed to.
451 EXPECT_EQ((*it)->GetIPs().end(),
452 std::find((*it)->GetIPs().begin(),
453 (*it)->GetIPs().end(),
454 ip));
455 }
456 }
457}
458
459// Test that DumpNetworks works.
460TEST_F(NetworkTest, TestDumpNetworks) {
461 BasicNetworkManager manager;
462 manager.DumpNetworks(true);
463}
464
465// Test that we can toggle IPv6 on and off.
466TEST_F(NetworkTest, TestIPv6Toggle) {
467 BasicNetworkManager manager;
468 bool ipv6_found = false;
469 NetworkManager::NetworkList list;
470#ifndef WIN32
471 // There should be at least one IPv6 network (fe80::/64 should be in there).
472 // TODO: Disabling this test on windows for the moment as the test
473 // machines don't seem to have IPv6 installed on them at all.
474 manager.set_ipv6_enabled(true);
475 list = GetNetworks(manager, true);
476 for (NetworkManager::NetworkList::iterator it = list.begin();
477 it != list.end(); ++it) {
478 if ((*it)->prefix().family() == AF_INET6) {
479 ipv6_found = true;
480 break;
481 }
482 }
483 EXPECT_TRUE(ipv6_found);
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000484 for (NetworkManager::NetworkList::iterator it = list.begin();
485 it != list.end(); ++it) {
486 delete (*it);
487 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000488#endif
489 ipv6_found = false;
490 manager.set_ipv6_enabled(false);
491 list = GetNetworks(manager, true);
492 for (NetworkManager::NetworkList::iterator it = list.begin();
493 it != list.end(); ++it) {
494 if ((*it)->prefix().family() == AF_INET6) {
495 ipv6_found = true;
496 break;
497 }
498 }
499 EXPECT_FALSE(ipv6_found);
henrike@webrtc.org723d6832013-07-12 16:04:50 +0000500 for (NetworkManager::NetworkList::iterator it = list.begin();
501 it != list.end(); ++it) {
502 delete (*it);
503 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000504}
505
506#if defined(POSIX)
507// Verify that we correctly handle interfaces with no address.
508TEST_F(NetworkTest, TestConvertIfAddrsNoAddress) {
509 ifaddrs list;
510 memset(&list, 0, sizeof(list));
511 list.ifa_name = const_cast<char*>("test_iface");
512
513 NetworkManager::NetworkList result;
514 BasicNetworkManager manager;
515 CallConvertIfAddrs(manager, &list, true, &result);
516 EXPECT_TRUE(result.empty());
517}
518#endif // defined(POSIX)
519
520
521} // namespace talk_base