1 /* 2 * Copyright (C) 2018 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.dhcp; 18 19 import static android.net.InetAddresses.parseNumericAddress; 20 import static android.net.dhcp.DhcpServingParams.MTU_UNSET; 21 import static android.net.shared.Inet4AddressUtils.inet4AddressToIntHTH; 22 23 import static junit.framework.Assert.assertEquals; 24 import static junit.framework.Assert.assertFalse; 25 import static junit.framework.Assert.assertTrue; 26 27 import android.annotation.NonNull; 28 import android.annotation.Nullable; 29 import android.net.LinkAddress; 30 import android.net.dhcp.DhcpServingParams.InvalidParameterException; 31 import android.net.shared.Inet4AddressUtils; 32 33 import androidx.test.filters.SmallTest; 34 import androidx.test.runner.AndroidJUnit4; 35 36 import org.junit.Before; 37 import org.junit.Test; 38 import org.junit.runner.RunWith; 39 40 import java.lang.reflect.Modifier; 41 import java.net.Inet4Address; 42 import java.util.Arrays; 43 import java.util.Collection; 44 import java.util.HashSet; 45 import java.util.Set; 46 47 @RunWith(AndroidJUnit4.class) 48 @SmallTest 49 public class DhcpServingParamsTest { 50 @NonNull 51 private DhcpServingParams.Builder mBuilder; 52 53 private static final Set<Inet4Address> TEST_DEFAULT_ROUTERS = new HashSet<>( 54 Arrays.asList(parseAddr("192.168.0.123"), parseAddr("192.168.0.124"))); 55 private static final long TEST_LEASE_TIME_SECS = 3600L; 56 private static final Set<Inet4Address> TEST_DNS_SERVERS = new HashSet<>( 57 Arrays.asList(parseAddr("192.168.0.126"), parseAddr("192.168.0.127"))); 58 private static final Inet4Address TEST_SERVER_ADDR = parseAddr("192.168.0.2"); 59 private static final LinkAddress TEST_LINKADDR = new LinkAddress(TEST_SERVER_ADDR, 20); 60 private static final int TEST_MTU = 1500; 61 private static final Set<Inet4Address> TEST_EXCLUDED_ADDRS = new HashSet<>( 62 Arrays.asList(parseAddr("192.168.0.200"), parseAddr("192.168.0.201"))); 63 private static final boolean TEST_METERED = true; 64 65 @Before setUp()66 public void setUp() { 67 mBuilder = new DhcpServingParams.Builder() 68 .setDefaultRouters(TEST_DEFAULT_ROUTERS) 69 .setDhcpLeaseTimeSecs(TEST_LEASE_TIME_SECS) 70 .setDnsServers(TEST_DNS_SERVERS) 71 .setServerAddr(TEST_LINKADDR) 72 .setLinkMtu(TEST_MTU) 73 .setExcludedAddrs(TEST_EXCLUDED_ADDRS) 74 .setMetered(TEST_METERED); 75 } 76 77 @Test testBuild_Immutable()78 public void testBuild_Immutable() throws InvalidParameterException { 79 final Set<Inet4Address> routers = new HashSet<>(TEST_DEFAULT_ROUTERS); 80 final Set<Inet4Address> dnsServers = new HashSet<>(TEST_DNS_SERVERS); 81 final Set<Inet4Address> excludedAddrs = new HashSet<>(TEST_EXCLUDED_ADDRS); 82 83 final DhcpServingParams params = mBuilder 84 .setDefaultRouters(routers) 85 .setDnsServers(dnsServers) 86 .setExcludedAddrs(excludedAddrs) 87 .build(); 88 89 // Modifications to source objects should not affect builder or final parameters 90 final Inet4Address addedAddr = parseAddr("192.168.0.223"); 91 routers.add(addedAddr); 92 dnsServers.add(addedAddr); 93 excludedAddrs.add(addedAddr); 94 95 assertEquals(TEST_DEFAULT_ROUTERS, params.defaultRouters); 96 assertEquals(TEST_LEASE_TIME_SECS, params.dhcpLeaseTimeSecs); 97 assertEquals(TEST_DNS_SERVERS, params.dnsServers); 98 assertEquals(TEST_LINKADDR, params.serverAddr); 99 assertEquals(TEST_MTU, params.linkMtu); 100 assertEquals(TEST_METERED, params.metered); 101 102 assertContains(params.excludedAddrs, TEST_EXCLUDED_ADDRS); 103 assertContains(params.excludedAddrs, TEST_DEFAULT_ROUTERS); 104 assertContains(params.excludedAddrs, TEST_DNS_SERVERS); 105 assertContains(params.excludedAddrs, TEST_SERVER_ADDR); 106 107 assertFalse("excludedAddrs should not contain " + addedAddr, 108 params.excludedAddrs.contains(addedAddr)); 109 } 110 111 @Test(expected = InvalidParameterException.class) testBuild_NegativeLeaseTime()112 public void testBuild_NegativeLeaseTime() throws InvalidParameterException { 113 mBuilder.setDhcpLeaseTimeSecs(-1).build(); 114 } 115 116 @Test(expected = InvalidParameterException.class) testBuild_LeaseTimeTooLarge()117 public void testBuild_LeaseTimeTooLarge() throws InvalidParameterException { 118 // Set lease time larger than max value for uint32 119 mBuilder.setDhcpLeaseTimeSecs(1L << 32).build(); 120 } 121 122 @Test testBuild_InfiniteLeaseTime()123 public void testBuild_InfiniteLeaseTime() throws InvalidParameterException { 124 final long infiniteLeaseTime = 0xffffffffL; 125 final DhcpServingParams params = mBuilder 126 .setDhcpLeaseTimeSecs(infiniteLeaseTime).build(); 127 assertEquals(infiniteLeaseTime, params.dhcpLeaseTimeSecs); 128 assertTrue(params.dhcpLeaseTimeSecs > 0L); 129 } 130 131 @Test testBuild_UnsetMtu()132 public void testBuild_UnsetMtu() throws InvalidParameterException { 133 final DhcpServingParams params = mBuilder.setLinkMtu(MTU_UNSET).build(); 134 assertEquals(MTU_UNSET, params.linkMtu); 135 } 136 137 @Test(expected = InvalidParameterException.class) testBuild_MtuTooSmall()138 public void testBuild_MtuTooSmall() throws InvalidParameterException { 139 mBuilder.setLinkMtu(20).build(); 140 } 141 142 @Test(expected = InvalidParameterException.class) testBuild_MtuTooLarge()143 public void testBuild_MtuTooLarge() throws InvalidParameterException { 144 mBuilder.setLinkMtu(65_536).build(); 145 } 146 147 @Test(expected = InvalidParameterException.class) testBuild_IPv6Addr()148 public void testBuild_IPv6Addr() throws InvalidParameterException { 149 mBuilder.setServerAddr(new LinkAddress(parseNumericAddress("fe80::1111"), 120)).build(); 150 } 151 152 @Test(expected = InvalidParameterException.class) testBuild_PrefixTooLarge()153 public void testBuild_PrefixTooLarge() throws InvalidParameterException { 154 mBuilder.setServerAddr(new LinkAddress(TEST_SERVER_ADDR, 15)).build(); 155 } 156 157 @Test(expected = InvalidParameterException.class) testBuild_PrefixTooSmall()158 public void testBuild_PrefixTooSmall() throws InvalidParameterException { 159 mBuilder.setDefaultRouters(parseAddr("192.168.0.254")) 160 .setServerAddr(new LinkAddress(TEST_SERVER_ADDR, 31)) 161 .build(); 162 } 163 164 @Test(expected = InvalidParameterException.class) testBuild_RouterNotInPrefix()165 public void testBuild_RouterNotInPrefix() throws InvalidParameterException { 166 mBuilder.setDefaultRouters(parseAddr("192.168.254.254")).build(); 167 } 168 169 @Test testFromParcelableObject()170 public void testFromParcelableObject() throws InvalidParameterException { 171 final DhcpServingParams params = mBuilder.build(); 172 final DhcpServingParamsParcel parcel = new DhcpServingParamsParcel(); 173 parcel.defaultRouters = toIntArray(TEST_DEFAULT_ROUTERS); 174 parcel.dhcpLeaseTimeSecs = TEST_LEASE_TIME_SECS; 175 parcel.dnsServers = toIntArray(TEST_DNS_SERVERS); 176 parcel.serverAddr = inet4AddressToIntHTH(TEST_SERVER_ADDR); 177 parcel.serverAddrPrefixLength = TEST_LINKADDR.getPrefixLength(); 178 parcel.linkMtu = TEST_MTU; 179 parcel.excludedAddrs = toIntArray(TEST_EXCLUDED_ADDRS); 180 parcel.metered = TEST_METERED; 181 final DhcpServingParams parceled = DhcpServingParams.fromParcelableObject(parcel); 182 183 assertEquals(params.defaultRouters, parceled.defaultRouters); 184 assertEquals(params.dhcpLeaseTimeSecs, parceled.dhcpLeaseTimeSecs); 185 assertEquals(params.dnsServers, parceled.dnsServers); 186 assertEquals(params.serverAddr, parceled.serverAddr); 187 assertEquals(params.linkMtu, parceled.linkMtu); 188 assertEquals(params.excludedAddrs, parceled.excludedAddrs); 189 assertEquals(params.metered, parceled.metered); 190 191 // Ensure that we do not miss any field if added in the future 192 final long numFields = Arrays.stream(DhcpServingParams.class.getDeclaredFields()) 193 .filter(f -> !Modifier.isStatic(f.getModifiers())) 194 .count(); 195 assertEquals(7, numFields); 196 } 197 198 @Test(expected = InvalidParameterException.class) testFromParcelableObject_NullArgument()199 public void testFromParcelableObject_NullArgument() throws InvalidParameterException { 200 DhcpServingParams.fromParcelableObject(null); 201 } 202 toIntArray(Collection<Inet4Address> addrs)203 private static int[] toIntArray(Collection<Inet4Address> addrs) { 204 return addrs.stream().mapToInt(Inet4AddressUtils::inet4AddressToIntHTH).toArray(); 205 } 206 assertContains(@onNull Set<T> set, @NonNull Set<T> subset)207 private static <T> void assertContains(@NonNull Set<T> set, @NonNull Set<T> subset) { 208 for (final T elem : subset) { 209 assertContains(set, elem); 210 } 211 } 212 assertContains(@onNull Set<T> set, @Nullable T elem)213 private static <T> void assertContains(@NonNull Set<T> set, @Nullable T elem) { 214 assertTrue("Set does not contain " + elem, set.contains(elem)); 215 } 216 217 @NonNull parseAddr(@onNull String inet4Addr)218 private static Inet4Address parseAddr(@NonNull String inet4Addr) { 219 return (Inet4Address) parseNumericAddress(inet4Addr); 220 } 221 } 222