1 /*
2  * Copyright (C) 2019 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.shared;
18 
19 import static android.net.InetAddresses.parseNumericAddress;
20 import static android.net.shared.ProvisioningConfiguration.fromStableParcelable;
21 
22 import static com.android.testutils.MiscAsserts.assertFieldCountEquals;
23 
24 import static org.junit.Assert.assertEquals;
25 import static org.junit.Assert.assertNotEquals;
26 
27 import android.net.LinkAddress;
28 import android.net.MacAddress;
29 import android.net.Network;
30 import android.net.ProvisioningConfigurationParcelable;
31 import android.net.StaticIpConfiguration;
32 import android.net.apf.ApfCapabilities;
33 import android.net.networkstack.aidl.dhcp.DhcpOption;
34 import android.net.shared.ProvisioningConfiguration.ScanResultInfo;
35 
36 import androidx.test.filters.SmallTest;
37 import androidx.test.runner.AndroidJUnit4;
38 
39 import org.junit.Before;
40 import org.junit.Test;
41 import org.junit.runner.RunWith;
42 
43 import java.nio.ByteBuffer;
44 import java.util.ArrayList;
45 import java.util.Collections;
46 import java.util.List;
47 import java.util.function.Consumer;
48 
49 /**
50  * Tests for {@link ProvisioningConfiguration}.
51  */
52 @RunWith(AndroidJUnit4.class)
53 @SmallTest
54 public class ProvisioningConfigurationTest {
55     private ProvisioningConfiguration mConfig;
56 
makeScanResultInfo(final String ssid)57     private ScanResultInfo makeScanResultInfo(final String ssid) {
58         final byte[] payload = new byte[] {
59             (byte) 0x00, (byte) 0x17, (byte) 0xF2, (byte) 0x06, (byte) 0x01,
60             (byte) 0x01, (byte) 0x03, (byte) 0x01, (byte) 0x00, (byte) 0x00,
61         };
62         final ScanResultInfo.InformationElement ie =
63                 new ScanResultInfo.InformationElement(0xdd /* vendor specific IE id */,
64                         ByteBuffer.wrap(payload));
65         return new ScanResultInfo(ssid, "01:02:03:04:05:06" /* bssid string */,
66                 Collections.singletonList(ie));
67     }
68 
makeCustomizedDhcpOptions(byte type, final byte[] value)69     private List<DhcpOption> makeCustomizedDhcpOptions(byte type, final byte[] value) {
70         final DhcpOption option = new DhcpOption();
71         option.type = type;
72         option.value = value;
73 
74         final List<DhcpOption> options = new ArrayList<DhcpOption>();
75         options.add(option);
76         return options;
77     }
78 
79     @Before
setUp()80     public void setUp() {
81         mConfig = new ProvisioningConfiguration();
82         mConfig.mEnableIPv4 = true;
83         mConfig.mEnableIPv6 = true;
84         mConfig.mUsingMultinetworkPolicyTracker = true;
85         mConfig.mUsingIpReachabilityMonitor = true;
86         mConfig.mRequestedPreDhcpActionMs = 42;
87         mConfig.mInitialConfig = new InitialConfiguration();
88         mConfig.mInitialConfig.ipAddresses.add(
89                 new LinkAddress(parseNumericAddress("192.168.42.42"), 24));
90         mConfig.mStaticIpConfig = new StaticIpConfiguration();
91         mConfig.mStaticIpConfig.ipAddress =
92                 new LinkAddress(parseNumericAddress("2001:db8::42"), 90);
93         // Not testing other InitialConfig or StaticIpConfig members: they have their own unit tests
94         mConfig.mApfCapabilities = new ApfCapabilities(1, 2, 3);
95         mConfig.mProvisioningTimeoutMs = 4200;
96         mConfig.mIPv6AddrGenMode = 123;
97         mConfig.mNetwork = new Network(321);
98         mConfig.mDisplayName = "test_config";
99         mConfig.mEnablePreconnection = false;
100         mConfig.mScanResultInfo = makeScanResultInfo("ssid");
101         mConfig.mLayer2Info = new Layer2Information("some l2key", "some cluster",
102                 MacAddress.fromString("00:01:02:03:04:05"));
103         mConfig.mDhcpOptions = makeCustomizedDhcpOptions((byte) 60,
104                 new String("android-dhcp-11").getBytes());
105         // Any added field must be included in equals() to be tested properly
106         assertFieldCountEquals(16, ProvisioningConfiguration.class);
107     }
108 
109     @Test
testParcelUnparcel()110     public void testParcelUnparcel() {
111         doParcelUnparcelTest();
112     }
113 
114     @Test
testParcelUnparcel_NullInitialConfiguration()115     public void testParcelUnparcel_NullInitialConfiguration() {
116         mConfig.mInitialConfig = null;
117         doParcelUnparcelTest();
118     }
119 
120     @Test
testParcelUnparcel_NullStaticConfiguration()121     public void testParcelUnparcel_NullStaticConfiguration() {
122         mConfig.mStaticIpConfig = null;
123         doParcelUnparcelTest();
124     }
125 
126     @Test
testParcelUnparcel_NullApfCapabilities()127     public void testParcelUnparcel_NullApfCapabilities() {
128         mConfig.mApfCapabilities = null;
129         doParcelUnparcelTest();
130     }
131 
132     @Test
testParcelUnparcel_NullNetwork()133     public void testParcelUnparcel_NullNetwork() {
134         mConfig.mNetwork = null;
135         doParcelUnparcelTest();
136     }
137 
138     @Test
testParcelUnparcel_NullScanResultInfo()139     public void testParcelUnparcel_NullScanResultInfo() {
140         mConfig.mScanResultInfo = null;
141         doParcelUnparcelTest();
142     }
143 
144     @Test
testParcelUnparcel_NullCustomizedDhcpOptions()145     public void testParcelUnparcel_NullCustomizedDhcpOptions() {
146         mConfig.mDhcpOptions = null;
147         doParcelUnparcelTest();
148     }
149 
150     @Test
testParcelUnparcel_WithPreDhcpConnection()151     public void testParcelUnparcel_WithPreDhcpConnection() {
152         mConfig.mEnablePreconnection = true;
153         doParcelUnparcelTest();
154     }
155 
doParcelUnparcelTest()156     private void doParcelUnparcelTest() {
157         final ProvisioningConfiguration unparceled =
158                 fromStableParcelable(mConfig.toStableParcelable());
159         assertEquals(mConfig, unparceled);
160     }
161 
162     @Test
testEquals()163     public void testEquals() {
164         assertEquals(mConfig, new ProvisioningConfiguration(mConfig));
165 
166         assertNotEqualsAfterChange(c -> c.mEnableIPv4 = false);
167         assertNotEqualsAfterChange(c -> c.mEnableIPv6 = false);
168         assertNotEqualsAfterChange(c -> c.mUsingMultinetworkPolicyTracker = false);
169         assertNotEqualsAfterChange(c -> c.mUsingIpReachabilityMonitor = false);
170         assertNotEqualsAfterChange(c -> c.mRequestedPreDhcpActionMs++);
171         assertNotEqualsAfterChange(c -> c.mInitialConfig.ipAddresses.add(
172                 new LinkAddress(parseNumericAddress("192.168.47.47"), 16)));
173         assertNotEqualsAfterChange(c -> c.mInitialConfig = null);
174         assertNotEqualsAfterChange(c -> c.mStaticIpConfig.ipAddress =
175                 new LinkAddress(parseNumericAddress("2001:db8::47"), 64));
176         assertNotEqualsAfterChange(c -> c.mStaticIpConfig = null);
177         assertNotEqualsAfterChange(c -> c.mApfCapabilities = new ApfCapabilities(4, 5, 6));
178         assertNotEqualsAfterChange(c -> c.mApfCapabilities = null);
179         assertNotEqualsAfterChange(c -> c.mProvisioningTimeoutMs++);
180         assertNotEqualsAfterChange(c -> c.mIPv6AddrGenMode++);
181         assertNotEqualsAfterChange(c -> c.mNetwork = new Network(123));
182         assertNotEqualsAfterChange(c -> c.mNetwork = null);
183         assertNotEqualsAfterChange(c -> c.mDisplayName = "other_test");
184         assertNotEqualsAfterChange(c -> c.mDisplayName = null);
185         assertNotEqualsAfterChange(c -> c.mEnablePreconnection = true);
186         assertNotEqualsAfterChange(c -> c.mScanResultInfo = null);
187         assertNotEqualsAfterChange(c -> c.mScanResultInfo = makeScanResultInfo("another ssid"));
188         assertNotEqualsAfterChange(c -> c.mLayer2Info = new Layer2Information("another l2key",
189                 "some cluster", MacAddress.fromString("00:01:02:03:04:05")));
190         assertNotEqualsAfterChange(c -> c.mLayer2Info = new Layer2Information("some l2key",
191                 "another cluster", MacAddress.fromString("00:01:02:03:04:05")));
192         assertNotEqualsAfterChange(c -> c.mLayer2Info = new Layer2Information("some l2key",
193                 "some cluster", MacAddress.fromString("01:02:03:04:05:06")));
194         assertNotEqualsAfterChange(c -> c.mLayer2Info = null);
195         assertNotEqualsAfterChange(c -> c.mDhcpOptions = new ArrayList<DhcpOption>());
196         assertNotEqualsAfterChange(c -> c.mDhcpOptions = null);
197         assertNotEqualsAfterChange(c -> c.mDhcpOptions = makeCustomizedDhcpOptions((byte) 60,
198                   new String("vendor-class-identifier").getBytes()));
199         assertNotEqualsAfterChange(c -> c.mDhcpOptions = makeCustomizedDhcpOptions((byte) 77,
200                   new String("vendor-class-identifier").getBytes()));
201         assertFieldCountEquals(16, ProvisioningConfiguration.class);
202     }
203 
assertNotEqualsAfterChange(Consumer<ProvisioningConfiguration> mutator)204     private void assertNotEqualsAfterChange(Consumer<ProvisioningConfiguration> mutator) {
205         final ProvisioningConfiguration newConfig = new ProvisioningConfiguration(mConfig);
206         mutator.accept(newConfig);
207         assertNotEquals(mConfig, newConfig);
208     }
209 
210     private static final String TEMPLATE = ""
211             + "android.net.ProvisioningConfigurationParcelable{enableIPv4: true, enableIPv6: true,"
212             + " usingMultinetworkPolicyTracker: true,"
213             + " usingIpReachabilityMonitor: true, requestedPreDhcpActionMs: 42,"
214             + " initialConfig: android.net.InitialConfigurationParcelable{ipAddresses:"
215             + " [192.168.42.42/24], directlyConnectedRoutes: [], dnsServers: [], gateway: null},"
216             + " staticIpConfig: IP address 2001:db8::42/90 Gateway  DNS servers: [ ] Domains ,"
217             + " apfCapabilities: ApfCapabilities{version: 1, maxSize: 2, format: 3},"
218             + " provisioningTimeoutMs: 4200, ipv6AddrGenMode: 123, network: 321,"
219             + " displayName: test_config, enablePreconnection: false, scanResultInfo:"
220             + " android.net.ScanResultInfoParcelable{ssid: ssid, bssid: 01:02:03:04:05:06,"
221             + " informationElements: [android.net.InformationElementParcelable{id: 221,"
222             + " payload: [0, 23, -14, 6, 1, 1, 3, 1, 0, 0]}]}, layer2Info:"
223             + " android.net.Layer2InformationParcelable{l2Key: some l2key,"
224             + " cluster: some cluster, bssid: %s},"
225             + " options: [android.net.networkstack.aidl.dhcp.DhcpOption{type: 60,"
226             + " value: [97, 110, 100, 114, 111, 105, 100, 45, 100, 104, 99, 112, 45, 49, 49]}]}";
227 
228     @Test
testParcelableToString()229     public void testParcelableToString() {
230         String expected = String.format(TEMPLATE, "00:01:02:03:04:05");
231         assertEquals(expected, mConfig.toStableParcelable().toString());
232 
233         final ProvisioningConfigurationParcelable parcelWithNull = mConfig.toStableParcelable();
234         parcelWithNull.layer2Info.bssid = null;
235         expected = String.format(TEMPLATE, "null");
236         assertEquals(expected, parcelWithNull.toString());
237     }
238 }
239