2 * Copyright 2016 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 <gtest/gtest.h>
19 #include <folly/Conv.h>
20 #include <folly/IPAddressV6.h>
21 #include <folly/MacAddress.h>
23 using folly::MacAddress;
24 using folly::IPAddressV6;
25 using folly::StringPiece;
27 void testMAC(const std::string& str, uint64_t expectedHBO) {
30 // Make sure parsing returned the expected value.
31 EXPECT_EQ(expectedHBO, addr.u64HBO());
33 // Perform additional checks on the MacAddress
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);
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);
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]);
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);
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);
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());
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);
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);
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());
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());
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());
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());
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());
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")));
141 void testCmp(const char* str1, const char* str2) {
142 SCOPED_TRACE(folly::to<std::string>(str1, " < ", str2));
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);
156 // Also test the copy constructor and assignment operator
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");