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", "", "", "")); 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 "device": 60 break; 61 default: 62 fail("Unknown attribute '" + attribute 63 + "' at " + parser.getPositionDescription()); 64 break; 65 } 66 } 67 } 68 } 69 } 70 }); 71 } 72 73 /** 74 * Tests that the variable names in each XML file match actual keys in CarrierConfigManager. 75 */ testVariableNames()76 public void testVariableNames() { 77 final Set<String> varXmlNames = getCarrierConfigXmlNames(); 78 // organize them into sets by type or unknown 79 forEachConfigXml(new ParserChecker() { 80 public void check(XmlPullParser parser) throws XmlPullParserException, IOException { 81 int event; 82 while (((event = parser.next()) != XmlPullParser.END_DOCUMENT)) { 83 if (event == XmlPullParser.START_TAG) { 84 switch (parser.getName()) { 85 case "int": 86 case "boolean": 87 case "string": 88 case "int-array": 89 case "string-array": 90 // NOTE: This doesn't check for other valid Bundle values, but it 91 // is limited to the key types in CarrierConfigManager. 92 final String varName = parser.getAttributeValue(null, "name"); 93 assertNotNull("No 'name' attribute: " 94 + parser.getPositionDescription(), varName); 95 assertTrue("Unknown variable: '" + varName 96 + "' at " + parser.getPositionDescription(), 97 varXmlNames.contains(varName)); 98 // TODO: Check that the type is correct. 99 break; 100 case "carrier_config_list": 101 case "carrier_config": 102 // do nothing 103 break; 104 default: 105 fail("unexpected tag: '" + parser.getName() 106 + "' at " + parser.getPositionDescription()); 107 break; 108 } 109 } 110 } 111 } 112 }); 113 } 114 115 /** 116 * Utility for iterating over each XML document in the assets folder. 117 * 118 * This can be used with {@link #forEachConfigXml} to run checks on each XML document. 119 * {@link #check} should {@link #fail} if the test does not pass. 120 */ 121 private interface ParserChecker { check(XmlPullParser parser)122 void check(XmlPullParser parser) throws XmlPullParserException, IOException; 123 } 124 125 /** 126 * Utility for iterating over each XML document in the assets folder. 127 */ forEachConfigXml(ParserChecker checker)128 private void forEachConfigXml(ParserChecker checker) { 129 AssetManager assetMgr = getInstrumentation().getTargetContext().getAssets(); 130 try { 131 String[] files = assetMgr.list(""); 132 assertNotNull("failed to list files", files); 133 assertTrue("no files", files.length > 0); 134 for (String fileName : files) { 135 try { 136 if (!fileName.startsWith("carrier_config_")) continue; 137 138 XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); 139 XmlPullParser parser = factory.newPullParser(); 140 parser.setInput(assetMgr.open(fileName), "utf-8"); 141 142 checker.check(parser); 143 144 } catch (Throwable e) { 145 throw new AssertionError("Problem in " + fileName + ": " + e.getMessage(), e); 146 } 147 } 148 // Check vendor.xml too 149 try { 150 Resources res = getInstrumentation().getTargetContext().getResources(); 151 checker.check(res.getXml(R.xml.vendor)); 152 } catch (Throwable e) { 153 throw new AssertionError("Problem in vendor.xml: " + e.getMessage(), e); 154 } 155 } catch (IOException e) { 156 fail(e.toString()); 157 } 158 } 159 160 /** 161 * Get the set of config variable names, as used in XML files. 162 */ getCarrierConfigXmlNames()163 private Set<String> getCarrierConfigXmlNames() { 164 // get values of all KEY_ members of CarrierConfigManager 165 Field[] fields = CarrierConfigManager.class.getDeclaredFields(); 166 HashSet<String> varXmlNames = new HashSet<>(); 167 for (Field f : fields) { 168 if (!f.getName().startsWith("KEY_")) continue; 169 if ((f.getModifiers() & Modifier.STATIC) == 0) { 170 fail("non-static key in CarrierConfigManager: " + f.toString()); 171 } 172 try { 173 String value = (String) f.get(null); 174 varXmlNames.add(value); 175 } 176 catch (IllegalAccessException e) { 177 throw new AssertionError("Failed to get config key: " + e.getMessage(), e); 178 } 179 } 180 assertTrue("Found zero keys", varXmlNames.size() > 0); 181 return varXmlNames; 182 } 183 } 184