Move IPAddress definitions to source files
[folly.git] / folly / test / MacAddressTest.cpp
1 /*
2  * Copyright 2016 Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <gtest/gtest.h>
18
19 #include <folly/Conv.h>
20 #include <folly/IPAddressV6.h>
21 #include <folly/MacAddress.h>
22
23 using folly::MacAddress;
24 using folly::IPAddressV6;
25 using folly::StringPiece;
26
27 void testMAC(const std::string& str, uint64_t expectedHBO) {
28   SCOPED_TRACE(str);
29   MacAddress addr(str);
30   // Make sure parsing returned the expected value.
31   EXPECT_EQ(expectedHBO, addr.u64HBO());
32
33   // Perform additional checks on the MacAddress
34
35   // Check using operator==()
36   EXPECT_EQ(MacAddress::fromHBO(expectedHBO), addr);
37   // Check using operator==() when passing in non-zero padding bytes
38   EXPECT_EQ(MacAddress::fromHBO(expectedHBO | 0xa5a5000000000000), addr);
39
40   // Similar checks after converting to network byte order
41   uint64_t expectedNBO = folly::Endian::big(expectedHBO);
42   EXPECT_EQ(expectedNBO, addr.u64NBO());
43   EXPECT_EQ(MacAddress::fromNBO(expectedNBO), addr);
44   uint64_t nboWithPad = folly::Endian::big(expectedHBO | 0xa5a5000000000000);
45   EXPECT_EQ(MacAddress::fromNBO(nboWithPad), addr);
46
47   // Check they value returned by bytes()
48   uint8_t expectedBytes[8];
49   memcpy(expectedBytes, &expectedNBO, 8);
50   for (int n = 0; n < 6; ++n) {
51     EXPECT_EQ(expectedBytes[n + 2], addr.bytes()[n]);
52   }
53 }
54
55 TEST(MacAddress, parse) {
56   testMAC("12:34:56:78:9a:bc", 0x123456789abc);
57   testMAC("00-11-22-33-44-55", 0x1122334455);
58   testMAC("abcdef123456", 0xabcdef123456);
59   testMAC("1:2:3:4:5:6", 0x010203040506);
60   testMAC("0:0:0:0:0:0", 0);
61   testMAC("0:0:5e:0:1:1", 0x00005e000101);
62
63   EXPECT_THROW(MacAddress(""), std::invalid_argument);
64   EXPECT_THROW(MacAddress("0"), std::invalid_argument);
65   EXPECT_THROW(MacAddress("12:34"), std::invalid_argument);
66   EXPECT_THROW(MacAddress("12:3"), std::invalid_argument);
67   EXPECT_THROW(MacAddress("12:"), std::invalid_argument);
68   EXPECT_THROW(MacAddress("12:x4:56:78:9a:bc"), std::invalid_argument);
69   EXPECT_THROW(MacAddress("12x34:56:78:9a:bc"), std::invalid_argument);
70   EXPECT_THROW(MacAddress("12:34:56:78:9a:bc:de"), std::invalid_argument);
71   EXPECT_THROW(MacAddress("12:34:56:78:9a:bcde"), std::invalid_argument);
72   EXPECT_THROW(MacAddress("12:34:56:78:9a:bc  "), std::invalid_argument);
73   EXPECT_THROW(MacAddress("  12:34:56:78:9a:bc"), std::invalid_argument);
74   EXPECT_THROW(MacAddress("12:34:56:78:-1:bc"), std::invalid_argument);
75 }
76
77 void testFromBinary(const char* str, uint64_t expectedHBO) {
78   StringPiece bin(str, 6);
79   auto mac = MacAddress::fromBinary(bin);
80   SCOPED_TRACE(mac.toString());
81   EXPECT_EQ(expectedHBO, mac.u64HBO());
82 }
83
84 TEST(MacAddress, fromBinary) {
85   testFromBinary("\0\0\0\0\0\0", 0);
86   testFromBinary("\x12\x34\x56\x78\x9a\xbc", 0x123456789abc);
87   testFromBinary("\x11\x22\x33\x44\x55\x66", 0x112233445566);
88
89   StringPiece empty("");
90   EXPECT_THROW(MacAddress::fromBinary(empty), std::invalid_argument);
91   StringPiece tooShort("\x11", 1);
92   EXPECT_THROW(MacAddress::fromBinary(tooShort), std::invalid_argument);
93   StringPiece tooLong("\x11\x22\x33\x44\x55\x66\x77", 7);
94   EXPECT_THROW(MacAddress::fromBinary(tooLong), std::invalid_argument);
95 }
96
97 TEST(MacAddress, toString) {
98   EXPECT_EQ("12:34:56:78:9a:bc",
99             MacAddress::fromHBO(0x123456789abc).toString());
100   EXPECT_EQ("12:34:56:78:9a:bc", MacAddress("12:34:56:78:9a:bc").toString());
101   EXPECT_EQ("01:23:45:67:89:ab", MacAddress("01-23-45-67-89-ab").toString());
102   EXPECT_EQ("01:23:45:67:89:ab", MacAddress("0123456789ab").toString());
103 }
104
105 TEST(MacAddress, attributes) {
106   EXPECT_TRUE(MacAddress("ff:ff:ff:ff:ff:ff").isBroadcast());
107   EXPECT_FALSE(MacAddress("7f:ff:ff:ff:ff:ff").isBroadcast());
108   EXPECT_FALSE(MacAddress("7f:ff:ff:ff:ff:fe").isBroadcast());
109   EXPECT_FALSE(MacAddress("00:00:00:00:00:00").isBroadcast());
110   EXPECT_TRUE(MacAddress::fromNBO(0xffffffffffffffffU).isBroadcast());
111
112   EXPECT_TRUE(MacAddress("ff:ff:ff:ff:ff:ff").isMulticast());
113   EXPECT_TRUE(MacAddress("01:00:00:00:00:00").isMulticast());
114   EXPECT_FALSE(MacAddress("00:00:00:00:00:00").isMulticast());
115   EXPECT_FALSE(MacAddress("fe:ff:ff:ff:ff:ff").isMulticast());
116   EXPECT_FALSE(MacAddress("00:00:5e:00:01:01").isMulticast());
117
118   EXPECT_FALSE(MacAddress("ff:ff:ff:ff:ff:ff").isUnicast());
119   EXPECT_FALSE(MacAddress("01:00:00:00:00:00").isUnicast());
120   EXPECT_TRUE(MacAddress("00:00:00:00:00:00").isUnicast());
121   EXPECT_TRUE(MacAddress("fe:ff:ff:ff:ff:ff").isUnicast());
122   EXPECT_TRUE(MacAddress("00:00:5e:00:01:01").isUnicast());
123
124   EXPECT_TRUE(MacAddress("ff:ff:ff:ff:ff:ff").isLocallyAdministered());
125   EXPECT_TRUE(MacAddress("02:00:00:00:00:00").isLocallyAdministered());
126   EXPECT_FALSE(MacAddress("01:00:00:00:00:00").isLocallyAdministered());
127   EXPECT_FALSE(MacAddress("00:00:00:00:00:00").isLocallyAdministered());
128   EXPECT_FALSE(MacAddress("fd:ff:ff:ff:ff:ff").isLocallyAdministered());
129   EXPECT_TRUE(MacAddress("fe:ff:ff:ff:ff:ff").isLocallyAdministered());
130   EXPECT_FALSE(MacAddress("00:00:5e:00:01:01").isLocallyAdministered());
131   EXPECT_TRUE(MacAddress("02:12:34:56:78:9a").isLocallyAdministered());
132 }
133
134 TEST(MacAddress, createMulticast) {
135   EXPECT_EQ(MacAddress("33:33:00:01:00:03"),
136             MacAddress::createMulticast(IPAddressV6("ff02:dead:beef::1:3")));
137   EXPECT_EQ(MacAddress("33:33:12:34:56:78"),
138             MacAddress::createMulticast(IPAddressV6("ff02::abcd:1234:5678")));
139 }
140
141 void testCmp(const char* str1, const char* str2) {
142   SCOPED_TRACE(folly::to<std::string>(str1, " < ", str2));
143   MacAddress m1(str1);
144   MacAddress m2(str2);
145
146   // Test the comparison operators
147   EXPECT_TRUE(m1 < m2);
148   EXPECT_FALSE(m1 < m1);
149   EXPECT_TRUE(m1 <= m2);
150   EXPECT_TRUE(m2 > m1);
151   EXPECT_TRUE(m2 >= m1);
152   EXPECT_TRUE(m1 != m2);
153   EXPECT_TRUE(m1 == (m1));
154   EXPECT_FALSE(m1 == m2);
155
156   // Also test the copy constructor and assignment operator
157   MacAddress copy(m1);
158   EXPECT_EQ(copy, m1);
159   copy = m2;
160   EXPECT_EQ(copy, m2);
161 }
162
163 TEST(MacAddress, ordering) {
164   testCmp("00:00:00:00:00:00", "00:00:00:00:00:01");
165   testCmp("00:00:00:00:00:01", "00:00:00:00:00:02");
166   testCmp("01:00:00:00:00:00", "02:00:00:00:00:00");
167   testCmp("00:00:00:00:00:01", "00:00:00:00:01:00");
168 }