blob: b0e5fb1a65f228fc1fae3401843b3bfe034c5a2b [file] [log] [blame]
Hugo Benichi88ad29b2017-10-12 21:33:40 +09001/*
2 * Copyright 2017 The Android Open Source Project
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
17package android.net;
18
Etan Cohenec1c4662018-11-02 15:07:20 -070019import static org.junit.Assert.assertArrayEquals;
Hugo Benichi88ad29b2017-10-12 21:33:40 +090020import static org.junit.Assert.assertEquals;
Hugo Benichi88ad29b2017-10-12 21:33:40 +090021import static org.junit.Assert.assertFalse;
Brett Chabot147f6cf2019-03-04 14:14:56 -080022import static org.junit.Assert.assertTrue;
Hugo Benichid380d142017-11-09 00:22:25 +090023import static org.junit.Assert.fail;
Hugo Benichi88ad29b2017-10-12 21:33:40 +090024
Brett Chabot147f6cf2019-03-04 14:14:56 -080025import androidx.test.filters.SmallTest;
26import androidx.test.runner.AndroidJUnit4;
Hugo Benichi88ad29b2017-10-12 21:33:40 +090027
Hugo Benichi88ad29b2017-10-12 21:33:40 +090028import org.junit.Test;
29import org.junit.runner.RunWith;
30
Etan Cohenec1c4662018-11-02 15:07:20 -070031import java.net.Inet6Address;
32import java.util.Arrays;
33import java.util.Random;
34
Hugo Benichi88ad29b2017-10-12 21:33:40 +090035@SmallTest
36@RunWith(AndroidJUnit4.class)
37public class MacAddressTest {
38
39 static class AddrTypeTestCase {
40 byte[] addr;
Hugo Benichi5bc35462017-11-16 14:40:16 +090041 int expectedType;
Hugo Benichi88ad29b2017-10-12 21:33:40 +090042
Hugo Benichi5bc35462017-11-16 14:40:16 +090043 static AddrTypeTestCase of(int expectedType, int... addr) {
Hugo Benichi88ad29b2017-10-12 21:33:40 +090044 AddrTypeTestCase t = new AddrTypeTestCase();
Hugo Benichi5bc35462017-11-16 14:40:16 +090045 t.expectedType = expectedType;
Hugo Benichi88ad29b2017-10-12 21:33:40 +090046 t.addr = toByteArray(addr);
47 return t;
48 }
49 }
50
51 @Test
52 public void testMacAddrTypes() {
53 AddrTypeTestCase[] testcases = {
Hugo Benichi5bc35462017-11-16 14:40:16 +090054 AddrTypeTestCase.of(MacAddress.TYPE_UNKNOWN),
55 AddrTypeTestCase.of(MacAddress.TYPE_UNKNOWN, 0),
56 AddrTypeTestCase.of(MacAddress.TYPE_UNKNOWN, 1, 2, 3, 4, 5),
57 AddrTypeTestCase.of(MacAddress.TYPE_UNKNOWN, 1, 2, 3, 4, 5, 6, 7),
58 AddrTypeTestCase.of(MacAddress.TYPE_UNICAST, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0),
59 AddrTypeTestCase.of(MacAddress.TYPE_BROADCAST, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff),
60 AddrTypeTestCase.of(MacAddress.TYPE_MULTICAST, 1, 2, 3, 4, 5, 6),
61 AddrTypeTestCase.of(MacAddress.TYPE_MULTICAST, 11, 22, 33, 44, 55, 66),
62 AddrTypeTestCase.of(MacAddress.TYPE_MULTICAST, 33, 33, 0xaa, 0xbb, 0xcc, 0xdd)
Hugo Benichi88ad29b2017-10-12 21:33:40 +090063 };
64
65 for (AddrTypeTestCase t : testcases) {
Hugo Benichi5bc35462017-11-16 14:40:16 +090066 int got = MacAddress.macAddressType(t.addr);
Hugo Benichi88ad29b2017-10-12 21:33:40 +090067 String msg = String.format("expected type of %s to be %s, but got %s",
Hugo Benichi5bc35462017-11-16 14:40:16 +090068 Arrays.toString(t.addr), t.expectedType, got);
69 assertEquals(msg, t.expectedType, got);
Hugo Benichid380d142017-11-09 00:22:25 +090070
Hugo Benichi5bc35462017-11-16 14:40:16 +090071 if (got != MacAddress.TYPE_UNKNOWN) {
Hugo Benichi8f217582018-01-12 09:46:29 +090072 assertEquals(got, MacAddress.fromBytes(t.addr).getAddressType());
Hugo Benichid380d142017-11-09 00:22:25 +090073 }
Hugo Benichi88ad29b2017-10-12 21:33:40 +090074 }
75 }
76
Hugo Benichid380d142017-11-09 00:22:25 +090077 @Test
Hugo Benichi3f83b8a2017-12-15 10:07:35 +090078 public void testToOuiString() {
Hugo Benichi5bc35462017-11-16 14:40:16 +090079 String[][] macs = {
Hugo Benichi3f83b8a2017-12-15 10:07:35 +090080 {"07:00:d3:56:8a:c4", "07:00:d3"},
81 {"33:33:aa:bb:cc:dd", "33:33:aa"},
82 {"06:00:00:00:00:00", "06:00:00"},
83 {"07:00:d3:56:8a:c4", "07:00:d3"}
Hugo Benichi5bc35462017-11-16 14:40:16 +090084 };
85
86 for (String[] pair : macs) {
87 String mac = pair[0];
88 String expected = pair[1];
Hugo Benichi3f83b8a2017-12-15 10:07:35 +090089 assertEquals(expected, MacAddress.fromString(mac).toOuiString());
Hugo Benichi5bc35462017-11-16 14:40:16 +090090 }
91 }
92
93 @Test
94 public void testHexPaddingWhenPrinting() {
95 String[] macs = {
96 "07:00:d3:56:8a:c4",
97 "33:33:aa:bb:cc:dd",
98 "06:00:00:00:00:00",
99 "07:00:d3:56:8a:c4"
100 };
101
102 for (String mac : macs) {
103 assertEquals(mac, MacAddress.fromString(mac).toString());
104 assertEquals(mac,
105 MacAddress.stringAddrFromByteAddr(MacAddress.byteAddrFromStringAddr(mac)));
106 }
107 }
108
109 @Test
Hugo Benichid380d142017-11-09 00:22:25 +0900110 public void testIsMulticastAddress() {
111 MacAddress[] multicastAddresses = {
112 MacAddress.BROADCAST_ADDRESS,
Hugo Benichi5bc35462017-11-16 14:40:16 +0900113 MacAddress.fromString("07:00:d3:56:8a:c4"),
114 MacAddress.fromString("33:33:aa:bb:cc:dd"),
Hugo Benichid380d142017-11-09 00:22:25 +0900115 };
116 MacAddress[] unicastAddresses = {
117 MacAddress.ALL_ZEROS_ADDRESS,
Hugo Benichi5bc35462017-11-16 14:40:16 +0900118 MacAddress.fromString("00:01:44:55:66:77"),
119 MacAddress.fromString("08:00:22:33:44:55"),
120 MacAddress.fromString("06:00:00:00:00:00"),
Hugo Benichid380d142017-11-09 00:22:25 +0900121 };
122
123 for (MacAddress mac : multicastAddresses) {
124 String msg = mac.toString() + " expected to be a multicast address";
125 assertTrue(msg, mac.isMulticastAddress());
126 }
127 for (MacAddress mac : unicastAddresses) {
128 String msg = mac.toString() + " expected not to be a multicast address";
129 assertFalse(msg, mac.isMulticastAddress());
130 }
131 }
132
133 @Test
134 public void testIsLocallyAssignedAddress() {
135 MacAddress[] localAddresses = {
Hugo Benichi5bc35462017-11-16 14:40:16 +0900136 MacAddress.fromString("06:00:00:00:00:00"),
137 MacAddress.fromString("07:00:d3:56:8a:c4"),
138 MacAddress.fromString("33:33:aa:bb:cc:dd"),
Hugo Benichid380d142017-11-09 00:22:25 +0900139 };
140 MacAddress[] universalAddresses = {
Hugo Benichi5bc35462017-11-16 14:40:16 +0900141 MacAddress.fromString("00:01:44:55:66:77"),
142 MacAddress.fromString("08:00:22:33:44:55"),
Hugo Benichid380d142017-11-09 00:22:25 +0900143 };
144
145 for (MacAddress mac : localAddresses) {
146 String msg = mac.toString() + " expected to be a locally assigned address";
147 assertTrue(msg, mac.isLocallyAssigned());
148 }
149 for (MacAddress mac : universalAddresses) {
150 String msg = mac.toString() + " expected not to be globally unique address";
151 assertFalse(msg, mac.isLocallyAssigned());
152 }
153 }
154
155 @Test
156 public void testMacAddressConversions() {
157 final int iterations = 10000;
158 for (int i = 0; i < iterations; i++) {
Hugo Benichi5bc35462017-11-16 14:40:16 +0900159 MacAddress mac = MacAddress.createRandomUnicastAddress();
Hugo Benichid380d142017-11-09 00:22:25 +0900160
161 String stringRepr = mac.toString();
162 byte[] bytesRepr = mac.toByteArray();
163
Hugo Benichi5bc35462017-11-16 14:40:16 +0900164 assertEquals(mac, MacAddress.fromString(stringRepr));
165 assertEquals(mac, MacAddress.fromBytes(bytesRepr));
Hugo Benichi21c7a522017-12-05 13:14:08 +0900166
167 assertEquals(mac, MacAddress.fromString(MacAddress.stringAddrFromByteAddr(bytesRepr)));
168 assertEquals(mac, MacAddress.fromBytes(MacAddress.byteAddrFromStringAddr(stringRepr)));
Hugo Benichid380d142017-11-09 00:22:25 +0900169 }
170 }
171
172 @Test
173 public void testMacAddressRandomGeneration() {
174 final int iterations = 1000;
175 final String expectedAndroidOui = "da:a1:19";
176 for (int i = 0; i < iterations; i++) {
Jong Wook Kim93dd5e62018-01-31 19:03:19 -0800177 MacAddress mac = MacAddress.createRandomUnicastAddressWithGoogleBase();
Hugo Benichid380d142017-11-09 00:22:25 +0900178 String stringRepr = mac.toString();
179
180 assertTrue(stringRepr + " expected to be a locally assigned address",
181 mac.isLocallyAssigned());
182 assertTrue(stringRepr + " expected to begin with " + expectedAndroidOui,
183 stringRepr.startsWith(expectedAndroidOui));
184 }
185
186 final Random r = new Random();
187 final String anotherOui = "24:5f:78";
188 final String expectedLocalOui = "26:5f:78";
Hugo Benichi5bc35462017-11-16 14:40:16 +0900189 final MacAddress base = MacAddress.fromString(anotherOui + ":0:0:0");
Hugo Benichid380d142017-11-09 00:22:25 +0900190 for (int i = 0; i < iterations; i++) {
Hugo Benichi5bc35462017-11-16 14:40:16 +0900191 MacAddress mac = MacAddress.createRandomUnicastAddress(base, r);
Hugo Benichid380d142017-11-09 00:22:25 +0900192 String stringRepr = mac.toString();
193
194 assertTrue(stringRepr + " expected to be a locally assigned address",
195 mac.isLocallyAssigned());
Hugo Benichi8f217582018-01-12 09:46:29 +0900196 assertEquals(MacAddress.TYPE_UNICAST, mac.getAddressType());
Hugo Benichid380d142017-11-09 00:22:25 +0900197 assertTrue(stringRepr + " expected to begin with " + expectedLocalOui,
198 stringRepr.startsWith(expectedLocalOui));
199 }
Jong Wook Kim93dd5e62018-01-31 19:03:19 -0800200
201 for (int i = 0; i < iterations; i++) {
202 MacAddress mac = MacAddress.createRandomUnicastAddress();
203 String stringRepr = mac.toString();
204
205 assertTrue(stringRepr + " expected to be a locally assigned address",
206 mac.isLocallyAssigned());
207 assertEquals(MacAddress.TYPE_UNICAST, mac.getAddressType());
208 }
Hugo Benichid380d142017-11-09 00:22:25 +0900209 }
210
211 @Test
212 public void testConstructorInputValidation() {
213 String[] invalidStringAddresses = {
Hugo Benichid380d142017-11-09 00:22:25 +0900214 "",
215 "abcd",
216 "1:2:3:4:5",
217 "1:2:3:4:5:6:7",
218 "10000:2:3:4:5:6",
219 };
220
221 for (String s : invalidStringAddresses) {
222 try {
Hugo Benichi5bc35462017-11-16 14:40:16 +0900223 MacAddress mac = MacAddress.fromString(s);
224 fail("MacAddress.fromString(" + s + ") should have failed, but returned " + mac);
Hugo Benichid380d142017-11-09 00:22:25 +0900225 } catch (IllegalArgumentException excepted) {
226 }
227 }
228
Hugo Benichi5bc35462017-11-16 14:40:16 +0900229 try {
230 MacAddress mac = MacAddress.fromString(null);
231 fail("MacAddress.fromString(null) should have failed, but returned " + mac);
232 } catch (NullPointerException excepted) {
233 }
234
Hugo Benichid380d142017-11-09 00:22:25 +0900235 byte[][] invalidBytesAddresses = {
Hugo Benichid380d142017-11-09 00:22:25 +0900236 {},
237 {1,2,3,4,5},
238 {1,2,3,4,5,6,7},
239 };
240
241 for (byte[] b : invalidBytesAddresses) {
242 try {
Hugo Benichi5bc35462017-11-16 14:40:16 +0900243 MacAddress mac = MacAddress.fromBytes(b);
244 fail("MacAddress.fromBytes(" + Arrays.toString(b)
Hugo Benichid380d142017-11-09 00:22:25 +0900245 + ") should have failed, but returned " + mac);
246 } catch (IllegalArgumentException excepted) {
247 }
248 }
Hugo Benichi5bc35462017-11-16 14:40:16 +0900249
250 try {
251 MacAddress mac = MacAddress.fromBytes(null);
252 fail("MacAddress.fromBytes(null) should have failed, but returned " + mac);
253 } catch (NullPointerException excepted) {
254 }
Hugo Benichid380d142017-11-09 00:22:25 +0900255 }
256
Etan Cohenec1c4662018-11-02 15:07:20 -0700257 /**
258 * Tests that link-local address generation from MAC is valid.
259 */
260 @Test
261 public void testLinkLocalFromMacGeneration() {
262 MacAddress mac = MacAddress.fromString("52:74:f2:b1:a8:7f");
263 byte[] inet6ll = {(byte) 0xfe, (byte) 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x74,
264 (byte) 0xf2, (byte) 0xff, (byte) 0xfe, (byte) 0xb1, (byte) 0xa8, 0x7f};
265 Inet6Address llv6 = mac.getLinkLocalIpv6FromEui48Mac();
266 assertTrue(llv6.isLinkLocalAddress());
267 assertArrayEquals(inet6ll, llv6.getAddress());
268 }
269
Hugo Benichid380d142017-11-09 00:22:25 +0900270 static byte[] toByteArray(int... in) {
Hugo Benichi88ad29b2017-10-12 21:33:40 +0900271 byte[] out = new byte[in.length];
272 for (int i = 0; i < in.length; i++) {
273 out[i] = (byte) in[i];
274 }
275 return out;
276 }
277}