2 * Copyright 2017 Facebook, Inc.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include <folly/Conv.h>
18 #include <folly/IPAddressV6.h>
19 #include <folly/MacAddress.h>
20 #include <folly/portability/GTest.h>
22 using folly::MacAddress;
23 using folly::IPAddressV6;
24 using folly::StringPiece;
26 void testMAC(const std::string& str, uint64_t expectedHBO) {
29 // Make sure parsing returned the expected value.
30 EXPECT_EQ(expectedHBO, addr.u64HBO());
32 // Perform additional checks on the MacAddress
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);
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);
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]);
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);
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);
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());
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);
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);
96 TEST(MacAddress, toString) {
97 EXPECT_EQ("12:34:56:78:9a:bc",
98 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());
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());
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());
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());
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());
133 TEST(MacAddress, createMulticast) {
134 EXPECT_EQ(MacAddress("33:33:00:01:00:03"),
135 MacAddress::createMulticast(IPAddressV6("ff02:dead:beef::1:3")));
136 EXPECT_EQ(MacAddress("33:33:12:34:56:78"),
137 MacAddress::createMulticast(IPAddressV6("ff02::abcd:1234:5678")));
140 void testCmp(const char* str1, const char* str2) {
141 SCOPED_TRACE(folly::to<std::string>(str1, " < ", str2));
145 // Test the comparison operators
146 EXPECT_TRUE(m1 < m2);
147 EXPECT_FALSE(m1 < m1);
148 EXPECT_TRUE(m1 <= m2);
149 EXPECT_TRUE(m2 > m1);
150 EXPECT_TRUE(m2 >= m1);
151 EXPECT_TRUE(m1 != m2);
152 EXPECT_TRUE(m1 == (m1));
153 EXPECT_FALSE(m1 == m2);
155 // Also test the copy constructor and assignment operator
162 TEST(MacAddress, ordering) {
163 testCmp("00:00:00:00:00:00", "00:00:00:00:00:01");
164 testCmp("00:00:00:00:00:01", "00:00:00:00:00:02");
165 testCmp("01:00:00:00:00:00", "02:00:00:00:00:00");
166 testCmp("00:00:00:00:00:01", "00:00:00:00:01:00");