1 // Copyright 2023 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/base/fuchsia/network_interface_cache.h"
6
7 #include <fuchsia/net/interfaces/cpp/fidl.h>
8 #include <fuchsia/net/interfaces/cpp/fidl_test_base.h>
9
10 #include "net/base/network_change_notifier.h"
11 #include "net/base/network_interfaces.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13
14 namespace net::internal {
15 namespace {
16
17 enum : InterfaceProperties::InterfaceId {
18 kDefaultInterfaceId = 1,
19 kSecondaryInterfaceId = 2
20 };
21
22 using IPv4Octets = std::array<uint8_t, 4>;
23
24 constexpr IPv4Octets kDefaultIPv4Address = {192, 168, 0, 2};
25 constexpr uint8_t kDefaultIPv4Prefix = 16;
26
27 constexpr const char kDefaultInterfaceName[] = "net1";
28
IpAddressFrom(IPv4Octets octets)29 fuchsia::net::IpAddress IpAddressFrom(IPv4Octets octets) {
30 fuchsia::net::IpAddress output;
31 output.ipv4().addr = octets;
32 return output;
33 }
34
35 template <typename T>
SubnetFrom(T octets,uint8_t prefix)36 fuchsia::net::Subnet SubnetFrom(T octets, uint8_t prefix) {
37 fuchsia::net::Subnet output;
38 output.addr = IpAddressFrom(octets);
39 output.prefix_len = prefix;
40 return output;
41 }
42
43 template <typename T>
InterfaceAddressFrom(T octets,uint8_t prefix)44 fuchsia::net::interfaces::Address InterfaceAddressFrom(T octets,
45 uint8_t prefix) {
46 fuchsia::net::interfaces::Address addr;
47 addr.set_addr(SubnetFrom(octets, prefix));
48 return addr;
49 }
50
51 template <typename T>
MakeSingleItemVec(T item)52 std::vector<T> MakeSingleItemVec(T item) {
53 std::vector<T> vec;
54 vec.push_back(std::move(item));
55 return vec;
56 }
57
DefaultInterfaceProperties(fuchsia::hardware::network::PortClass device_class=fuchsia::hardware::network::PortClass::ETHERNET)58 fuchsia::net::interfaces::Properties DefaultInterfaceProperties(
59 fuchsia::hardware::network::PortClass device_class =
60 fuchsia::hardware::network::PortClass::ETHERNET) {
61 // For most tests a live interface with an IPv4 address and ethernet class is
62 // sufficient.
63 fuchsia::net::interfaces::Properties properties;
64 properties.set_id(kDefaultInterfaceId);
65 properties.set_name(kDefaultInterfaceName);
66 properties.set_online(true);
67 properties.set_has_default_ipv4_route(true);
68 properties.set_has_default_ipv6_route(false);
69 properties.set_port_class(fuchsia::net::interfaces::PortClass::WithDevice(
70 std::move(device_class)));
71 properties.set_addresses(MakeSingleItemVec(
72 InterfaceAddressFrom(kDefaultIPv4Address, kDefaultIPv4Prefix)));
73 return properties;
74 }
75
76 } // namespace
77
78 class NetworkInterfaceCacheTest : public testing::Test {};
79
TEST_F(NetworkInterfaceCacheTest,AddInterface)80 TEST_F(NetworkInterfaceCacheTest, AddInterface) {
81 NetworkInterfaceCache cache(false);
82
83 auto change_bits = cache.AddInterface(DefaultInterfaceProperties());
84
85 ASSERT_TRUE(change_bits.has_value());
86 EXPECT_EQ(change_bits.value(),
87 NetworkInterfaceCache::kIpAddressChanged |
88 NetworkInterfaceCache::kConnectionTypeChanged);
89
90 NetworkInterfaceList networks;
91 EXPECT_TRUE(cache.GetOnlineInterfaces(&networks));
92 EXPECT_EQ(networks.size(), 1u);
93
94 EXPECT_EQ(cache.GetConnectionType(),
95 NetworkChangeNotifier::CONNECTION_ETHERNET);
96 }
97
TEST_F(NetworkInterfaceCacheTest,RemoveInterface)98 TEST_F(NetworkInterfaceCacheTest, RemoveInterface) {
99 NetworkInterfaceCache cache(false);
100 cache.AddInterface(DefaultInterfaceProperties());
101
102 auto change_bits = cache.RemoveInterface(kDefaultInterfaceId);
103
104 ASSERT_TRUE(change_bits.has_value());
105 EXPECT_EQ(change_bits.value(),
106 NetworkInterfaceCache::kIpAddressChanged |
107 NetworkInterfaceCache::kConnectionTypeChanged);
108
109 NetworkInterfaceList networks;
110 EXPECT_TRUE(cache.GetOnlineInterfaces(&networks));
111 EXPECT_EQ(networks.size(), 0u);
112
113 EXPECT_EQ(cache.GetConnectionType(), NetworkChangeNotifier::CONNECTION_NONE);
114 }
115
TEST_F(NetworkInterfaceCacheTest,ChangeInterface)116 TEST_F(NetworkInterfaceCacheTest, ChangeInterface) {
117 NetworkInterfaceCache cache(false);
118 cache.AddInterface(DefaultInterfaceProperties());
119
120 fuchsia::net::interfaces::Properties properties;
121 properties.set_id(kDefaultInterfaceId);
122 properties.set_port_class(
123 fuchsia::net::interfaces::PortClass::WithLoopback(
124 fuchsia::net::interfaces::Empty()));
125 properties.set_addresses({});
126
127 auto change_bits = cache.ChangeInterface(std::move(properties));
128
129 ASSERT_TRUE(change_bits.has_value());
130 EXPECT_EQ(change_bits.value(),
131 NetworkInterfaceCache::kIpAddressChanged |
132 NetworkInterfaceCache::kConnectionTypeChanged);
133
134 NetworkInterfaceList networks;
135 EXPECT_TRUE(cache.GetOnlineInterfaces(&networks));
136 EXPECT_EQ(networks.size(), 0u);
137
138 EXPECT_EQ(cache.GetConnectionType(), NetworkChangeNotifier::CONNECTION_NONE);
139 }
140
141 // TODO(crbug.com/40721278): Add more tests that exercise different error
142 // states.
143
144 } // namespace net::internal
145