1 /* 2 * Copyright (C) 2011 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 com.android.cts.xmlgenerator; 18 19 import vogar.Expectation; 20 import vogar.ExpectationStore; 21 import vogar.Result; 22 23 import com.android.compatibility.common.util.AbiUtils; 24 25 import java.io.File; 26 import java.io.FileOutputStream; 27 import java.io.IOException; 28 import java.io.OutputStream; 29 import java.io.PrintWriter; 30 import java.util.ArrayList; 31 import java.util.Collection; 32 import java.util.Collections; 33 import java.util.Map; 34 import java.util.List; 35 import java.util.Set; 36 37 /** 38 * Generator of TestPackage XML files for native tests. 39 * 40 * It takes in an input of the following form: 41 * 42 * suite: x.y.z 43 * case:TestClass1 44 * test:testMethod1 45 * test:testMethod2 46 * case:TestClass2 47 * test:testMethod1 48 * suite: x.y 49 * case:TestClass3 50 * test:testMethod2 51 */ 52 class XmlGenerator { 53 54 /** Example: com.android.cts.holo */ 55 private final String mAppNamespace; 56 57 /** Test package name like "android.nativemedia" to group the tests. */ 58 private final String mAppPackageName; 59 60 /** Name of the native executable. */ 61 private final String mName; 62 63 /** Test runner */ 64 private final String mRunner; 65 66 private final String mTargetBinaryName; 67 68 private final String mTargetNameSpace; 69 70 private final String mJarPath; 71 72 private final String mTestType; 73 74 /** Path to output file or null to just dump to standard out. */ 75 private final String mOutputPath; 76 77 /** ExpectationStore to filter out known failures. */ 78 private final ExpectationStore mKnownFailures; 79 80 /** ExpectationStore to filter out unsupported abis. */ 81 private final ExpectationStore mUnsupportedAbis; 82 83 private final String mArchitecture; 84 85 private final Map<String, String> mAdditionalAttributes; 86 XmlGenerator(ExpectationStore knownFailures, ExpectationStore unsupportedAbis, String architecture, String appNameSpace, String appPackageName, String name, String runner, String targetBinaryName, String targetNameSpace, String jarPath, String testType, String outputPath, Map<String, String> additionalAttributes)87 XmlGenerator(ExpectationStore knownFailures, ExpectationStore unsupportedAbis, 88 String architecture, String appNameSpace, String appPackageName, String name, 89 String runner, String targetBinaryName, String targetNameSpace, String jarPath, 90 String testType, String outputPath, Map<String, String> additionalAttributes) { 91 mAppNamespace = appNameSpace; 92 mAppPackageName = appPackageName; 93 mName = name; 94 mRunner = runner; 95 mTargetBinaryName = targetBinaryName; 96 mTargetNameSpace = targetNameSpace; 97 mJarPath = jarPath; 98 mTestType = testType; 99 mOutputPath = outputPath; 100 mKnownFailures = knownFailures; 101 mUnsupportedAbis = unsupportedAbis; 102 mArchitecture = architecture; 103 mAdditionalAttributes = additionalAttributes; 104 } 105 writePackageXml()106 public void writePackageXml() throws IOException { 107 OutputStream output = System.out; 108 if (mOutputPath != null) { 109 File outputFile = new File(mOutputPath); 110 output = new FileOutputStream(outputFile); 111 } 112 113 PrintWriter writer = null; 114 try { 115 writer = new PrintWriter(output); 116 writer.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"); 117 writeTestPackage(writer); 118 } finally { 119 if (writer != null) { 120 writer.close(); 121 } 122 } 123 } 124 writeTestPackage(PrintWriter writer)125 private void writeTestPackage(PrintWriter writer) { 126 writer.append("<TestPackage"); 127 if (mAppNamespace != null) { 128 writer.append(" appNameSpace=\"").append(mAppNamespace).append("\""); 129 } 130 131 writer.append(" appPackageName=\"").append(mAppPackageName).append("\""); 132 writer.append(" name=\"").append(mName).append("\""); 133 134 if (mRunner != null) { 135 writer.append(" runner=\"").append(mRunner).append("\""); 136 } 137 138 if (mAppNamespace != null && mTargetNameSpace != null 139 && !mAppNamespace.equals(mTargetNameSpace)) { 140 writer.append(" targetBinaryName=\"").append(mTargetBinaryName).append("\""); 141 writer.append(" targetNameSpace=\"").append(mTargetNameSpace).append("\""); 142 } 143 144 if (mTestType != null && !mTestType.isEmpty()) { 145 writer.append(" testType=\"").append(mTestType).append("\""); 146 } 147 148 if (mJarPath != null) { 149 writer.append(" jarPath=\"").append(mJarPath).append("\""); 150 } 151 152 for (Map.Entry<String, String> entry : mAdditionalAttributes.entrySet()) { 153 writer.append(String.format(" %s=\"%s\"", entry.getKey(), entry.getValue())); 154 } 155 156 writer.println(" version=\"1.0\">"); 157 158 TestListParser parser = new TestListParser(); 159 Collection<TestSuite> suites = parser.parse(System.in); 160 StringBuilder nameCollector = new StringBuilder(); 161 writeTestSuites(writer, suites, nameCollector); 162 writer.println("</TestPackage>"); 163 } 164 writeTestSuites(PrintWriter writer, Collection<TestSuite> suites, StringBuilder nameCollector)165 private void writeTestSuites(PrintWriter writer, Collection<TestSuite> suites, 166 StringBuilder nameCollector) { 167 Collection<TestSuite> sorted = sortCollection(suites); 168 for (TestSuite suite : sorted) { 169 if (suite.countTests() == 0) { 170 continue; 171 } 172 writer.append("<TestSuite name=\"").append(suite.getName()).println("\">"); 173 174 String namePart = suite.getName(); 175 if (nameCollector.length() > 0) { 176 namePart = "." + namePart; 177 } 178 nameCollector.append(namePart); 179 180 writeTestSuites(writer, suite.getSuites(), nameCollector); 181 writeTestCases(writer, suite.getCases(), nameCollector); 182 183 nameCollector.delete(nameCollector.length() - namePart.length(), 184 nameCollector.length()); 185 writer.println("</TestSuite>"); 186 } 187 } 188 writeTestCases(PrintWriter writer, Collection<TestCase> cases, StringBuilder nameCollector)189 private void writeTestCases(PrintWriter writer, Collection<TestCase> cases, 190 StringBuilder nameCollector) { 191 Collection<TestCase> sorted = sortCollection(cases); 192 for (TestCase testCase : sorted) { 193 if (testCase.countTests() == 0) { 194 continue; 195 } 196 String name = testCase.getName(); 197 writer.append("<TestCase name=\"").append(name).println("\">"); 198 nameCollector.append('.').append(name); 199 200 writeTests(writer, testCase.getTests(), nameCollector); 201 202 nameCollector.delete(nameCollector.length() - name.length() - 1, 203 nameCollector.length()); 204 writer.println("</TestCase>"); 205 } 206 } 207 writeTests(PrintWriter writer, Collection<Test> tests, StringBuilder nameCollector)208 private void writeTests(PrintWriter writer, Collection<Test> tests, 209 StringBuilder nameCollector) { 210 Collection<Test> sorted = sortCollection(tests); 211 for (Test test : sorted) { 212 String className = nameCollector.toString(); 213 nameCollector.append('#').append(test.getName()); 214 writer.append("<Test name=\"").append(test.getName()).append("\""); 215 String abis = getSupportedAbis(mUnsupportedAbis, mArchitecture, 216 className, nameCollector.toString()).toString(); 217 writer.append(" abis=\"" + abis.substring(1, abis.length() - 1) + "\""); 218 if (isKnownFailure(mKnownFailures, nameCollector.toString())) { 219 writer.append(" expectation=\"failure\""); 220 } 221 if (test.getTimeout() >= 0) { 222 writer.append(" timeout=\"" + test.getTimeout() + "\""); 223 } 224 writer.println(" />"); 225 226 nameCollector.delete(nameCollector.length() - test.getName().length() - 1, 227 nameCollector.length()); 228 } 229 } 230 sortCollection(Collection<E> col)231 private <E extends Comparable<E>> Collection<E> sortCollection(Collection<E> col) { 232 List<E> list = new ArrayList<E>(col); 233 Collections.sort(list); 234 return list; 235 } 236 isKnownFailure(ExpectationStore expectationStore, String testName)237 public static boolean isKnownFailure(ExpectationStore expectationStore, String testName) { 238 return expectationStore != null 239 && expectationStore.get(testName).getResult() != Result.SUCCESS; 240 } 241 242 // Returns the list of ABIs supported by this TestCase on this architecture. getSupportedAbis(ExpectationStore expectationStore, String architecture, String className, String testName)243 public static Set<String> getSupportedAbis(ExpectationStore expectationStore, 244 String architecture, String className, String testName) { 245 Set<String> supportedAbis = AbiUtils.getAbisForArch(architecture); 246 if (expectationStore == null) { 247 return supportedAbis; 248 } 249 250 removeUnsupportedAbis(expectationStore.get(className), supportedAbis); 251 removeUnsupportedAbis(expectationStore.get(testName), supportedAbis); 252 return supportedAbis; 253 } 254 removeUnsupportedAbis(Expectation expectation, Set<String> supportedAbis)255 public static void removeUnsupportedAbis(Expectation expectation, Set<String> supportedAbis) { 256 if (expectation == null) { 257 return; 258 } 259 260 String description = expectation.getDescription(); 261 if (description.isEmpty()) { 262 return; 263 } 264 265 String[] unsupportedAbis = description.split(":")[1].split(","); 266 for (String a : unsupportedAbis) { 267 String abi = a.trim(); 268 if (!AbiUtils.isAbiSupportedByCompatibility(abi)) { 269 throw new RuntimeException( 270 String.format("Unrecognised ABI %s in %s", abi, description)); 271 } 272 supportedAbis.remove(abi); 273 } 274 } 275 276 } 277