1 #include "types.hpp"
2 
3 #include <arpa/inet.h>
4 #include <fmt/chrono.h>
5 #include <fmt/format.h>
6 
7 #include <array>
8 #include <sstream>
9 #include <string_view>
10 
11 #include <gtest/gtest.h>
12 
13 using std::literals::string_view_literals::operator""sv;
14 
15 TEST(EqualOperator, EthAddr)
16 {
17     EXPECT_EQ((ether_addr{0x11, 0x22, 0x33, 0x44, 0x55, 0x66}),
18               (ether_addr{0x11, 0x22, 0x33, 0x44, 0x55, 0x66}));
19     EXPECT_EQ((ether_addr{}), (ether_addr{}));
20     EXPECT_NE((ether_addr{1}), (ether_addr{}));
21 }
22 
23 TEST(EqualOperator, InAddr)
24 {
25     EXPECT_EQ((in_addr{0xff00ff00}), (in_addr{0xff00ff00}));
26     EXPECT_EQ((in_addr{}), (in_addr{}));
27     EXPECT_NE((in_addr{1}), (in_addr{}));
28 }
29 
30 TEST(EqualOperator, In6Addr)
31 {
32     EXPECT_EQ((in6_addr{0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff}),
33               (in6_addr{0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff}));
34     EXPECT_EQ((in6_addr{}), (in6_addr{}));
35     EXPECT_NE((in6_addr{1}), (in6_addr{}));
36 }
37 
38 namespace phosphor::network
39 {
40 
41 TEST(Byteswap, Swap)
42 {
43     EXPECT_EQ(38, bswap(uint8_t{38}));
44     EXPECT_EQ(38 << 8, bswap(uint16_t{38}));
45     EXPECT_EQ(0x240082fe, bswap(uint32_t{0xfe820024}));
46     EXPECT_EQ(0x240082fe00000000, bswap(uint64_t{0xfe820024}));
47     struct
48     {
49         std::array<char, 4> a = {1, 2, 3, 4};
50     } s;
51     EXPECT_EQ((std::array<char, 4>{4, 3, 2, 1}), bswap(s).a);
52 }
53 
54 TEST(DecodeInt, uint8_10)
55 {
56     DecodeInt<uint8_t, 10> d;
57     EXPECT_EQ(42, d("42"));
58     EXPECT_EQ(255, d("255"));
59     EXPECT_THROW(d(""), std::invalid_argument);
60     EXPECT_THROW(d("a0"), std::invalid_argument);
61     EXPECT_THROW(d(".0"), std::invalid_argument);
62     EXPECT_THROW(d("257"), std::overflow_error);
63     EXPECT_THROW(d("300"), std::overflow_error);
64 }
65 
66 TEST(DecodeInt, uint8_16)
67 {
68     DecodeInt<uint8_t, 16> d;
69     EXPECT_EQ(0x42, d("42"));
70     EXPECT_EQ(0xff, d("ff"));
71     EXPECT_THROW(d(""), std::invalid_argument);
72     EXPECT_THROW(d("g0"), std::invalid_argument);
73     EXPECT_THROW(d(".0"), std::invalid_argument);
74     EXPECT_THROW(d("100"), std::overflow_error);
75 }
76 
77 TEST(EncodeInt, uint8_10)
78 {
79     EncodeInt<uint8_t, 10> e;
80     static_assert(e.buf_size == 3);
81     char buf[e.buf_size];
82     EXPECT_EQ("0", std::string_view(buf, e(buf, 0)));
83     EXPECT_EQ("42", std::string_view(buf, e(buf, 42)));
84     EXPECT_EQ("255", std::string_view(buf, e(buf, 255)));
85     EXPECT_EQ("000", std::string_view(buf, e(buf, 0, 3)));
86     EXPECT_EQ("255", std::string_view(buf, e(buf, 255, 3)));
87 }
88 
89 TEST(EncodeInt, uint8_16)
90 {
91     EncodeInt<uint8_t, 16> e;
92     static_assert(e.buf_size == 2);
93     char buf[e.buf_size];
94     EXPECT_EQ("0", std::string_view(buf, e(buf, 0)));
95     EXPECT_EQ("2a", std::string_view(buf, e(buf, 42)));
96     EXPECT_EQ("ff", std::string_view(buf, e(buf, 255)));
97     EXPECT_EQ("00", std::string_view(buf, e(buf, 0, 2)));
98     EXPECT_EQ("02", std::string_view(buf, e(buf, 2, 2)));
99     EXPECT_EQ("ff", std::string_view(buf, e(buf, 255, 2)));
100 }
101 
102 TEST(EqualOperator, InAddrAny)
103 {
104     EXPECT_EQ(InAddrAny(in6_addr{0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
105                                  0xff}),
106               (in6_addr{0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff}));
107     EXPECT_NE(InAddrAny(in6_addr{0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
108                                  0xff}),
109               (in_addr{}));
110     EXPECT_EQ((in6_addr{}), InAddrAny(in6_addr{}));
111     EXPECT_NE((in_addr{}), InAddrAny(in6_addr{}));
112     EXPECT_NE(InAddrAny(in6_addr{1}), InAddrAny(in6_addr{}));
113 }
114 
115 TEST(ToAddr, EtherAddr)
116 {
117     EXPECT_THROW(ToAddr<ether_addr>{}("0x:00:00:00:00:00"),
118                  std::invalid_argument);
119     EXPECT_THROW(ToAddr<ether_addr>{}("00:00:00:00:00"), std::invalid_argument);
120     EXPECT_THROW(ToAddr<ether_addr>{}("00:00:00:00:00:"),
121                  std::invalid_argument);
122     EXPECT_THROW(ToAddr<ether_addr>{}("00:00:00:00::00"),
123                  std::invalid_argument);
124     EXPECT_THROW(ToAddr<ether_addr>{}(":00:00:00:00:00"),
125                  std::invalid_argument);
126     EXPECT_THROW(ToAddr<ether_addr>{}("00::00:00:00:00"),
127                  std::invalid_argument);
128     EXPECT_THROW(ToAddr<ether_addr>{}(":::::"), std::invalid_argument);
129     EXPECT_THROW(ToAddr<ether_addr>{}("00:0:0:0:0"), std::invalid_argument);
130     EXPECT_THROW(ToAddr<ether_addr>{}("00:00:00:00:00:00:00"),
131                  std::invalid_argument);
132     EXPECT_THROW(ToAddr<ether_addr>{}(""), std::invalid_argument);
133     EXPECT_THROW(ToAddr<ether_addr>{}("123456789XYZ"), std::invalid_argument);
134     EXPECT_THROW(ToAddr<ether_addr>{}("123456789AB"), std::overflow_error);
135     EXPECT_THROW(ToAddr<ether_addr>{}("123456789ABCD"), std::overflow_error);
136 
137     EXPECT_EQ((ether_addr{}), ToAddr<ether_addr>{}("00:00:00:00:00:00"));
138     EXPECT_EQ((ether_addr{0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa}),
139               ToAddr<ether_addr>{}("FF:EE:DD:cc:bb:aa"));
140     EXPECT_EQ((ether_addr{0x00, 0x01, 0x02, 0x03, 0x04, 0x05}),
141               ToAddr<ether_addr>{}("0:1:2:3:4:5"));
142     EXPECT_EQ((ether_addr{0x01, 0x23, 0x45, 0x67, 0x89, 0xab}),
143               ToAddr<ether_addr>{}("0123456789AB"));
144     EXPECT_EQ((ether_addr{0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa}),
145               ToAddr<ether_addr>{}("FFEEDDccbbaa"));
146 }
147 
148 TEST(ToAddr, InAddr)
149 {
150     EXPECT_THROW(ToAddr<in_addr>{}(""), std::invalid_argument);
151     EXPECT_THROW(ToAddr<in_addr>{}("0"), std::invalid_argument);
152     EXPECT_THROW(ToAddr<in_addr>{}("0.0.0"), std::invalid_argument);
153     EXPECT_THROW(ToAddr<in_addr>{}("0.0.0."), std::invalid_argument);
154     EXPECT_THROW(ToAddr<in_addr>{}(".0.0.0"), std::invalid_argument);
155     EXPECT_THROW(ToAddr<in_addr>{}("0.0.0.0.0"), std::invalid_argument);
156     EXPECT_THROW(ToAddr<in_addr>{}("x.0.0.0"), std::invalid_argument);
157     EXPECT_THROW(ToAddr<in_addr>{}("ff.0.0.0"), std::invalid_argument);
158     EXPECT_THROW(ToAddr<in_addr>{}("256.0.0.0"), std::overflow_error);
159 
160     EXPECT_EQ((in_addr{}), ToAddr<in_addr>{}("0.0.0.0"));
161     EXPECT_EQ((in_addr{htonl(0xc0a80101)}), ToAddr<in_addr>{}("192.168.001.1"));
162 }
163 
164 TEST(ToAddr, In6Addr)
165 {
166     constexpr ToAddr<in6_addr> ta;
167     EXPECT_THROW(ta(""), std::invalid_argument);
168     EXPECT_THROW(ta("0"), std::invalid_argument);
169     EXPECT_THROW(ta("0:0"), std::invalid_argument);
170     EXPECT_THROW(ta("0::0:"), std::invalid_argument);
171     EXPECT_THROW(ta("0:::"), std::invalid_argument);
172     EXPECT_THROW(ta(":::0"), std::invalid_argument);
173     EXPECT_THROW(ta("0:::0"), std::invalid_argument);
174     EXPECT_THROW(ta("0::0::0"), std::invalid_argument);
175     EXPECT_THROW(ta("1::0.0.0."), std::invalid_argument);
176     EXPECT_THROW(ta("1::.0.0.0"), std::invalid_argument);
177     EXPECT_THROW(ta("x::0"), std::invalid_argument);
178     EXPECT_THROW(ta("g::0"), std::invalid_argument);
179     EXPECT_THROW(ta("0:1:2:3:4::5:6:7"), std::invalid_argument);
180     EXPECT_THROW(ta("::0:1:2:3:4:5:6:7"), std::invalid_argument);
181     EXPECT_THROW(ta("0:1:2:3:4:5:6:7::"), std::invalid_argument);
182     EXPECT_THROW(ta("0:1:2:3:4:5:6:7:8"), std::invalid_argument);
183     EXPECT_THROW(ta("0:1:2:3:4:5:6:0.0.0.0"), std::invalid_argument);
184     EXPECT_THROW(ta("0:1:2:3:4:5::0.0.0.0"), std::invalid_argument);
185     EXPECT_THROW(ta("ffff0::0"), std::overflow_error);
186 
187     EXPECT_EQ((in6_addr{}), ta("::"));
188     EXPECT_EQ((in6_addr{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
189                         255, 255, 255, 255, 255}),
190               ta("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"sv));
191     EXPECT_EQ((in6_addr{}), ta("0:0:0:0:0:0:0:0"));
192     EXPECT_EQ((in6_addr{0, 0xff}), ta("ff::"));
193     EXPECT_EQ((in6_addr{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff}),
194               ta("::ff"));
195     EXPECT_EQ((in6_addr{0, 0, 0, 0, 0, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff}),
196               ta("0:0:ff::ff"));
197     EXPECT_EQ((in6_addr{0, 1, 0, 2, 0, 3, 0, 4, 0, 0, 0, 6, 0, 7, 0, 8}),
198               ta("1:2:3:4::6:7:8"));
199     EXPECT_EQ((in6_addr{0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 0}),
200               ta("1:2:3:4:5:6:7::"));
201     EXPECT_EQ((in6_addr{0, 0, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8}),
202               ta("::2:3:4:5:6:7:8"));
203     EXPECT_EQ(
204         (in6_addr{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 192, 168, 0, 1}),
205         ta("::ffff:192.168.0.1"));
206     EXPECT_EQ((in6_addr{0, 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 168, 0, 1}),
207               ta("ff::255.168.0.1"));
208     EXPECT_EQ((in6_addr{0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 255, 168, 0, 1}),
209               ta("0:1:2:3:4:5:255.168.0.1"));
210 }
211 
212 TEST(ToAddr, InAddrAny)
213 {
214     constexpr ToAddr<InAddrAny> ta;
215     EXPECT_EQ((InAddrAny{in_addr{}}), ta("0.0.0.0"));
216     EXPECT_EQ((InAddrAny{in6_addr{}}), ta("::"));
217     EXPECT_EQ((InAddrAny{in6_addr{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 192,
218                                   168, 0, 1}}),
219               ta("::ffff:192.168.0.1"));
220 }
221 
222 TEST(ToAddr, IfAddr)
223 {
224     constexpr ToAddr<IfAddr> ta;
225     EXPECT_THROW(ta("10"), std::invalid_argument);
226     EXPECT_THROW(ta("/10"), std::invalid_argument);
227     EXPECT_THROW(ta("0.0.0.0"), std::invalid_argument);
228     EXPECT_THROW(ta("0.0.0.0/"), std::invalid_argument);
229     EXPECT_EQ((IfAddr{in_addr{}, 0}), ta("0.0.0.0/0"));
230     EXPECT_EQ((IfAddr{in_addr{}, 30}), ta("0.0.0.0/30"));
231     EXPECT_EQ((IfAddr{in6_addr{}, 80}), ta("::/80"));
232 }
233 
234 namespace detail
235 {
236 
237 TEST(BufMaker, EthAddr)
238 {
239     ToStrBuf<ether_addr> abm;
240     EXPECT_EQ("11:22:33:44:55:66"sv,
241               abm(ether_addr{0x11, 0x22, 0x33, 0x44, 0x55, 0x66}));
242     EXPECT_EQ("01:02:03:04:05:67"sv,
243               abm(ether_addr{0x01, 0x02, 0x03, 0x04, 0x05, 0x67}));
244     EXPECT_EQ("00:00:00:00:00:00"sv,
245               abm(ether_addr{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}));
246 }
247 
248 TEST(BufMaker, InAddr)
249 {
250     ToStrBuf<in_addr> abm;
251     EXPECT_EQ("255.255.255.255"sv, abm(in_addr{0xffffffff}));
252     EXPECT_EQ("1.15.3.4"sv, abm(in_addr{htonl(0x010f0304)}));
253     EXPECT_EQ("0.0.0.0"sv, abm(in_addr{}));
254 }
255 
256 TEST(BufMaker, In6Addr)
257 {
258     ToStrBuf<in6_addr> abm;
259     EXPECT_EQ("::"sv, abm(in6_addr{}));
260     EXPECT_EQ("ff::"sv, abm(in6_addr{0, 0xff}));
261     EXPECT_EQ("::ff"sv,
262               abm(in6_addr{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff}));
263     EXPECT_EQ("0:0:ff::ff"sv, abm(in6_addr{0, 0, 0, 0, 0, 0xff, 0, 0, 0, 0, 0,
264                                            0, 0, 0, 0, 0xff}));
265     EXPECT_EQ("::100:0:ff"sv,
266               abm(in6_addr{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0xff}));
267     EXPECT_EQ("ff00::"sv, abm(in6_addr{0xff}));
268     EXPECT_EQ("1:2:3:4:5:6:7:8"sv,
269               abm(in6_addr{0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8}));
270     EXPECT_EQ("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"sv,
271               abm(in6_addr{255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
272                            255, 255, 255, 255, 255, 255}));
273     // rfc5952 4.2.2
274     EXPECT_EQ("1:2:3:4:0:6:7:8"sv,
275               abm(in6_addr{0, 1, 0, 2, 0, 3, 0, 4, 0, 0, 0, 6, 0, 7, 0, 8}));
276     // rfc5952 4.2.3
277     EXPECT_EQ("1::4:0:0:7:8"sv,
278               abm(in6_addr{0, 1, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 7, 0, 8}));
279     // rfc5952 5
280     EXPECT_EQ("::ffff:192.168.0.1"sv,
281               abm(in6_addr{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 192, 168,
282                            0, 1}));
283 }
284 
285 TEST(BasicOps, AllAddrs)
286 {
287     EXPECT_NE(InAddrAny{in6_addr{}}, InAddrAny{in_addr{}});
288 
289     EXPECT_EQ("a 01:00:00:00:00:00", fmt::format("a {}", ether_addr{1}));
290     EXPECT_EQ("a 0.0.0.1", fmt::format("a {}", in_addr{htonl(1)}));
291     EXPECT_EQ("a 0.0.0.1", fmt::format("a {}", InAddrAny{in_addr{htonl(1)}}));
292     EXPECT_EQ("a 100::", fmt::format("a {}", in6_addr{1}));
293     EXPECT_EQ("a 100::", fmt::format("a {}", InAddrAny{in6_addr{1}}));
294     EXPECT_EQ("a 100::/90", fmt::format("a {}", IfAddr{in6_addr{1}, 90}));
295 
296     EXPECT_EQ("01:00:00:00:00:00", std::to_string(ether_addr{1}));
297     EXPECT_EQ("0.0.0.1", std::to_string(in_addr{htonl(1)}));
298     EXPECT_EQ("0.0.0.1", std::to_string(InAddrAny{in_addr{htonl(1)}}));
299     EXPECT_EQ("100::", std::to_string(in6_addr{1}));
300     EXPECT_EQ("100::", std::to_string(InAddrAny{in6_addr{1}}));
301     EXPECT_EQ("100::/22", std::to_string(IfAddr{in6_addr{1}, 22}));
302 
303     EXPECT_EQ("a01:00:00:00:00:00",
304               (std::stringstream{} << "a" << ether_addr{1}).str());
305     EXPECT_EQ("a0.0.0.1",
306               (std::stringstream{} << "a" << in_addr{htonl(1)}).str());
307     EXPECT_EQ(
308         "a0.0.0.1",
309         (std::stringstream{} << "a" << InAddrAny{in_addr{htonl(1)}}).str());
310     EXPECT_EQ("a100::", (std::stringstream{} << "a" << in6_addr{1}).str());
311     EXPECT_EQ("a100::",
312               (std::stringstream{} << "a" << InAddrAny{in6_addr{1}}).str());
313     auto ss = std::stringstream{};
314     constexpr auto addr = IfAddr{in6_addr{1}, 30};
315     ss << "a" << addr;
316     EXPECT_EQ("a100::/30", ss.str());
317 
318     EXPECT_NO_THROW(IfAddr(in6_addr{}, 128));
319     EXPECT_NO_THROW(IfAddr(in_addr{}, 32));
320     EXPECT_THROW(IfAddr(in6_addr{}, 129), std::invalid_argument);
321     EXPECT_THROW(IfAddr(in_addr{}, 33), std::invalid_argument);
322 }
323 
324 TEST(Perf, In6Addr)
325 {
326     GTEST_SKIP();
327     auto start = std::chrono::steady_clock::now();
328     for (size_t i = 0; i < 10000000; ++i)
329     {
330         ToStrBuf<in6_addr>{}(in6_addr{1});
331     }
332     fmt::print("Duration: {}\n", std::chrono::steady_clock::now() - start);
333     // Make sure this test isn't enabled
334     EXPECT_FALSE(true);
335 }
336 
337 } // namespace detail
338 } // namespace phosphor::network
339