1 /*
2  * Copyright (C) 2013 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 
17 package android.net;
18 
19 import static android.system.OsConstants.IFA_F_DADFAILED;
20 import static android.system.OsConstants.IFA_F_DEPRECATED;
21 import static android.system.OsConstants.IFA_F_OPTIMISTIC;
22 import static android.system.OsConstants.IFA_F_PERMANENT;
23 import static android.system.OsConstants.IFA_F_TEMPORARY;
24 import static android.system.OsConstants.IFA_F_TENTATIVE;
25 import static android.system.OsConstants.RT_SCOPE_HOST;
26 import static android.system.OsConstants.RT_SCOPE_LINK;
27 import static android.system.OsConstants.RT_SCOPE_SITE;
28 import static android.system.OsConstants.RT_SCOPE_UNIVERSE;
29 
30 import static com.android.testutils.MiscAssertsKt.assertEqualBothWays;
31 import static com.android.testutils.MiscAssertsKt.assertFieldCountEquals;
32 import static com.android.testutils.MiscAssertsKt.assertNotEqualEitherWay;
33 import static com.android.testutils.ParcelUtilsKt.assertParcelingIsLossless;
34 
35 import static org.junit.Assert.assertEquals;
36 import static org.junit.Assert.assertFalse;
37 import static org.junit.Assert.assertNotEquals;
38 import static org.junit.Assert.assertTrue;
39 import static org.junit.Assert.fail;
40 
41 import android.os.Build;
42 import android.os.SystemClock;
43 
44 import androidx.test.filters.SmallTest;
45 import androidx.test.runner.AndroidJUnit4;
46 
47 import com.android.testutils.DevSdkIgnoreRule;
48 import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter;
49 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
50 
51 import org.junit.Rule;
52 import org.junit.Test;
53 import org.junit.runner.RunWith;
54 
55 import java.net.Inet4Address;
56 import java.net.InetAddress;
57 import java.net.InterfaceAddress;
58 import java.net.NetworkInterface;
59 import java.net.SocketException;
60 import java.util.Arrays;
61 import java.util.List;
62 
63 @RunWith(AndroidJUnit4.class)
64 @SmallTest
65 public class LinkAddressTest {
66     @Rule
67     public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule();
68 
69     private static final String V4 = "192.0.2.1";
70     private static final String V6 = "2001:db8::1";
71     private static final InetAddress V4_ADDRESS = NetworkUtils.numericToInetAddress(V4);
72     private static final InetAddress V6_ADDRESS = NetworkUtils.numericToInetAddress(V6);
73 
74     @Test
testConstants()75     public void testConstants() {
76         // RT_SCOPE_UNIVERSE = 0, but all the other constants should be nonzero.
77         assertNotEquals(0, RT_SCOPE_HOST);
78         assertNotEquals(0, RT_SCOPE_LINK);
79         assertNotEquals(0, RT_SCOPE_SITE);
80 
81         assertNotEquals(0, IFA_F_DEPRECATED);
82         assertNotEquals(0, IFA_F_PERMANENT);
83         assertNotEquals(0, IFA_F_TENTATIVE);
84     }
85 
86     @Test
testConstructors()87     public void testConstructors() throws SocketException {
88         LinkAddress address;
89 
90         // Valid addresses work as expected.
91         address = new LinkAddress(V4_ADDRESS, 25);
92         assertEquals(V4_ADDRESS, address.getAddress());
93         assertEquals(25, address.getPrefixLength());
94         assertEquals(0, address.getFlags());
95         assertEquals(RT_SCOPE_UNIVERSE, address.getScope());
96         assertTrue(address.isIpv4());
97 
98         address = new LinkAddress(V6_ADDRESS, 127);
99         assertEquals(V6_ADDRESS, address.getAddress());
100         assertEquals(127, address.getPrefixLength());
101         assertEquals(0, address.getFlags());
102         assertEquals(RT_SCOPE_UNIVERSE, address.getScope());
103         assertTrue(address.isIpv6());
104 
105         // Nonsensical flags/scopes or combinations thereof are acceptable.
106         address = new LinkAddress(V6 + "/64", IFA_F_DEPRECATED | IFA_F_PERMANENT, RT_SCOPE_LINK);
107         assertEquals(V6_ADDRESS, address.getAddress());
108         assertEquals(64, address.getPrefixLength());
109         assertEquals(IFA_F_DEPRECATED | IFA_F_PERMANENT, address.getFlags());
110         assertEquals(RT_SCOPE_LINK, address.getScope());
111         assertTrue(address.isIpv6());
112 
113         address = new LinkAddress(V4 + "/23", 123, 456);
114         assertEquals(V4_ADDRESS, address.getAddress());
115         assertEquals(23, address.getPrefixLength());
116         assertEquals(123, address.getFlags());
117         assertEquals(456, address.getScope());
118         assertTrue(address.isIpv4());
119 
120         // InterfaceAddress doesn't have a constructor. Fetch some from an interface.
121         List<InterfaceAddress> addrs = NetworkInterface.getByName("lo").getInterfaceAddresses();
122 
123         // We expect to find 127.0.0.1/8 and ::1/128, in any order.
124         LinkAddress ipv4Loopback, ipv6Loopback;
125         assertEquals(2, addrs.size());
126         if (addrs.get(0).getAddress() instanceof Inet4Address) {
127             ipv4Loopback = new LinkAddress(addrs.get(0));
128             ipv6Loopback = new LinkAddress(addrs.get(1));
129         } else {
130             ipv4Loopback = new LinkAddress(addrs.get(1));
131             ipv6Loopback = new LinkAddress(addrs.get(0));
132         }
133 
134         assertEquals(NetworkUtils.numericToInetAddress("127.0.0.1"), ipv4Loopback.getAddress());
135         assertEquals(8, ipv4Loopback.getPrefixLength());
136 
137         assertEquals(NetworkUtils.numericToInetAddress("::1"), ipv6Loopback.getAddress());
138         assertEquals(128, ipv6Loopback.getPrefixLength());
139 
140         // Null addresses are rejected.
141         try {
142             address = new LinkAddress(null, 24);
143             fail("Null InetAddress should cause IllegalArgumentException");
144         } catch(IllegalArgumentException expected) {}
145 
146         try {
147             address = new LinkAddress((String) null, IFA_F_PERMANENT, RT_SCOPE_UNIVERSE);
148             fail("Null string should cause IllegalArgumentException");
149         } catch(IllegalArgumentException expected) {}
150 
151         try {
152             address = new LinkAddress((InterfaceAddress) null);
153             fail("Null string should cause NullPointerException");
154         } catch(NullPointerException expected) {}
155 
156         // Invalid prefix lengths are rejected.
157         try {
158             address = new LinkAddress(V4_ADDRESS, -1);
159             fail("Negative IPv4 prefix length should cause IllegalArgumentException");
160         } catch(IllegalArgumentException expected) {}
161 
162         try {
163             address = new LinkAddress(V6_ADDRESS, -1);
164             fail("Negative IPv6 prefix length should cause IllegalArgumentException");
165         } catch(IllegalArgumentException expected) {}
166 
167         try {
168             address = new LinkAddress(V4_ADDRESS, 33);
169             fail("/33 IPv4 prefix length should cause IllegalArgumentException");
170         } catch(IllegalArgumentException expected) {}
171 
172         try {
173             address = new LinkAddress(V4 + "/33", IFA_F_PERMANENT, RT_SCOPE_UNIVERSE);
174             fail("/33 IPv4 prefix length should cause IllegalArgumentException");
175         } catch(IllegalArgumentException expected) {}
176 
177 
178         try {
179             address = new LinkAddress(V6_ADDRESS, 129, IFA_F_PERMANENT, RT_SCOPE_UNIVERSE);
180             fail("/129 IPv6 prefix length should cause IllegalArgumentException");
181         } catch(IllegalArgumentException expected) {}
182 
183         try {
184             address = new LinkAddress(V6 + "/129", IFA_F_PERMANENT, RT_SCOPE_UNIVERSE);
185             fail("/129 IPv6 prefix length should cause IllegalArgumentException");
186         } catch(IllegalArgumentException expected) {}
187 
188         // Multicast addresses are rejected.
189         try {
190             address = new LinkAddress("224.0.0.2/32");
191             fail("IPv4 multicast address should cause IllegalArgumentException");
192         } catch(IllegalArgumentException expected) {}
193 
194         try {
195             address = new LinkAddress("ff02::1/128");
196             fail("IPv6 multicast address should cause IllegalArgumentException");
197         } catch(IllegalArgumentException expected) {}
198     }
199 
200     @Test
testAddressScopes()201     public void testAddressScopes() {
202         assertEquals(RT_SCOPE_HOST, new LinkAddress("::/128").getScope());
203         assertEquals(RT_SCOPE_HOST, new LinkAddress("0.0.0.0/32").getScope());
204 
205         assertEquals(RT_SCOPE_LINK, new LinkAddress("::1/128").getScope());
206         assertEquals(RT_SCOPE_LINK, new LinkAddress("127.0.0.5/8").getScope());
207         assertEquals(RT_SCOPE_LINK, new LinkAddress("fe80::ace:d00d/64").getScope());
208         assertEquals(RT_SCOPE_LINK, new LinkAddress("169.254.5.12/16").getScope());
209 
210         assertEquals(RT_SCOPE_SITE, new LinkAddress("fec0::dead/64").getScope());
211 
212         assertEquals(RT_SCOPE_UNIVERSE, new LinkAddress("10.1.2.3/21").getScope());
213         assertEquals(RT_SCOPE_UNIVERSE, new LinkAddress("192.0.2.1/25").getScope());
214         assertEquals(RT_SCOPE_UNIVERSE, new LinkAddress("2001:db8::/64").getScope());
215         assertEquals(RT_SCOPE_UNIVERSE, new LinkAddress("5000::/127").getScope());
216     }
217 
assertIsSameAddressAs(LinkAddress l1, LinkAddress l2)218     private void assertIsSameAddressAs(LinkAddress l1, LinkAddress l2) {
219         assertTrue(l1 + " unexpectedly does not have same address as " + l2,
220                 l1.isSameAddressAs(l2));
221         assertTrue(l2 + " unexpectedly does not have same address as " + l1,
222                 l2.isSameAddressAs(l1));
223     }
224 
assertIsNotSameAddressAs(LinkAddress l1, LinkAddress l2)225     private void assertIsNotSameAddressAs(LinkAddress l1, LinkAddress l2) {
226         assertFalse(l1 + " unexpectedly has same address as " + l2,
227                 l1.isSameAddressAs(l2));
228         assertFalse(l2 + " unexpectedly has same address as " + l1,
229                 l1.isSameAddressAs(l2));
230     }
231 
232     @Test
testEqualsAndSameAddressAs()233     public void testEqualsAndSameAddressAs() {
234         LinkAddress l1, l2, l3;
235 
236         l1 = new LinkAddress("2001:db8::1/64");
237         l2 = new LinkAddress("2001:db8::1/64");
238         assertEqualBothWays(l1, l2);
239         assertIsSameAddressAs(l1, l2);
240 
241         l2 = new LinkAddress("2001:db8::1/65");
242         assertNotEqualEitherWay(l1, l2);
243         assertIsNotSameAddressAs(l1, l2);
244 
245         l2 = new LinkAddress("2001:db8::2/64");
246         assertNotEqualEitherWay(l1, l2);
247         assertIsNotSameAddressAs(l1, l2);
248 
249 
250         l1 = new LinkAddress("192.0.2.1/24");
251         l2 = new LinkAddress("192.0.2.1/24");
252         assertEqualBothWays(l1, l2);
253         assertIsSameAddressAs(l1, l2);
254 
255         l2 = new LinkAddress("192.0.2.1/23");
256         assertNotEqualEitherWay(l1, l2);
257         assertIsNotSameAddressAs(l1, l2);
258 
259         l2 = new LinkAddress("192.0.2.2/24");
260         assertNotEqualEitherWay(l1, l2);
261         assertIsNotSameAddressAs(l1, l2);
262 
263 
264         // Check equals() and isSameAddressAs() on identical addresses with different flags.
265         l1 = new LinkAddress(V6_ADDRESS, 64);
266         l2 = new LinkAddress(V6_ADDRESS, 64, 0, RT_SCOPE_UNIVERSE);
267         assertEqualBothWays(l1, l2);
268         assertIsSameAddressAs(l1, l2);
269 
270         l2 = new LinkAddress(V6_ADDRESS, 64, IFA_F_DEPRECATED, RT_SCOPE_UNIVERSE);
271         assertNotEqualEitherWay(l1, l2);
272         assertIsSameAddressAs(l1, l2);
273 
274         // Check equals() and isSameAddressAs() on identical addresses with different scope.
275         l1 = new LinkAddress(V4_ADDRESS, 24);
276         l2 = new LinkAddress(V4_ADDRESS, 24, 0, RT_SCOPE_UNIVERSE);
277         assertEqualBothWays(l1, l2);
278         assertIsSameAddressAs(l1, l2);
279 
280         l2 = new LinkAddress(V4_ADDRESS, 24, 0, RT_SCOPE_HOST);
281         assertNotEqualEitherWay(l1, l2);
282         assertIsSameAddressAs(l1, l2);
283 
284         // Addresses with the same start or end bytes aren't equal between families.
285         l1 = new LinkAddress("32.1.13.184/24");
286         l2 = new LinkAddress("2001:db8::1/24");
287         l3 = new LinkAddress("::2001:db8/24");
288 
289         byte[] ipv4Bytes = l1.getAddress().getAddress();
290         byte[] l2FirstIPv6Bytes = Arrays.copyOf(l2.getAddress().getAddress(), 4);
291         byte[] l3LastIPv6Bytes = Arrays.copyOfRange(l3.getAddress().getAddress(), 12, 16);
292         assertTrue(Arrays.equals(ipv4Bytes, l2FirstIPv6Bytes));
293         assertTrue(Arrays.equals(ipv4Bytes, l3LastIPv6Bytes));
294 
295         assertNotEqualEitherWay(l1, l2);
296         assertIsNotSameAddressAs(l1, l2);
297 
298         assertNotEqualEitherWay(l1, l3);
299         assertIsNotSameAddressAs(l1, l3);
300 
301         // Because we use InetAddress, an IPv4 address is equal to its IPv4-mapped address.
302         // TODO: Investigate fixing this.
303         String addressString = V4 + "/24";
304         l1 = new LinkAddress(addressString);
305         l2 = new LinkAddress("::ffff:" + addressString);
306         assertEqualBothWays(l1, l2);
307         assertIsSameAddressAs(l1, l2);
308     }
309 
310     @Test
testHashCode()311     public void testHashCode() {
312         LinkAddress l1, l2;
313 
314         l1 = new LinkAddress(V4_ADDRESS, 23);
315         l2 = new LinkAddress(V4_ADDRESS, 23, 0, RT_SCOPE_HOST);
316         assertNotEquals(l1.hashCode(), l2.hashCode());
317 
318         l1 = new LinkAddress(V6_ADDRESS, 128);
319         l2 = new LinkAddress(V6_ADDRESS, 128, IFA_F_TENTATIVE, RT_SCOPE_UNIVERSE);
320         assertNotEquals(l1.hashCode(), l2.hashCode());
321     }
322 
323     @Test
testParceling()324     public void testParceling() {
325         LinkAddress l;
326 
327         l = new LinkAddress(V6_ADDRESS, 64, 123, 456);
328         assertParcelingIsLossless(l);
329 
330         l = new LinkAddress(V4 + "/28", IFA_F_PERMANENT, RT_SCOPE_LINK);
331         assertParcelingIsLossless(l);
332     }
333 
334     @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
testLifetimeParceling()335     public void testLifetimeParceling() {
336         final LinkAddress l = new LinkAddress(V6_ADDRESS, 64, 123, 456, 1L, 3600000L);
337         assertParcelingIsLossless(l);
338     }
339 
340     @Test @IgnoreAfter(Build.VERSION_CODES.Q)
testFieldCount_Q()341     public void testFieldCount_Q() {
342         assertFieldCountEquals(4, LinkAddress.class);
343     }
344 
345     @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
testFieldCount()346     public void testFieldCount() {
347         // Make sure any new field is covered by the above parceling tests when changing this number
348         assertFieldCountEquals(6, LinkAddress.class);
349     }
350 
351     @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
testDeprecationTime()352     public void testDeprecationTime() {
353         try {
354             new LinkAddress(V6_ADDRESS, 64, 0, 456,
355                     LinkAddress.LIFETIME_UNKNOWN, 100000L);
356             fail("Only one time provided should cause exception");
357         } catch (IllegalArgumentException expected) { }
358 
359         try {
360             new LinkAddress(V6_ADDRESS, 64, 0, 456,
361                     200000L, 100000L);
362             fail("deprecation time later than expiration time should cause exception");
363         } catch (IllegalArgumentException expected) { }
364 
365         try {
366             new LinkAddress(V6_ADDRESS, 64, 0, 456,
367                     -2, 100000L);
368             fail("negative deprecation time should cause exception");
369         } catch (IllegalArgumentException expected) { }
370 
371         LinkAddress addr = new LinkAddress(V6_ADDRESS, 64, 0, 456, 100000L, 200000L);
372         assertEquals(100000L, addr.getDeprecationTime());
373     }
374 
375     @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
testExpirationTime()376     public void testExpirationTime() {
377         try {
378             new LinkAddress(V6_ADDRESS, 64, 0, 456,
379                     200000L, LinkAddress.LIFETIME_UNKNOWN);
380             fail("Only one time provided should cause exception");
381         } catch (IllegalArgumentException expected) { }
382 
383         try {
384             new LinkAddress(V6_ADDRESS, 64, 0, 456,
385                     100000L, -2);
386             fail("negative expiration time should cause exception");
387         } catch (IllegalArgumentException expected) { }
388 
389         LinkAddress addr = new LinkAddress(V6_ADDRESS, 64, 0, 456, 100000L, 200000L);
390         assertEquals(200000L, addr.getExpirationTime());
391     }
392 
393     @Test
testGetFlags()394     public void testGetFlags() {
395         LinkAddress l = new LinkAddress(V6_ADDRESS, 64, 123, RT_SCOPE_HOST);
396         assertEquals(123, l.getFlags());
397     }
398 
399     @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
testGetFlags_Deprecation()400     public void testGetFlags_Deprecation() {
401         // Test if deprecated bit was added/remove automatically based on the provided deprecation
402         // time
403         LinkAddress l = new LinkAddress(V6_ADDRESS, 64, 0, RT_SCOPE_HOST,
404                 1L, LinkAddress.LIFETIME_PERMANENT);
405         // Check if the flag is added automatically.
406         assertTrue((l.getFlags() & IFA_F_DEPRECATED) != 0);
407 
408         l = new LinkAddress(V6_ADDRESS, 64, IFA_F_DEPRECATED, RT_SCOPE_HOST,
409                 SystemClock.elapsedRealtime() + 100000L, LinkAddress.LIFETIME_PERMANENT);
410         // Check if the flag is removed automatically.
411         assertTrue((l.getFlags() & IFA_F_DEPRECATED) == 0);
412 
413         l = new LinkAddress(V6_ADDRESS, 64, IFA_F_DEPRECATED, RT_SCOPE_HOST,
414                 LinkAddress.LIFETIME_PERMANENT, LinkAddress.LIFETIME_PERMANENT);
415         // Check if the permanent flag is added.
416         assertTrue((l.getFlags() & IFA_F_PERMANENT) != 0);
417 
418         l = new LinkAddress(V6_ADDRESS, 64, IFA_F_PERMANENT, RT_SCOPE_HOST,
419                 1000L, SystemClock.elapsedRealtime() + 100000L);
420         // Check if the permanent flag is removed
421         assertTrue((l.getFlags() & IFA_F_PERMANENT) == 0);
422     }
423 
assertGlobalPreferred(LinkAddress l, String msg)424     private void assertGlobalPreferred(LinkAddress l, String msg) {
425         assertTrue(msg, l.isGlobalPreferred());
426     }
427 
assertNotGlobalPreferred(LinkAddress l, String msg)428     private void assertNotGlobalPreferred(LinkAddress l, String msg) {
429         assertFalse(msg, l.isGlobalPreferred());
430     }
431 
432     @Test
testIsGlobalPreferred()433     public void testIsGlobalPreferred() {
434         LinkAddress l;
435 
436         l = new LinkAddress(V4_ADDRESS, 32, 0, RT_SCOPE_UNIVERSE);
437         assertGlobalPreferred(l, "v4,global,noflags");
438 
439         l = new LinkAddress("10.10.1.7/23", 0, RT_SCOPE_UNIVERSE);
440         assertGlobalPreferred(l, "v4-rfc1918,global,noflags");
441 
442         l = new LinkAddress("10.10.1.7/23", 0, RT_SCOPE_SITE);
443         assertNotGlobalPreferred(l, "v4-rfc1918,site-local,noflags");
444 
445         l = new LinkAddress("127.0.0.7/8", 0, RT_SCOPE_HOST);
446         assertNotGlobalPreferred(l, "v4-localhost,node-local,noflags");
447 
448         l = new LinkAddress(V6_ADDRESS, 64, 0, RT_SCOPE_UNIVERSE);
449         assertGlobalPreferred(l, "v6,global,noflags");
450 
451         l = new LinkAddress(V6_ADDRESS, 64, IFA_F_PERMANENT, RT_SCOPE_UNIVERSE);
452         assertGlobalPreferred(l, "v6,global,permanent");
453 
454         // IPv6 ULAs are not acceptable "global preferred" addresses.
455         l = new LinkAddress("fc12::1/64", 0, RT_SCOPE_UNIVERSE);
456         assertNotGlobalPreferred(l, "v6,ula1,noflags");
457 
458         l = new LinkAddress("fd34::1/64", 0, RT_SCOPE_UNIVERSE);
459         assertNotGlobalPreferred(l, "v6,ula2,noflags");
460 
461         l = new LinkAddress(V6_ADDRESS, 64, IFA_F_TEMPORARY, RT_SCOPE_UNIVERSE);
462         assertGlobalPreferred(l, "v6,global,tempaddr");
463 
464         l = new LinkAddress(V6_ADDRESS, 64, (IFA_F_TEMPORARY|IFA_F_DADFAILED),
465                             RT_SCOPE_UNIVERSE);
466         assertNotGlobalPreferred(l, "v6,global,tempaddr+dadfailed");
467 
468         l = new LinkAddress(V6_ADDRESS, 64, (IFA_F_TEMPORARY|IFA_F_DEPRECATED),
469                             RT_SCOPE_UNIVERSE);
470         assertNotGlobalPreferred(l, "v6,global,tempaddr+deprecated");
471 
472         l = new LinkAddress(V6_ADDRESS, 64, IFA_F_TEMPORARY, RT_SCOPE_SITE);
473         assertNotGlobalPreferred(l, "v6,site-local,tempaddr");
474 
475         l = new LinkAddress(V6_ADDRESS, 64, IFA_F_TEMPORARY, RT_SCOPE_LINK);
476         assertNotGlobalPreferred(l, "v6,link-local,tempaddr");
477 
478         l = new LinkAddress(V6_ADDRESS, 64, IFA_F_TEMPORARY, RT_SCOPE_HOST);
479         assertNotGlobalPreferred(l, "v6,node-local,tempaddr");
480 
481         l = new LinkAddress("::1/128", IFA_F_PERMANENT, RT_SCOPE_HOST);
482         assertNotGlobalPreferred(l, "v6-localhost,node-local,permanent");
483 
484         l = new LinkAddress(V6_ADDRESS, 64, (IFA_F_TEMPORARY|IFA_F_TENTATIVE),
485                             RT_SCOPE_UNIVERSE);
486         assertNotGlobalPreferred(l, "v6,global,tempaddr+tentative");
487 
488         l = new LinkAddress(V6_ADDRESS, 64,
489                             (IFA_F_TEMPORARY|IFA_F_TENTATIVE|IFA_F_OPTIMISTIC),
490                             RT_SCOPE_UNIVERSE);
491         assertGlobalPreferred(l, "v6,global,tempaddr+optimistic");
492     }
493 
494     @Test @IgnoreUpTo(Build.VERSION_CODES.Q)
testIsGlobalPreferred_DeprecatedInFuture()495     public void testIsGlobalPreferred_DeprecatedInFuture() {
496         final LinkAddress l = new LinkAddress(V6_ADDRESS, 64, IFA_F_DEPRECATED,
497                 RT_SCOPE_UNIVERSE, SystemClock.elapsedRealtime() + 100000,
498                 SystemClock.elapsedRealtime() + 200000);
499         // Although the deprecated bit is set, but the deprecation time is in the future, test
500         // if the flag is removed automatically.
501         assertGlobalPreferred(l, "v6,global,tempaddr+deprecated in the future");
502     }
503 }
504