Fix copyright lines
[folly.git] / folly / test / MacAddressTest.cpp
1 /*
2  * Copyright 2014-present 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 <folly/Format.h>
18 #include <folly/IPAddressV6.h>
19 #include <folly/MacAddress.h>
20 #include <folly/portability/GTest.h>
21
22 using folly::MacAddress;
23 using folly::IPAddressV6;
24 using folly::StringPiece;
25
26 void testMAC(const std::string& str, uint64_t expectedHBO) {
27   SCOPED_TRACE(str);
28   MacAddress addr(str);
29   // Make sure parsing returned the expected value.
30   EXPECT_EQ(expectedHBO, addr.u64HBO());
31
32   // Perform additional checks on the MacAddress
33
34   // Check using operator==()
35   EXPECT_EQ(MacAddress::fromHBO(expectedHBO), addr);
36   // Check using operator==() when passing in non-zero padding bytes
37   EXPECT_EQ(MacAddress::fromHBO(expectedHBO | 0xa5a5000000000000), addr);
38
39   // Similar checks after converting to network byte order
40   uint64_t expectedNBO = folly::Endian::big(expectedHBO);
41   EXPECT_EQ(expectedNBO, addr.u64NBO());
42   EXPECT_EQ(MacAddress::fromNBO(expectedNBO), addr);
43   uint64_t nboWithPad = folly::Endian::big(expectedHBO | 0xa5a5000000000000);
44   EXPECT_EQ(MacAddress::fromNBO(nboWithPad), addr);
45
46   // Check they value returned by bytes()
47   uint8_t expectedBytes[8];
48   memcpy(expectedBytes, &expectedNBO, 8);
49   for (int n = 0; n < 6; ++n) {
50     EXPECT_EQ(expectedBytes[n + 2], addr.bytes()[n]);
51   }
52 }
53
54 TEST(MacAddress, parse) {
55   testMAC("12:34:56:78:9a:bc", 0x123456789abc);
56   testMAC("00-11-22-33-44-55", 0x1122334455);
57   testMAC("abcdef123456", 0xabcdef123456);
58   testMAC("1:2:3:4:5:6", 0x010203040506);
59   testMAC("0:0:0:0:0:0", 0);
60   testMAC("0:0:5e:0:1:1", 0x00005e000101);
61
62   EXPECT_THROW(MacAddress(""), std::invalid_argument);
63   EXPECT_THROW(MacAddress("0"), std::invalid_argument);
64   EXPECT_THROW(MacAddress("12:34"), std::invalid_argument);
65   EXPECT_THROW(MacAddress("12:3"), std::invalid_argument);
66   EXPECT_THROW(MacAddress("12:"), std::invalid_argument);
67   EXPECT_THROW(MacAddress("12:x4:56:78:9a:bc"), std::invalid_argument);
68   EXPECT_THROW(MacAddress("12x34:56:78:9a:bc"), std::invalid_argument);
69   EXPECT_THROW(MacAddress("12:34:56:78:9a:bc:de"), std::invalid_argument);
70   EXPECT_THROW(MacAddress("12:34:56:78:9a:bcde"), std::invalid_argument);
71   EXPECT_THROW(MacAddress("12:34:56:78:9a:bc  "), std::invalid_argument);
72   EXPECT_THROW(MacAddress("  12:34:56:78:9a:bc"), std::invalid_argument);
73   EXPECT_THROW(MacAddress("12:34:56:78:-1:bc"), std::invalid_argument);
74 }
75
76 void testFromBinary(const char* str, uint64_t expectedHBO) {
77   StringPiece bin(str, 6);
78   auto mac = MacAddress::fromBinary(bin);
79   SCOPED_TRACE(mac.toString());
80   EXPECT_EQ(expectedHBO, mac.u64HBO());
81 }
82
83 TEST(MacAddress, fromBinary) {
84   testFromBinary("\0\0\0\0\0\0", 0);
85   testFromBinary("\x12\x34\x56\x78\x9a\xbc", 0x123456789abc);
86   testFromBinary("\x11\x22\x33\x44\x55\x66", 0x112233445566);
87
88   StringPiece empty("");
89   EXPECT_THROW(MacAddress::fromBinary(empty), std::invalid_argument);
90   StringPiece tooShort("\x11", 1);
91   EXPECT_THROW(MacAddress::fromBinary(tooShort), std::invalid_argument);
92   StringPiece tooLong("\x11\x22\x33\x44\x55\x66\x77", 7);
93   EXPECT_THROW(MacAddress::fromBinary(tooLong), std::invalid_argument);
94 }
95
96 TEST(MacAddress, toString) {
97   EXPECT_EQ(
98       "12:34:56:78:9a:bc", MacAddress::fromHBO(0x123456789abc).toString());
99   EXPECT_EQ("12:34:56:78:9a:bc", MacAddress("12:34:56:78:9a:bc").toString());
100   EXPECT_EQ("01:23:45:67:89:ab", MacAddress("01-23-45-67-89-ab").toString());
101   EXPECT_EQ("01:23:45:67:89:ab", MacAddress("0123456789ab").toString());
102 }
103
104 TEST(MacAddress, attributes) {
105   EXPECT_TRUE(MacAddress("ff:ff:ff:ff:ff:ff").isBroadcast());
106   EXPECT_FALSE(MacAddress("7f:ff:ff:ff:ff:ff").isBroadcast());
107   EXPECT_FALSE(MacAddress("7f:ff:ff:ff:ff:fe").isBroadcast());
108   EXPECT_FALSE(MacAddress("00:00:00:00:00:00").isBroadcast());
109   EXPECT_TRUE(MacAddress::fromNBO(0xffffffffffffffffU).isBroadcast());
110
111   EXPECT_TRUE(MacAddress("ff:ff:ff:ff:ff:ff").isMulticast());
112   EXPECT_TRUE(MacAddress("01:00:00:00:00:00").isMulticast());
113   EXPECT_FALSE(MacAddress("00:00:00:00:00:00").isMulticast());
114   EXPECT_FALSE(MacAddress("fe:ff:ff:ff:ff:ff").isMulticast());
115   EXPECT_FALSE(MacAddress("00:00:5e:00:01:01").isMulticast());
116
117   EXPECT_FALSE(MacAddress("ff:ff:ff:ff:ff:ff").isUnicast());
118   EXPECT_FALSE(MacAddress("01:00:00:00:00:00").isUnicast());
119   EXPECT_TRUE(MacAddress("00:00:00:00:00:00").isUnicast());
120   EXPECT_TRUE(MacAddress("fe:ff:ff:ff:ff:ff").isUnicast());
121   EXPECT_TRUE(MacAddress("00:00:5e:00:01:01").isUnicast());
122
123   EXPECT_TRUE(MacAddress("ff:ff:ff:ff:ff:ff").isLocallyAdministered());
124   EXPECT_TRUE(MacAddress("02:00:00:00:00:00").isLocallyAdministered());
125   EXPECT_FALSE(MacAddress("01:00:00:00:00:00").isLocallyAdministered());
126   EXPECT_FALSE(MacAddress("00:00:00:00:00:00").isLocallyAdministered());
127   EXPECT_FALSE(MacAddress("fd:ff:ff:ff:ff:ff").isLocallyAdministered());
128   EXPECT_TRUE(MacAddress("fe:ff:ff:ff:ff:ff").isLocallyAdministered());
129   EXPECT_FALSE(MacAddress("00:00:5e:00:01:01").isLocallyAdministered());
130   EXPECT_TRUE(MacAddress("02:12:34:56:78:9a").isLocallyAdministered());
131 }
132
133 TEST(MacAddress, createMulticast) {
134   EXPECT_EQ(
135       MacAddress("33:33:00:01:00:03"),
136       MacAddress::createMulticast(IPAddressV6("ff02:dead:beef::1:3")));
137   EXPECT_EQ(
138       MacAddress("33:33:12:34:56:78"),
139       MacAddress::createMulticast(IPAddressV6("ff02::abcd:1234:5678")));
140 }
141
142 void testCmp(const char* str1, const char* str2) {
143   SCOPED_TRACE(folly::sformat("{} < {}", str1, str2));
144   MacAddress m1(str1);
145   MacAddress m2(str2);
146
147   // Test the comparison operators
148   EXPECT_TRUE(m1 < m2);
149   EXPECT_FALSE(m1 < m1);
150   EXPECT_TRUE(m1 <= m2);
151   EXPECT_TRUE(m2 > m1);
152   EXPECT_TRUE(m2 >= m1);
153   EXPECT_TRUE(m1 != m2);
154   EXPECT_TRUE(m1 == (m1));
155   EXPECT_FALSE(m1 == m2);
156
157   // Also test the copy constructor and assignment operator
158   MacAddress copy(m1);
159   EXPECT_EQ(copy, m1);
160   copy = m2;
161   EXPECT_EQ(copy, m2);
162 }
163
164 TEST(MacAddress, ordering) {
165   testCmp("00:00:00:00:00:00", "00:00:00:00:00:01");
166   testCmp("00:00:00:00:00:01", "00:00:00:00:00:02");
167   testCmp("01:00:00:00:00:00", "02:00:00:00:00:00");
168   testCmp("00:00:00:00:00:01", "00:00:00:00:01:00");
169 }