PasspointConfigStoreDataTest.java revision 8f4f48b96b690aa099f85aad7a361cf39e431f42
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
17package com.android.server.wifi.hotspot2;
18
19import static org.junit.Assert.*;
20import static org.mockito.Mockito.*;
21
22import android.net.wifi.hotspot2.PasspointConfiguration;
23import android.net.wifi.hotspot2.pps.Credential;
24import android.net.wifi.hotspot2.pps.HomeSp;
25import android.net.wifi.hotspot2.pps.Policy;
26import android.net.wifi.hotspot2.pps.UpdateParameter;
27import android.test.suitebuilder.annotation.SmallTest;
28import android.util.Xml;
29
30import com.android.internal.util.FastXmlSerializer;
31import com.android.server.wifi.SIMAccessor;
32import com.android.server.wifi.WifiKeyStore;
33
34import org.junit.Before;
35import org.junit.Test;
36import org.mockito.ArgumentCaptor;
37import org.mockito.Mock;
38import org.mockito.MockitoAnnotations;
39import org.xmlpull.v1.XmlPullParser;
40import org.xmlpull.v1.XmlSerializer;
41
42import java.io.ByteArrayInputStream;
43import java.io.ByteArrayOutputStream;
44import java.nio.charset.StandardCharsets;
45import java.text.DateFormat;
46import java.text.SimpleDateFormat;
47import java.util.ArrayList;
48import java.util.Arrays;
49import java.util.HashMap;
50import java.util.List;
51import java.util.Map;
52
53/**
54 * Unit tests for {@link com.android.server.wifi.hotspot2.PasspointConfigStoreData}.
55 */
56@SmallTest
57public class PasspointConfigStoreDataTest {
58    private static final String TEST_CA_CERTIFICATE_ALIAS = "CaCert";
59    private static final String TEST_CLIENT_CERTIFICATE_ALIAS = "ClientCert";
60    private static final String TEST_CLIENT_PRIVATE_KEY_ALIAS = "ClientPrivateKey";
61    private static final long TEST_PROVIDER_ID = 1;
62    private static final int TEST_CREATOR_UID = 1234;
63
64    @Mock WifiKeyStore mKeyStore;
65    @Mock SIMAccessor mSimAccessor;
66    @Mock PasspointConfigStoreData.DataSource mDataSource;
67    PasspointConfigStoreData mConfigStoreData;
68
69    /** Sets up test. */
70    @Before
71    public void setUp() throws Exception {
72        MockitoAnnotations.initMocks(this);
73        mConfigStoreData = new PasspointConfigStoreData(mKeyStore, mSimAccessor, mDataSource);
74    }
75
76    /**
77     * Helper function for generating a {@link PasspointConfiguration} for testing the XML
78     * serialization/deserialization logic.
79     *
80     * @return {@link PasspointConfiguration}
81     * @throws Exception
82     */
83    private PasspointConfiguration createFullPasspointConfiguration() throws Exception {
84        DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
85        byte[] certFingerprint = new byte[32];
86        Arrays.fill(certFingerprint, (byte) 0x1f);
87
88        PasspointConfiguration config = new PasspointConfiguration();
89        config.setUpdateIdentifier(12);
90        config.setCredentialPriority(99);
91
92        // AAA Server trust root.
93        Map<String, byte[]> trustRootCertList = new HashMap<>();
94        trustRootCertList.put("server1.trust.root.com", certFingerprint);
95        config.setTrustRootCertList(trustRootCertList);
96
97        // Subscription update.
98        UpdateParameter subscriptionUpdate = new UpdateParameter();
99        subscriptionUpdate.setUpdateIntervalInMinutes(120);
100        subscriptionUpdate.setUpdateMethod(UpdateParameter.UPDATE_METHOD_SSP);
101        subscriptionUpdate.setRestriction(UpdateParameter.UPDATE_RESTRICTION_ROAMING_PARTNER);
102        subscriptionUpdate.setServerUri("subscription.update.com");
103        subscriptionUpdate.setUsername("subscriptionUser");
104        subscriptionUpdate.setBase64EncodedPassword("subscriptionPass");
105        subscriptionUpdate.setTrustRootCertUrl("subscription.update.cert.com");
106        subscriptionUpdate.setTrustRootCertSha256Fingerprint(certFingerprint);
107        config.setSubscriptionUpdate(subscriptionUpdate);
108
109        // Subscription parameters.
110        config.setSubscriptionCreationTimeInMillis(format.parse("2016-02-01T10:00:00Z").getTime());
111        config.setSubscriptionExpirationTimeInMillis(
112                format.parse("2016-03-01T10:00:00Z").getTime());
113        config.setSubscriptionType("Gold");
114        config.setUsageLimitDataLimit(921890);
115        config.setUsageLimitStartTimeInMillis(format.parse("2016-12-01T10:00:00Z").getTime());
116        config.setUsageLimitTimeLimitInMinutes(120);
117        config.setUsageLimitUsageTimePeriodInMinutes(99910);
118
119        // HomeSP configuration.
120        HomeSp homeSp = new HomeSp();
121        homeSp.setFriendlyName("Century House");
122        homeSp.setFqdn("mi6.co.uk");
123        homeSp.setRoamingConsortiumOis(new long[] {0x112233L, 0x445566L});
124        homeSp.setIconUrl("icon.test.com");
125        Map<String, Long> homeNetworkIds = new HashMap<>();
126        homeNetworkIds.put("TestSSID", 0x12345678L);
127        homeNetworkIds.put("NullHESSID", null);
128        homeSp.setHomeNetworkIds(homeNetworkIds);
129        homeSp.setMatchAllOis(new long[] {0x11223344});
130        homeSp.setMatchAnyOis(new long[] {0x55667788});
131        homeSp.setOtherHomePartners(new String[] {"other.fqdn.com"});
132        config.setHomeSp(homeSp);
133
134        // Credential configuration.
135        Credential credential = new Credential();
136        credential.setCreationTimeInMillis(format.parse("2016-01-01T10:00:00Z").getTime());
137        credential.setExpirationTimeInMillis(format.parse("2016-02-01T10:00:00Z").getTime());
138        credential.setRealm("shaken.stirred.com");
139        credential.setCheckAaaServerCertStatus(true);
140        Credential.UserCredential userCredential = new Credential.UserCredential();
141        userCredential.setUsername("james");
142        userCredential.setPassword("Ym9uZDAwNw==");
143        userCredential.setMachineManaged(true);
144        userCredential.setSoftTokenApp("TestApp");
145        userCredential.setAbleToShare(true);
146        userCredential.setEapType(21);
147        userCredential.setNonEapInnerMethod("MS-CHAP-V2");
148        credential.setUserCredential(userCredential);
149        Credential.CertificateCredential certCredential = new Credential.CertificateCredential();
150        certCredential.setCertType("x509v3");
151        certCredential.setCertSha256Fingerprint(certFingerprint);
152        credential.setCertCredential(certCredential);
153        Credential.SimCredential simCredential = new Credential.SimCredential();
154        simCredential.setImsi("imsi");
155        simCredential.setEapType(24);
156        credential.setSimCredential(simCredential);
157        config.setCredential(credential);
158
159        // Policy configuration.
160        Policy policy = new Policy();
161        List<Policy.RoamingPartner> preferredRoamingPartnerList = new ArrayList<>();
162        Policy.RoamingPartner partner1 = new Policy.RoamingPartner();
163        partner1.setFqdn("test1.fqdn.com");
164        partner1.setFqdnExactMatch(true);
165        partner1.setPriority(127);
166        partner1.setCountries("us,fr");
167        Policy.RoamingPartner partner2 = new Policy.RoamingPartner();
168        partner2.setFqdn("test2.fqdn.com");
169        partner2.setFqdnExactMatch(false);
170        partner2.setPriority(200);
171        partner2.setCountries("*");
172        preferredRoamingPartnerList.add(partner1);
173        preferredRoamingPartnerList.add(partner2);
174        policy.setPreferredRoamingPartnerList(preferredRoamingPartnerList);
175        policy.setMinHomeDownlinkBandwidth(23412);
176        policy.setMinHomeUplinkBandwidth(9823);
177        policy.setMinRoamingDownlinkBandwidth(9271);
178        policy.setMinRoamingUplinkBandwidth(2315);
179        policy.setExcludedSsidList(new String[] {"excludeSSID"});
180        Map<Integer, String> requiredProtoPortMap = new HashMap<>();
181        requiredProtoPortMap.put(12, "34,92,234");
182        policy.setRequiredProtoPortMap(requiredProtoPortMap);
183        policy.setMaximumBssLoadValue(23);
184        UpdateParameter policyUpdate = new UpdateParameter();
185        policyUpdate.setUpdateIntervalInMinutes(120);
186        policyUpdate.setUpdateMethod(UpdateParameter.UPDATE_METHOD_OMADM);
187        policyUpdate.setRestriction(UpdateParameter.UPDATE_RESTRICTION_HOMESP);
188        policyUpdate.setServerUri("policy.update.com");
189        policyUpdate.setUsername("updateUser");
190        policyUpdate.setBase64EncodedPassword("updatePass");
191        policyUpdate.setTrustRootCertUrl("update.cert.com");
192        policyUpdate.setTrustRootCertSha256Fingerprint(certFingerprint);
193        policy.setPolicyUpdate(policyUpdate);
194        config.setPolicy(policy);
195        return config;
196    }
197
198    /**
199     * Helper function for serializing store data to a XML block.
200     *
201     * @param share Flag indicating share or user data
202     * @return byte[]
203     * @throws Exception
204     */
205    private byte[] serializeData(boolean share) throws Exception {
206        final XmlSerializer out = new FastXmlSerializer();
207        final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
208        out.setOutput(outputStream, StandardCharsets.UTF_8.name());
209        mConfigStoreData.serializeData(out, share);
210        out.flush();
211        return outputStream.toByteArray();
212    }
213
214    /**
215     * Helper function for deserializing store data from a XML block.
216     *
217     * @param data The XML block data bytes
218     * @param share Flag indicating share or user data
219     * @throws Exception
220     */
221    private void deserializeData(byte[] data, boolean share) throws Exception {
222        final XmlPullParser in = Xml.newPullParser();
223        final ByteArrayInputStream inputStream = new ByteArrayInputStream(data);
224        in.setInput(inputStream, StandardCharsets.UTF_8.name());
225        mConfigStoreData.deserializeData(in, in.getDepth(), share);
226    }
227
228    /**
229     * Verify that the serialization and deserialization of user store data works as expected.
230     * The data used for serialization matches the result of the deserialization.
231     *
232     * @throws Exception
233     */
234    @Test
235    public void serializeAndDeserializeUserStoreData() throws Exception {
236        // Setup expected data.
237        List<PasspointProvider> providerList = new ArrayList<>();
238        providerList.add(new PasspointProvider(createFullPasspointConfiguration(),
239                mKeyStore, mSimAccessor, TEST_PROVIDER_ID, TEST_CREATOR_UID,
240                TEST_CA_CERTIFICATE_ALIAS, TEST_CLIENT_CERTIFICATE_ALIAS,
241                TEST_CLIENT_PRIVATE_KEY_ALIAS));
242
243        // Serialize data for user store.
244        when(mDataSource.getProviders()).thenReturn(providerList);
245        byte[] data = serializeData(false);
246
247        // Deserialize data for user store and verify the content.
248        ArgumentCaptor<ArrayList> providersCaptor = ArgumentCaptor.forClass(ArrayList.class);
249        deserializeData(data, false);
250        verify(mDataSource).setProviders(providersCaptor.capture());
251        assertEquals(providerList, providersCaptor.getValue());
252    }
253
254    /**
255     * Verify that the serialization and deserialization of share store data works as expected.
256     * The data used for serialization matches the result of the deserialization.
257     *
258     * @throws Exception
259     */
260    @Test
261    public void serializeAndDeserializeShareStoreData() throws Exception {
262        // Setup expected data.
263        long providerIndex = 412;
264
265        // Serialize data for share store.
266        when(mDataSource.getProviderIndex()).thenReturn(providerIndex);
267        byte[] data = serializeData(true);
268
269        // Deserialize data for share store and verify the content.
270        deserializeData(data, true);
271        verify(mDataSource).setProviderIndex(providerIndex);
272    }
273
274    /**
275     * Verify that deserialization of an empty user store data doesn't cause any exception and
276     * the corresponding data source should not be updated.
277     *
278     * @throws Exception
279     */
280    @Test
281    public void deserializeEmptyUserStoreData() throws Exception {
282        deserializeData(new byte[0], false);
283        verify(mDataSource, never()).setProviders(any(ArrayList.class));
284    }
285
286    /**
287     * Verify that deserialization of an empty share store data doesn't cause any exception
288     * and the corresponding data source should not be updated.
289     *
290     * @throws Exception
291     */
292    @Test
293    public void deserializeEmptyShareStoreData() throws Exception {
294        deserializeData(new byte[0], true);
295        verify(mDataSource, never()).setProviderIndex(anyLong());
296    }
297}
298