• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertFalse;
21 import static org.junit.Assert.assertTrue;
22 import static org.junit.Assert.fail;
23 import static org.mockito.Mockito.any;
24 import static org.mockito.Mockito.anyString;
25 import static org.mockito.Mockito.eq;
26 import static org.mockito.Mockito.never;
27 import static org.mockito.Mockito.reset;
28 import static org.mockito.Mockito.timeout;
29 import static org.mockito.Mockito.times;
30 import static org.mockito.Mockito.verify;
31 import static org.mockito.Mockito.verifyNoMoreInteractions;
32 import static org.mockito.Mockito.when;
33 
34 import android.app.AlarmManager;
35 import android.content.ContentResolver;
36 import android.content.Context;
37 import android.content.res.Resources;
38 import android.net.ConnectivityManager;
39 import android.net.INetd;
40 import android.net.IpPrefix;
41 import android.net.LinkAddress;
42 import android.net.LinkProperties;
43 import android.net.MacAddress;
44 import android.net.NetworkStackIpMemoryStore;
45 import android.net.RouteInfo;
46 import android.net.ipmemorystore.NetworkAttributes;
47 import android.net.shared.InitialConfiguration;
48 import android.net.shared.ProvisioningConfiguration;
49 import android.net.util.InterfaceParams;
50 
51 import androidx.test.filters.SmallTest;
52 import androidx.test.runner.AndroidJUnit4;
53 
54 import com.android.internal.R;
55 import com.android.server.NetworkObserver;
56 import com.android.server.NetworkObserverRegistry;
57 import com.android.server.NetworkStackService;
58 
59 import org.junit.Before;
60 import org.junit.Test;
61 import org.junit.runner.RunWith;
62 import org.mockito.ArgumentCaptor;
63 import org.mockito.Mock;
64 import org.mockito.MockitoAnnotations;
65 
66 import java.net.InetAddress;
67 import java.util.Arrays;
68 import java.util.HashSet;
69 import java.util.List;
70 import java.util.Set;
71 
72 /**
73  * Tests for IpClient.
74  */
75 @RunWith(AndroidJUnit4.class)
76 @SmallTest
77 public class IpClientTest {
78     private static final int DEFAULT_AVOIDBADWIFI_CONFIG_VALUE = 1;
79 
80     private static final String VALID = "VALID";
81     private static final String INVALID = "INVALID";
82     private static final String TEST_IFNAME = "test_wlan0";
83     private static final int TEST_IFINDEX = 1001;
84     // See RFC 7042#section-2.1.2 for EUI-48 documentation values.
85     private static final MacAddress TEST_MAC = MacAddress.fromString("00:00:5E:00:53:01");
86     private static final int TEST_TIMEOUT_MS = 400;
87     private static final String TEST_L2KEY = "some l2key";
88     private static final String TEST_GROUPHINT = "some grouphint";
89 
90     @Mock private Context mContext;
91     @Mock private ConnectivityManager mCm;
92     @Mock private NetworkObserverRegistry mObserverRegistry;
93     @Mock private INetd mNetd;
94     @Mock private Resources mResources;
95     @Mock private IIpClientCallbacks mCb;
96     @Mock private AlarmManager mAlarm;
97     @Mock private IpClient.Dependencies mDependencies;
98     @Mock private ContentResolver mContentResolver;
99     @Mock private NetworkStackService.NetworkStackServiceManager mNetworkStackServiceManager;
100     @Mock private NetworkStackIpMemoryStore mIpMemoryStore;
101 
102     private NetworkObserver mObserver;
103     private InterfaceParams mIfParams;
104 
105     @Before
setUp()106     public void setUp() throws Exception {
107         MockitoAnnotations.initMocks(this);
108 
109         when(mContext.getSystemService(eq(Context.ALARM_SERVICE))).thenReturn(mAlarm);
110         when(mContext.getSystemService(eq(ConnectivityManager.class))).thenReturn(mCm);
111         when(mContext.getResources()).thenReturn(mResources);
112         when(mDependencies.getNetd(any())).thenReturn(mNetd);
113         when(mResources.getInteger(R.integer.config_networkAvoidBadWifi))
114                 .thenReturn(DEFAULT_AVOIDBADWIFI_CONFIG_VALUE);
115         when(mContext.getContentResolver()).thenReturn(mContentResolver);
116 
117         mIfParams = null;
118     }
119 
setTestInterfaceParams(String ifname)120     private void setTestInterfaceParams(String ifname) {
121         mIfParams = (ifname != null)
122                 ? new InterfaceParams(ifname, TEST_IFINDEX, TEST_MAC)
123                 : null;
124         when(mDependencies.getInterfaceParams(anyString())).thenReturn(mIfParams);
125     }
126 
makeIpClient(String ifname)127     private IpClient makeIpClient(String ifname) throws Exception {
128         setTestInterfaceParams(ifname);
129         final IpClient ipc = new IpClient(mContext, ifname, mCb, mObserverRegistry,
130                 mNetworkStackServiceManager, mDependencies);
131         verify(mNetd, timeout(TEST_TIMEOUT_MS).times(1)).interfaceSetEnableIPv6(ifname, false);
132         verify(mNetd, timeout(TEST_TIMEOUT_MS).times(1)).interfaceClearAddrs(ifname);
133         ArgumentCaptor<NetworkObserver> arg = ArgumentCaptor.forClass(NetworkObserver.class);
134         verify(mObserverRegistry, times(1)).registerObserverForNonblockingCallback(arg.capture());
135         mObserver = arg.getValue();
136         reset(mObserverRegistry);
137         reset(mNetd);
138         // Verify IpClient doesn't call onLinkPropertiesChange() when it starts.
139         verify(mCb, never()).onLinkPropertiesChange(any());
140         reset(mCb);
141         return ipc;
142     }
143 
makeEmptyLinkProperties(String iface)144     private static LinkProperties makeEmptyLinkProperties(String iface) {
145         final LinkProperties empty = new LinkProperties();
146         empty.setInterfaceName(iface);
147         return empty;
148     }
149 
verifyNetworkAttributesStored(final String l2Key, final NetworkAttributes attributes)150     private void verifyNetworkAttributesStored(final String l2Key,
151             final NetworkAttributes attributes) {
152         // TODO : when storing is implemented, turn this on
153         // verify(mIpMemoryStore).storeNetworkAttributes(eq(l2Key), eq(attributes), any());
154     }
155 
156     @Test
testNullInterfaceNameMostDefinitelyThrows()157     public void testNullInterfaceNameMostDefinitelyThrows() throws Exception {
158         setTestInterfaceParams(null);
159         try {
160             final IpClient ipc = new IpClient(mContext, null, mCb, mObserverRegistry,
161                     mNetworkStackServiceManager, mDependencies);
162             ipc.shutdown();
163             fail();
164         } catch (NullPointerException npe) {
165             // Phew; null interface names not allowed.
166         }
167     }
168 
169     @Test
testNullCallbackMostDefinitelyThrows()170     public void testNullCallbackMostDefinitelyThrows() throws Exception {
171         final String ifname = "lo";
172         setTestInterfaceParams(ifname);
173         try {
174             final IpClient ipc = new IpClient(mContext, ifname, null, mObserverRegistry,
175                     mNetworkStackServiceManager, mDependencies);
176             ipc.shutdown();
177             fail();
178         } catch (NullPointerException npe) {
179             // Phew; null callbacks not allowed.
180         }
181     }
182 
183     @Test
testInvalidInterfaceDoesNotThrow()184     public void testInvalidInterfaceDoesNotThrow() throws Exception {
185         setTestInterfaceParams(TEST_IFNAME);
186         final IpClient ipc = new IpClient(mContext, TEST_IFNAME, mCb, mObserverRegistry,
187                 mNetworkStackServiceManager, mDependencies);
188         verifyNoMoreInteractions(mIpMemoryStore);
189         ipc.shutdown();
190     }
191 
192     @Test
testInterfaceNotFoundFailsImmediately()193     public void testInterfaceNotFoundFailsImmediately() throws Exception {
194         setTestInterfaceParams(null);
195         final IpClient ipc = new IpClient(mContext, TEST_IFNAME, mCb, mObserverRegistry,
196                 mNetworkStackServiceManager, mDependencies);
197         ipc.startProvisioning(new ProvisioningConfiguration());
198         verify(mCb, times(1)).onProvisioningFailure(any());
199         verify(mIpMemoryStore, never()).storeNetworkAttributes(any(), any(), any());
200         ipc.shutdown();
201     }
202 
203     @Test
testDefaultProvisioningConfiguration()204     public void testDefaultProvisioningConfiguration() throws Exception {
205         final String iface = TEST_IFNAME;
206         final IpClient ipc = makeIpClient(iface);
207 
208         ProvisioningConfiguration config = new ProvisioningConfiguration.Builder()
209                 .withoutIPv4()
210                 // TODO: mock IpReachabilityMonitor's dependencies (NetworkInterface, PowerManager)
211                 // and enable it in this test
212                 .withoutIpReachabilityMonitor()
213                 .build();
214 
215         ipc.startProvisioning(config);
216         verify(mCb, times(1)).setNeighborDiscoveryOffload(true);
217         verify(mCb, timeout(TEST_TIMEOUT_MS).times(1)).setFallbackMulticastFilter(false);
218         verify(mCb, never()).onProvisioningFailure(any());
219         verify(mIpMemoryStore, never()).storeNetworkAttributes(any(), any(), any());
220 
221         ipc.shutdown();
222         verify(mNetd, timeout(TEST_TIMEOUT_MS).times(1)).interfaceSetEnableIPv6(iface, false);
223         verify(mNetd, timeout(TEST_TIMEOUT_MS).times(1)).interfaceClearAddrs(iface);
224         verify(mCb, timeout(TEST_TIMEOUT_MS).times(1))
225                 .onLinkPropertiesChange(makeEmptyLinkProperties(iface));
226     }
227 
228     @Test
testProvisioningWithInitialConfiguration()229     public void testProvisioningWithInitialConfiguration() throws Exception {
230         final String iface = TEST_IFNAME;
231         final IpClient ipc = makeIpClient(iface);
232         final String l2Key = TEST_L2KEY;
233         final String groupHint = TEST_GROUPHINT;
234 
235         String[] addresses = {
236             "fe80::a4be:f92:e1f7:22d1/64",
237             "fe80::f04a:8f6:6a32:d756/64",
238             "fd2c:4e57:8e3c:0:548d:2db2:4fcf:ef75/64"
239         };
240         String[] prefixes = { "fe80::/64", "fd2c:4e57:8e3c::/64" };
241 
242         ProvisioningConfiguration config = new ProvisioningConfiguration.Builder()
243                 .withoutIPv4()
244                 .withoutIpReachabilityMonitor()
245                 .withInitialConfiguration(conf(links(addresses), prefixes(prefixes), ips()))
246                 .build();
247 
248         ipc.startProvisioning(config);
249         verify(mCb, times(1)).setNeighborDiscoveryOffload(true);
250         verify(mCb, timeout(TEST_TIMEOUT_MS).times(1)).setFallbackMulticastFilter(false);
251         verify(mCb, never()).onProvisioningFailure(any());
252         ipc.setL2KeyAndGroupHint(l2Key, groupHint);
253 
254         for (String addr : addresses) {
255             String[] parts = addr.split("/");
256             verify(mNetd, timeout(TEST_TIMEOUT_MS).times(1))
257                     .interfaceAddAddress(iface, parts[0], Integer.parseInt(parts[1]));
258         }
259 
260         final int lastAddr = addresses.length - 1;
261 
262         // Add N - 1 addresses
263         for (int i = 0; i < lastAddr; i++) {
264             mObserver.onInterfaceAddressUpdated(new LinkAddress(addresses[i]), iface);
265             verify(mCb, timeout(TEST_TIMEOUT_MS)).onLinkPropertiesChange(any());
266             reset(mCb);
267         }
268 
269         // Add Nth address
270         mObserver.onInterfaceAddressUpdated(new LinkAddress(addresses[lastAddr]), iface);
271         LinkProperties want = linkproperties(links(addresses), routes(prefixes));
272         want.setInterfaceName(iface);
273         verify(mCb, timeout(TEST_TIMEOUT_MS).times(1)).onProvisioningSuccess(want);
274         verifyNetworkAttributesStored(l2Key, new NetworkAttributes.Builder()
275                 .setGroupHint(groupHint)
276                 .build());
277 
278         ipc.shutdown();
279         verify(mNetd, timeout(TEST_TIMEOUT_MS).times(1)).interfaceSetEnableIPv6(iface, false);
280         verify(mNetd, timeout(TEST_TIMEOUT_MS).times(1)).interfaceClearAddrs(iface);
281         verify(mCb, timeout(TEST_TIMEOUT_MS).times(1))
282                 .onLinkPropertiesChange(makeEmptyLinkProperties(iface));
283         verifyNoMoreInteractions(mIpMemoryStore);
284     }
285 
286     @Test
testIsProvisioned()287     public void testIsProvisioned() throws Exception {
288         InitialConfiguration empty = conf(links(), prefixes());
289         IsProvisionedTestCase[] testcases = {
290             // nothing
291             notProvisionedCase(links(), routes(), dns(), null),
292             notProvisionedCase(links(), routes(), dns(), empty),
293 
294             // IPv4
295             provisionedCase(links("192.0.2.12/24"), routes(), dns(), empty),
296 
297             // IPv6
298             notProvisionedCase(
299                     links("fe80::a4be:f92:e1f7:22d1/64", "fd2c:4e57:8e3c:0:548d:2db2:4fcf:ef75/64"),
300                     routes(), dns(), empty),
301             notProvisionedCase(
302                     links("fe80::a4be:f92:e1f7:22d1/64", "fd2c:4e57:8e3c:0:548d:2db2:4fcf:ef75/64"),
303                     routes("fe80::/64", "fd2c:4e57:8e3c::/64"), dns("fd00:1234:5678::1000"), empty),
304             provisionedCase(
305                     links("2001:db8:dead:beef:f00::a0/64", "fe80::1/64"),
306                     routes("::/0"),
307                     dns("2001:db8:dead:beef:f00::02"), empty),
308 
309             // Initial configuration
310             provisionedCase(
311                     links("fe80::e1f7:22d1/64", "fd2c:4e57:8e3c:0:548d:2db2:4fcf:ef75/64"),
312                     routes("fe80::/64", "fd2c:4e57:8e3c::/64"),
313                     dns(),
314                     conf(links("fe80::e1f7:22d1/64", "fd2c:4e57:8e3c:0:548d:2db2:4fcf:ef75/64"),
315                         prefixes( "fe80::/64", "fd2c:4e57:8e3c::/64"), ips()))
316         };
317 
318         for (IsProvisionedTestCase testcase : testcases) {
319             if (IpClient.isProvisioned(testcase.lp, testcase.config) != testcase.isProvisioned) {
320                 fail(testcase.errorMessage());
321             }
322         }
323     }
324 
325     static class IsProvisionedTestCase {
326         boolean isProvisioned;
327         LinkProperties lp;
328         InitialConfiguration config;
329 
errorMessage()330         String errorMessage() {
331             return String.format("expected %s with config %s to be %s, but was %s",
332                      lp, config, provisioned(isProvisioned), provisioned(!isProvisioned));
333         }
334 
provisioned(boolean isProvisioned)335         static String provisioned(boolean isProvisioned) {
336             return isProvisioned ? "provisioned" : "not provisioned";
337         }
338     }
339 
provisionedCase(Set<LinkAddress> lpAddrs, Set<RouteInfo> lpRoutes, Set<InetAddress> lpDns, InitialConfiguration config)340     static IsProvisionedTestCase provisionedCase(Set<LinkAddress> lpAddrs, Set<RouteInfo> lpRoutes,
341             Set<InetAddress> lpDns, InitialConfiguration config) {
342         return provisioningTest(true, lpAddrs, lpRoutes, lpDns, config);
343     }
344 
notProvisionedCase(Set<LinkAddress> lpAddrs, Set<RouteInfo> lpRoutes, Set<InetAddress> lpDns, InitialConfiguration config)345     static IsProvisionedTestCase notProvisionedCase(Set<LinkAddress> lpAddrs,
346             Set<RouteInfo> lpRoutes, Set<InetAddress> lpDns, InitialConfiguration config) {
347         return provisioningTest(false, lpAddrs, lpRoutes, lpDns, config);
348     }
349 
provisioningTest(boolean isProvisioned, Set<LinkAddress> lpAddrs, Set<RouteInfo> lpRoutes, Set<InetAddress> lpDns, InitialConfiguration config)350     static IsProvisionedTestCase provisioningTest(boolean isProvisioned, Set<LinkAddress> lpAddrs,
351             Set<RouteInfo> lpRoutes, Set<InetAddress> lpDns, InitialConfiguration config) {
352         IsProvisionedTestCase testcase = new IsProvisionedTestCase();
353         testcase.isProvisioned = isProvisioned;
354         testcase.lp = new LinkProperties();
355         testcase.lp.setLinkAddresses(lpAddrs);
356         for (RouteInfo route : lpRoutes) {
357             testcase.lp.addRoute(route);
358         }
359         for (InetAddress dns : lpDns) {
360             testcase.lp.addDnsServer(dns);
361         }
362         testcase.config = config;
363         return testcase;
364     }
365 
366     @Test
testInitialConfigurations()367     public void testInitialConfigurations() throws Exception {
368         InitialConfigurationTestCase[] testcases = {
369             validConf("valid IPv4 configuration",
370                     links("192.0.2.12/24"), prefixes("192.0.2.0/24"), dns("192.0.2.2")),
371             validConf("another valid IPv4 configuration",
372                     links("192.0.2.12/24"), prefixes("192.0.2.0/24"), dns()),
373             validConf("valid IPv6 configurations",
374                     links("2001:db8:dead:beef:f00::a0/64", "fe80::1/64"),
375                     prefixes("2001:db8:dead:beef::/64", "fe80::/64"),
376                     dns("2001:db8:dead:beef:f00::02")),
377             validConf("valid IPv6 configurations",
378                     links("fe80::1/64"), prefixes("fe80::/64"), dns()),
379             validConf("valid IPv6/v4 configuration",
380                     links("2001:db8:dead:beef:f00::a0/48", "192.0.2.12/24"),
381                     prefixes("2001:db8:dead:beef::/64", "192.0.2.0/24"),
382                     dns("192.0.2.2", "2001:db8:dead:beef:f00::02")),
383             validConf("valid IPv6 configuration without any GUA.",
384                     links("fd00:1234:5678::1/48"),
385                     prefixes("fd00:1234:5678::/48"),
386                     dns("fd00:1234:5678::1000")),
387 
388             invalidConf("empty configuration", links(), prefixes(), dns()),
389             invalidConf("v4 addr and dns not in any prefix",
390                     links("192.0.2.12/24"), prefixes("198.51.100.0/24"), dns("192.0.2.2")),
391             invalidConf("v4 addr not in any prefix",
392                     links("198.51.2.12/24"), prefixes("198.51.100.0/24"), dns("192.0.2.2")),
393             invalidConf("v4 dns addr not in any prefix",
394                     links("192.0.2.12/24"), prefixes("192.0.2.0/24"), dns("198.51.100.2")),
395             invalidConf("v6 addr not in any prefix",
396                     links("2001:db8:dead:beef:f00::a0/64", "fe80::1/64"),
397                     prefixes("2001:db8:dead:beef::/64"),
398                     dns("2001:db8:dead:beef:f00::02")),
399             invalidConf("v6 dns addr not in any prefix",
400                     links("fe80::1/64"), prefixes("fe80::/64"), dns("2001:db8:dead:beef:f00::02")),
401             invalidConf("default ipv6 route and no GUA",
402                     links("fd01:1111:2222:3333::a0/128"), prefixes("::/0"), dns()),
403             invalidConf("invalid v6 prefix length",
404                     links("2001:db8:dead:beef:f00::a0/128"), prefixes("2001:db8:dead:beef::/32"),
405                     dns()),
406             invalidConf("another invalid v6 prefix length",
407                     links("2001:db8:dead:beef:f00::a0/128"), prefixes("2001:db8:dead:beef::/72"),
408                     dns())
409         };
410 
411         for (InitialConfigurationTestCase testcase : testcases) {
412             if (testcase.config.isValid() != testcase.isValid) {
413                 fail(testcase.errorMessage());
414             }
415         }
416     }
417 
418     static class InitialConfigurationTestCase {
419         String descr;
420         boolean isValid;
421         InitialConfiguration config;
errorMessage()422         public String errorMessage() {
423             return String.format("%s: expected configuration %s to be %s, but was %s",
424                     descr, config, validString(isValid), validString(!isValid));
425         }
validString(boolean isValid)426         static String validString(boolean isValid) {
427             return isValid ? VALID : INVALID;
428         }
429     }
430 
validConf(String descr, Set<LinkAddress> links, Set<IpPrefix> prefixes, Set<InetAddress> dns)431     static InitialConfigurationTestCase validConf(String descr, Set<LinkAddress> links,
432             Set<IpPrefix> prefixes, Set<InetAddress> dns) {
433         return confTestCase(descr, true, conf(links, prefixes, dns));
434     }
435 
invalidConf(String descr, Set<LinkAddress> links, Set<IpPrefix> prefixes, Set<InetAddress> dns)436     static InitialConfigurationTestCase invalidConf(String descr, Set<LinkAddress> links,
437             Set<IpPrefix> prefixes, Set<InetAddress> dns) {
438         return confTestCase(descr, false, conf(links, prefixes, dns));
439     }
440 
confTestCase( String descr, boolean isValid, InitialConfiguration config)441     static InitialConfigurationTestCase confTestCase(
442             String descr, boolean isValid, InitialConfiguration config) {
443         InitialConfigurationTestCase testcase = new InitialConfigurationTestCase();
444         testcase.descr = descr;
445         testcase.isValid = isValid;
446         testcase.config = config;
447         return testcase;
448     }
449 
linkproperties(Set<LinkAddress> addresses, Set<RouteInfo> routes)450     static LinkProperties linkproperties(Set<LinkAddress> addresses, Set<RouteInfo> routes) {
451         LinkProperties lp = new LinkProperties();
452         lp.setLinkAddresses(addresses);
453         for (RouteInfo route : routes) {
454             lp.addRoute(route);
455         }
456         return lp;
457     }
458 
conf(Set<LinkAddress> links, Set<IpPrefix> prefixes)459     static InitialConfiguration conf(Set<LinkAddress> links, Set<IpPrefix> prefixes) {
460         return conf(links, prefixes, new HashSet<>());
461     }
462 
conf( Set<LinkAddress> links, Set<IpPrefix> prefixes, Set<InetAddress> dns)463     static InitialConfiguration conf(
464             Set<LinkAddress> links, Set<IpPrefix> prefixes, Set<InetAddress> dns) {
465         InitialConfiguration conf = new InitialConfiguration();
466         conf.ipAddresses.addAll(links);
467         conf.directlyConnectedRoutes.addAll(prefixes);
468         conf.dnsServers.addAll(dns);
469         return conf;
470     }
471 
routes(String... routes)472     static Set<RouteInfo> routes(String... routes) {
473         return mapIntoSet(routes, (r) -> new RouteInfo(new IpPrefix(r)));
474     }
475 
prefixes(String... prefixes)476     static Set<IpPrefix> prefixes(String... prefixes) {
477         return mapIntoSet(prefixes, IpPrefix::new);
478     }
479 
links(String... addresses)480     static Set<LinkAddress> links(String... addresses) {
481         return mapIntoSet(addresses, LinkAddress::new);
482     }
483 
ips(String... addresses)484     static Set<InetAddress> ips(String... addresses) {
485         return mapIntoSet(addresses, InetAddress::getByName);
486     }
487 
dns(String... addresses)488     static Set<InetAddress> dns(String... addresses) {
489         return ips(addresses);
490     }
491 
mapIntoSet(A[] in, Fn<A, B> fn)492     static <A, B> Set<B> mapIntoSet(A[] in, Fn<A, B> fn) {
493         Set<B> out = new HashSet<>(in.length);
494         for (A item : in) {
495             try {
496                 out.add(fn.call(item));
497             } catch (Exception e) {
498                 throw new RuntimeException(e);
499             }
500         }
501         return out;
502     }
503 
504     interface Fn<A,B> {
call(A a)505         B call(A a) throws Exception;
506     }
507 
508     @Test
testAll()509     public void testAll() {
510         List<String> list1 = Arrays.asList();
511         List<String> list2 = Arrays.asList("foo");
512         List<String> list3 = Arrays.asList("bar", "baz");
513         List<String> list4 = Arrays.asList("foo", "bar", "baz");
514 
515         assertTrue(InitialConfiguration.all(list1, (x) -> false));
516         assertFalse(InitialConfiguration.all(list2, (x) -> false));
517         assertTrue(InitialConfiguration.all(list3, (x) -> true));
518         assertTrue(InitialConfiguration.all(list2, (x) -> x.charAt(0) == 'f'));
519         assertFalse(InitialConfiguration.all(list4, (x) -> x.charAt(0) == 'f'));
520     }
521 
522     @Test
testAny()523     public void testAny() {
524         List<String> list1 = Arrays.asList();
525         List<String> list2 = Arrays.asList("foo");
526         List<String> list3 = Arrays.asList("bar", "baz");
527         List<String> list4 = Arrays.asList("foo", "bar", "baz");
528 
529         assertFalse(InitialConfiguration.any(list1, (x) -> true));
530         assertTrue(InitialConfiguration.any(list2, (x) -> true));
531         assertTrue(InitialConfiguration.any(list2, (x) -> x.charAt(0) == 'f'));
532         assertFalse(InitialConfiguration.any(list3, (x) -> x.charAt(0) == 'f'));
533         assertTrue(InitialConfiguration.any(list4, (x) -> x.charAt(0) == 'f'));
534     }
535 
536     @Test
testFindAll()537     public void testFindAll() {
538         List<String> list1 = Arrays.asList();
539         List<String> list2 = Arrays.asList("foo");
540         List<String> list3 = Arrays.asList("foo", "bar", "baz");
541 
542         assertEquals(list1, IpClient.findAll(list1, (x) -> true));
543         assertEquals(list1, IpClient.findAll(list3, (x) -> false));
544         assertEquals(list3, IpClient.findAll(list3, (x) -> true));
545         assertEquals(list2, IpClient.findAll(list3, (x) -> x.charAt(0) == 'f'));
546     }
547 }
548