1/* 2 * Copyright (C) 2016 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 android.net.wifi.hotspot2.omadm; 18 19import static org.junit.Assert.assertEquals; 20import static org.junit.Assert.assertTrue; 21 22import android.net.wifi.hotspot2.omadm.PpsMoParser; 23import android.net.wifi.hotspot2.PasspointConfiguration; 24import android.net.wifi.hotspot2.pps.Credential; 25import android.net.wifi.hotspot2.pps.HomeSp; 26import android.net.wifi.hotspot2.pps.Policy; 27import android.net.wifi.hotspot2.pps.UpdateParameter; 28import android.support.test.filters.SmallTest; 29import android.text.TextUtils; 30 31import org.junit.Test; 32 33import java.io.BufferedReader; 34import java.io.IOException; 35import java.io.InputStream; 36import java.io.InputStreamReader; 37import java.text.DateFormat; 38import java.text.SimpleDateFormat; 39import java.util.ArrayList; 40import java.util.Arrays; 41import java.util.HashMap; 42import java.util.List; 43import java.util.Map; 44 45/** 46 * Unit tests for {@link android.net.wifi.hotspot2.omadm.PpsMoParser}. 47 */ 48@SmallTest 49public class PpsMoParserTest { 50 private static final String VALID_PPS_MO_XML_FILE = "assets/pps/PerProviderSubscription.xml"; 51 private static final String PPS_MO_XML_FILE_DUPLICATE_HOMESP = 52 "assets/pps/PerProviderSubscription_DuplicateHomeSP.xml"; 53 private static final String PPS_MO_XML_FILE_DUPLICATE_VALUE = 54 "assets/pps/PerProviderSubscription_DuplicateValue.xml"; 55 private static final String PPS_MO_XML_FILE_MISSING_VALUE = 56 "assets/pps/PerProviderSubscription_MissingValue.xml"; 57 private static final String PPS_MO_XML_FILE_MISSING_NAME = 58 "assets/pps/PerProviderSubscription_MissingName.xml"; 59 private static final String PPS_MO_XML_FILE_INVALID_NODE = 60 "assets/pps/PerProviderSubscription_InvalidNode.xml"; 61 private static final String PPS_MO_XML_FILE_INVALID_NAME = 62 "assets/pps/PerProviderSubscription_InvalidName.xml"; 63 64 /** 65 * Read the content of the given resource file into a String. 66 * 67 * @param filename String name of the file 68 * @return String 69 * @throws IOException 70 */ 71 private String loadResourceFile(String filename) throws IOException { 72 InputStream in = getClass().getClassLoader().getResourceAsStream(filename); 73 BufferedReader reader = new BufferedReader(new InputStreamReader(in)); 74 StringBuilder builder = new StringBuilder(); 75 String line; 76 while ((line = reader.readLine()) != null) { 77 builder.append(line).append("\n"); 78 } 79 80 return builder.toString(); 81 } 82 83 /** 84 * Generate a {@link PasspointConfiguration} that matches the configuration specified in the 85 * XML file {@link #VALID_PPS_MO_XML_FILE}. 86 * 87 * @return {@link PasspointConfiguration} 88 */ 89 private PasspointConfiguration generateConfigurationFromPPSMOTree() throws Exception { 90 DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); 91 byte[] certFingerprint = new byte[32]; 92 Arrays.fill(certFingerprint, (byte) 0x1f); 93 94 PasspointConfiguration config = new PasspointConfiguration(); 95 config.setUpdateIdentifier(12); 96 config.setCredentialPriority(99); 97 98 // AAA Server trust root. 99 Map<String, byte[]> trustRootCertList = new HashMap<>(); 100 trustRootCertList.put("server1.trust.root.com", certFingerprint); 101 config.setTrustRootCertList(trustRootCertList); 102 103 // Subscription update. 104 UpdateParameter subscriptionUpdate = new UpdateParameter(); 105 subscriptionUpdate.setUpdateIntervalInMinutes(120); 106 subscriptionUpdate.setUpdateMethod(UpdateParameter.UPDATE_METHOD_SSP); 107 subscriptionUpdate.setRestriction(UpdateParameter.UPDATE_RESTRICTION_ROAMING_PARTNER); 108 subscriptionUpdate.setServerUri("subscription.update.com"); 109 subscriptionUpdate.setUsername("subscriptionUser"); 110 subscriptionUpdate.setBase64EncodedPassword("subscriptionPass"); 111 subscriptionUpdate.setTrustRootCertUrl("subscription.update.cert.com"); 112 subscriptionUpdate.setTrustRootCertSha256Fingerprint(certFingerprint); 113 config.setSubscriptionUpdate(subscriptionUpdate); 114 115 // Subscription parameters. 116 config.setSubscriptionCreationTimeInMillis(format.parse("2016-02-01T10:00:00Z").getTime()); 117 config.setSubscriptionExpirationTimeInMillis(format.parse("2016-03-01T10:00:00Z").getTime()); 118 config.setSubscriptionType("Gold"); 119 config.setUsageLimitDataLimit(921890); 120 config.setUsageLimitStartTimeInMillis(format.parse("2016-12-01T10:00:00Z").getTime()); 121 config.setUsageLimitTimeLimitInMinutes(120); 122 config.setUsageLimitUsageTimePeriodInMinutes(99910); 123 124 // HomeSP configuration. 125 HomeSp homeSp = new HomeSp(); 126 homeSp.setFriendlyName("Century House"); 127 homeSp.setFqdn("mi6.co.uk"); 128 homeSp.setRoamingConsortiumOis(new long[] {0x112233L, 0x445566L}); 129 homeSp.setIconUrl("icon.test.com"); 130 Map<String, Long> homeNetworkIds = new HashMap<>(); 131 homeNetworkIds.put("TestSSID", 0x12345678L); 132 homeNetworkIds.put("NullHESSID", null); 133 homeSp.setHomeNetworkIds(homeNetworkIds); 134 homeSp.setMatchAllOis(new long[] {0x11223344}); 135 homeSp.setMatchAnyOis(new long[] {0x55667788}); 136 homeSp.setOtherHomePartners(new String[] {"other.fqdn.com"}); 137 config.setHomeSp(homeSp); 138 139 // Credential configuration. 140 Credential credential = new Credential(); 141 credential.setCreationTimeInMillis(format.parse("2016-01-01T10:00:00Z").getTime()); 142 credential.setExpirationTimeInMillis(format.parse("2016-02-01T10:00:00Z").getTime()); 143 credential.setRealm("shaken.stirred.com"); 144 credential.setCheckAaaServerCertStatus(true); 145 Credential.UserCredential userCredential = new Credential.UserCredential(); 146 userCredential.setUsername("james"); 147 userCredential.setPassword("Ym9uZDAwNw=="); 148 userCredential.setMachineManaged(true); 149 userCredential.setSoftTokenApp("TestApp"); 150 userCredential.setAbleToShare(true); 151 userCredential.setEapType(21); 152 userCredential.setNonEapInnerMethod("MS-CHAP-V2"); 153 credential.setUserCredential(userCredential); 154 Credential.CertificateCredential certCredential = new Credential.CertificateCredential(); 155 certCredential.setCertType("x509v3"); 156 certCredential.setCertSha256Fingerprint(certFingerprint); 157 credential.setCertCredential(certCredential); 158 Credential.SimCredential simCredential = new Credential.SimCredential(); 159 simCredential.setImsi("imsi"); 160 simCredential.setEapType(24); 161 credential.setSimCredential(simCredential); 162 config.setCredential(credential); 163 164 // Policy configuration. 165 Policy policy = new Policy(); 166 List<Policy.RoamingPartner> preferredRoamingPartnerList = new ArrayList<>(); 167 Policy.RoamingPartner partner1 = new Policy.RoamingPartner(); 168 partner1.setFqdn("test1.fqdn.com"); 169 partner1.setFqdnExactMatch(true); 170 partner1.setPriority(127); 171 partner1.setCountries("us,fr"); 172 Policy.RoamingPartner partner2 = new Policy.RoamingPartner(); 173 partner2.setFqdn("test2.fqdn.com"); 174 partner2.setFqdnExactMatch(false); 175 partner2.setPriority(200); 176 partner2.setCountries("*"); 177 preferredRoamingPartnerList.add(partner1); 178 preferredRoamingPartnerList.add(partner2); 179 policy.setPreferredRoamingPartnerList(preferredRoamingPartnerList); 180 policy.setMinHomeDownlinkBandwidth(23412); 181 policy.setMinHomeUplinkBandwidth(9823); 182 policy.setMinRoamingDownlinkBandwidth(9271); 183 policy.setMinRoamingUplinkBandwidth(2315); 184 policy.setExcludedSsidList(new String[] {"excludeSSID"}); 185 Map<Integer, String> requiredProtoPortMap = new HashMap<>(); 186 requiredProtoPortMap.put(12, "34,92,234"); 187 policy.setRequiredProtoPortMap(requiredProtoPortMap); 188 policy.setMaximumBssLoadValue(23); 189 UpdateParameter policyUpdate = new UpdateParameter(); 190 policyUpdate.setUpdateIntervalInMinutes(120); 191 policyUpdate.setUpdateMethod(UpdateParameter.UPDATE_METHOD_OMADM); 192 policyUpdate.setRestriction(UpdateParameter.UPDATE_RESTRICTION_HOMESP); 193 policyUpdate.setServerUri("policy.update.com"); 194 policyUpdate.setUsername("updateUser"); 195 policyUpdate.setBase64EncodedPassword("updatePass"); 196 policyUpdate.setTrustRootCertUrl("update.cert.com"); 197 policyUpdate.setTrustRootCertSha256Fingerprint(certFingerprint); 198 policy.setPolicyUpdate(policyUpdate); 199 config.setPolicy(policy); 200 return config; 201 } 202 203 /** 204 * Parse and verify all supported fields under PPS MO tree. 205 * 206 * @throws Exception 207 */ 208 @Test 209 public void parseValidPPSMOTree() throws Exception { 210 String ppsMoTree = loadResourceFile(VALID_PPS_MO_XML_FILE); 211 PasspointConfiguration expectedConfig = generateConfigurationFromPPSMOTree(); 212 PasspointConfiguration actualConfig = PpsMoParser.parseMoText(ppsMoTree); 213 assertTrue(actualConfig.equals(expectedConfig)); 214 } 215 216 @Test 217 public void parseNullPPSMOTree() throws Exception { 218 assertEquals(null, PpsMoParser.parseMoText(null)); 219 } 220 221 @Test 222 public void parseEmptyPPSMOTree() throws Exception { 223 assertEquals(null, PpsMoParser.parseMoText(new String())); 224 } 225 226 @Test 227 public void parsePPSMOTreeWithDuplicateHomeSP() throws Exception { 228 assertEquals(null, PpsMoParser.parseMoText( 229 loadResourceFile(PPS_MO_XML_FILE_DUPLICATE_HOMESP))); 230 } 231 232 @Test 233 public void parsePPSMOTreeWithDuplicateValue() throws Exception { 234 assertEquals(null, PpsMoParser.parseMoText( 235 loadResourceFile(PPS_MO_XML_FILE_DUPLICATE_VALUE))); 236 } 237 238 @Test 239 public void parsePPSMOTreeWithMissingValue() throws Exception { 240 assertEquals(null, PpsMoParser.parseMoText( 241 loadResourceFile(PPS_MO_XML_FILE_MISSING_VALUE))); 242 } 243 244 @Test 245 public void parsePPSMOTreeWithMissingName() throws Exception { 246 assertEquals(null, PpsMoParser.parseMoText( 247 loadResourceFile(PPS_MO_XML_FILE_MISSING_NAME))); 248 } 249 250 @Test 251 public void parsePPSMOTreeWithInvalidNode() throws Exception { 252 assertEquals(null, PpsMoParser.parseMoText( 253 loadResourceFile(PPS_MO_XML_FILE_INVALID_NODE))); 254 } 255 256 @Test 257 public void parsePPSMOTreeWithInvalidName() throws Exception { 258 assertEquals(null, PpsMoParser.parseMoText( 259 loadResourceFile(PPS_MO_XML_FILE_INVALID_NAME))); 260 } 261} 262