• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 com.android.server.ethernet;
18 
19 import static android.net.TestNetworkManager.TEST_TAP_PREFIX;
20 
21 import static org.junit.Assert.assertEquals;
22 import static org.junit.Assert.assertFalse;
23 import static org.junit.Assert.assertThrows;
24 import static org.junit.Assert.assertTrue;
25 import static org.junit.Assert.fail;
26 import static org.mockito.ArgumentMatchers.anyBoolean;
27 import static org.mockito.ArgumentMatchers.anyString;
28 import static org.mockito.ArgumentMatchers.eq;
29 import static org.mockito.Mockito.doReturn;
30 import static org.mockito.Mockito.verify;
31 
32 import android.content.Context;
33 import android.net.INetd;
34 import android.net.InetAddresses;
35 import android.net.IpConfiguration;
36 import android.net.IpConfiguration.IpAssignment;
37 import android.net.IpConfiguration.ProxySettings;
38 import android.net.LinkAddress;
39 import android.net.NetworkCapabilities;
40 import android.net.StaticIpConfiguration;
41 import android.os.Build;
42 import android.os.HandlerThread;
43 import android.os.RemoteException;
44 
45 import androidx.test.filters.SmallTest;
46 
47 import com.android.testutils.DevSdkIgnoreRule;
48 import com.android.testutils.DevSdkIgnoreRunner;
49 import com.android.testutils.HandlerUtils;
50 
51 import org.junit.After;
52 import org.junit.Before;
53 import org.junit.Test;
54 import org.junit.runner.RunWith;
55 import org.mockito.Mock;
56 import org.mockito.MockitoAnnotations;
57 
58 import java.net.InetAddress;
59 import java.util.ArrayList;
60 
61 @SmallTest
62 @RunWith(DevSdkIgnoreRunner.class)
63 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
64 public class EthernetTrackerTest {
65     private static final String TEST_IFACE = "test123";
66     private static final int TIMEOUT_MS = 1_000;
67     private static final String THREAD_NAME = "EthernetServiceThread";
68     private static final EthernetCallback NULL_CB = new EthernetCallback(null);
69     private EthernetTracker tracker;
70     private HandlerThread mHandlerThread;
71     @Mock private Context mContext;
72     @Mock private EthernetNetworkFactory mFactory;
73     @Mock private INetd mNetd;
74     @Mock private EthernetTracker.Dependencies mDeps;
75 
76     @Before
setUp()77     public void setUp() throws RemoteException {
78         MockitoAnnotations.initMocks(this);
79         initMockResources();
80         doReturn(false).when(mFactory).updateInterfaceLinkState(anyString(), anyBoolean());
81         doReturn(new String[0]).when(mNetd).interfaceGetList();
82         mHandlerThread = new HandlerThread(THREAD_NAME);
83         mHandlerThread.start();
84         tracker = new EthernetTracker(mContext, mHandlerThread.getThreadHandler(), mFactory, mNetd,
85                 mDeps);
86     }
87 
88     @After
cleanUp()89     public void cleanUp() throws InterruptedException {
90         mHandlerThread.quitSafely();
91         mHandlerThread.join();
92     }
93 
initMockResources()94     private void initMockResources() {
95         doReturn("").when(mDeps).getInterfaceRegexFromResource(eq(mContext));
96         doReturn(new String[0]).when(mDeps).getInterfaceConfigFromResource(eq(mContext));
97     }
98 
waitForIdle()99     private void waitForIdle() {
100         HandlerUtils.waitForIdle(mHandlerThread, TIMEOUT_MS);
101     }
102 
103     /**
104      * Test: Creation of various valid static IP configurations
105      */
106     @Test
createStaticIpConfiguration()107     public void createStaticIpConfiguration() {
108         // Empty gives default StaticIPConfiguration object
109         assertStaticConfiguration(new StaticIpConfiguration(), "");
110 
111         // Setting only the IP address properly cascades and assumes defaults
112         assertStaticConfiguration(new StaticIpConfiguration.Builder()
113                 .setIpAddress(new LinkAddress("192.0.2.10/24")).build(), "ip=192.0.2.10/24");
114 
115         final ArrayList<InetAddress> dnsAddresses = new ArrayList<>();
116         dnsAddresses.add(InetAddresses.parseNumericAddress("4.4.4.4"));
117         dnsAddresses.add(InetAddresses.parseNumericAddress("8.8.8.8"));
118         // Setting other fields properly cascades them
119         assertStaticConfiguration(new StaticIpConfiguration.Builder()
120                 .setIpAddress(new LinkAddress("192.0.2.10/24"))
121                 .setDnsServers(dnsAddresses)
122                 .setGateway(InetAddresses.parseNumericAddress("192.0.2.1"))
123                 .setDomains("android").build(),
124                 "ip=192.0.2.10/24 dns=4.4.4.4,8.8.8.8 gateway=192.0.2.1 domains=android");
125 
126         // Verify order doesn't matter
127         assertStaticConfiguration(new StaticIpConfiguration.Builder()
128                 .setIpAddress(new LinkAddress("192.0.2.10/24"))
129                 .setDnsServers(dnsAddresses)
130                 .setGateway(InetAddresses.parseNumericAddress("192.0.2.1"))
131                 .setDomains("android").build(),
132                 "domains=android ip=192.0.2.10/24 gateway=192.0.2.1 dns=4.4.4.4,8.8.8.8 ");
133     }
134 
135     /**
136      * Test: Attempt creation of various bad static IP configurations
137      */
138     @Test
createStaticIpConfiguration_Bad()139     public void createStaticIpConfiguration_Bad() {
140         assertStaticConfigurationFails("ip=192.0.2.1/24 gateway= blah=20.20.20.20");  // Unknown key
141         assertStaticConfigurationFails("ip=192.0.2.1");  // mask is missing
142         assertStaticConfigurationFails("ip=a.b.c");  // not a valid ip address
143         assertStaticConfigurationFails("dns=4.4.4.4,1.2.3.A");  // not valid ip address in dns
144         assertStaticConfigurationFails("=");  // Key and value is empty
145         assertStaticConfigurationFails("ip=");  // Value is empty
146         assertStaticConfigurationFails("ip=192.0.2.1/24 gateway=");  // Gateway is empty
147     }
148 
assertStaticConfigurationFails(String config)149     private void assertStaticConfigurationFails(String config) {
150         try {
151             EthernetTracker.parseStaticIpConfiguration(config);
152             fail("Expected to fail: " + config);
153         } catch (IllegalArgumentException e) {
154             // expected
155         }
156     }
157 
assertStaticConfiguration(StaticIpConfiguration expectedStaticIpConfig, String configAsString)158     private void assertStaticConfiguration(StaticIpConfiguration expectedStaticIpConfig,
159                 String configAsString) {
160         final IpConfiguration expectedIpConfiguration = new IpConfiguration();
161         expectedIpConfiguration.setIpAssignment(IpAssignment.STATIC);
162         expectedIpConfiguration.setProxySettings(ProxySettings.NONE);
163         expectedIpConfiguration.setStaticIpConfiguration(expectedStaticIpConfig);
164 
165         assertEquals(expectedIpConfiguration,
166                 EthernetTracker.parseStaticIpConfiguration(configAsString));
167     }
168 
makeEthernetCapabilitiesBuilder(boolean clearAll)169     private NetworkCapabilities.Builder makeEthernetCapabilitiesBuilder(boolean clearAll) {
170         final NetworkCapabilities.Builder builder =
171                 clearAll ? NetworkCapabilities.Builder.withoutDefaultCapabilities()
172                         : new NetworkCapabilities.Builder();
173         return builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING)
174                 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED)
175                 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED);
176     }
177 
178     /**
179      * Test: Attempt to create a capabilties with various valid sets of capabilities/transports
180      */
181     @Test
createNetworkCapabilities()182     public void createNetworkCapabilities() {
183 
184         // Particularly common expected results
185         NetworkCapabilities defaultEthernetCleared =
186                 makeEthernetCapabilitiesBuilder(true /* clearAll */)
187                         .setLinkUpstreamBandwidthKbps(100000)
188                         .setLinkDownstreamBandwidthKbps(100000)
189                         .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
190                         .build();
191 
192         NetworkCapabilities ethernetClearedWithCommonCaps =
193                 makeEthernetCapabilitiesBuilder(true /* clearAll */)
194                         .setLinkUpstreamBandwidthKbps(100000)
195                         .setLinkDownstreamBandwidthKbps(100000)
196                         .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
197                         .addCapability(12)
198                         .addCapability(13)
199                         .addCapability(14)
200                         .addCapability(15)
201                         .build();
202 
203         // Empty capabilities and transports lists with a "please clear defaults" should
204         // yield an empty capabilities set with TRANPORT_ETHERNET
205         assertParsedNetworkCapabilities(defaultEthernetCleared, true, "", "");
206 
207         // Empty capabilities and transports without the clear defaults flag should return the
208         // default capabilities set with TRANSPORT_ETHERNET
209         assertParsedNetworkCapabilities(
210                 makeEthernetCapabilitiesBuilder(false /* clearAll */)
211                         .setLinkUpstreamBandwidthKbps(100000)
212                         .setLinkDownstreamBandwidthKbps(100000)
213                         .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
214                         .build(),
215                 false, "", "");
216 
217         // A list of capabilities without the clear defaults flag should return the default
218         // capabilities, mixed with the desired capabilities, and TRANSPORT_ETHERNET
219         assertParsedNetworkCapabilities(
220                 makeEthernetCapabilitiesBuilder(false /* clearAll */)
221                         .setLinkUpstreamBandwidthKbps(100000)
222                         .setLinkDownstreamBandwidthKbps(100000)
223                         .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
224                         .addCapability(11)
225                         .addCapability(12)
226                         .build(),
227                 false, "11,12", "");
228 
229         // Adding a list of capabilities with a clear defaults will leave exactly those capabilities
230         // with a default TRANSPORT_ETHERNET since no overrides are specified
231         assertParsedNetworkCapabilities(ethernetClearedWithCommonCaps, true, "12,13,14,15", "");
232 
233         // Adding any invalid capabilities to the list will cause them to be ignored
234         assertParsedNetworkCapabilities(ethernetClearedWithCommonCaps, true, "12,13,14,15,65,73", "");
235         assertParsedNetworkCapabilities(ethernetClearedWithCommonCaps, true, "12,13,14,15,abcdefg", "");
236 
237         // Adding a valid override transport will remove the default TRANSPORT_ETHERNET transport
238         // and apply only the override to the capabiltities object
239         assertParsedNetworkCapabilities(
240                 makeEthernetCapabilitiesBuilder(true /* clearAll */)
241                         .setLinkUpstreamBandwidthKbps(100000)
242                         .setLinkDownstreamBandwidthKbps(100000)
243                         .addTransportType(0)
244                         .build(),
245                 true, "", "0");
246         assertParsedNetworkCapabilities(
247                 makeEthernetCapabilitiesBuilder(true /* clearAll */)
248                         .setLinkUpstreamBandwidthKbps(100000)
249                         .setLinkDownstreamBandwidthKbps(100000)
250                         .addTransportType(1)
251                         .build(),
252                 true, "", "1");
253         assertParsedNetworkCapabilities(
254                 makeEthernetCapabilitiesBuilder(true /* clearAll */)
255                         .setLinkUpstreamBandwidthKbps(100000)
256                         .setLinkDownstreamBandwidthKbps(100000)
257                         .addTransportType(2)
258                         .build(),
259                 true, "", "2");
260         assertParsedNetworkCapabilities(
261                 makeEthernetCapabilitiesBuilder(true /* clearAll */)
262                         .setLinkUpstreamBandwidthKbps(100000)
263                         .setLinkDownstreamBandwidthKbps(100000)
264                         .addTransportType(3)
265                         .build(),
266                 true, "", "3");
267 
268         // "4" is TRANSPORT_VPN, which is unsupported. Should default back to TRANPORT_ETHERNET
269         assertParsedNetworkCapabilities(defaultEthernetCleared, true, "", "4");
270 
271         // "5" is TRANSPORT_WIFI_AWARE, which is currently supported due to no legacy TYPE_NONE
272         // conversion. When that becomes available, this test must be updated
273         assertParsedNetworkCapabilities(defaultEthernetCleared, true, "", "5");
274 
275         // "6" is TRANSPORT_LOWPAN, which is currently supported due to no legacy TYPE_NONE
276         // conversion. When that becomes available, this test must be updated
277         assertParsedNetworkCapabilities(defaultEthernetCleared, true, "", "6");
278 
279         // Adding an invalid override transport will leave the transport as TRANSPORT_ETHERNET
280         assertParsedNetworkCapabilities(defaultEthernetCleared,true, "", "100");
281         assertParsedNetworkCapabilities(defaultEthernetCleared, true, "", "abcdefg");
282 
283         // Ensure the adding of both capabilities and transports work
284         assertParsedNetworkCapabilities(
285                 makeEthernetCapabilitiesBuilder(true /* clearAll */)
286                         .setLinkUpstreamBandwidthKbps(100000)
287                         .setLinkDownstreamBandwidthKbps(100000)
288                         .addCapability(12)
289                         .addCapability(13)
290                         .addCapability(14)
291                         .addCapability(15)
292                         .addTransportType(3)
293                         .build(),
294                 true, "12,13,14,15", "3");
295 
296         // Ensure order does not matter for capability list
297         assertParsedNetworkCapabilities(ethernetClearedWithCommonCaps, true, "13,12,15,14", "");
298     }
299 
assertParsedNetworkCapabilities(NetworkCapabilities expectedNetworkCapabilities, boolean clearCapabilties, String configCapabiltiies,String configTransports)300     private void assertParsedNetworkCapabilities(NetworkCapabilities expectedNetworkCapabilities,
301             boolean clearCapabilties, String configCapabiltiies,String configTransports) {
302         assertEquals(expectedNetworkCapabilities,
303                 EthernetTracker.createNetworkCapabilities(clearCapabilties, configCapabiltiies,
304                         configTransports).build());
305     }
306 
307     @Test
testCreateEthernetTrackerConfigReturnsCorrectValue()308     public void testCreateEthernetTrackerConfigReturnsCorrectValue() {
309         final String capabilities = "2";
310         final String ipConfig = "3";
311         final String transport = "4";
312         final String configString = String.join(";", TEST_IFACE, capabilities, ipConfig, transport);
313 
314         final EthernetTracker.EthernetTrackerConfig config =
315                 EthernetTracker.createEthernetTrackerConfig(configString);
316 
317         assertEquals(TEST_IFACE, config.mIface);
318         assertEquals(capabilities, config.mCapabilities);
319         assertEquals(ipConfig, config.mIpConfig);
320         assertEquals(transport, config.mTransport);
321     }
322 
323     @Test
testCreateEthernetTrackerConfigThrowsNpeWithNullInput()324     public void testCreateEthernetTrackerConfigThrowsNpeWithNullInput() {
325         assertThrows(NullPointerException.class,
326                 () -> EthernetTracker.createEthernetTrackerConfig(null));
327     }
328 
329     @Test
testUpdateConfiguration()330     public void testUpdateConfiguration() {
331         final NetworkCapabilities capabilities = new NetworkCapabilities.Builder().build();
332         final LinkAddress linkAddr = new LinkAddress("192.0.2.2/25");
333         final StaticIpConfiguration staticIpConfig =
334                 new StaticIpConfiguration.Builder().setIpAddress(linkAddr).build();
335         final IpConfiguration ipConfig =
336                 new IpConfiguration.Builder().setStaticIpConfiguration(staticIpConfig).build();
337         final EthernetCallback listener = new EthernetCallback(null);
338 
339         tracker.updateConfiguration(TEST_IFACE, ipConfig, capabilities, listener);
340         waitForIdle();
341 
342         verify(mFactory).updateInterface(
343                 eq(TEST_IFACE), eq(ipConfig), eq(capabilities));
344     }
345 
346     @Test
testIsValidTestInterfaceIsFalseWhenTestInterfacesAreNotIncluded()347     public void testIsValidTestInterfaceIsFalseWhenTestInterfacesAreNotIncluded() {
348         final String validIfaceName = TEST_TAP_PREFIX + "123";
349         tracker.setIncludeTestInterfaces(false);
350         waitForIdle();
351 
352         final boolean isValidTestInterface = tracker.isValidTestInterface(validIfaceName);
353 
354         assertFalse(isValidTestInterface);
355     }
356 
357     @Test
testIsValidTestInterfaceIsFalseWhenTestInterfaceNameIsInvalid()358     public void testIsValidTestInterfaceIsFalseWhenTestInterfaceNameIsInvalid() {
359         final String invalidIfaceName = "123" + TEST_TAP_PREFIX;
360         tracker.setIncludeTestInterfaces(true);
361         waitForIdle();
362 
363         final boolean isValidTestInterface = tracker.isValidTestInterface(invalidIfaceName);
364 
365         assertFalse(isValidTestInterface);
366     }
367 
368     @Test
testIsValidTestInterfaceIsTrueWhenTestInterfacesIncludedAndValidName()369     public void testIsValidTestInterfaceIsTrueWhenTestInterfacesIncludedAndValidName() {
370         final String validIfaceName = TEST_TAP_PREFIX + "123";
371         tracker.setIncludeTestInterfaces(true);
372         waitForIdle();
373 
374         final boolean isValidTestInterface = tracker.isValidTestInterface(validIfaceName);
375 
376         assertTrue(isValidTestInterface);
377     }
378 }
379