Additionally, no longer try to transition from within a State's
enter() method (this can encounter Log.wtf()s). Introduce some
CMD_JUMP_* commands and use deferMessage().
Test: as follows
- built, flashed, booted
- runtest -x IpClientTest passes
- basic DHCP wifi association works
Bug: 69800563
Bug: 70394432
Bug: 80284937
Change-Id: I7ed6e1a994a3556af345e8a4dfb51c383f6d5478
(cherry picked from commit ffacb517d40df8ebb52d5906fa844b20c6520cd8)
526 lines
20 KiB
Java
526 lines
20 KiB
Java
/*
|
|
* Copyright (C) 2017 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package android.net.ip;
|
|
|
|
import static org.junit.Assert.assertEquals;
|
|
import static org.junit.Assert.assertFalse;
|
|
import static org.junit.Assert.assertTrue;
|
|
import static org.junit.Assert.fail;
|
|
import static org.mockito.Mockito.any;
|
|
import static org.mockito.Mockito.anyString;
|
|
import static org.mockito.Mockito.eq;
|
|
import static org.mockito.Mockito.mock;
|
|
import static org.mockito.Mockito.never;
|
|
import static org.mockito.Mockito.reset;
|
|
import static org.mockito.Mockito.timeout;
|
|
import static org.mockito.Mockito.times;
|
|
import static org.mockito.Mockito.verify;
|
|
import static org.mockito.Mockito.when;
|
|
|
|
import android.app.AlarmManager;
|
|
import android.content.ContentResolver;
|
|
import android.content.Context;
|
|
import android.content.res.Resources;
|
|
import android.net.INetd;
|
|
import android.net.IpPrefix;
|
|
import android.net.LinkAddress;
|
|
import android.net.LinkProperties;
|
|
import android.net.MacAddress;
|
|
import android.net.RouteInfo;
|
|
import android.net.ip.IpClient.Callback;
|
|
import android.net.ip.IpClient.InitialConfiguration;
|
|
import android.net.ip.IpClient.ProvisioningConfiguration;
|
|
import android.net.util.InterfaceParams;
|
|
import android.os.INetworkManagementService;
|
|
import android.provider.Settings;
|
|
import android.support.test.filters.SmallTest;
|
|
import android.support.test.runner.AndroidJUnit4;
|
|
import android.test.mock.MockContentResolver;
|
|
|
|
import com.android.internal.util.test.FakeSettingsProvider;
|
|
import com.android.internal.R;
|
|
import com.android.server.net.BaseNetworkObserver;
|
|
|
|
import org.junit.Before;
|
|
import org.junit.Test;
|
|
import org.junit.runner.RunWith;
|
|
import org.mockito.ArgumentCaptor;
|
|
import org.mockito.Mock;
|
|
import org.mockito.MockitoAnnotations;
|
|
|
|
import java.net.Inet4Address;
|
|
import java.net.Inet6Address;
|
|
import java.net.InetAddress;
|
|
import java.util.Arrays;
|
|
import java.util.List;
|
|
import java.util.HashSet;
|
|
import java.util.Set;
|
|
|
|
/**
|
|
* Tests for IpClient.
|
|
*/
|
|
@RunWith(AndroidJUnit4.class)
|
|
@SmallTest
|
|
public class IpClientTest {
|
|
private static final int DEFAULT_AVOIDBADWIFI_CONFIG_VALUE = 1;
|
|
|
|
private static final String VALID = "VALID";
|
|
private static final String INVALID = "INVALID";
|
|
private static final String TEST_IFNAME = "test_wlan0";
|
|
private static final int TEST_IFINDEX = 1001;
|
|
// See RFC 7042#section-2.1.2 for EUI-48 documentation values.
|
|
private static final MacAddress TEST_MAC = MacAddress.fromString("00:00:5E:00:53:01");
|
|
|
|
@Mock private Context mContext;
|
|
@Mock private INetworkManagementService mNMService;
|
|
@Mock private INetd mNetd;
|
|
@Mock private Resources mResources;
|
|
@Mock private Callback mCb;
|
|
@Mock private AlarmManager mAlarm;
|
|
@Mock private IpClient.Dependencies mDependecies;
|
|
private MockContentResolver mContentResolver;
|
|
|
|
private BaseNetworkObserver mObserver;
|
|
private InterfaceParams mIfParams;
|
|
|
|
@Before
|
|
public void setUp() throws Exception {
|
|
MockitoAnnotations.initMocks(this);
|
|
|
|
when(mContext.getSystemService(eq(Context.ALARM_SERVICE))).thenReturn(mAlarm);
|
|
when(mContext.getResources()).thenReturn(mResources);
|
|
when(mResources.getInteger(R.integer.config_networkAvoidBadWifi))
|
|
.thenReturn(DEFAULT_AVOIDBADWIFI_CONFIG_VALUE);
|
|
|
|
mContentResolver = new MockContentResolver();
|
|
mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
|
|
when(mContext.getContentResolver()).thenReturn(mContentResolver);
|
|
|
|
mIfParams = null;
|
|
|
|
when(mDependecies.getNMS()).thenReturn(mNMService);
|
|
when(mDependecies.getNetd()).thenReturn(mNetd);
|
|
}
|
|
|
|
private void setTestInterfaceParams(String ifname) {
|
|
mIfParams = (ifname != null)
|
|
? new InterfaceParams(ifname, TEST_IFINDEX, TEST_MAC)
|
|
: null;
|
|
when(mDependecies.getInterfaceParams(anyString())).thenReturn(mIfParams);
|
|
}
|
|
|
|
private IpClient makeIpClient(String ifname) throws Exception {
|
|
setTestInterfaceParams(ifname);
|
|
final IpClient ipc = new IpClient(mContext, ifname, mCb, mDependecies);
|
|
verify(mNMService, timeout(100).times(1)).disableIpv6(ifname);
|
|
verify(mNMService, timeout(100).times(1)).clearInterfaceAddresses(ifname);
|
|
ArgumentCaptor<BaseNetworkObserver> arg =
|
|
ArgumentCaptor.forClass(BaseNetworkObserver.class);
|
|
verify(mNMService, times(1)).registerObserver(arg.capture());
|
|
mObserver = arg.getValue();
|
|
reset(mNMService);
|
|
// Verify IpClient doesn't call onLinkPropertiesChange() when it starts.
|
|
verify(mCb, never()).onLinkPropertiesChange(any());
|
|
reset(mCb);
|
|
return ipc;
|
|
}
|
|
|
|
private static LinkProperties makeEmptyLinkProperties(String iface) {
|
|
final LinkProperties empty = new LinkProperties();
|
|
empty.setInterfaceName(iface);
|
|
return empty;
|
|
}
|
|
|
|
@Test
|
|
public void testNullInterfaceNameMostDefinitelyThrows() throws Exception {
|
|
setTestInterfaceParams(null);
|
|
try {
|
|
final IpClient ipc = new IpClient(mContext, null, mCb, mDependecies);
|
|
ipc.shutdown();
|
|
fail();
|
|
} catch (NullPointerException npe) {
|
|
// Phew; null interface names not allowed.
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testNullCallbackMostDefinitelyThrows() throws Exception {
|
|
final String ifname = "lo";
|
|
setTestInterfaceParams(ifname);
|
|
try {
|
|
final IpClient ipc = new IpClient(mContext, ifname, null, mDependecies);
|
|
ipc.shutdown();
|
|
fail();
|
|
} catch (NullPointerException npe) {
|
|
// Phew; null callbacks not allowed.
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testInvalidInterfaceDoesNotThrow() throws Exception {
|
|
setTestInterfaceParams(TEST_IFNAME);
|
|
final IpClient ipc = new IpClient(mContext, TEST_IFNAME, mCb, mDependecies);
|
|
ipc.shutdown();
|
|
}
|
|
|
|
@Test
|
|
public void testInterfaceNotFoundFailsImmediately() throws Exception {
|
|
setTestInterfaceParams(null);
|
|
final IpClient ipc = new IpClient(mContext, TEST_IFNAME, mCb, mDependecies);
|
|
ipc.startProvisioning(new IpClient.ProvisioningConfiguration());
|
|
verify(mCb, times(1)).onProvisioningFailure(any());
|
|
ipc.shutdown();
|
|
}
|
|
|
|
@Test
|
|
public void testDefaultProvisioningConfiguration() throws Exception {
|
|
final String iface = TEST_IFNAME;
|
|
final IpClient ipc = makeIpClient(iface);
|
|
|
|
ProvisioningConfiguration config = new ProvisioningConfiguration.Builder()
|
|
.withoutIPv4()
|
|
// TODO: mock IpReachabilityMonitor's dependencies (NetworkInterface, PowerManager)
|
|
// and enable it in this test
|
|
.withoutIpReachabilityMonitor()
|
|
.build();
|
|
|
|
ipc.startProvisioning(config);
|
|
verify(mCb, times(1)).setNeighborDiscoveryOffload(true);
|
|
verify(mCb, timeout(100).times(1)).setFallbackMulticastFilter(false);
|
|
verify(mCb, never()).onProvisioningFailure(any());
|
|
|
|
ipc.shutdown();
|
|
verify(mNMService, timeout(100).times(1)).disableIpv6(iface);
|
|
verify(mNMService, timeout(100).times(1)).clearInterfaceAddresses(iface);
|
|
verify(mCb, timeout(100).times(1))
|
|
.onLinkPropertiesChange(eq(makeEmptyLinkProperties(iface)));
|
|
}
|
|
|
|
@Test
|
|
public void testProvisioningWithInitialConfiguration() throws Exception {
|
|
final String iface = TEST_IFNAME;
|
|
final IpClient ipc = makeIpClient(iface);
|
|
|
|
String[] addresses = {
|
|
"fe80::a4be:f92:e1f7:22d1/64",
|
|
"fe80::f04a:8f6:6a32:d756/64",
|
|
"fd2c:4e57:8e3c:0:548d:2db2:4fcf:ef75/64"
|
|
};
|
|
String[] prefixes = { "fe80::/64", "fd2c:4e57:8e3c::/64" };
|
|
|
|
ProvisioningConfiguration config = new ProvisioningConfiguration.Builder()
|
|
.withoutIPv4()
|
|
.withoutIpReachabilityMonitor()
|
|
.withInitialConfiguration(conf(links(addresses), prefixes(prefixes), ips()))
|
|
.build();
|
|
|
|
ipc.startProvisioning(config);
|
|
verify(mCb, times(1)).setNeighborDiscoveryOffload(true);
|
|
verify(mCb, timeout(100).times(1)).setFallbackMulticastFilter(false);
|
|
verify(mCb, never()).onProvisioningFailure(any());
|
|
|
|
for (String addr : addresses) {
|
|
String[] parts = addr.split("/");
|
|
verify(mNetd, timeout(100).times(1))
|
|
.interfaceAddAddress(iface, parts[0], Integer.parseInt(parts[1]));
|
|
}
|
|
|
|
final int lastAddr = addresses.length - 1;
|
|
|
|
// Add N - 1 addresses
|
|
for (int i = 0; i < lastAddr; i++) {
|
|
mObserver.addressUpdated(iface, new LinkAddress(addresses[i]));
|
|
verify(mCb, timeout(100)).onLinkPropertiesChange(any());
|
|
reset(mCb);
|
|
}
|
|
|
|
// Add Nth address
|
|
mObserver.addressUpdated(iface, new LinkAddress(addresses[lastAddr]));
|
|
LinkProperties want = linkproperties(links(addresses), routes(prefixes));
|
|
want.setInterfaceName(iface);
|
|
verify(mCb, timeout(100).times(1)).onProvisioningSuccess(eq(want));
|
|
|
|
ipc.shutdown();
|
|
verify(mNMService, timeout(100).times(1)).disableIpv6(iface);
|
|
verify(mNMService, timeout(100).times(1)).clearInterfaceAddresses(iface);
|
|
verify(mCb, timeout(100).times(1))
|
|
.onLinkPropertiesChange(eq(makeEmptyLinkProperties(iface)));
|
|
}
|
|
|
|
@Test
|
|
public void testIsProvisioned() throws Exception {
|
|
InitialConfiguration empty = conf(links(), prefixes());
|
|
IsProvisionedTestCase[] testcases = {
|
|
// nothing
|
|
notProvisionedCase(links(), routes(), dns(), null),
|
|
notProvisionedCase(links(), routes(), dns(), empty),
|
|
|
|
// IPv4
|
|
provisionedCase(links("192.0.2.12/24"), routes(), dns(), empty),
|
|
|
|
// IPv6
|
|
notProvisionedCase(
|
|
links("fe80::a4be:f92:e1f7:22d1/64", "fd2c:4e57:8e3c:0:548d:2db2:4fcf:ef75/64"),
|
|
routes(), dns(), empty),
|
|
notProvisionedCase(
|
|
links("fe80::a4be:f92:e1f7:22d1/64", "fd2c:4e57:8e3c:0:548d:2db2:4fcf:ef75/64"),
|
|
routes("fe80::/64", "fd2c:4e57:8e3c::/64"), dns("fd00:1234:5678::1000"), empty),
|
|
provisionedCase(
|
|
links("2001:db8:dead:beef:f00::a0/64", "fe80::1/64"),
|
|
routes("::/0"),
|
|
dns("2001:db8:dead:beef:f00::02"), empty),
|
|
|
|
// Initial configuration
|
|
provisionedCase(
|
|
links("fe80::e1f7:22d1/64", "fd2c:4e57:8e3c:0:548d:2db2:4fcf:ef75/64"),
|
|
routes("fe80::/64", "fd2c:4e57:8e3c::/64"),
|
|
dns(),
|
|
conf(links("fe80::e1f7:22d1/64", "fd2c:4e57:8e3c:0:548d:2db2:4fcf:ef75/64"),
|
|
prefixes( "fe80::/64", "fd2c:4e57:8e3c::/64"), ips()))
|
|
};
|
|
|
|
for (IsProvisionedTestCase testcase : testcases) {
|
|
if (IpClient.isProvisioned(testcase.lp, testcase.config) != testcase.isProvisioned) {
|
|
fail(testcase.errorMessage());
|
|
}
|
|
}
|
|
}
|
|
|
|
static class IsProvisionedTestCase {
|
|
boolean isProvisioned;
|
|
LinkProperties lp;
|
|
InitialConfiguration config;
|
|
|
|
String errorMessage() {
|
|
return String.format("expected %s with config %s to be %s, but was %s",
|
|
lp, config, provisioned(isProvisioned), provisioned(!isProvisioned));
|
|
}
|
|
|
|
static String provisioned(boolean isProvisioned) {
|
|
return isProvisioned ? "provisioned" : "not provisioned";
|
|
}
|
|
}
|
|
|
|
static IsProvisionedTestCase provisionedCase(Set<LinkAddress> lpAddrs, Set<RouteInfo> lpRoutes,
|
|
Set<InetAddress> lpDns, InitialConfiguration config) {
|
|
return provisioningTest(true, lpAddrs, lpRoutes, lpDns, config);
|
|
}
|
|
|
|
static IsProvisionedTestCase notProvisionedCase(Set<LinkAddress> lpAddrs,
|
|
Set<RouteInfo> lpRoutes, Set<InetAddress> lpDns, InitialConfiguration config) {
|
|
return provisioningTest(false, lpAddrs, lpRoutes, lpDns, config);
|
|
}
|
|
|
|
static IsProvisionedTestCase provisioningTest(boolean isProvisioned, Set<LinkAddress> lpAddrs,
|
|
Set<RouteInfo> lpRoutes, Set<InetAddress> lpDns, InitialConfiguration config) {
|
|
IsProvisionedTestCase testcase = new IsProvisionedTestCase();
|
|
testcase.isProvisioned = isProvisioned;
|
|
testcase.lp = new LinkProperties();
|
|
testcase.lp.setLinkAddresses(lpAddrs);
|
|
for (RouteInfo route : lpRoutes) {
|
|
testcase.lp.addRoute(route);
|
|
}
|
|
for (InetAddress dns : lpDns) {
|
|
testcase.lp.addDnsServer(dns);
|
|
}
|
|
testcase.config = config;
|
|
return testcase;
|
|
}
|
|
|
|
@Test
|
|
public void testInitialConfigurations() throws Exception {
|
|
InitialConfigurationTestCase[] testcases = {
|
|
validConf("valid IPv4 configuration",
|
|
links("192.0.2.12/24"), prefixes("192.0.2.0/24"), dns("192.0.2.2")),
|
|
validConf("another valid IPv4 configuration",
|
|
links("192.0.2.12/24"), prefixes("192.0.2.0/24"), dns()),
|
|
validConf("valid IPv6 configurations",
|
|
links("2001:db8:dead:beef:f00::a0/64", "fe80::1/64"),
|
|
prefixes("2001:db8:dead:beef::/64", "fe80::/64"),
|
|
dns("2001:db8:dead:beef:f00::02")),
|
|
validConf("valid IPv6 configurations",
|
|
links("fe80::1/64"), prefixes("fe80::/64"), dns()),
|
|
validConf("valid IPv6/v4 configuration",
|
|
links("2001:db8:dead:beef:f00::a0/48", "192.0.2.12/24"),
|
|
prefixes("2001:db8:dead:beef::/64", "192.0.2.0/24"),
|
|
dns("192.0.2.2", "2001:db8:dead:beef:f00::02")),
|
|
validConf("valid IPv6 configuration without any GUA.",
|
|
links("fd00:1234:5678::1/48"),
|
|
prefixes("fd00:1234:5678::/48"),
|
|
dns("fd00:1234:5678::1000")),
|
|
|
|
invalidConf("empty configuration", links(), prefixes(), dns()),
|
|
invalidConf("v4 addr and dns not in any prefix",
|
|
links("192.0.2.12/24"), prefixes("198.51.100.0/24"), dns("192.0.2.2")),
|
|
invalidConf("v4 addr not in any prefix",
|
|
links("198.51.2.12/24"), prefixes("198.51.100.0/24"), dns("192.0.2.2")),
|
|
invalidConf("v4 dns addr not in any prefix",
|
|
links("192.0.2.12/24"), prefixes("192.0.2.0/24"), dns("198.51.100.2")),
|
|
invalidConf("v6 addr not in any prefix",
|
|
links("2001:db8:dead:beef:f00::a0/64", "fe80::1/64"),
|
|
prefixes("2001:db8:dead:beef::/64"),
|
|
dns("2001:db8:dead:beef:f00::02")),
|
|
invalidConf("v6 dns addr not in any prefix",
|
|
links("fe80::1/64"), prefixes("fe80::/64"), dns("2001:db8:dead:beef:f00::02")),
|
|
invalidConf("default ipv6 route and no GUA",
|
|
links("fd01:1111:2222:3333::a0/128"), prefixes("::/0"), dns()),
|
|
invalidConf("invalid v6 prefix length",
|
|
links("2001:db8:dead:beef:f00::a0/128"), prefixes("2001:db8:dead:beef::/32"),
|
|
dns()),
|
|
invalidConf("another invalid v6 prefix length",
|
|
links("2001:db8:dead:beef:f00::a0/128"), prefixes("2001:db8:dead:beef::/72"),
|
|
dns())
|
|
};
|
|
|
|
for (InitialConfigurationTestCase testcase : testcases) {
|
|
if (testcase.config.isValid() != testcase.isValid) {
|
|
fail(testcase.errorMessage());
|
|
}
|
|
}
|
|
}
|
|
|
|
static class InitialConfigurationTestCase {
|
|
String descr;
|
|
boolean isValid;
|
|
InitialConfiguration config;
|
|
public String errorMessage() {
|
|
return String.format("%s: expected configuration %s to be %s, but was %s",
|
|
descr, config, validString(isValid), validString(!isValid));
|
|
}
|
|
static String validString(boolean isValid) {
|
|
return isValid ? VALID : INVALID;
|
|
}
|
|
}
|
|
|
|
static InitialConfigurationTestCase validConf(String descr, Set<LinkAddress> links,
|
|
Set<IpPrefix> prefixes, Set<InetAddress> dns) {
|
|
return confTestCase(descr, true, conf(links, prefixes, dns));
|
|
}
|
|
|
|
static InitialConfigurationTestCase invalidConf(String descr, Set<LinkAddress> links,
|
|
Set<IpPrefix> prefixes, Set<InetAddress> dns) {
|
|
return confTestCase(descr, false, conf(links, prefixes, dns));
|
|
}
|
|
|
|
static InitialConfigurationTestCase confTestCase(
|
|
String descr, boolean isValid, InitialConfiguration config) {
|
|
InitialConfigurationTestCase testcase = new InitialConfigurationTestCase();
|
|
testcase.descr = descr;
|
|
testcase.isValid = isValid;
|
|
testcase.config = config;
|
|
return testcase;
|
|
}
|
|
|
|
static LinkProperties linkproperties(Set<LinkAddress> addresses, Set<RouteInfo> routes) {
|
|
LinkProperties lp = new LinkProperties();
|
|
lp.setLinkAddresses(addresses);
|
|
for (RouteInfo route : routes) {
|
|
lp.addRoute(route);
|
|
}
|
|
return lp;
|
|
}
|
|
|
|
static InitialConfiguration conf(Set<LinkAddress> links, Set<IpPrefix> prefixes) {
|
|
return conf(links, prefixes, new HashSet<>());
|
|
}
|
|
|
|
static InitialConfiguration conf(
|
|
Set<LinkAddress> links, Set<IpPrefix> prefixes, Set<InetAddress> dns) {
|
|
InitialConfiguration conf = new InitialConfiguration();
|
|
conf.ipAddresses.addAll(links);
|
|
conf.directlyConnectedRoutes.addAll(prefixes);
|
|
conf.dnsServers.addAll(dns);
|
|
return conf;
|
|
}
|
|
|
|
static Set<RouteInfo> routes(String... routes) {
|
|
return mapIntoSet(routes, (r) -> new RouteInfo(new IpPrefix(r)));
|
|
}
|
|
|
|
static Set<IpPrefix> prefixes(String... prefixes) {
|
|
return mapIntoSet(prefixes, IpPrefix::new);
|
|
}
|
|
|
|
static Set<LinkAddress> links(String... addresses) {
|
|
return mapIntoSet(addresses, LinkAddress::new);
|
|
}
|
|
|
|
static Set<InetAddress> ips(String... addresses) {
|
|
return mapIntoSet(addresses, InetAddress::getByName);
|
|
}
|
|
|
|
static Set<InetAddress> dns(String... addresses) {
|
|
return ips(addresses);
|
|
}
|
|
|
|
static <A, B> Set<B> mapIntoSet(A[] in, Fn<A, B> fn) {
|
|
Set<B> out = new HashSet<>(in.length);
|
|
for (A item : in) {
|
|
try {
|
|
out.add(fn.call(item));
|
|
} catch (Exception e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
}
|
|
return out;
|
|
}
|
|
|
|
interface Fn<A,B> {
|
|
B call(A a) throws Exception;
|
|
}
|
|
|
|
@Test
|
|
public void testAll() {
|
|
List<String> list1 = Arrays.asList();
|
|
List<String> list2 = Arrays.asList("foo");
|
|
List<String> list3 = Arrays.asList("bar", "baz");
|
|
List<String> list4 = Arrays.asList("foo", "bar", "baz");
|
|
|
|
assertTrue(IpClient.all(list1, (x) -> false));
|
|
assertFalse(IpClient.all(list2, (x) -> false));
|
|
assertTrue(IpClient.all(list3, (x) -> true));
|
|
assertTrue(IpClient.all(list2, (x) -> x.charAt(0) == 'f'));
|
|
assertFalse(IpClient.all(list4, (x) -> x.charAt(0) == 'f'));
|
|
}
|
|
|
|
@Test
|
|
public void testAny() {
|
|
List<String> list1 = Arrays.asList();
|
|
List<String> list2 = Arrays.asList("foo");
|
|
List<String> list3 = Arrays.asList("bar", "baz");
|
|
List<String> list4 = Arrays.asList("foo", "bar", "baz");
|
|
|
|
assertFalse(IpClient.any(list1, (x) -> true));
|
|
assertTrue(IpClient.any(list2, (x) -> true));
|
|
assertTrue(IpClient.any(list2, (x) -> x.charAt(0) == 'f'));
|
|
assertFalse(IpClient.any(list3, (x) -> x.charAt(0) == 'f'));
|
|
assertTrue(IpClient.any(list4, (x) -> x.charAt(0) == 'f'));
|
|
}
|
|
|
|
@Test
|
|
public void testFindAll() {
|
|
List<String> list1 = Arrays.asList();
|
|
List<String> list2 = Arrays.asList("foo");
|
|
List<String> list3 = Arrays.asList("foo", "bar", "baz");
|
|
|
|
assertEquals(list1, IpClient.findAll(list1, (x) -> true));
|
|
assertEquals(list1, IpClient.findAll(list3, (x) -> false));
|
|
assertEquals(list3, IpClient.findAll(list3, (x) -> true));
|
|
assertEquals(list2, IpClient.findAll(list3, (x) -> x.charAt(0) == 'f'));
|
|
}
|
|
}
|