• 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 com.android.server.ethernet.EthernetTracker.DEFAULT_CAPABILITIES;
22 import static com.google.common.truth.Truth.assertThat;
23 
24 import static org.junit.Assert.assertEquals;
25 import static org.junit.Assert.assertFalse;
26 import static org.junit.Assert.assertThrows;
27 import static org.junit.Assert.assertTrue;
28 import static org.junit.Assert.fail;
29 import static org.mockito.ArgumentMatchers.anyBoolean;
30 import static org.mockito.ArgumentMatchers.anyString;
31 import static org.mockito.ArgumentMatchers.eq;
32 import static org.mockito.Mockito.doReturn;
33 import static org.mockito.Mockito.verify;
34 
35 import android.content.Context;
36 import android.net.INetd;
37 import android.net.InetAddresses;
38 import android.net.IpConfiguration;
39 import android.net.IpConfiguration.IpAssignment;
40 import android.net.IpConfiguration.ProxySettings;
41 import android.net.LinkAddress;
42 import android.net.NetworkCapabilities;
43 import android.net.StaticIpConfiguration;
44 import android.os.Build;
45 import android.os.HandlerThread;
46 import android.os.RemoteException;
47 
48 import androidx.test.filters.SmallTest;
49 
50 import com.android.server.ethernet.EthernetTracker.EthernetConfigParser;
51 import com.android.testutils.DevSdkIgnoreRule;
52 import com.android.testutils.DevSdkIgnoreRunner;
53 import com.android.testutils.HandlerUtils;
54 
55 import org.junit.After;
56 import org.junit.Before;
57 import org.junit.Test;
58 import org.junit.runner.RunWith;
59 import org.mockito.Mock;
60 import org.mockito.MockitoAnnotations;
61 
62 import java.net.InetAddress;
63 import java.util.ArrayList;
64 
65 @SmallTest
66 @RunWith(DevSdkIgnoreRunner.class)
67 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.S_V2)
68 public class EthernetTrackerTest {
69     private static final String TEST_IFACE = "test123";
70     private static final int TIMEOUT_MS = 1_000;
71     private static final String THREAD_NAME = "EthernetServiceThread";
72     private static final EthernetCallback NULL_CB = new EthernetCallback(null);
73     private EthernetTracker tracker;
74     private HandlerThread mHandlerThread;
75     @Mock private Context mContext;
76     @Mock private EthernetNetworkFactory mFactory;
77     @Mock private INetd mNetd;
78     @Mock private EthernetTracker.Dependencies mDeps;
79 
80     @Before
setUp()81     public void setUp() throws RemoteException {
82         MockitoAnnotations.initMocks(this);
83         initMockResources();
84         doReturn(false).when(mFactory).updateInterfaceLinkState(anyString(), anyBoolean());
85         doReturn(new String[0]).when(mNetd).interfaceGetList();
86         doReturn(new String[0]).when(mFactory).getAvailableInterfaces(anyBoolean());
87         mHandlerThread = new HandlerThread(THREAD_NAME);
88         mHandlerThread.start();
89         tracker = new EthernetTracker(mContext, mHandlerThread.getThreadHandler(), mFactory, mNetd,
90                 mDeps);
91     }
92 
93     @After
cleanUp()94     public void cleanUp() throws InterruptedException {
95         mHandlerThread.quitSafely();
96         mHandlerThread.join();
97     }
98 
initMockResources()99     private void initMockResources() {
100         doReturn("").when(mDeps).getInterfaceRegexFromResource(eq(mContext));
101         doReturn(new String[0]).when(mDeps).getInterfaceConfigFromResource(eq(mContext));
102     }
103 
waitForIdle()104     private void waitForIdle() {
105         HandlerUtils.waitForIdle(mHandlerThread, TIMEOUT_MS);
106     }
107 
108     /**
109      * Test: Creation of various valid static IP configurations
110      */
111     @Test
createStaticIpConfiguration()112     public void createStaticIpConfiguration() {
113         // Empty gives default StaticIPConfiguration object
114         assertStaticConfiguration(new StaticIpConfiguration(), "");
115 
116         // Setting only the IP address properly cascades and assumes defaults
117         assertStaticConfiguration(new StaticIpConfiguration.Builder()
118                 .setIpAddress(new LinkAddress("192.0.2.10/24")).build(), "ip=192.0.2.10/24");
119 
120         final ArrayList<InetAddress> dnsAddresses = new ArrayList<>();
121         dnsAddresses.add(InetAddresses.parseNumericAddress("4.4.4.4"));
122         dnsAddresses.add(InetAddresses.parseNumericAddress("8.8.8.8"));
123         // Setting other fields properly cascades them
124         assertStaticConfiguration(new StaticIpConfiguration.Builder()
125                 .setIpAddress(new LinkAddress("192.0.2.10/24"))
126                 .setDnsServers(dnsAddresses)
127                 .setGateway(InetAddresses.parseNumericAddress("192.0.2.1"))
128                 .setDomains("android").build(),
129                 "ip=192.0.2.10/24 dns=4.4.4.4,8.8.8.8 gateway=192.0.2.1 domains=android");
130 
131         // Verify order doesn't matter
132         assertStaticConfiguration(new StaticIpConfiguration.Builder()
133                 .setIpAddress(new LinkAddress("192.0.2.10/24"))
134                 .setDnsServers(dnsAddresses)
135                 .setGateway(InetAddresses.parseNumericAddress("192.0.2.1"))
136                 .setDomains("android").build(),
137                 "domains=android ip=192.0.2.10/24 gateway=192.0.2.1 dns=4.4.4.4,8.8.8.8 ");
138     }
139 
140     /**
141      * Test: Attempt creation of various bad static IP configurations
142      */
143     @Test
createStaticIpConfiguration_Bad()144     public void createStaticIpConfiguration_Bad() {
145         assertStaticConfigurationFails("ip=192.0.2.1/24 gateway= blah=20.20.20.20");  // Unknown key
146         assertStaticConfigurationFails("ip=192.0.2.1");  // mask is missing
147         assertStaticConfigurationFails("ip=a.b.c");  // not a valid ip address
148         assertStaticConfigurationFails("dns=4.4.4.4,1.2.3.A");  // not valid ip address in dns
149         assertStaticConfigurationFails("=");  // Key and value is empty
150         assertStaticConfigurationFails("ip=");  // Value is empty
151         assertStaticConfigurationFails("ip=192.0.2.1/24 gateway=");  // Gateway is empty
152     }
153 
assertStaticConfigurationFails(String config)154     private void assertStaticConfigurationFails(String config) {
155         try {
156             EthernetTracker.parseStaticIpConfiguration(config);
157             fail("Expected to fail: " + config);
158         } catch (IllegalArgumentException e) {
159             // expected
160         }
161     }
162 
assertStaticConfiguration(StaticIpConfiguration expectedStaticIpConfig, String configAsString)163     private void assertStaticConfiguration(StaticIpConfiguration expectedStaticIpConfig,
164                 String configAsString) {
165         final IpConfiguration expectedIpConfiguration = new IpConfiguration();
166         expectedIpConfiguration.setIpAssignment(IpAssignment.STATIC);
167         expectedIpConfiguration.setProxySettings(ProxySettings.NONE);
168         expectedIpConfiguration.setStaticIpConfiguration(expectedStaticIpConfig);
169 
170         assertEquals(expectedIpConfiguration,
171                 EthernetTracker.parseStaticIpConfiguration(configAsString));
172     }
173 
makeEthernetCapabilitiesBuilder(boolean clearDefaults)174     private NetworkCapabilities.Builder makeEthernetCapabilitiesBuilder(boolean clearDefaults) {
175         final NetworkCapabilities.Builder builder =
176                 clearDefaults
177                         ? NetworkCapabilities.Builder.withoutDefaultCapabilities()
178                         : new NetworkCapabilities.Builder();
179         return builder.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING)
180                 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED)
181                 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED);
182     }
183 
184 
185     @Test
testNetworkCapabilityParsing()186     public void testNetworkCapabilityParsing() {
187         final NetworkCapabilities baseNc = NetworkCapabilities.Builder.withoutDefaultCapabilities()
188                 .addTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
189                 .setLinkUpstreamBandwidthKbps(100 * 1000 /* 100 Mbps */)
190                 .setLinkDownstreamBandwidthKbps(100 * 1000 /* 100 Mbps */)
191                 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING)
192                 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED)
193                 .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED)
194                 .build();
195 
196         // Empty capabilities always default to the baseNc above.
197         EthernetConfigParser p = new EthernetConfigParser("eth0;", false /*isAtLeastB*/);
198         assertThat(p.mCaps).isEqualTo(baseNc);
199         p = new EthernetConfigParser("eth0;", true /*isAtLeastB*/);
200         assertThat(p.mCaps).isEqualTo(baseNc);
201 
202         // On Android B+, "*" defaults to using DEFAULT_CAPABILITIES.
203         p = new EthernetConfigParser("eth0;*;;;;;;", true /*isAtLeastB*/);
204         assertThat(p.mCaps).isEqualTo(DEFAULT_CAPABILITIES);
205 
206         // But not so before B.
207         p = new EthernetConfigParser("eth0;*", false /*isAtLeastB*/);
208         assertThat(p.mCaps).isEqualTo(baseNc);
209 
210         p = new EthernetConfigParser("eth0;12,13,14,15;", false /*isAtLeastB*/);
211         assertThat(p.mCaps.getCapabilities()).asList().containsAtLeast(12, 13, 14, 15);
212 
213         p = new EthernetConfigParser("eth0;12,13,500,abc", false /*isAtLeastB*/);
214         // 18, 20, 21 are added by EthernetConfigParser.
215         assertThat(p.mCaps.getCapabilities()).asList().containsExactly(12, 13, 18, 20, 21);
216 
217         p = new EthernetConfigParser("eth0;1,2,3;;0", false /*isAtLeastB*/);
218         assertThat(p.mCaps.getCapabilities()).asList().containsAtLeast(1, 2, 3);
219         assertThat(p.mCaps.hasSingleTransport(NetworkCapabilities.TRANSPORT_CELLULAR)).isTrue();
220 
221         // TRANSPORT_VPN (4) is not allowed.
222         p = new EthernetConfigParser("eth0;;;4", false /*isAtLeastB*/);
223         assertThat(p.mCaps.hasSingleTransport(NetworkCapabilities.TRANSPORT_ETHERNET)).isTrue();
224         p = new EthernetConfigParser("eth0;*;;4", true /*isAtLeastB*/);
225         assertThat(p.mCaps.hasSingleTransport(NetworkCapabilities.TRANSPORT_ETHERNET)).isTrue();
226 
227         // invalid capability and transport type
228         p = new EthernetConfigParser("eth0;-1,a,1000,,;;-1", false /*isAtLeastB*/);
229         assertThat(p.mCaps).isEqualTo(baseNc);
230 
231         p = new EthernetConfigParser("eth0;*;;0", false /*isAtLeastB*/);
232         assertThat(p.mCaps.hasSingleTransport(NetworkCapabilities.TRANSPORT_CELLULAR)).isTrue();
233         p = new EthernetConfigParser("eth0;*;;0", true /*isAtLeastB*/);
234         assertThat(p.mCaps.hasSingleTransport(NetworkCapabilities.TRANSPORT_CELLULAR)).isTrue();
235 
236         NetworkCapabilities nc = new NetworkCapabilities.Builder(DEFAULT_CAPABILITIES)
237                 .removeTransportType(NetworkCapabilities.TRANSPORT_ETHERNET)
238                 .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
239                 .build();
240         p = new EthernetConfigParser("eth0;*;;0", true /*isAtLeastB*/);
241         assertThat(p.mCaps).isEqualTo(nc);
242     }
243 
244     @Test
testInterfaceNameParsing()245     public void testInterfaceNameParsing() {
246         EthernetConfigParser p = new EthernetConfigParser("eth12", false /*isAtLeastB*/);
247         assertThat(p.mIface).isEqualTo("eth12");
248 
249         p = new EthernetConfigParser("", true /*isAtLeastB*/);
250         assertThat(p.mIface).isEqualTo("");
251 
252         p = new EthernetConfigParser("eth0;12;", true /*isAtLeastB*/);
253         assertThat(p.mIface).isEqualTo("eth0");
254     }
255 
256     @Test
testIpConfigParsing()257     public void testIpConfigParsing() {
258         // Note that EthernetConfigParser doesn't actually parse the IpConfig (yet).
259         final EthernetConfigParser p = new EthernetConfigParser(
260                 "eth0;1,2,3;ip=192.168.0.10/24 gateway=192.168.0.1 dns=4.4.4.4,8.8.8.8;1",
261                 false /*isAtLeastB*/);
262         assertThat(p.mIpConfig)
263                 .isEqualTo("ip=192.168.0.10/24 gateway=192.168.0.1 dns=4.4.4.4,8.8.8.8");
264     }
265 
266     @Test
testCreateEthernetConfigParserThrowsNpeWithNullInput()267     public void testCreateEthernetConfigParserThrowsNpeWithNullInput() {
268         assertThrows(NullPointerException.class, () -> new EthernetConfigParser(null, false));
269     }
270 
271     @Test
testUpdateConfiguration()272     public void testUpdateConfiguration() {
273         final NetworkCapabilities capabilities = new NetworkCapabilities.Builder().build();
274         final LinkAddress linkAddr = new LinkAddress("192.0.2.2/25");
275         final StaticIpConfiguration staticIpConfig =
276                 new StaticIpConfiguration.Builder().setIpAddress(linkAddr).build();
277         final IpConfiguration ipConfig =
278                 new IpConfiguration.Builder().setStaticIpConfiguration(staticIpConfig).build();
279         final EthernetCallback listener = new EthernetCallback(null);
280 
281         tracker.updateConfiguration(TEST_IFACE, ipConfig, capabilities, listener);
282         waitForIdle();
283 
284         verify(mFactory).updateInterface(
285                 eq(TEST_IFACE), eq(ipConfig), eq(capabilities));
286     }
287 
288     @Test
testIsValidTestInterfaceIsFalseWhenTestInterfacesAreNotIncluded()289     public void testIsValidTestInterfaceIsFalseWhenTestInterfacesAreNotIncluded() {
290         final String validIfaceName = TEST_TAP_PREFIX + "123";
291         tracker.setIncludeTestInterfaces(false);
292         waitForIdle();
293 
294         final boolean isValidTestInterface = tracker.isValidTestInterface(validIfaceName);
295 
296         assertFalse(isValidTestInterface);
297     }
298 
299     @Test
testIsValidTestInterfaceIsFalseWhenTestInterfaceNameIsInvalid()300     public void testIsValidTestInterfaceIsFalseWhenTestInterfaceNameIsInvalid() {
301         final String invalidIfaceName = "123" + TEST_TAP_PREFIX;
302         tracker.setIncludeTestInterfaces(true);
303         waitForIdle();
304 
305         final boolean isValidTestInterface = tracker.isValidTestInterface(invalidIfaceName);
306 
307         assertFalse(isValidTestInterface);
308     }
309 
310     @Test
testIsValidTestInterfaceIsTrueWhenTestInterfacesIncludedAndValidName()311     public void testIsValidTestInterfaceIsTrueWhenTestInterfacesIncludedAndValidName() {
312         final String validIfaceName = TEST_TAP_PREFIX + "123";
313         tracker.setIncludeTestInterfaces(true);
314         waitForIdle();
315 
316         final boolean isValidTestInterface = tracker.isValidTestInterface(validIfaceName);
317 
318         assertTrue(isValidTestInterface);
319     }
320 }
321