1 /* 2 * Copyright (C) 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 17 package android.net.ip; 18 19 import static android.system.OsConstants.RT_SCOPE_UNIVERSE; 20 21 import static com.android.networkstack.util.NetworkStackUtils.IPCLIENT_PARSE_NETLINK_EVENTS_VERSION; 22 23 import static org.junit.Assert.assertArrayEquals; 24 import static org.junit.Assert.assertEquals; 25 import static org.junit.Assert.assertFalse; 26 import static org.junit.Assert.assertNotNull; 27 import static org.junit.Assert.assertNull; 28 import static org.junit.Assert.assertTrue; 29 import static org.junit.Assert.fail; 30 import static org.mockito.Mockito.any; 31 import static org.mockito.Mockito.anyBoolean; 32 import static org.mockito.Mockito.anyString; 33 import static org.mockito.Mockito.clearInvocations; 34 import static org.mockito.Mockito.doReturn; 35 import static org.mockito.Mockito.eq; 36 import static org.mockito.Mockito.never; 37 import static org.mockito.Mockito.reset; 38 import static org.mockito.Mockito.timeout; 39 import static org.mockito.Mockito.times; 40 import static org.mockito.Mockito.verify; 41 import static org.mockito.Mockito.verifyNoMoreInteractions; 42 import static org.mockito.Mockito.when; 43 44 import static java.util.Collections.emptySet; 45 46 import android.annotation.SuppressLint; 47 import android.app.AlarmManager; 48 import android.content.ContentResolver; 49 import android.content.Context; 50 import android.content.res.Resources; 51 import android.net.ConnectivityManager; 52 import android.net.INetd; 53 import android.net.InetAddresses; 54 import android.net.IpPrefix; 55 import android.net.LinkAddress; 56 import android.net.LinkProperties; 57 import android.net.MacAddress; 58 import android.net.NetworkStackIpMemoryStore; 59 import android.net.RouteInfo; 60 import android.net.apf.ApfCapabilities; 61 import android.net.apf.ApfFilter.ApfConfiguration; 62 import android.net.ipmemorystore.NetworkAttributes; 63 import android.net.metrics.IpConnectivityLog; 64 import android.net.shared.InitialConfiguration; 65 import android.net.shared.Layer2Information; 66 import android.net.shared.ProvisioningConfiguration; 67 import android.net.shared.ProvisioningConfiguration.ScanResultInfo; 68 import android.os.Build; 69 70 import androidx.test.filters.SmallTest; 71 import androidx.test.runner.AndroidJUnit4; 72 73 import com.android.net.module.util.InterfaceParams; 74 import com.android.networkstack.R; 75 import com.android.networkstack.ipmemorystore.IpMemoryStoreService; 76 import com.android.server.NetworkObserver; 77 import com.android.server.NetworkObserverRegistry; 78 import com.android.server.NetworkStackService; 79 import com.android.testutils.DevSdkIgnoreRule; 80 import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter; 81 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; 82 import com.android.testutils.HandlerUtils; 83 84 import org.junit.Before; 85 import org.junit.Rule; 86 import org.junit.Test; 87 import org.junit.runner.RunWith; 88 import org.mockito.ArgumentCaptor; 89 import org.mockito.Mock; 90 import org.mockito.MockitoAnnotations; 91 92 import java.net.Inet4Address; 93 import java.net.Inet6Address; 94 import java.net.InetAddress; 95 import java.nio.ByteBuffer; 96 import java.util.Arrays; 97 import java.util.Collections; 98 import java.util.HashSet; 99 import java.util.List; 100 import java.util.Random; 101 import java.util.Set; 102 103 104 /** 105 * Tests for IpClient. 106 */ 107 @RunWith(AndroidJUnit4.class) 108 @SmallTest 109 public class IpClientTest { 110 @Rule 111 public final DevSdkIgnoreRule mIgnoreRule = new DevSdkIgnoreRule(); 112 113 private static final String VALID = "VALID"; 114 private static final String INVALID = "INVALID"; 115 private static final String TEST_IFNAME = "test_wlan0"; 116 private static final int TEST_IFINDEX = 1001; 117 // See RFC 7042#section-2.1.2 for EUI-48 documentation values. 118 private static final MacAddress TEST_MAC = MacAddress.fromString("00:00:5E:00:53:01"); 119 private static final int TEST_TIMEOUT_MS = 30_000; 120 private static final String TEST_L2KEY = "some l2key"; 121 private static final String TEST_CLUSTER = "some cluster"; 122 private static final String TEST_SSID = "test_ssid"; 123 private static final String TEST_BSSID = "00:11:22:33:44:55"; 124 private static final String TEST_BSSID2 = "00:1A:11:22:33:44"; 125 126 private static final String TEST_GLOBAL_ADDRESS = "1234:4321::548d:2db2:4fcf:ef75/64"; 127 private static final String[] TEST_LOCAL_ADDRESSES = { 128 "fe80::a4be:f92:e1f7:22d1/64", 129 "fe80::f04a:8f6:6a32:d756/64", 130 "fd2c:4e57:8e3c:0:548d:2db2:4fcf:ef75/64" 131 }; 132 private static final String TEST_IPV4_LINKADDRESS = "192.168.42.24/24"; 133 private static final String[] TEST_PREFIXES = { "fe80::/64", "fd2c:4e57:8e3c::/64" }; 134 private static final String[] TEST_DNSES = { "fd2c:4e57:8e3c::42" }; 135 private static final String TEST_IPV6_GATEWAY = "fd2c:4e57:8e3c::43"; 136 private static final String TEST_IPV4_GATEWAY = "192.168.42.11"; 137 private static final long TEST_DNS_LIFETIME = 3600; 138 139 @Mock private Context mContext; 140 @Mock private ConnectivityManager mCm; 141 @Mock private NetworkObserverRegistry mObserverRegistry; 142 @Mock private INetd mNetd; 143 @Mock private Resources mResources; 144 @Mock private IIpClientCallbacks mCb; 145 @Mock private AlarmManager mAlarm; 146 @Mock private IpClient.Dependencies mDependencies; 147 @Mock private ContentResolver mContentResolver; 148 @Mock private NetworkStackService.NetworkStackServiceManager mNetworkStackServiceManager; 149 @Mock private NetworkStackIpMemoryStore mIpMemoryStore; 150 @Mock private IpMemoryStoreService mIpMemoryStoreService; 151 @Mock private InterfaceParams mInterfaceParams; 152 @Mock private IpConnectivityLog mMetricsLog; 153 154 private NetworkObserver mObserver; 155 private InterfaceParams mIfParams; 156 157 @Before setUp()158 public void setUp() throws Exception { 159 MockitoAnnotations.initMocks(this); 160 161 when(mContext.getSystemService(eq(Context.ALARM_SERVICE))).thenReturn(mAlarm); 162 when(mContext.getSystemService(eq(ConnectivityManager.class))).thenReturn(mCm); 163 when(mContext.getResources()).thenReturn(mResources); 164 when(mDependencies.getNetd(any())).thenReturn(mNetd); 165 when(mCm.shouldAvoidBadWifi()).thenReturn(true); 166 when(mContext.getContentResolver()).thenReturn(mContentResolver); 167 when(mNetworkStackServiceManager.getIpMemoryStoreService()) 168 .thenReturn(mIpMemoryStoreService); 169 when(mDependencies.getInterfaceParams(any())).thenReturn(mInterfaceParams); 170 when(mDependencies.getIpMemoryStore(mContext, mNetworkStackServiceManager)) 171 .thenReturn(mIpMemoryStore); 172 when(mDependencies.getIpConnectivityLog()).thenReturn(mMetricsLog); 173 when(mDependencies.isFeatureEnabled(eq(mContext), 174 eq(IPCLIENT_PARSE_NETLINK_EVENTS_VERSION), anyBoolean())).thenReturn(false); 175 176 mIfParams = null; 177 } 178 setTestInterfaceParams(String ifname)179 private void setTestInterfaceParams(String ifname) { 180 mIfParams = (ifname != null) 181 ? new InterfaceParams(ifname, TEST_IFINDEX, TEST_MAC) 182 : null; 183 when(mDependencies.getInterfaceParams(anyString())).thenReturn(mIfParams); 184 } 185 makeIpClient(String ifname)186 private IpClient makeIpClient(String ifname) throws Exception { 187 setTestInterfaceParams(ifname); 188 final IpClient ipc = new IpClient(mContext, ifname, mCb, mObserverRegistry, 189 mNetworkStackServiceManager, mDependencies); 190 verify(mNetd, timeout(TEST_TIMEOUT_MS).times(1)).interfaceSetEnableIPv6(ifname, false); 191 verify(mNetd, timeout(TEST_TIMEOUT_MS).times(1)).interfaceClearAddrs(ifname); 192 ArgumentCaptor<NetworkObserver> arg = ArgumentCaptor.forClass(NetworkObserver.class); 193 verify(mObserverRegistry, times(1)).registerObserverForNonblockingCallback(arg.capture()); 194 mObserver = arg.getValue(); 195 reset(mObserverRegistry); 196 reset(mNetd); 197 // Verify IpClient doesn't call onLinkPropertiesChange() when it starts. 198 verify(mCb, never()).onLinkPropertiesChange(any()); 199 reset(mCb); 200 return ipc; 201 } 202 makeEmptyLinkProperties(String iface)203 private static LinkProperties makeEmptyLinkProperties(String iface) { 204 final LinkProperties empty = new LinkProperties(); 205 empty.setInterfaceName(iface); 206 return empty; 207 } 208 verifyNetworkAttributesStored(final String l2Key, final NetworkAttributes attributes)209 private void verifyNetworkAttributesStored(final String l2Key, 210 final NetworkAttributes attributes) { 211 // TODO : when storing is implemented, turn this on 212 // verify(mIpMemoryStore).storeNetworkAttributes(eq(l2Key), eq(attributes), any()); 213 } 214 215 @Test testNullInterfaceNameMostDefinitelyThrows()216 public void testNullInterfaceNameMostDefinitelyThrows() throws Exception { 217 setTestInterfaceParams(null); 218 try { 219 final IpClient ipc = new IpClient(mContext, null, mCb, mObserverRegistry, 220 mNetworkStackServiceManager, mDependencies); 221 ipc.shutdown(); 222 fail(); 223 } catch (NullPointerException npe) { 224 // Phew; null interface names not allowed. 225 } 226 } 227 228 @Test testNullCallbackMostDefinitelyThrows()229 public void testNullCallbackMostDefinitelyThrows() throws Exception { 230 final String ifname = "lo"; 231 setTestInterfaceParams(ifname); 232 try { 233 final IpClient ipc = new IpClient(mContext, ifname, null, mObserverRegistry, 234 mNetworkStackServiceManager, mDependencies); 235 ipc.shutdown(); 236 fail(); 237 } catch (NullPointerException npe) { 238 // Phew; null callbacks not allowed. 239 } 240 } 241 242 @Test testInvalidInterfaceDoesNotThrow()243 public void testInvalidInterfaceDoesNotThrow() throws Exception { 244 setTestInterfaceParams(TEST_IFNAME); 245 final IpClient ipc = new IpClient(mContext, TEST_IFNAME, mCb, mObserverRegistry, 246 mNetworkStackServiceManager, mDependencies); 247 verifyNoMoreInteractions(mIpMemoryStore); 248 ipc.shutdown(); 249 } 250 251 @Test testInterfaceNotFoundFailsImmediately()252 public void testInterfaceNotFoundFailsImmediately() throws Exception { 253 setTestInterfaceParams(null); 254 final IpClient ipc = new IpClient(mContext, TEST_IFNAME, mCb, mObserverRegistry, 255 mNetworkStackServiceManager, mDependencies); 256 ipc.startProvisioning(new ProvisioningConfiguration()); 257 verify(mCb, timeout(TEST_TIMEOUT_MS).times(1)).onProvisioningFailure(any()); 258 verify(mIpMemoryStore, never()).storeNetworkAttributes(any(), any(), any()); 259 ipc.shutdown(); 260 } 261 makeIPv6ProvisionedLinkProperties()262 private LinkProperties makeIPv6ProvisionedLinkProperties() { 263 // Add local addresses, and a global address with global scope 264 final Set<LinkAddress> addresses = links(TEST_LOCAL_ADDRESSES); 265 addresses.add(new LinkAddress(TEST_GLOBAL_ADDRESS, 0, RT_SCOPE_UNIVERSE)); 266 267 // Add a route on the interface for each prefix, and a global route 268 final Set<RouteInfo> routes = routes(TEST_PREFIXES); 269 routes.add(defaultIPV6Route(TEST_IPV6_GATEWAY)); 270 271 return linkproperties(addresses, routes, ips(TEST_DNSES)); 272 } 273 doProvisioningWithDefaultConfiguration()274 private IpClient doProvisioningWithDefaultConfiguration() throws Exception { 275 final IpClient ipc = makeIpClient(TEST_IFNAME); 276 277 ProvisioningConfiguration config = new ProvisioningConfiguration.Builder() 278 .withoutIPv4() 279 // TODO: mock IpReachabilityMonitor's dependencies (NetworkInterface, PowerManager) 280 // and enable it in this test 281 .withoutIpReachabilityMonitor() 282 .build(); 283 284 ipc.startProvisioning(config); 285 verify(mCb, timeout(TEST_TIMEOUT_MS).times(1)).setNeighborDiscoveryOffload(true); 286 verify(mCb, timeout(TEST_TIMEOUT_MS).times(1)).setFallbackMulticastFilter(false); 287 288 final LinkProperties lp = makeIPv6ProvisionedLinkProperties(); 289 lp.getRoutes().forEach(mObserver::onRouteUpdated); 290 lp.getLinkAddresses().forEach(la -> mObserver.onInterfaceAddressUpdated(la, TEST_IFNAME)); 291 mObserver.onInterfaceDnsServerInfo(TEST_IFNAME, TEST_DNS_LIFETIME, 292 lp.getDnsServers().stream().map(InetAddress::getHostAddress) 293 .toArray(String[]::new)); 294 295 HandlerUtils.waitForIdle(ipc.getHandler(), TEST_TIMEOUT_MS); 296 verify(mCb, never()).onProvisioningFailure(any()); 297 verify(mIpMemoryStore, never()).storeNetworkAttributes(any(), any(), any()); 298 299 verify(mCb).onProvisioningSuccess(lp); 300 return ipc; 301 } 302 303 @SuppressLint("NewApi") addIPv4Provisioning(LinkProperties lp)304 private void addIPv4Provisioning(LinkProperties lp) { 305 final LinkAddress la = new LinkAddress(TEST_IPV4_LINKADDRESS); 306 final RouteInfo defaultRoute = new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), 307 InetAddresses.parseNumericAddress(TEST_IPV4_GATEWAY), TEST_IFNAME); 308 mObserver.onInterfaceAddressUpdated(la, TEST_IFNAME); 309 mObserver.onRouteUpdated(defaultRoute); 310 311 lp.addLinkAddress(la); 312 lp.addRoute(defaultRoute); 313 } 314 315 /** 316 * Simulate loss of IPv6 provisioning (default route lost). 317 * 318 * @return The expected new LinkProperties. 319 */ doIPv6ProvisioningLoss(LinkProperties lp)320 private void doIPv6ProvisioningLoss(LinkProperties lp) { 321 final RouteInfo defaultRoute = defaultIPV6Route(TEST_IPV6_GATEWAY); 322 mObserver.onRouteRemoved(defaultRoute); 323 324 lp.removeRoute(defaultRoute); 325 } 326 doDefaultIPv6ProvisioningConfigurationAndProvisioningLossTest(boolean avoidBadWifi)327 private void doDefaultIPv6ProvisioningConfigurationAndProvisioningLossTest(boolean avoidBadWifi) 328 throws Exception { 329 when(mCm.shouldAvoidBadWifi()).thenReturn(avoidBadWifi); 330 final IpClient ipc = doProvisioningWithDefaultConfiguration(); 331 final LinkProperties lp = makeIPv6ProvisionedLinkProperties(); 332 333 reset(mCb); 334 doIPv6ProvisioningLoss(lp); 335 HandlerUtils.waitForIdle(ipc.getHandler(), TEST_TIMEOUT_MS); 336 verify(mCb).onProvisioningFailure(lp); 337 verify(mCb).onLinkPropertiesChange(makeEmptyLinkProperties(TEST_IFNAME)); 338 339 verifyShutdown(ipc); 340 } 341 342 @Test testDefaultIPv6ProvisioningConfiguration_AvoidBadWifi()343 public void testDefaultIPv6ProvisioningConfiguration_AvoidBadWifi() throws Exception { 344 doDefaultIPv6ProvisioningConfigurationAndProvisioningLossTest(true /* avoidBadWifi */); 345 } 346 347 @Test testDefaultIPv6ProvisioningConfiguration_StayOnBadWifi()348 public void testDefaultIPv6ProvisioningConfiguration_StayOnBadWifi() throws Exception { 349 // Even when avoidBadWifi=false, if IPv6 only, loss of all provisioning causes 350 // onProvisioningFailure to be called. 351 doDefaultIPv6ProvisioningConfigurationAndProvisioningLossTest(false /* avoidBadWifi */); 352 } 353 doDefaultDualStackProvisioningConfigurationTest( boolean avoidBadWifi)354 private void doDefaultDualStackProvisioningConfigurationTest( 355 boolean avoidBadWifi) throws Exception { 356 when(mCm.shouldAvoidBadWifi()).thenReturn(avoidBadWifi); 357 final IpClient ipc = doProvisioningWithDefaultConfiguration(); 358 final LinkProperties lp = makeIPv6ProvisionedLinkProperties(); 359 addIPv4Provisioning(lp); 360 HandlerUtils.waitForIdle(ipc.getHandler(), TEST_TIMEOUT_MS); 361 362 reset(mCb); 363 doIPv6ProvisioningLoss(lp); 364 HandlerUtils.waitForIdle(ipc.getHandler(), TEST_TIMEOUT_MS); 365 if (avoidBadWifi) { // Provisioning failure is expected only when avoidBadWifi is true 366 verify(mCb).onProvisioningFailure(lp); 367 verify(mCb).onLinkPropertiesChange(makeEmptyLinkProperties(TEST_IFNAME)); 368 } else { 369 verify(mCb, never()).onProvisioningFailure(any()); 370 verify(mCb).onLinkPropertiesChange(lp); 371 } 372 373 verifyShutdown(ipc); 374 } 375 376 @Test testDefaultDualStackProvisioningConfiguration_AvoidBadWifi()377 public void testDefaultDualStackProvisioningConfiguration_AvoidBadWifi() throws Exception { 378 doDefaultDualStackProvisioningConfigurationTest(true /* avoidBadWifi */); 379 } 380 381 @Test testDefaultDualStackProvisioningConfiguration_StayOnBadWifi()382 public void testDefaultDualStackProvisioningConfiguration_StayOnBadWifi() throws Exception { 383 doDefaultDualStackProvisioningConfigurationTest(false /* avoidBadWifi */); 384 } 385 386 @Test testProvisioningWithInitialConfiguration()387 public void testProvisioningWithInitialConfiguration() throws Exception { 388 final String iface = TEST_IFNAME; 389 final IpClient ipc = makeIpClient(iface); 390 final String l2Key = TEST_L2KEY; 391 final String cluster = TEST_CLUSTER; 392 393 ProvisioningConfiguration config = new ProvisioningConfiguration.Builder() 394 .withoutIPv4() 395 .withoutIpReachabilityMonitor() 396 .withInitialConfiguration( 397 conf(links(TEST_LOCAL_ADDRESSES), prefixes(TEST_PREFIXES), ips())) 398 .build(); 399 400 ipc.startProvisioning(config); 401 verify(mCb, timeout(TEST_TIMEOUT_MS).times(1)).setNeighborDiscoveryOffload(true); 402 verify(mCb, timeout(TEST_TIMEOUT_MS).times(1)).setFallbackMulticastFilter(false); 403 verify(mCb, never()).onProvisioningFailure(any()); 404 ipc.setL2KeyAndCluster(l2Key, cluster); 405 406 for (String addr : TEST_LOCAL_ADDRESSES) { 407 String[] parts = addr.split("/"); 408 verify(mNetd, timeout(TEST_TIMEOUT_MS).times(1)) 409 .interfaceAddAddress(iface, parts[0], Integer.parseInt(parts[1])); 410 } 411 412 final int lastAddr = TEST_LOCAL_ADDRESSES.length - 1; 413 414 // Add N - 1 addresses 415 for (int i = 0; i < lastAddr; i++) { 416 mObserver.onInterfaceAddressUpdated(new LinkAddress(TEST_LOCAL_ADDRESSES[i]), iface); 417 verify(mCb, timeout(TEST_TIMEOUT_MS)).onLinkPropertiesChange(any()); 418 reset(mCb); 419 } 420 421 // Add Nth address 422 mObserver.onInterfaceAddressUpdated(new LinkAddress(TEST_LOCAL_ADDRESSES[lastAddr]), iface); 423 LinkProperties want = linkproperties(links(TEST_LOCAL_ADDRESSES), 424 routes(TEST_PREFIXES), emptySet() /* dnses */); 425 want.setInterfaceName(iface); 426 verify(mCb, timeout(TEST_TIMEOUT_MS).times(1)).onProvisioningSuccess(want); 427 verifyNetworkAttributesStored(l2Key, new NetworkAttributes.Builder() 428 .setCluster(cluster) 429 .build()); 430 } 431 verifyShutdown(IpClient ipc)432 private void verifyShutdown(IpClient ipc) throws Exception { 433 ipc.shutdown(); 434 verify(mNetd, timeout(TEST_TIMEOUT_MS).times(1)).interfaceSetEnableIPv6(TEST_IFNAME, false); 435 verify(mNetd, timeout(TEST_TIMEOUT_MS).times(1)).interfaceClearAddrs(TEST_IFNAME); 436 verify(mCb, timeout(TEST_TIMEOUT_MS).times(1)) 437 .onLinkPropertiesChange(makeEmptyLinkProperties(TEST_IFNAME)); 438 verifyNoMoreInteractions(mIpMemoryStore); 439 } 440 441 @Test testIsProvisioned()442 public void testIsProvisioned() throws Exception { 443 final IpClient ipc = makeIpClient(TEST_IFNAME); 444 InitialConfiguration empty = conf(links(), prefixes()); 445 IsProvisionedTestCase[] testcases = { 446 // nothing 447 notProvisionedCase(links(), routes(), dns(), null), 448 notProvisionedCase(links(), routes(), dns(), empty), 449 450 // IPv4 451 provisionedCase(links("192.0.2.12/24"), routes(), dns(), empty), 452 453 // IPv6 454 notProvisionedCase( 455 links("fe80::a4be:f92:e1f7:22d1/64", "fd2c:4e57:8e3c:0:548d:2db2:4fcf:ef75/64"), 456 routes(), dns(), empty), 457 notProvisionedCase( 458 links("fe80::a4be:f92:e1f7:22d1/64", "fd2c:4e57:8e3c:0:548d:2db2:4fcf:ef75/64"), 459 routes("fe80::/64", "fd2c:4e57:8e3c::/64"), dns("fd00:1234:5678::1000"), empty), 460 provisionedCase( 461 links("2001:db8:dead:beef:f00::a0/64", "fe80::1/64"), 462 routes("::/0"), 463 dns("2001:db8:dead:beef:f00::02"), empty), 464 465 // Initial configuration 466 provisionedCase( 467 links("fe80::e1f7:22d1/64", "fd2c:4e57:8e3c:0:548d:2db2:4fcf:ef75/64"), 468 routes("fe80::/64", "fd2c:4e57:8e3c::/64"), 469 dns(), 470 conf(links("fe80::e1f7:22d1/64", "fd2c:4e57:8e3c:0:548d:2db2:4fcf:ef75/64"), 471 prefixes("fe80::/64", "fd2c:4e57:8e3c::/64"), ips())), 472 473 // Test case with excluded route 474 notProvisionedCase( 475 links("fe80::e1f7:22d1/64", "fd2c:4e57:8e3c:0:548d:2db2:4fcf:ef75/64"), 476 routes( 477 routes("fe80::/64"), 478 excludedRoutes("fd2c:4e57:8e3c::/64")), 479 dns(), 480 conf(links("fe80::e1f7:22d1/64", "fd2c:4e57:8e3c:0:548d:2db2:4fcf:ef75/64"), 481 prefixes("fe80::/64", "fd2c:4e57:8e3c::/64"), ips())) 482 }; 483 484 for (IsProvisionedTestCase testcase : testcases) { 485 if (ipc.isProvisioned(testcase.lp, testcase.config) != testcase.isProvisioned) { 486 fail(testcase.errorMessage()); 487 } 488 } 489 } 490 491 static class IsProvisionedTestCase { 492 boolean isProvisioned; 493 LinkProperties lp; 494 InitialConfiguration config; 495 errorMessage()496 String errorMessage() { 497 return String.format("expected %s with config %s to be %s, but was %s", 498 lp, config, provisioned(isProvisioned), provisioned(!isProvisioned)); 499 } 500 provisioned(boolean isProvisioned)501 static String provisioned(boolean isProvisioned) { 502 return isProvisioned ? "provisioned" : "not provisioned"; 503 } 504 } 505 provisionedCase(Set<LinkAddress> lpAddrs, Set<RouteInfo> lpRoutes, Set<InetAddress> lpDns, InitialConfiguration config)506 static IsProvisionedTestCase provisionedCase(Set<LinkAddress> lpAddrs, Set<RouteInfo> lpRoutes, 507 Set<InetAddress> lpDns, InitialConfiguration config) { 508 return provisioningTest(true, lpAddrs, lpRoutes, lpDns, config); 509 } 510 notProvisionedCase(Set<LinkAddress> lpAddrs, Set<RouteInfo> lpRoutes, Set<InetAddress> lpDns, InitialConfiguration config)511 static IsProvisionedTestCase notProvisionedCase(Set<LinkAddress> lpAddrs, 512 Set<RouteInfo> lpRoutes, Set<InetAddress> lpDns, InitialConfiguration config) { 513 return provisioningTest(false, lpAddrs, lpRoutes, lpDns, config); 514 } 515 provisioningTest(boolean isProvisioned, Set<LinkAddress> lpAddrs, Set<RouteInfo> lpRoutes, Set<InetAddress> lpDns, InitialConfiguration config)516 static IsProvisionedTestCase provisioningTest(boolean isProvisioned, Set<LinkAddress> lpAddrs, 517 Set<RouteInfo> lpRoutes, Set<InetAddress> lpDns, InitialConfiguration config) { 518 IsProvisionedTestCase testcase = new IsProvisionedTestCase(); 519 testcase.isProvisioned = isProvisioned; 520 testcase.lp = makeEmptyLinkProperties(TEST_IFNAME); 521 testcase.lp.setLinkAddresses(lpAddrs); 522 for (RouteInfo route : lpRoutes) { 523 testcase.lp.addRoute(route); 524 } 525 for (InetAddress dns : lpDns) { 526 testcase.lp.addDnsServer(dns); 527 } 528 testcase.config = config; 529 return testcase; 530 } 531 532 @Test testInitialConfigurations()533 public void testInitialConfigurations() throws Exception { 534 InitialConfigurationTestCase[] testcases = { 535 validConf("valid IPv4 configuration", 536 links("192.0.2.12/24"), prefixes("192.0.2.0/24"), dns("192.0.2.2")), 537 validConf("another valid IPv4 configuration", 538 links("192.0.2.12/24"), prefixes("192.0.2.0/24"), dns()), 539 validConf("valid IPv6 configurations", 540 links("2001:db8:dead:beef:f00::a0/64", "fe80::1/64"), 541 prefixes("2001:db8:dead:beef::/64", "fe80::/64"), 542 dns("2001:db8:dead:beef:f00::02")), 543 validConf("valid IPv6 configurations", 544 links("fe80::1/64"), prefixes("fe80::/64"), dns()), 545 validConf("valid IPv6/v4 configuration", 546 links("2001:db8:dead:beef:f00::a0/48", "192.0.2.12/24"), 547 prefixes("2001:db8:dead:beef::/64", "192.0.2.0/24"), 548 dns("192.0.2.2", "2001:db8:dead:beef:f00::02")), 549 validConf("valid IPv6 configuration without any GUA.", 550 links("fd00:1234:5678::1/48"), 551 prefixes("fd00:1234:5678::/48"), 552 dns("fd00:1234:5678::1000")), 553 554 invalidConf("empty configuration", links(), prefixes(), dns()), 555 invalidConf("v4 addr and dns not in any prefix", 556 links("192.0.2.12/24"), prefixes("198.51.100.0/24"), dns("192.0.2.2")), 557 invalidConf("v4 addr not in any prefix", 558 links("198.51.2.12/24"), prefixes("198.51.100.0/24"), dns("192.0.2.2")), 559 invalidConf("v4 dns addr not in any prefix", 560 links("192.0.2.12/24"), prefixes("192.0.2.0/24"), dns("198.51.100.2")), 561 invalidConf("v6 addr not in any prefix", 562 links("2001:db8:dead:beef:f00::a0/64", "fe80::1/64"), 563 prefixes("2001:db8:dead:beef::/64"), 564 dns("2001:db8:dead:beef:f00::02")), 565 invalidConf("v6 dns addr not in any prefix", 566 links("fe80::1/64"), prefixes("fe80::/64"), dns("2001:db8:dead:beef:f00::02")), 567 invalidConf("default ipv6 route and no GUA", 568 links("fd01:1111:2222:3333::a0/128"), prefixes("::/0"), dns()), 569 invalidConf("invalid v6 prefix length", 570 links("2001:db8:dead:beef:f00::a0/128"), prefixes("2001:db8:dead:beef::/32"), 571 dns()), 572 invalidConf("another invalid v6 prefix length", 573 links("2001:db8:dead:beef:f00::a0/128"), prefixes("2001:db8:dead:beef::/72"), 574 dns()) 575 }; 576 577 for (InitialConfigurationTestCase testcase : testcases) { 578 if (testcase.config.isValid() != testcase.isValid) { 579 fail(testcase.errorMessage()); 580 } 581 } 582 } 583 584 static class InitialConfigurationTestCase { 585 String descr; 586 boolean isValid; 587 InitialConfiguration config; errorMessage()588 public String errorMessage() { 589 return String.format("%s: expected configuration %s to be %s, but was %s", 590 descr, config, validString(isValid), validString(!isValid)); 591 } validString(boolean isValid)592 static String validString(boolean isValid) { 593 return isValid ? VALID : INVALID; 594 } 595 } 596 validConf(String descr, Set<LinkAddress> links, Set<IpPrefix> prefixes, Set<InetAddress> dns)597 static InitialConfigurationTestCase validConf(String descr, Set<LinkAddress> links, 598 Set<IpPrefix> prefixes, Set<InetAddress> dns) { 599 return confTestCase(descr, true, conf(links, prefixes, dns)); 600 } 601 invalidConf(String descr, Set<LinkAddress> links, Set<IpPrefix> prefixes, Set<InetAddress> dns)602 static InitialConfigurationTestCase invalidConf(String descr, Set<LinkAddress> links, 603 Set<IpPrefix> prefixes, Set<InetAddress> dns) { 604 return confTestCase(descr, false, conf(links, prefixes, dns)); 605 } 606 confTestCase( String descr, boolean isValid, InitialConfiguration config)607 static InitialConfigurationTestCase confTestCase( 608 String descr, boolean isValid, InitialConfiguration config) { 609 InitialConfigurationTestCase testcase = new InitialConfigurationTestCase(); 610 testcase.descr = descr; 611 testcase.isValid = isValid; 612 testcase.config = config; 613 return testcase; 614 } 615 linkproperties(Set<LinkAddress> addresses, Set<RouteInfo> routes, Set<InetAddress> dnses)616 static LinkProperties linkproperties(Set<LinkAddress> addresses, 617 Set<RouteInfo> routes, Set<InetAddress> dnses) { 618 LinkProperties lp = makeEmptyLinkProperties(TEST_IFNAME); 619 lp.setLinkAddresses(addresses); 620 routes.forEach(lp::addRoute); 621 dnses.forEach(lp::addDnsServer); 622 return lp; 623 } 624 conf(Set<LinkAddress> links, Set<IpPrefix> prefixes)625 static InitialConfiguration conf(Set<LinkAddress> links, Set<IpPrefix> prefixes) { 626 return conf(links, prefixes, new HashSet<>()); 627 } 628 conf( Set<LinkAddress> links, Set<IpPrefix> prefixes, Set<InetAddress> dns)629 static InitialConfiguration conf( 630 Set<LinkAddress> links, Set<IpPrefix> prefixes, Set<InetAddress> dns) { 631 InitialConfiguration conf = new InitialConfiguration(); 632 conf.ipAddresses.addAll(links); 633 conf.directlyConnectedRoutes.addAll(prefixes); 634 conf.dnsServers.addAll(dns); 635 return conf; 636 } 637 routes(String... routes)638 static Set<RouteInfo> routes(String... routes) { 639 return mapIntoSet(routes, (r) -> new RouteInfo(new IpPrefix(r), null /* gateway */, 640 TEST_IFNAME)); 641 } 642 excludedRoutes(String... excludedRoutes)643 static Set<RouteInfo> excludedRoutes(String... excludedRoutes) { 644 return mapIntoSet(excludedRoutes, (r) -> new RouteInfo(new IpPrefix(r), null /* gateway */, 645 TEST_IFNAME, RouteInfo.RTN_THROW)); 646 } 647 routes(Set<RouteInfo> includedRoutes, Set<RouteInfo> excludedRoutes)648 static Set<RouteInfo> routes(Set<RouteInfo> includedRoutes, Set<RouteInfo> excludedRoutes) { 649 Set<RouteInfo> result = new HashSet<>(includedRoutes.size() + excludedRoutes.size()); 650 651 result.addAll(includedRoutes); 652 result.addAll(excludedRoutes); 653 654 return result; 655 } 656 657 @SuppressLint("NewApi") defaultIPV6Route(String gateway)658 static RouteInfo defaultIPV6Route(String gateway) { 659 return new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), 660 InetAddresses.parseNumericAddress(gateway), TEST_IFNAME); 661 } 662 prefixes(String... prefixes)663 static Set<IpPrefix> prefixes(String... prefixes) { 664 return mapIntoSet(prefixes, IpPrefix::new); 665 } 666 links(String... addresses)667 static Set<LinkAddress> links(String... addresses) { 668 return mapIntoSet(addresses, LinkAddress::new); 669 } 670 ips(String... addresses)671 static Set<InetAddress> ips(String... addresses) { 672 return mapIntoSet(addresses, InetAddress::getByName); 673 } 674 dns(String... addresses)675 static Set<InetAddress> dns(String... addresses) { 676 return ips(addresses); 677 } 678 mapIntoSet(A[] in, Fn<A, B> fn)679 static <A, B> Set<B> mapIntoSet(A[] in, Fn<A, B> fn) { 680 Set<B> out = new HashSet<>(in.length); 681 for (A item : in) { 682 try { 683 out.add(fn.call(item)); 684 } catch (Exception e) { 685 throw new RuntimeException(e); 686 } 687 } 688 return out; 689 } 690 verifyApfFilterCreatedOnStart(IpClient ipc, boolean isApfSupported)691 private ApfConfiguration verifyApfFilterCreatedOnStart(IpClient ipc, boolean isApfSupported) { 692 ProvisioningConfiguration.Builder config = new ProvisioningConfiguration.Builder() 693 .withoutIPv4() 694 .withoutIpReachabilityMonitor() 695 .withInitialConfiguration( 696 conf(links(TEST_LOCAL_ADDRESSES), prefixes(TEST_PREFIXES), ips())); 697 if (isApfSupported) { 698 config.withApfCapabilities(new ApfCapabilities(4 /* version */, 699 4096 /* maxProgramSize */, 4 /* format */)); 700 } 701 702 ipc.startProvisioning(config.build()); 703 final ArgumentCaptor<ApfConfiguration> configCaptor = ArgumentCaptor.forClass( 704 ApfConfiguration.class); 705 verify(mDependencies, timeout(TEST_TIMEOUT_MS)).maybeCreateApfFilter( 706 any(), configCaptor.capture(), any(), any()); 707 708 return configCaptor.getValue(); 709 } 710 711 @Test @IgnoreAfter(Build.VERSION_CODES.R) testApfConfiguration_R()712 public void testApfConfiguration_R() throws Exception { 713 final IpClient ipc = makeIpClient(TEST_IFNAME); 714 final ApfConfiguration config = verifyApfFilterCreatedOnStart(ipc, 715 true /* isApfSupported */); 716 717 assertEquals(ApfCapabilities.getApfDrop8023Frames(), config.ieee802_3Filter); 718 assertArrayEquals(ApfCapabilities.getApfEtherTypeBlackList(), config.ethTypeBlackList); 719 720 verify(mResources, never()).getBoolean(R.bool.config_apfDrop802_3Frames); 721 verify(mResources, never()).getIntArray(R.array.config_apfEthTypeDenyList); 722 723 verifyShutdown(ipc); 724 } 725 726 @Test @IgnoreUpTo(Build.VERSION_CODES.R) testApfConfiguration()727 public void testApfConfiguration() throws Exception { 728 doReturn(true).when(mResources).getBoolean(R.bool.config_apfDrop802_3Frames); 729 final int[] ethTypeDenyList = new int[] { 0x88A2, 0x88A4 }; 730 doReturn(ethTypeDenyList).when(mResources).getIntArray( 731 R.array.config_apfEthTypeDenyList); 732 733 final IpClient ipc = makeIpClient(TEST_IFNAME); 734 final ApfConfiguration config = verifyApfFilterCreatedOnStart(ipc, 735 true /* isApfSupported */); 736 737 assertTrue(config.ieee802_3Filter); 738 assertArrayEquals(ethTypeDenyList, config.ethTypeBlackList); 739 740 verifyShutdown(ipc); 741 } 742 743 @Test @IgnoreUpTo(Build.VERSION_CODES.R) testApfConfiguration_NoApfDrop8023Frames()744 public void testApfConfiguration_NoApfDrop8023Frames() throws Exception { 745 doReturn(false).when(mResources).getBoolean(R.bool.config_apfDrop802_3Frames); 746 final int[] ethTypeDenyList = new int[] { 0x88A3, 0x88A5 }; 747 doReturn(ethTypeDenyList).when(mResources).getIntArray( 748 R.array.config_apfEthTypeDenyList); 749 750 final IpClient ipc = makeIpClient(TEST_IFNAME); 751 final ApfConfiguration config = verifyApfFilterCreatedOnStart(ipc, 752 true /* isApfSupported */); 753 754 assertFalse(config.ieee802_3Filter); 755 assertArrayEquals(ethTypeDenyList, config.ethTypeBlackList); 756 757 verifyShutdown(ipc); 758 } 759 760 @Test testApfUpdateCapabilities()761 public void testApfUpdateCapabilities() throws Exception { 762 final IpClient ipc = makeIpClient(TEST_IFNAME); 763 final ApfConfiguration config = verifyApfFilterCreatedOnStart(ipc, 764 false /* isApfSupported */); 765 assertNull(config.apfCapabilities); 766 clearInvocations(mDependencies); 767 768 ipc.updateApfCapabilities(new ApfCapabilities(4 /* version */, 4096 /* maxProgramSize */, 769 4 /* format */)); 770 HandlerUtils.waitForIdle(ipc.getHandler(), TEST_TIMEOUT_MS); 771 772 final ArgumentCaptor<ApfConfiguration> configCaptor = ArgumentCaptor.forClass( 773 ApfConfiguration.class); 774 verify(mDependencies, timeout(TEST_TIMEOUT_MS)).maybeCreateApfFilter( 775 any(), configCaptor.capture(), any(), any()); 776 final ApfConfiguration actual = configCaptor.getValue(); 777 assertNotNull(actual); 778 assertEquals(4, actual.apfCapabilities.apfVersionSupported); 779 assertEquals(4096, actual.apfCapabilities.maximumApfProgramSize); 780 assertEquals(4, actual.apfCapabilities.apfPacketFormat); 781 782 verifyShutdown(ipc); 783 } 784 785 @Test testApfUpdateCapabilities_nonNullInitialApfCapabilities()786 public void testApfUpdateCapabilities_nonNullInitialApfCapabilities() throws Exception { 787 final IpClient ipc = makeIpClient(TEST_IFNAME); 788 final ApfConfiguration config = verifyApfFilterCreatedOnStart(ipc, 789 true /* isApfSupported */); 790 assertNotNull(config.apfCapabilities); 791 clearInvocations(mDependencies); 792 793 final ApfCapabilities newApfCapabilities = new ApfCapabilities(4 /* version */, 794 8192 /* maxProgramSize */, 4 /* format */); 795 ipc.updateApfCapabilities(newApfCapabilities); 796 HandlerUtils.waitForIdle(ipc.getHandler(), TEST_TIMEOUT_MS); 797 verify(mDependencies, never()).maybeCreateApfFilter(any(), any(), any(), any()); 798 verifyShutdown(ipc); 799 } 800 801 @Test testApfUpdateCapabilities_nullNewApfCapabilities()802 public void testApfUpdateCapabilities_nullNewApfCapabilities() throws Exception { 803 final IpClient ipc = makeIpClient(TEST_IFNAME); 804 final ApfConfiguration config = verifyApfFilterCreatedOnStart(ipc, 805 true /* isApfSupported */); 806 assertNotNull(config.apfCapabilities); 807 clearInvocations(mDependencies); 808 809 ipc.updateApfCapabilities(null /* apfCapabilities */); 810 HandlerUtils.waitForIdle(ipc.getHandler(), TEST_TIMEOUT_MS); 811 verify(mDependencies, never()).maybeCreateApfFilter(any(), any(), any(), any()); 812 verifyShutdown(ipc); 813 } 814 makeScanResultInfo(final String ssid, final String bssid)815 private ScanResultInfo makeScanResultInfo(final String ssid, final String bssid) { 816 final ByteBuffer payload = ByteBuffer.allocate(14 /* oui + type + data */); 817 final byte[] data = new byte[10]; 818 new Random().nextBytes(data); 819 payload.put(new byte[] { 0x00, 0x1A, 0x11 }); 820 payload.put((byte) 0x06); 821 payload.put(data); 822 823 final ScanResultInfo.InformationElement ie = 824 new ScanResultInfo.InformationElement(0xdd /* IE id */, payload); 825 return new ScanResultInfo(ssid, bssid, Collections.singletonList(ie)); 826 } 827 828 @Test testGetInitialBssidOnSOrAbove()829 public void testGetInitialBssidOnSOrAbove() throws Exception { 830 final IpClient ipc = makeIpClient(TEST_IFNAME); 831 final Layer2Information layer2Info = new Layer2Information(TEST_L2KEY, TEST_CLUSTER, 832 MacAddress.fromString(TEST_BSSID)); 833 final ScanResultInfo scanResultInfo = makeScanResultInfo(TEST_SSID, TEST_BSSID2); 834 final MacAddress bssid = ipc.getInitialBssid(layer2Info, scanResultInfo, 835 true /* isAtLeastS */); 836 assertEquals(bssid, MacAddress.fromString(TEST_BSSID)); 837 } 838 839 @Test testGetInitialBssidOnSOrAbove_NullScanReqsultInfo()840 public void testGetInitialBssidOnSOrAbove_NullScanReqsultInfo() throws Exception { 841 final IpClient ipc = makeIpClient(TEST_IFNAME); 842 final Layer2Information layer2Info = new Layer2Information(TEST_L2KEY, TEST_CLUSTER, 843 MacAddress.fromString(TEST_BSSID)); 844 final MacAddress bssid = ipc.getInitialBssid(layer2Info, null /* ScanResultInfo */, 845 true /* isAtLeastS */); 846 assertEquals(bssid, MacAddress.fromString(TEST_BSSID)); 847 } 848 849 @Test testGetInitialBssidOnSOrAbove_NullBssid()850 public void testGetInitialBssidOnSOrAbove_NullBssid() throws Exception { 851 final IpClient ipc = makeIpClient(TEST_IFNAME); 852 final Layer2Information layer2Info = new Layer2Information(TEST_L2KEY, TEST_CLUSTER, 853 null /* bssid */); 854 final ScanResultInfo scanResultInfo = makeScanResultInfo(TEST_SSID, TEST_BSSID); 855 final MacAddress bssid = ipc.getInitialBssid(layer2Info, scanResultInfo, 856 true /* isAtLeastS */); 857 assertNull(bssid); 858 } 859 860 @Test testGetInitialBssidOnSOrAbove_NullLayer2Info()861 public void testGetInitialBssidOnSOrAbove_NullLayer2Info() throws Exception { 862 final IpClient ipc = makeIpClient(TEST_IFNAME); 863 final ScanResultInfo scanResultInfo = makeScanResultInfo(TEST_SSID, TEST_BSSID); 864 final MacAddress bssid = ipc.getInitialBssid(null /* layer2Info */, scanResultInfo, 865 true /* isAtLeastS */); 866 assertNull(bssid); 867 } 868 869 @Test testGetInitialBssidBeforeS()870 public void testGetInitialBssidBeforeS() throws Exception { 871 final IpClient ipc = makeIpClient(TEST_IFNAME); 872 final Layer2Information layer2Info = new Layer2Information(TEST_L2KEY, TEST_CLUSTER, 873 MacAddress.fromString(TEST_BSSID2)); 874 final ScanResultInfo scanResultInfo = makeScanResultInfo(TEST_SSID, TEST_BSSID); 875 final MacAddress bssid = ipc.getInitialBssid(layer2Info, scanResultInfo, 876 false /* isAtLeastS */); 877 assertEquals(bssid, MacAddress.fromString(TEST_BSSID)); 878 } 879 880 @Test testGetInitialBssidBeforeS_NullLayer2Info()881 public void testGetInitialBssidBeforeS_NullLayer2Info() throws Exception { 882 final IpClient ipc = makeIpClient(TEST_IFNAME); 883 final ScanResultInfo scanResultInfo = makeScanResultInfo(TEST_SSID, TEST_BSSID); 884 final MacAddress bssid = ipc.getInitialBssid(null /* layer2Info */, scanResultInfo, 885 false /* isAtLeastS */); 886 assertEquals(bssid, MacAddress.fromString(TEST_BSSID)); 887 } 888 889 @Test testGetInitialBssidBeforeS_BrokenInitialBssid()890 public void testGetInitialBssidBeforeS_BrokenInitialBssid() throws Exception { 891 final IpClient ipc = makeIpClient(TEST_IFNAME); 892 final ScanResultInfo scanResultInfo = makeScanResultInfo(TEST_SSID, "00:11:22:33:44:"); 893 final MacAddress bssid = ipc.getInitialBssid(null /* layer2Info */, scanResultInfo, 894 false /* isAtLeastS */); 895 assertNull(bssid); 896 } 897 898 @Test testGetInitialBssidBeforeS_BrokenInitialBssidFallback()899 public void testGetInitialBssidBeforeS_BrokenInitialBssidFallback() throws Exception { 900 final IpClient ipc = makeIpClient(TEST_IFNAME); 901 final Layer2Information layer2Info = new Layer2Information(TEST_L2KEY, TEST_CLUSTER, 902 MacAddress.fromString(TEST_BSSID)); 903 final ScanResultInfo scanResultInfo = makeScanResultInfo(TEST_SSID, "00:11:22:33:44:"); 904 final MacAddress bssid = ipc.getInitialBssid(layer2Info, scanResultInfo, 905 false /* isAtLeastS */); 906 assertEquals(bssid, MacAddress.fromString(TEST_BSSID)); 907 } 908 909 @Test testGetInitialBssidBeforeS_NullScanResultInfoFallback()910 public void testGetInitialBssidBeforeS_NullScanResultInfoFallback() throws Exception { 911 final IpClient ipc = makeIpClient(TEST_IFNAME); 912 final Layer2Information layer2Info = new Layer2Information(TEST_L2KEY, TEST_CLUSTER, 913 MacAddress.fromString(TEST_BSSID)); 914 final MacAddress bssid = ipc.getInitialBssid(layer2Info, null /* scanResultInfo */, 915 false /* isAtLeastS */); 916 assertEquals(bssid, MacAddress.fromString(TEST_BSSID)); 917 } 918 919 @Test testGetInitialBssidBeforeS_NullScanResultInfoAndLayer2Info()920 public void testGetInitialBssidBeforeS_NullScanResultInfoAndLayer2Info() throws Exception { 921 final IpClient ipc = makeIpClient(TEST_IFNAME); 922 final MacAddress bssid = ipc.getInitialBssid(null /* layer2Info */, 923 null /* scanResultInfo */, false /* isAtLeastS */); 924 assertNull(bssid); 925 } 926 927 interface Fn<A,B> { call(A a)928 B call(A a) throws Exception; 929 } 930 931 @Test testAll()932 public void testAll() { 933 List<String> list1 = Arrays.asList(); 934 List<String> list2 = Arrays.asList("foo"); 935 List<String> list3 = Arrays.asList("bar", "baz"); 936 List<String> list4 = Arrays.asList("foo", "bar", "baz"); 937 938 assertTrue(InitialConfiguration.all(list1, (x) -> false)); 939 assertFalse(InitialConfiguration.all(list2, (x) -> false)); 940 assertTrue(InitialConfiguration.all(list3, (x) -> true)); 941 assertTrue(InitialConfiguration.all(list2, (x) -> x.charAt(0) == 'f')); 942 assertFalse(InitialConfiguration.all(list4, (x) -> x.charAt(0) == 'f')); 943 } 944 945 @Test testAny()946 public void testAny() { 947 List<String> list1 = Arrays.asList(); 948 List<String> list2 = Arrays.asList("foo"); 949 List<String> list3 = Arrays.asList("bar", "baz"); 950 List<String> list4 = Arrays.asList("foo", "bar", "baz"); 951 952 assertFalse(InitialConfiguration.any(list1, (x) -> true)); 953 assertTrue(InitialConfiguration.any(list2, (x) -> true)); 954 assertTrue(InitialConfiguration.any(list2, (x) -> x.charAt(0) == 'f')); 955 assertFalse(InitialConfiguration.any(list3, (x) -> x.charAt(0) == 'f')); 956 assertTrue(InitialConfiguration.any(list4, (x) -> x.charAt(0) == 'f')); 957 } 958 959 @Test testFindAll()960 public void testFindAll() { 961 List<String> list1 = Arrays.asList(); 962 List<String> list2 = Arrays.asList("foo"); 963 List<String> list3 = Arrays.asList("foo", "bar", "baz"); 964 965 assertEquals(list1, IpClient.findAll(list1, (x) -> true)); 966 assertEquals(list1, IpClient.findAll(list3, (x) -> false)); 967 assertEquals(list3, IpClient.findAll(list3, (x) -> true)); 968 assertEquals(list2, IpClient.findAll(list3, (x) -> x.charAt(0) == 'f')); 969 } 970 } 971