William A. Kennington III | 14dd4eb | 2023-01-12 10:51:12 -0800 | [diff] [blame] | 1 | #include <fmt/format.h> |
| 2 | |
| 3 | #include <stdplus/net/addr/subnet.hpp> |
| 4 | |
William A. Kennington III | 5b20b0a | 2023-07-18 13:38:37 -0700 | [diff] [blame] | 5 | #include <format> |
William A. Kennington III | 160e382 | 2023-06-16 17:09:43 -0700 | [diff] [blame] | 6 | #include <string_view> |
| 7 | |
William A. Kennington III | 14dd4eb | 2023-01-12 10:51:12 -0800 | [diff] [blame] | 8 | #include <gtest/gtest.h> |
| 9 | |
William A. Kennington III | 160e382 | 2023-06-16 17:09:43 -0700 | [diff] [blame] | 10 | using std::literals::string_view_literals::operator""sv; |
| 11 | |
William A. Kennington III | 14dd4eb | 2023-01-12 10:51:12 -0800 | [diff] [blame] | 12 | namespace stdplus |
| 13 | { |
| 14 | |
| 15 | auto addr4Full = In4Addr{255, 255, 255, 255}; |
| 16 | auto addr6Full = In6Addr{255, 255, 255, 255, 255, 255, 255, 255, |
| 17 | 255, 255, 255, 255, 255, 255, 255, 255}; |
| 18 | |
| 19 | TEST(Subnet4, Basic) |
| 20 | { |
| 21 | EXPECT_NO_THROW(Subnet4(in_addr{0xffffffff}, 32)); |
| 22 | EXPECT_NO_THROW(Subnet4(addr4Full, 0)); |
| 23 | EXPECT_NO_THROW(Subnet4(in_addr{}, 10)); |
| 24 | EXPECT_THROW(Subnet4(in_addr{0xffffffff}, 33), std::invalid_argument); |
| 25 | EXPECT_THROW(Subnet4(in_addr{0xffffffff}, 64), std::invalid_argument); |
| 26 | |
| 27 | EXPECT_NE(Subnet4(in_addr{0xff}, 32), Subnet4(in_addr{}, 32)); |
| 28 | EXPECT_NE(Subnet4(in_addr{0xff}, 26), Subnet4(in_addr{0xff}, 27)); |
| 29 | EXPECT_EQ(Subnet4(in_addr{0xff}, 32), Subnet4(in_addr{0xff}, 32)); |
| 30 | EXPECT_EQ(Subnet4(in_addr{}, 1), Subnet4(in_addr{}, 1)); |
| 31 | } |
| 32 | |
| 33 | TEST(Subnet4, Network) |
| 34 | { |
| 35 | EXPECT_EQ((In4Addr{}), Subnet4(In4Addr{}, 32).network()); |
| 36 | EXPECT_EQ(addr4Full, Subnet4(addr4Full, 32).network()); |
| 37 | EXPECT_EQ((In4Addr{255, 255, 128, 0}), Subnet4(addr4Full, 17).network()); |
| 38 | EXPECT_EQ((In4Addr{255, 255, 0, 0}), Subnet4(addr4Full, 16).network()); |
| 39 | EXPECT_EQ((In4Addr{255, 254, 0, 0}), Subnet4(addr4Full, 15).network()); |
| 40 | EXPECT_EQ((In4Addr{}), Subnet4(addr4Full, 0).network()); |
| 41 | EXPECT_EQ((In4Addr{}), Subnet4(In4Addr{}, 0).network()); |
| 42 | } |
| 43 | |
| 44 | TEST(Subnet4, Contains) |
| 45 | { |
| 46 | EXPECT_TRUE(Subnet4(addr4Full, 32).contains(addr4Full)); |
| 47 | EXPECT_FALSE(Subnet4(addr4Full, 32).contains(In4Addr{255, 255, 255, 254})); |
| 48 | EXPECT_FALSE(Subnet4(addr4Full, 32).contains(In4Addr{})); |
| 49 | EXPECT_TRUE( |
| 50 | Subnet4(addr4Full, 17).contains(static_cast<in_addr>(addr4Full))); |
| 51 | EXPECT_TRUE(Subnet4(addr4Full, 17).contains(In4Addr{255, 255, 128, 134})); |
| 52 | EXPECT_FALSE(Subnet4(addr4Full, 17).contains(In4Addr{255, 255, 127, 132})); |
| 53 | EXPECT_TRUE(Subnet4(addr4Full, 14).contains(addr4Full)); |
| 54 | EXPECT_TRUE(Subnet4(addr4Full, 0).contains(addr4Full)); |
| 55 | EXPECT_TRUE(Subnet4(In4Addr{}, 0).contains(addr4Full)); |
| 56 | EXPECT_TRUE(Subnet4(addr4Full, 0).contains(In4Addr{})); |
| 57 | } |
| 58 | |
William A. Kennington III | 160e382 | 2023-06-16 17:09:43 -0700 | [diff] [blame] | 59 | TEST(Subnet4, FromStr) |
| 60 | { |
| 61 | constexpr FromStr<Subnet4> fs; |
| 62 | EXPECT_THROW(fs("10"sv), std::invalid_argument); |
| 63 | EXPECT_THROW(fs("/10"sv), std::invalid_argument); |
| 64 | EXPECT_THROW(fs("0.0.0.0"sv), std::invalid_argument); |
| 65 | EXPECT_THROW(fs("0.0.0.0/"sv), std::invalid_argument); |
| 66 | EXPECT_THROW(fs("::/80"sv), std::invalid_argument); |
| 67 | EXPECT_EQ((SubnetAny{in_addr{}, 30}), fs("0.0.0.0/30"sv)); |
William A. Kennington III | 39011c8 | 2023-06-28 17:49:30 -0700 | [diff] [blame] | 68 | EXPECT_EQ((SubnetAny{in_addr{}, 30}), "0.0.0.0/30"_sub4); |
William A. Kennington III | 160e382 | 2023-06-16 17:09:43 -0700 | [diff] [blame] | 69 | } |
| 70 | |
William A. Kennington III | d5957f5 | 2023-06-16 16:55:01 -0700 | [diff] [blame] | 71 | TEST(Subnet4, ToStr) |
| 72 | { |
| 73 | ToStrHandle<ToStr<Subnet4>> tsh; |
| 74 | EXPECT_EQ("0.0.0.0/16", tsh(Subnet4({}, 16))); |
| 75 | EXPECT_EQ("255.0.255.255/28", tsh(Subnet4(In4Addr{255, 0, 255, 255}, 28))); |
| 76 | EXPECT_EQ("a 1.2.3.4/32 b", |
| 77 | fmt::format("a {} b", Subnet4(In4Addr{1, 2, 3, 4}, 32))); |
William A. Kennington III | 5b20b0a | 2023-07-18 13:38:37 -0700 | [diff] [blame] | 78 | EXPECT_EQ("a 1.2.3.4/32 b", |
| 79 | std::format("a {} b", Subnet4(In4Addr{1, 2, 3, 4}, 32))); |
William A. Kennington III | d5957f5 | 2023-06-16 16:55:01 -0700 | [diff] [blame] | 80 | } |
| 81 | |
William A. Kennington III | 14dd4eb | 2023-01-12 10:51:12 -0800 | [diff] [blame] | 82 | TEST(Subnet6, Basic) |
| 83 | { |
| 84 | EXPECT_NO_THROW(Subnet6(in6_addr{0xff}, 128)); |
| 85 | EXPECT_NO_THROW(Subnet6(addr6Full, 0)); |
| 86 | EXPECT_NO_THROW(Subnet6(in6_addr{}, 65)); |
| 87 | EXPECT_THROW(Subnet6(in6_addr{0xff}, 129), std::invalid_argument); |
| 88 | EXPECT_THROW(Subnet6(in6_addr{0xff}, 150), std::invalid_argument); |
| 89 | |
| 90 | EXPECT_NE(Subnet6(in6_addr{0xff}, 32), Subnet6(in6_addr{}, 32)); |
| 91 | EXPECT_NE(Subnet6(in6_addr{0xff}, 26), Subnet6(in6_addr{0xff}, 27)); |
| 92 | EXPECT_EQ(Subnet6(in6_addr{0xff}, 32), Subnet6(in6_addr{0xff}, 32)); |
| 93 | EXPECT_EQ(Subnet6(in6_addr{}, 1), Subnet6(in6_addr{}, 1)); |
| 94 | } |
| 95 | |
| 96 | TEST(Subnet6, Network) |
| 97 | { |
| 98 | EXPECT_EQ(In6Addr(), Subnet6(In6Addr(), 128).network()); |
| 99 | EXPECT_EQ(addr6Full, Subnet6(addr6Full, 128).network()); |
| 100 | EXPECT_EQ((In6Addr{255, 255, 255, 255, 224}), |
| 101 | Subnet6(addr6Full, 35).network()); |
| 102 | EXPECT_EQ((In6Addr{255, 255, 255, 255}), Subnet6(addr6Full, 32).network()); |
| 103 | EXPECT_EQ((In6Addr{255, 255, 128, 0}), Subnet6(addr6Full, 17).network()); |
| 104 | EXPECT_EQ((In6Addr{255, 255, 0, 0}), Subnet6(addr6Full, 16).network()); |
| 105 | EXPECT_EQ((In6Addr{255, 254, 0, 0}), Subnet6(addr6Full, 15).network()); |
| 106 | EXPECT_EQ((In6Addr{}), Subnet6(addr6Full, 0).network()); |
| 107 | EXPECT_EQ((In6Addr{}), Subnet6(In6Addr{}, 0).network()); |
| 108 | } |
| 109 | |
| 110 | TEST(Subnet6, Contains) |
| 111 | { |
| 112 | auto addr6NFull = addr6Full; |
| 113 | addr6NFull.s6_addr[15] = 254; |
| 114 | EXPECT_TRUE(Subnet6(addr6Full, 128).contains(addr6Full)); |
| 115 | EXPECT_FALSE(Subnet6(addr6Full, 128).contains(addr6NFull)); |
| 116 | EXPECT_FALSE(Subnet6(addr6Full, 128).contains(In6Addr{})); |
| 117 | EXPECT_TRUE( |
| 118 | Subnet6(addr6Full, 127).contains(static_cast<in6_addr>(addr6Full))); |
| 119 | EXPECT_TRUE(Subnet6(addr6Full, 127).contains(addr6NFull)); |
| 120 | EXPECT_TRUE( |
| 121 | Subnet6(addr6Full, 33).contains(In6Addr{255, 255, 255, 255, 128, 255})); |
| 122 | EXPECT_FALSE( |
| 123 | Subnet6(addr6Full, 33).contains(In6Addr{255, 255, 255, 255, 127})); |
| 124 | EXPECT_TRUE(Subnet6(In6Addr{}, 33).contains(In6Addr{0, 0, 0, 0, 127})); |
| 125 | EXPECT_TRUE( |
| 126 | Subnet6(addr6Full, 14).contains(In6Addr{255, 255, 0, 0, 0, 0, 0, 145})); |
| 127 | EXPECT_FALSE(Subnet6(addr6Full, 14).contains(In6Addr{255, 127, 1})); |
| 128 | EXPECT_TRUE(Subnet6(addr6Full, 0).contains(addr6Full)); |
| 129 | EXPECT_TRUE(Subnet6(In6Addr{}, 0).contains(addr6Full)); |
| 130 | EXPECT_TRUE(Subnet6(addr6Full, 0).contains(In6Addr{})); |
| 131 | } |
| 132 | |
William A. Kennington III | 160e382 | 2023-06-16 17:09:43 -0700 | [diff] [blame] | 133 | TEST(Subnet6, FromStr) |
| 134 | { |
| 135 | constexpr FromStr<Subnet6> fs; |
| 136 | EXPECT_THROW(fs("10"sv), std::invalid_argument); |
| 137 | EXPECT_THROW(fs("/10"sv), std::invalid_argument); |
| 138 | EXPECT_THROW(fs("ff::"sv), std::invalid_argument); |
| 139 | EXPECT_THROW(fs("::/"sv), std::invalid_argument); |
| 140 | EXPECT_THROW(fs("0.0.0.0/0"sv), std::invalid_argument); |
| 141 | EXPECT_EQ((Subnet6{in6_addr{}, 80}), fs("::/80"sv)); |
William A. Kennington III | 39011c8 | 2023-06-28 17:49:30 -0700 | [diff] [blame] | 142 | EXPECT_EQ((Subnet6{in6_addr{}, 80}), "::/80"_sub6); |
William A. Kennington III | 160e382 | 2023-06-16 17:09:43 -0700 | [diff] [blame] | 143 | } |
| 144 | |
William A. Kennington III | d5957f5 | 2023-06-16 16:55:01 -0700 | [diff] [blame] | 145 | TEST(Subnet6, ToStr) |
| 146 | { |
| 147 | ToStrHandle<ToStr<Subnet6>> tsh; |
| 148 | EXPECT_EQ("::/0", tsh(Subnet6({}, 0))); |
| 149 | EXPECT_EQ("ff00::/128", tsh(Subnet6(In6Addr{0xff}, 128))); |
| 150 | EXPECT_EQ("a 102:304::/32 b", |
| 151 | fmt::format("a {} b", Subnet6(In6Addr{1, 2, 3, 4}, 32))); |
William A. Kennington III | 5b20b0a | 2023-07-18 13:38:37 -0700 | [diff] [blame] | 152 | EXPECT_EQ("a 102:304::/32 b", |
| 153 | std::format("a {} b", Subnet6(In6Addr{1, 2, 3, 4}, 32))); |
William A. Kennington III | d5957f5 | 2023-06-16 16:55:01 -0700 | [diff] [blame] | 154 | } |
| 155 | |
William A. Kennington III | 14dd4eb | 2023-01-12 10:51:12 -0800 | [diff] [blame] | 156 | TEST(SubnetAny, Basic) |
| 157 | { |
| 158 | EXPECT_NO_THROW(SubnetAny(in_addr{0xffffffff}, 32)); |
| 159 | EXPECT_NO_THROW(SubnetAny(addr4Full, 0)); |
| 160 | EXPECT_NO_THROW(SubnetAny(InAnyAddr{addr4Full}, 0)); |
| 161 | EXPECT_NO_THROW(SubnetAny(in_addr{}, 10)); |
| 162 | EXPECT_THROW(SubnetAny(in_addr{0xffffffff}, 33), std::invalid_argument); |
| 163 | EXPECT_THROW(SubnetAny(InAnyAddr{in_addr{0xffffffff}}, 33), |
| 164 | std::invalid_argument); |
| 165 | EXPECT_THROW(SubnetAny(in_addr{0xffffffff}, 64), std::invalid_argument); |
| 166 | EXPECT_NO_THROW(SubnetAny(in6_addr{0xff}, 128)); |
| 167 | EXPECT_NO_THROW(SubnetAny(addr6Full, 0)); |
| 168 | EXPECT_NO_THROW(SubnetAny(InAnyAddr{addr6Full}, 0)); |
| 169 | EXPECT_NO_THROW(SubnetAny(in6_addr{}, 65)); |
| 170 | EXPECT_THROW(SubnetAny(in6_addr{0xff}, 129), std::invalid_argument); |
| 171 | EXPECT_THROW(SubnetAny(InAnyAddr{in6_addr{0xff}}, 129), |
| 172 | std::invalid_argument); |
| 173 | EXPECT_THROW(SubnetAny(in6_addr{0xff}, 150), std::invalid_argument); |
| 174 | |
| 175 | EXPECT_NO_THROW(SubnetAny(Subnet4(in_addr{}, 32))); |
| 176 | EXPECT_NO_THROW(SubnetAny(Subnet6(in6_addr{0xff}, 128))); |
| 177 | |
| 178 | EXPECT_NE(SubnetAny(in6_addr{0xff}, 32), Subnet6(in6_addr{}, 32)); |
| 179 | EXPECT_NE(Subnet6(in6_addr{0xff}, 26), SubnetAny(in6_addr{0xff}, 27)); |
| 180 | EXPECT_EQ(SubnetAny(in6_addr{0xff}, 32), Subnet6(in6_addr{0xff}, 32)); |
| 181 | EXPECT_EQ(SubnetAny(in6_addr{0xff}, 32), SubnetAny(in6_addr{0xff}, 32)); |
| 182 | EXPECT_NE(SubnetAny(in6_addr{0xff}, 32), Subnet4(in_addr{0xff}, 32)); |
| 183 | EXPECT_NE(SubnetAny(in_addr{0xff}, 32), Subnet4(in_addr{}, 32)); |
| 184 | EXPECT_NE(Subnet4(in_addr{0xff}, 26), SubnetAny(in_addr{0xff}, 27)); |
| 185 | EXPECT_EQ(SubnetAny(in_addr{0xff}, 32), Subnet4(in_addr{0xff}, 32)); |
| 186 | EXPECT_EQ(SubnetAny(in_addr{0xff}, 32), SubnetAny(in_addr{0xff}, 32)); |
| 187 | } |
| 188 | |
| 189 | TEST(SubnetAny, Network) |
| 190 | { |
| 191 | EXPECT_EQ(In6Addr(), SubnetAny(In6Addr(), 128).network()); |
| 192 | EXPECT_EQ(addr6Full, SubnetAny(addr6Full, 128).network()); |
| 193 | EXPECT_EQ(In6Addr(), SubnetAny(addr6Full, 0).network()); |
| 194 | EXPECT_EQ(In4Addr(), SubnetAny(In4Addr(), 32).network()); |
| 195 | EXPECT_EQ(addr4Full, SubnetAny(addr4Full, 32).network()); |
| 196 | EXPECT_EQ(In4Addr(), SubnetAny(addr4Full, 0).network()); |
| 197 | } |
| 198 | |
| 199 | TEST(SubnetAny, Contains) |
| 200 | { |
| 201 | EXPECT_TRUE(SubnetAny(addr6Full, 128).contains(addr6Full)); |
| 202 | EXPECT_TRUE(SubnetAny(addr6Full, 128).contains(InAnyAddr{addr6Full})); |
| 203 | EXPECT_FALSE(SubnetAny(addr6Full, 128).contains(in6_addr{})); |
| 204 | EXPECT_FALSE(SubnetAny(addr6Full, 128).contains(InAnyAddr(in6_addr{}))); |
| 205 | EXPECT_TRUE(SubnetAny(addr4Full, 32).contains(addr4Full)); |
| 206 | EXPECT_TRUE(SubnetAny(addr4Full, 32).contains(InAnyAddr{addr4Full})); |
| 207 | EXPECT_FALSE(SubnetAny(addr4Full, 32).contains(in_addr{})); |
| 208 | EXPECT_FALSE(SubnetAny(addr4Full, 32).contains(InAnyAddr{In4Addr{}})); |
| 209 | } |
| 210 | |
William A. Kennington III | 160e382 | 2023-06-16 17:09:43 -0700 | [diff] [blame] | 211 | TEST(SubnetAny, FromStr) |
| 212 | { |
| 213 | constexpr FromStr<SubnetAny> fs; |
| 214 | EXPECT_THROW(fs("10"sv), std::invalid_argument); |
| 215 | EXPECT_THROW(fs("/10"sv), std::invalid_argument); |
| 216 | EXPECT_THROW(fs("0.0.0.0"sv), std::invalid_argument); |
| 217 | EXPECT_THROW(fs("0.0.0.0/"sv), std::invalid_argument); |
| 218 | EXPECT_EQ((SubnetAny{in_addr{}, 0}), fs("0.0.0.0/0"sv)); |
| 219 | EXPECT_EQ((SubnetAny{in_addr{}, 30}), fs("0.0.0.0/30"sv)); |
William A. Kennington III | 39011c8 | 2023-06-28 17:49:30 -0700 | [diff] [blame] | 220 | EXPECT_EQ((SubnetAny{in_addr{}, 30}), "0.0.0.0/30"_sub); |
William A. Kennington III | 160e382 | 2023-06-16 17:09:43 -0700 | [diff] [blame] | 221 | EXPECT_EQ((SubnetAny{in6_addr{}, 80}), fs("::/80"sv)); |
William A. Kennington III | 39011c8 | 2023-06-28 17:49:30 -0700 | [diff] [blame] | 222 | EXPECT_EQ((SubnetAny{in6_addr{}, 80}), "::/80"_sub); |
William A. Kennington III | 160e382 | 2023-06-16 17:09:43 -0700 | [diff] [blame] | 223 | } |
| 224 | |
William A. Kennington III | d5957f5 | 2023-06-16 16:55:01 -0700 | [diff] [blame] | 225 | TEST(SubnetAny, ToStr) |
| 226 | { |
| 227 | ToStrHandle<ToStr<SubnetAny>> tsh; |
| 228 | EXPECT_EQ("0.0.0.0/16", tsh(SubnetAny(In4Addr{}, 16))); |
| 229 | EXPECT_EQ("ff00::/128", tsh(SubnetAny(In6Addr{0xff}, 128))); |
| 230 | EXPECT_EQ("a 102:304::/32 b", |
| 231 | fmt::format("a {} b", SubnetAny(In6Addr{1, 2, 3, 4}, 32))); |
William A. Kennington III | 5b20b0a | 2023-07-18 13:38:37 -0700 | [diff] [blame] | 232 | EXPECT_EQ("a 102:304::/32 b", |
| 233 | std::format("a {} b", SubnetAny(In6Addr{1, 2, 3, 4}, 32))); |
William A. Kennington III | d5957f5 | 2023-06-16 16:55:01 -0700 | [diff] [blame] | 234 | EXPECT_EQ("a 1.2.3.4/32 b", |
| 235 | fmt::format("a {} b", SubnetAny(In4Addr{1, 2, 3, 4}, 32))); |
William A. Kennington III | 5b20b0a | 2023-07-18 13:38:37 -0700 | [diff] [blame] | 236 | EXPECT_EQ("a 1.2.3.4/32 b", |
| 237 | std::format("a {} b", SubnetAny(In4Addr{1, 2, 3, 4}, 32))); |
William A. Kennington III | d5957f5 | 2023-06-16 16:55:01 -0700 | [diff] [blame] | 238 | } |
| 239 | |
William A. Kennington III | c870ac3 | 2023-06-17 17:13:45 -0700 | [diff] [blame] | 240 | TEST(Ops, MaskToPfx) |
| 241 | { |
| 242 | EXPECT_EQ(32, maskToPfx(In4Addr{0xff, 0xff, 0xff, 0xff})); |
| 243 | EXPECT_EQ(28, maskToPfx(In4Addr{0xff, 0xff, 0xff, 0xf0})); |
| 244 | EXPECT_EQ(16, maskToPfx(In4Addr{0xff, 0xff, 0, 0})); |
| 245 | EXPECT_EQ(0, maskToPfx(In4Addr{})); |
| 246 | |
| 247 | EXPECT_THROW(maskToPfx(In4Addr{0, 0x8}), std::invalid_argument); |
| 248 | EXPECT_THROW(maskToPfx(In4Addr{0x40}), std::invalid_argument); |
| 249 | } |
| 250 | |
William A. Kennington III | 14dd4eb | 2023-01-12 10:51:12 -0800 | [diff] [blame] | 251 | } // namespace stdplus |