1 package com.android.carrierconfig; 2 3 import android.content.Context; 4 import android.content.res.AssetManager; 5 import android.content.res.Resources; 6 import android.os.PersistableBundle; 7 import android.service.carrier.CarrierIdentifier; 8 import android.telephony.CarrierConfigManager; 9 import android.test.InstrumentationTestCase; 10 import android.util.Log; 11 12 import java.io.IOException; 13 import java.io.InputStream; 14 import java.lang.reflect.Field; 15 import java.lang.reflect.Modifier; 16 import java.util.HashSet; 17 import java.util.Set; 18 19 import junit.framework.AssertionFailedError; 20 21 import org.xmlpull.v1.XmlPullParser; 22 import org.xmlpull.v1.XmlPullParserException; 23 import org.xmlpull.v1.XmlPullParserFactory; 24 25 public class CarrierConfigTest extends InstrumentationTestCase { 26 27 /** 28 * Iterate over all XML files in assets/ and ensure they parse without error. 29 */ testAllFilesParse()30 public void testAllFilesParse() { 31 forEachConfigXml(new ParserChecker() { 32 public void check(XmlPullParser parser) throws XmlPullParserException, IOException { 33 PersistableBundle b = DefaultCarrierConfigService.readConfigFromXml(parser, 34 new CarrierIdentifier("001", "001", "Test", "001001123456789", "", "")); 35 assertNotNull("got null bundle", b); 36 } 37 }); 38 } 39 40 /** 41 * Check that the config bundles in XML files have valid filter attributes. 42 * This checks the attribute names only. 43 */ testFilterValidAttributes()44 public void testFilterValidAttributes() { 45 forEachConfigXml(new ParserChecker() { 46 public void check(XmlPullParser parser) throws XmlPullParserException, IOException { 47 int event; 48 while (((event = parser.next()) != XmlPullParser.END_DOCUMENT)) { 49 if (event == XmlPullParser.START_TAG 50 && "carrier_config".equals(parser.getName())) { 51 for (int i = 0; i < parser.getAttributeCount(); ++i) { 52 String attribute = parser.getAttributeName(i); 53 switch (attribute) { 54 case "mcc": 55 case "mnc": 56 case "gid1": 57 case "gid2": 58 case "spn": 59 case "imsi": 60 case "device": 61 break; 62 default: 63 fail("Unknown attribute '" + attribute 64 + "' at " + parser.getPositionDescription()); 65 break; 66 } 67 } 68 } 69 } 70 } 71 }); 72 } 73 74 /** 75 * Tests that the variable names in each XML file match actual keys in CarrierConfigManager. 76 */ testVariableNames()77 public void testVariableNames() { 78 final Set<String> varXmlNames = getCarrierConfigXmlNames(); 79 // organize them into sets by type or unknown 80 forEachConfigXml(new ParserChecker() { 81 public void check(XmlPullParser parser) throws XmlPullParserException, IOException { 82 int event; 83 while (((event = parser.next()) != XmlPullParser.END_DOCUMENT)) { 84 if (event == XmlPullParser.START_TAG) { 85 switch (parser.getName()) { 86 case "int-array": 87 case "string-array": 88 // string-array and int-array require the 'num' attribute 89 final String varNum = parser.getAttributeValue(null, "num"); 90 assertNotNull("No 'num' attribute in array: " 91 + parser.getPositionDescription(), varNum); 92 case "int": 93 case "long": 94 case "boolean": 95 case "string": 96 // NOTE: This doesn't check for other valid Bundle values, but it 97 // is limited to the key types in CarrierConfigManager. 98 final String varName = parser.getAttributeValue(null, "name"); 99 assertNotNull("No 'name' attribute: " 100 + parser.getPositionDescription(), varName); 101 assertTrue("Unknown variable: '" + varName 102 + "' at " + parser.getPositionDescription(), 103 varXmlNames.contains(varName)); 104 // TODO: Check that the type is correct. 105 break; 106 case "carrier_config_list": 107 case "item": 108 case "carrier_config": 109 // do nothing 110 break; 111 default: 112 fail("unexpected tag: '" + parser.getName() 113 + "' at " + parser.getPositionDescription()); 114 break; 115 } 116 } 117 } 118 } 119 }); 120 } 121 122 /** 123 * Utility for iterating over each XML document in the assets folder. 124 * 125 * This can be used with {@link #forEachConfigXml} to run checks on each XML document. 126 * {@link #check} should {@link #fail} if the test does not pass. 127 */ 128 private interface ParserChecker { check(XmlPullParser parser)129 void check(XmlPullParser parser) throws XmlPullParserException, IOException; 130 } 131 132 /** 133 * Utility for iterating over each XML document in the assets folder. 134 */ forEachConfigXml(ParserChecker checker)135 private void forEachConfigXml(ParserChecker checker) { 136 AssetManager assetMgr = getInstrumentation().getTargetContext().getAssets(); 137 try { 138 String[] files = assetMgr.list(""); 139 assertNotNull("failed to list files", files); 140 assertTrue("no files", files.length > 0); 141 for (String fileName : files) { 142 try { 143 if (!fileName.startsWith("carrier_config_")) continue; 144 145 XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); 146 XmlPullParser parser = factory.newPullParser(); 147 parser.setInput(assetMgr.open(fileName), "utf-8"); 148 149 checker.check(parser); 150 151 } catch (Throwable e) { 152 throw new AssertionError("Problem in " + fileName + ": " + e.getMessage(), e); 153 } 154 } 155 // Check vendor.xml too 156 try { 157 Resources res = getInstrumentation().getTargetContext().getResources(); 158 checker.check(res.getXml(R.xml.vendor)); 159 } catch (Throwable e) { 160 throw new AssertionError("Problem in vendor.xml: " + e.getMessage(), e); 161 } 162 } catch (IOException e) { 163 fail(e.toString()); 164 } 165 } 166 167 /** 168 * Get the set of config variable names, as used in XML files. 169 */ getCarrierConfigXmlNames()170 private Set<String> getCarrierConfigXmlNames() { 171 // get values of all KEY_ members of CarrierConfigManager 172 Field[] fields = CarrierConfigManager.class.getDeclaredFields(); 173 HashSet<String> varXmlNames = new HashSet<>(); 174 for (Field f : fields) { 175 if (!f.getName().startsWith("KEY_")) continue; 176 if ((f.getModifiers() & Modifier.STATIC) == 0) { 177 fail("non-static key in CarrierConfigManager: " + f.toString()); 178 } 179 try { 180 String value = (String) f.get(null); 181 varXmlNames.add(value); 182 } 183 catch (IllegalAccessException e) { 184 throw new AssertionError("Failed to get config key: " + e.getMessage(), e); 185 } 186 } 187 assertTrue("Found zero keys", varXmlNames.size() > 0); 188 return varXmlNames; 189 } 190 } 191