1 /* 2 * Copyright (C) 2015 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 package com.android.compatibility.common.util; 17 18 import com.android.tradefed.util.FileUtil; 19 import com.android.tradefed.util.AbiUtils; 20 21 import org.w3c.dom.Element; 22 import org.w3c.dom.NodeList; 23 import org.xml.sax.InputSource; 24 25 import junit.framework.TestCase; 26 27 import java.io.File; 28 import java.io.FileWriter; 29 import java.io.IOException; 30 import java.io.StringReader; 31 import java.net.InetAddress; 32 import java.net.UnknownHostException; 33 import java.util.ArrayList; 34 import java.util.Arrays; 35 import java.util.Collection; 36 import java.util.HashMap; 37 import java.util.HashSet; 38 import java.util.List; 39 import java.util.Map; 40 import java.util.Set; 41 42 import javax.xml.xpath.XPath; 43 import javax.xml.xpath.XPathConstants; 44 import javax.xml.xpath.XPathExpressionException; 45 import javax.xml.xpath.XPathFactory; 46 47 /** 48 * Unit tests for {@link ResultHandler} 49 */ 50 public class ResultHandlerTest extends TestCase { 51 52 private static final String SUITE_NAME = "CTS"; 53 private static final String SUITE_VERSION = "5.0"; 54 private static final String SUITE_PLAN = "cts"; 55 private static final String SUITE_BUILD = "12345"; 56 private static final String REPORT_VERSION = "5.0"; 57 private static final String OS_NAME = System.getProperty("os.name"); 58 private static final String OS_VERSION = System.getProperty("os.version"); 59 private static final String OS_ARCH = System.getProperty("os.arch"); 60 private static final String JAVA_VENDOR = System.getProperty("java.vendor"); 61 private static final String JAVA_VERSION = System.getProperty("java.version"); 62 private static final String NAME_A = "ModuleA"; 63 private static final String NAME_B = "ModuleB"; 64 private static final String DONE_A = "false"; 65 private static final String DONE_B = "true"; 66 private static final String RUNTIME_A = "100"; 67 private static final String RUNTIME_B = "200"; 68 private static final String ABI = "mips64"; 69 private static final String ID_A = AbiUtils.createId(ABI, NAME_A); 70 private static final String ID_B = AbiUtils.createId(ABI, NAME_B); 71 72 private static final String BUILD_FINGERPRINT = "build_fingerprint"; 73 private static final String BUILD_FINGERPRINT_UNALTERED = "build_fingerprint_unaltered"; 74 private static final String BUILD_ID = "build_id"; 75 private static final String BUILD_PRODUCT = "build_product"; 76 private static final String RUN_HISTORY = "run_history"; 77 private static final String EXAMPLE_BUILD_ID = "XYZ"; 78 private static final String EXAMPLE_BUILD_PRODUCT = "wolverine"; 79 private static final String EXAMPLE_BUILD_FINGERPRINT = "example_build_fingerprint"; 80 private static final String EXAMPLE_BUILD_FINGERPRINT_UNALTERED = "example_build_fingerprint_unaltered"; 81 private static final String EXAMPLE_RUN_HISTORY = 82 "[{\"startTime\":10000000000000,\"endTime\":10000000000001}," 83 + "{\"startTime\":10000000000002,\"endTime\":10000000000003}]"; 84 85 private static final String DEVICE_A = "device123"; 86 private static final String DEVICE_B = "device456"; 87 private static final String DEVICES = "device456,device123"; 88 private static final String CLASS_A = "android.test.Foor"; 89 private static final String CLASS_B = "android.test.Bar"; 90 private static final String METHOD_1 = "testBlah1"; 91 private static final String METHOD_2 = "testBlah2"; 92 private static final String METHOD_3 = "testBlah3"; 93 private static final String METHOD_4 = "testBlah4"; 94 private static final String METHOD_5 = "testBlah5"; 95 private static final String METHOD_6_BRACKETS = "testBlah6[suffix]"; 96 private static final String SUB_METHOD_3 = "subTestBlah3"; 97 private static final String SUB_METHOD_6_BRACKETS = "subTestBlah6[suffix]"; 98 private static final String SUMMARY_SOURCE = String.format("%s#%s:20", CLASS_B, METHOD_4); 99 private static final String SUMMARY_MESSAGE = "Headline"; 100 private static final double SUMMARY_VALUE = 9001; 101 private static final String MESSAGE = "Something small is not alright"; 102 private static final String STACK_TRACE = "Something small is not alright\n " + 103 "at four.big.insects.Marley.sing(Marley.java:10)"; 104 private static final String BUG_REPORT = "https://cnsviewer.corp.google.com/cns/bugreport.txt"; 105 private static final String LOGCAT = "https://cnsviewer.corp.google.com/cns/logcat.gz"; 106 private static final String SCREENSHOT = "https://cnsviewer.corp.google.com/screenshot.png"; 107 private static final long START_MS = 1431586801000L; 108 private static final long END_MS = 1431673199000L; 109 private static final String START_DISPLAY = "Fri Aug 20 15:13:03 PDT 2010"; 110 private static final String END_DISPLAY = "Fri Aug 20 15:13:04 PDT 2010"; 111 private static final long TEST_START_MS = 1000000000011L; 112 private static final long TEST_END_MS = 1000000000012L; 113 private static final boolean TEST_IS_AUTOMATED = false; 114 115 private static final String REFERENCE_URL = "http://android.com"; 116 private static final String LOG_URL = "file:///path/to/logs"; 117 private static final String COMMAND_LINE_ARGS = "cts -m CtsMyModuleTestCases"; 118 private static final String XML_BASE = 119 "<?xml version='1.0' encoding='UTF-8' standalone='no' ?>" + 120 "<?xml-stylesheet type=\"text/xsl\" href=\"compatibility_result.xsl\"?>\n" + 121 "<Result start=\"%d\" end=\"%d\" start_display=\"%s\"" + 122 "end_display=\"%s\" suite_name=\"%s\" suite_version=\"%s\" " + 123 "suite_plan=\"%s\" suite_build_number=\"%s\" report_version=\"%s\" " + 124 "devices=\"%s\" host_name=\"%s\"" + 125 "os_name=\"%s\" os_version=\"%s\" os_arch=\"%s\" java_vendor=\"%s\"" + 126 "java_version=\"%s\" reference_url=\"%s\" log_url=\"%s\"" + 127 "command_line_args=\"%s\">\n" + 128 "%s%s%s" + 129 "</Result>"; 130 private static final String XML_BUILD_INFO = 131 " <Build " + 132 BUILD_FINGERPRINT + "=\"%s\" " + 133 BUILD_ID + "=\"%s\" " + 134 BUILD_PRODUCT + "=\"%s\" " + 135 " />\n"; 136 private static final String XML_BUILD_INFO_WITH_UNALTERED_BUILD_FINGERPRINT = 137 " <Build " + 138 BUILD_FINGERPRINT + "=\"%s\" " + 139 BUILD_FINGERPRINT_UNALTERED + "=\"%s\" " + 140 BUILD_ID + "=\"%s\" " + 141 BUILD_PRODUCT + "=\"%s\" " + 142 " />\n"; 143 private static final String XML_SUMMARY = 144 " <Summary pass=\"%d\" failed=\"%d\" " + 145 "modules_done=\"1\" modules_total=\"1\" />\n"; 146 private static final String XML_MODULE = 147 " <Module name=\"%s\" abi=\"%s\" device=\"%s\" runtime=\"%s\" done=\"%s\">\n" + 148 "%s" + 149 " </Module>\n"; 150 private static final String XML_CASE = 151 " <TestCase name=\"%s\">\n" + 152 "%s" + 153 " </TestCase>\n"; 154 private static final String XML_TEST_PASS = 155 " <Test result=\"pass\" name=\"%s\"/>\n"; 156 private static final String XML_TEST_SKIP = 157 " <Test result=\"pass\" name=\"%s\" skipped=\"true\"/>\n"; 158 private static final String XML_TEST_FAIL = 159 " <Test result=\"fail\" name=\"%s\">\n" + 160 " <Failure message=\"%s\">\n" + 161 " <StackTrace>%s</StackTrace>\n" + 162 " </Failure>\n" + 163 " <BugReport>%s</BugReport>\n" + 164 " <Logcat>%s</Logcat>\n" + 165 " <Screenshot>%s</Screenshot>\n" + 166 " </Test>\n"; 167 private static final String XML_TEST_RESULT = 168 " <Test result=\"pass\" name=\"%s\">\n" + 169 " <Summary>\n" + 170 " <Metric source=\"%s\" message=\"%s\" score_type=\"%s\" score_unit=\"%s\">\n" + 171 " <Value>%s</Value>\n" + 172 " </Metric>\n" + 173 " </Summary>\n" + 174 " </Test>\n"; 175 private static final String NEW_XML_TEST_RESULT = 176 " <Test result=\"pass\" name=\"%s\">\n" 177 + " <Metric key=\"%s\">%s</Metric>\n" 178 + " </Test>\n"; 179 180 private File resultsDir = null; 181 private File resultDir = null; 182 183 @Override setUp()184 public void setUp() throws Exception { 185 resultsDir = FileUtil.createTempDir("results"); 186 resultDir = FileUtil.createTempDir("12345", resultsDir); 187 } 188 189 @Override tearDown()190 public void tearDown() throws Exception { 191 FileUtil.recursiveDelete(resultsDir); 192 } 193 testSerialization()194 public void testSerialization() throws Exception { 195 IInvocationResult result = new InvocationResult(); 196 result.setStartTime(START_MS); 197 result.setTestPlan(SUITE_PLAN); 198 result.addDeviceSerial(DEVICE_A); 199 result.addDeviceSerial(DEVICE_B); 200 result.addInvocationInfo(BUILD_FINGERPRINT, EXAMPLE_BUILD_FINGERPRINT); 201 result.addInvocationInfo(BUILD_ID, EXAMPLE_BUILD_ID); 202 result.addInvocationInfo(BUILD_PRODUCT, EXAMPLE_BUILD_PRODUCT); 203 result.addInvocationInfo(RUN_HISTORY, EXAMPLE_RUN_HISTORY); 204 Collection<InvocationResult.RunHistory> runHistories = 205 ((InvocationResult) result).getRunHistories(); 206 InvocationResult.RunHistory runHistory1 = new InvocationResult.RunHistory(); 207 runHistory1.startTime = 10000000000000L; 208 runHistory1.endTime = 10000000000001L; 209 runHistories.add(runHistory1); 210 InvocationResult.RunHistory runHistory2 = new InvocationResult.RunHistory(); 211 runHistory2.startTime = 10000000000002L; 212 runHistory2.endTime = 10000000000003L; 213 runHistories.add(runHistory2); 214 215 // Module A: test1 passes, test2 not executed 216 IModuleResult moduleA = result.getOrCreateModule(ID_A); 217 moduleA.setDone(false); 218 moduleA.addRuntime(Integer.parseInt(RUNTIME_A)); 219 ICaseResult moduleACase = moduleA.getOrCreateResult(CLASS_A); 220 ITestResult moduleATest1 = moduleACase.getOrCreateResult(METHOD_1); 221 moduleATest1.setResultStatus(TestStatus.PASS); 222 ITestResult moduleATest2 = moduleACase.getOrCreateResult(METHOD_2); 223 moduleATest2.setResultStatus(null); // not executed test 224 // Module B: test3 fails, test4 passes with report log, test5 passes with skip 225 IModuleResult moduleB = result.getOrCreateModule(ID_B); 226 moduleB.setDone(true); 227 moduleB.addRuntime(Integer.parseInt(RUNTIME_B)); 228 ICaseResult moduleBCase = moduleB.getOrCreateResult(CLASS_B); 229 ITestResult moduleBTest3 = moduleBCase.getOrCreateResult(METHOD_3); 230 moduleBTest3.setResultStatus(TestStatus.FAIL); 231 moduleBTest3.setMessage(MESSAGE); 232 moduleBTest3.setStackTrace(STACK_TRACE); 233 moduleBTest3.setBugReport(BUG_REPORT); 234 moduleBTest3.setLog(LOGCAT); 235 moduleBTest3.setScreenshot(SCREENSHOT); 236 ITestResult moduleBTest4 = moduleBCase.getOrCreateResult(METHOD_4); 237 moduleBTest4.setResultStatus(TestStatus.PASS); 238 ReportLog report = new ReportLog(); 239 ReportLog.Metric summary = new ReportLog.Metric(SUMMARY_SOURCE, SUMMARY_MESSAGE, 240 SUMMARY_VALUE, ResultType.HIGHER_BETTER, ResultUnit.SCORE); 241 report.setSummary(summary); 242 moduleBTest4.setReportLog(report); 243 ITestResult moduleBTest5 = moduleBCase.getOrCreateResult(METHOD_5); 244 moduleBTest5.skipped(); 245 246 Map<String, String> testAttributes = new HashMap<String, String>(); 247 testAttributes.put("foo1", "bar1"); 248 testAttributes.put("foo2", "bar2"); 249 // Serialize to file 250 File res = 251 ResultHandler.writeResults( 252 SUITE_NAME, 253 SUITE_VERSION, 254 SUITE_PLAN, 255 SUITE_BUILD, 256 result, 257 resultDir, 258 START_MS, 259 END_MS, 260 REFERENCE_URL, 261 LOG_URL, 262 COMMAND_LINE_ARGS, 263 testAttributes); 264 String content = FileUtil.readStringFromFile(res); 265 assertXmlContainsAttribute(content, "Result", "foo1", "bar1"); 266 assertXmlContainsAttribute(content, "Result", "foo2", "bar2"); 267 assertXmlContainsAttribute(content, "Result/Build", "run_history", EXAMPLE_RUN_HISTORY); 268 assertXmlContainsNode(content, "Result/RunHistory"); 269 assertXmlContainsAttribute(content, "Result/RunHistory/Run", "start", "10000000000000"); 270 assertXmlContainsAttribute(content, "Result/RunHistory/Run", "end", "10000000000001"); 271 assertXmlContainsAttribute(content, "Result/RunHistory/Run", "start", "10000000000002"); 272 assertXmlContainsAttribute(content, "Result/RunHistory/Run", "end", "10000000000003"); 273 274 // Parse the results and assert correctness 275 result = ResultHandler.getResultFromDir(resultDir); 276 checkResult(result, false); 277 checkRunHistory(result); 278 } 279 280 /* 281 * Test serialization for CTS Verifier since test results with test result history is only in 282 * CTS Verifier and was not parsed by suite harness. 283 */ testSerialization_whenTestResultWithTestResultHistoryWithoutParsing()284 public void testSerialization_whenTestResultWithTestResultHistoryWithoutParsing() 285 throws Exception { 286 IInvocationResult result = new InvocationResult(); 287 result.setStartTime(START_MS); 288 result.setTestPlan(SUITE_PLAN); 289 result.addDeviceSerial(DEVICE_A); 290 result.addDeviceSerial(DEVICE_B); 291 result.addInvocationInfo(BUILD_FINGERPRINT, EXAMPLE_BUILD_FINGERPRINT); 292 result.addInvocationInfo(BUILD_ID, EXAMPLE_BUILD_ID); 293 result.addInvocationInfo(BUILD_PRODUCT, EXAMPLE_BUILD_PRODUCT); 294 295 // Module A: test1 passes, test2 not executed 296 IModuleResult moduleA = result.getOrCreateModule(ID_A); 297 moduleA.setDone(false); 298 moduleA.addRuntime(Integer.parseInt(RUNTIME_A)); 299 ICaseResult moduleACase = moduleA.getOrCreateResult(CLASS_A); 300 ITestResult moduleATest1 = moduleACase.getOrCreateResult(METHOD_1); 301 moduleATest1.setResultStatus(TestStatus.PASS); 302 // Module B: test3 fails with test result history, test4 passes with report log, 303 // test5 passes with skip 304 IModuleResult moduleB = result.getOrCreateModule(ID_B); 305 moduleB.setDone(true); 306 moduleB.addRuntime(Integer.parseInt(RUNTIME_B)); 307 ICaseResult moduleBCase = moduleB.getOrCreateResult(CLASS_B); 308 Set<TestResultHistory.ExecutionRecord> executionRecords = 309 new HashSet<TestResultHistory.ExecutionRecord>(); 310 executionRecords.add( 311 new TestResultHistory.ExecutionRecord( 312 TEST_START_MS, TEST_END_MS, TEST_IS_AUTOMATED)); 313 314 ITestResult moduleBTest3 = moduleBCase.getOrCreateResult(METHOD_3); 315 moduleBTest3.setResultStatus(TestStatus.FAIL); 316 moduleBTest3.setMessage(MESSAGE); 317 moduleBTest3.setStackTrace(STACK_TRACE); 318 moduleBTest3.setBugReport(BUG_REPORT); 319 moduleBTest3.setLog(LOGCAT); 320 moduleBTest3.setScreenshot(SCREENSHOT); 321 List<TestResultHistory> resultHistories = new ArrayList<TestResultHistory>(); 322 TestResultHistory resultHistory = 323 new TestResultHistory(METHOD_3 + ":" + SUB_METHOD_3, executionRecords); 324 resultHistories.add(resultHistory); 325 moduleBTest3.setTestResultHistories(resultHistories); 326 ITestResult moduleBTest4 = moduleBCase.getOrCreateResult(METHOD_4); 327 moduleBTest4.setResultStatus(TestStatus.PASS); 328 ReportLog report = new ReportLog(); 329 ReportLog.Metric summary = 330 new ReportLog.Metric( 331 SUMMARY_SOURCE, 332 SUMMARY_MESSAGE, 333 SUMMARY_VALUE, 334 ResultType.HIGHER_BETTER, 335 ResultUnit.SCORE); 336 report.setSummary(summary); 337 moduleBTest4.setReportLog(report); 338 ITestResult moduleBTest5 = moduleBCase.getOrCreateResult(METHOD_5); 339 moduleBTest5.skipped(); 340 // For test name with bracket as suffix in CTS Verifier. 341 ITestResult moduleBTest6 = moduleBCase.getOrCreateResult(METHOD_6_BRACKETS); 342 moduleBTest6.setResultStatus(TestStatus.FAIL); 343 List<TestResultHistory> resultHistories2 = new ArrayList<TestResultHistory>(); 344 TestResultHistory resultHistory2 = 345 new TestResultHistory( 346 METHOD_6_BRACKETS + ":" + SUB_METHOD_6_BRACKETS, executionRecords); 347 resultHistories2.add(resultHistory2); 348 moduleBTest6.setTestResultHistories(resultHistories2); 349 350 // Serialize to file 351 File res = 352 ResultHandler.writeResults( 353 SUITE_NAME, 354 SUITE_VERSION, 355 SUITE_PLAN, 356 SUITE_BUILD, 357 result, 358 resultDir, 359 START_MS, 360 END_MS, 361 REFERENCE_URL, 362 LOG_URL, 363 COMMAND_LINE_ARGS, 364 null); 365 String content = FileUtil.readStringFromFile(res); 366 assertXmlContainsNode(content, "Result/Module/TestCase/Test/RunHistory"); 367 assertXmlContainsAttribute( 368 content, 369 "Result/Module/TestCase/Test/RunHistory/Run", 370 "start", 371 Long.toString(TEST_START_MS)); 372 assertXmlContainsAttribute( 373 content, 374 "Result/Module/TestCase/Test/RunHistory/Run", 375 "end", 376 Long.toString(TEST_END_MS)); 377 assertXmlContainsAttribute( 378 content, 379 "Result/Module/TestCase/Test/RunHistory/Run", 380 "isAutomated", 381 Boolean.toString(TEST_IS_AUTOMATED)); 382 checkResult(result, EXAMPLE_BUILD_FINGERPRINT, false, false); 383 } 384 testParsing()385 public void testParsing() throws Exception { 386 File resultDir = writeResultDir(resultsDir, false); 387 // Parse the results and assert correctness 388 checkResult(ResultHandler.getResultFromDir(resultDir), false); 389 } 390 testParsing_newTestFormat()391 public void testParsing_newTestFormat() throws Exception { 392 File resultDir = writeResultDir(resultsDir, true); 393 // Parse the results and assert correctness 394 checkResult(ResultHandler.getResultFromDir(resultDir), true); 395 } 396 testParsing_usesUnalteredBuildFingerprintWhenPresent()397 public void testParsing_usesUnalteredBuildFingerprintWhenPresent() throws Exception { 398 String buildInfo = String.format(XML_BUILD_INFO_WITH_UNALTERED_BUILD_FINGERPRINT, 399 EXAMPLE_BUILD_FINGERPRINT, EXAMPLE_BUILD_FINGERPRINT_UNALTERED, 400 EXAMPLE_BUILD_ID, EXAMPLE_BUILD_PRODUCT); 401 File resultDir = writeResultDir(resultsDir, buildInfo, false); 402 checkResult( 403 ResultHandler.getResultFromDir(resultDir), 404 EXAMPLE_BUILD_FINGERPRINT_UNALTERED, 405 false, 406 true); 407 } 408 testParsing_whenUnalteredBuildFingerprintIsEmpty_usesRegularBuildFingerprint()409 public void testParsing_whenUnalteredBuildFingerprintIsEmpty_usesRegularBuildFingerprint() throws Exception { 410 String buildInfo = String.format(XML_BUILD_INFO_WITH_UNALTERED_BUILD_FINGERPRINT, 411 EXAMPLE_BUILD_FINGERPRINT, "", EXAMPLE_BUILD_ID, EXAMPLE_BUILD_PRODUCT); 412 File resultDir = writeResultDir(resultsDir, buildInfo, false); 413 checkResult( 414 ResultHandler.getResultFromDir(resultDir), EXAMPLE_BUILD_FINGERPRINT, false, true); 415 } 416 testGetLightResults()417 public void testGetLightResults() throws Exception { 418 File resultDir = writeResultDir(resultsDir, false); 419 List<IInvocationResult> lightResults = ResultHandler.getLightResults(resultsDir); 420 assertEquals("Expected one result", 1, lightResults.size()); 421 IInvocationResult lightResult = lightResults.get(0); 422 checkLightResult(lightResult); 423 } 424 writeResultDir(File resultsDir, boolean newTestFormat)425 static File writeResultDir(File resultsDir, boolean newTestFormat) throws IOException { 426 String buildInfo = String.format(XML_BUILD_INFO, EXAMPLE_BUILD_FINGERPRINT, 427 EXAMPLE_BUILD_ID, EXAMPLE_BUILD_PRODUCT); 428 return writeResultDir(resultsDir, buildInfo, newTestFormat); 429 } 430 431 /* 432 * Helper to write a result to the results dir, for testing. 433 * @return the written resultDir 434 */ writeResultDir(File resultsDir, String buildInfo, boolean newTestFormat)435 static File writeResultDir(File resultsDir, String buildInfo, boolean newTestFormat) 436 throws IOException { 437 File resultDir = null; 438 FileWriter writer = null; 439 try { 440 resultDir = FileUtil.createTempDir("12345", resultsDir); 441 // Create the result file 442 File resultFile = new File(resultDir, ResultHandler.TEST_RESULT_FILE_NAME); 443 writer = new FileWriter(resultFile); 444 String summary = String.format(XML_SUMMARY, 2, 1); 445 String moduleATest = String.format(XML_TEST_PASS, METHOD_1); 446 String moduleACases = String.format(XML_CASE, CLASS_A, moduleATest); 447 String moduleA = String.format(XML_MODULE, NAME_A, ABI, DEVICE_A, RUNTIME_A, DONE_A, 448 moduleACases); 449 String moduleBTest3 = String.format(XML_TEST_FAIL, METHOD_3, MESSAGE, STACK_TRACE, 450 BUG_REPORT, LOGCAT, SCREENSHOT); 451 String moduleBTest4 = ""; 452 if (newTestFormat) { 453 moduleBTest4 = 454 String.format( 455 NEW_XML_TEST_RESULT, 456 METHOD_4, 457 SUMMARY_MESSAGE, 458 Double.toString(SUMMARY_VALUE)); 459 } else { 460 moduleBTest4 = 461 String.format( 462 XML_TEST_RESULT, 463 METHOD_4, 464 SUMMARY_SOURCE, 465 SUMMARY_MESSAGE, 466 ResultType.HIGHER_BETTER.toReportString(), 467 ResultUnit.SCORE.toReportString(), 468 Double.toString(SUMMARY_VALUE)); 469 } 470 471 String moduleBTest5 = String.format(XML_TEST_SKIP, METHOD_5); 472 String moduleBTests = String.join("", moduleBTest3, moduleBTest4, moduleBTest5); 473 String moduleBCases = String.format(XML_CASE, CLASS_B, moduleBTests); 474 String moduleB = String.format(XML_MODULE, NAME_B, ABI, DEVICE_B, RUNTIME_B, DONE_B, 475 moduleBCases); 476 String modules = String.join("", moduleA, moduleB); 477 String hostName = ""; 478 try { 479 hostName = InetAddress.getLocalHost().getHostName(); 480 } catch (UnknownHostException ignored) {} 481 String output = String.format(XML_BASE, START_MS, END_MS, START_DISPLAY, END_DISPLAY, 482 SUITE_NAME, SUITE_VERSION, SUITE_PLAN, SUITE_BUILD, REPORT_VERSION, DEVICES, 483 hostName, OS_NAME, OS_VERSION, OS_ARCH, JAVA_VENDOR, 484 JAVA_VERSION, REFERENCE_URL, LOG_URL, COMMAND_LINE_ARGS, 485 buildInfo, summary, modules); 486 writer.write(output); 487 writer.flush(); 488 } finally { 489 if (writer != null) { 490 writer.close(); 491 } 492 } 493 return resultDir; 494 } 495 checkLightResult(IInvocationResult lightResult)496 static void checkLightResult(IInvocationResult lightResult) throws Exception { 497 assertEquals("Expected 3 passes", 3, lightResult.countResults(TestStatus.PASS)); 498 assertEquals("Expected 1 failure", 1, lightResult.countResults(TestStatus.FAIL)); 499 500 Map<String, String> buildInfo = lightResult.getInvocationInfo(); 501 assertEquals("Incorrect Build ID", EXAMPLE_BUILD_ID, buildInfo.get(BUILD_ID)); 502 assertEquals("Incorrect Build Product", 503 EXAMPLE_BUILD_PRODUCT, buildInfo.get(BUILD_PRODUCT)); 504 505 Set<String> serials = lightResult.getDeviceSerials(); 506 assertTrue("Missing device", serials.contains(DEVICE_A)); 507 assertTrue("Missing device", serials.contains(DEVICE_B)); 508 assertEquals("Expected 2 devices", 2, serials.size()); 509 assertTrue("Incorrect devices", serials.contains(DEVICE_A) && serials.contains(DEVICE_B)); 510 assertEquals("Incorrect start time", START_MS, lightResult.getStartTime()); 511 assertEquals("Incorrect test plan", SUITE_PLAN, lightResult.getTestPlan()); 512 List<IModuleResult> modules = lightResult.getModules(); 513 assertEquals("Expected 1 completed module", 1, lightResult.getModuleCompleteCount()); 514 assertEquals("Expected 2 total modules", 2, modules.size()); 515 } 516 checkResult(IInvocationResult result, boolean newTestFormat)517 static void checkResult(IInvocationResult result, boolean newTestFormat) throws Exception { 518 checkResult(result, EXAMPLE_BUILD_FINGERPRINT, newTestFormat, true); 519 } 520 checkRunHistory(IInvocationResult result)521 static void checkRunHistory(IInvocationResult result) { 522 Map<String, String> buildInfo = result.getInvocationInfo(); 523 assertEquals("Incorrect run history", EXAMPLE_RUN_HISTORY, buildInfo.get(RUN_HISTORY)); 524 } 525 checkResult( IInvocationResult result, String expectedBuildFingerprint, boolean newTestFormat, boolean checkResultHistories)526 static void checkResult( 527 IInvocationResult result, String expectedBuildFingerprint, boolean newTestFormat, 528 boolean checkResultHistories) throws Exception { 529 assertEquals("Expected 3 passes", 3, result.countResults(TestStatus.PASS)); 530 if (checkResultHistories) { 531 assertEquals("Expected 1 failure", 1, result.countResults(TestStatus.FAIL)); 532 } else { 533 // CTS Verifier needs to check the condition of the test name with bracket, 534 // so adds one more test with failure result. 535 assertEquals("Expected 2 failure", 2, result.countResults(TestStatus.FAIL)); 536 } 537 538 Map<String, String> buildInfo = result.getInvocationInfo(); 539 assertEquals("Incorrect Build Fingerprint", expectedBuildFingerprint, result.getBuildFingerprint()); 540 assertEquals("Incorrect Build ID", EXAMPLE_BUILD_ID, buildInfo.get(BUILD_ID)); 541 assertEquals("Incorrect Build Product", 542 EXAMPLE_BUILD_PRODUCT, buildInfo.get(BUILD_PRODUCT)); 543 544 Set<String> serials = result.getDeviceSerials(); 545 assertTrue("Missing device", serials.contains(DEVICE_A)); 546 assertTrue("Missing device", serials.contains(DEVICE_B)); 547 assertEquals("Expected 2 devices", 2, serials.size()); 548 assertTrue("Incorrect devices", serials.contains(DEVICE_A) && serials.contains(DEVICE_B)); 549 assertEquals("Incorrect start time", START_MS, result.getStartTime()); 550 assertEquals("Incorrect test plan", SUITE_PLAN, result.getTestPlan()); 551 552 List<IModuleResult> modules = result.getModules(); 553 assertEquals("Expected 2 modules", 2, modules.size()); 554 555 IModuleResult moduleA = modules.get(0); 556 assertEquals("Expected 1 pass", 1, moduleA.countResults(TestStatus.PASS)); 557 assertEquals("Expected 0 failures", 0, moduleA.countResults(TestStatus.FAIL)); 558 assertEquals("Incorrect ABI", ABI, moduleA.getAbi()); 559 assertEquals("Incorrect name", NAME_A, moduleA.getName()); 560 assertEquals("Incorrect ID", ID_A, moduleA.getId()); 561 assertEquals("Incorrect runtime", Integer.parseInt(RUNTIME_A), moduleA.getRuntime()); 562 List<ICaseResult> moduleACases = moduleA.getResults(); 563 assertEquals("Expected 1 test case", 1, moduleACases.size()); 564 ICaseResult moduleACase = moduleACases.get(0); 565 assertEquals("Incorrect name", CLASS_A, moduleACase.getName()); 566 List<ITestResult> moduleAResults = moduleACase.getResults(); 567 assertEquals("Expected 1 result", 1, moduleAResults.size()); 568 ITestResult moduleATest1 = moduleAResults.get(0); 569 assertEquals("Incorrect name", METHOD_1, moduleATest1.getName()); 570 assertEquals("Incorrect result", TestStatus.PASS, moduleATest1.getResultStatus()); 571 assertNull("Unexpected bugreport", moduleATest1.getBugReport()); 572 assertNull("Unexpected log", moduleATest1.getLog()); 573 assertNull("Unexpected screenshot", moduleATest1.getScreenshot()); 574 assertNull("Unexpected message", moduleATest1.getMessage()); 575 assertNull("Unexpected stack trace", moduleATest1.getStackTrace()); 576 assertNull("Unexpected report", moduleATest1.getReportLog()); 577 578 IModuleResult moduleB = modules.get(1); 579 assertEquals("Expected 2 passes", 2, moduleB.countResults(TestStatus.PASS)); 580 if (checkResultHistories) { 581 assertEquals("Expected 1 failure", 1, moduleB.countResults(TestStatus.FAIL)); 582 } else { 583 // CTS Verifier needs to check the condition of the test name with bracket, 584 // so adds one more test with failure result. 585 assertEquals("Expected 2 failure", 2, moduleB.countResults(TestStatus.FAIL)); 586 } 587 assertEquals("Incorrect ABI", ABI, moduleB.getAbi()); 588 assertEquals("Incorrect name", NAME_B, moduleB.getName()); 589 assertEquals("Incorrect ID", ID_B, moduleB.getId()); 590 assertEquals("Incorrect runtime", Integer.parseInt(RUNTIME_B), moduleB.getRuntime()); 591 List<ICaseResult> moduleBCases = moduleB.getResults(); 592 assertEquals("Expected 1 test case", 1, moduleBCases.size()); 593 ICaseResult moduleBCase = moduleBCases.get(0); 594 assertEquals("Incorrect name", CLASS_B, moduleBCase.getName()); 595 List<ITestResult> moduleBResults = moduleBCase.getResults(); 596 if (checkResultHistories) { 597 assertEquals("Expected 3 results", 3, moduleBResults.size()); 598 } else { 599 // CTS Verifier needs to check the condition of the test name with bracket, 600 // so adds one more test with failure result. 601 assertEquals("Expected 4 results", 4, moduleBResults.size()); 602 } 603 ITestResult moduleBTest3 = moduleBResults.get(0); 604 assertEquals("Incorrect name", METHOD_3, moduleBTest3.getName()); 605 assertEquals("Incorrect result", TestStatus.FAIL, moduleBTest3.getResultStatus()); 606 assertEquals("Incorrect bugreport", BUG_REPORT, moduleBTest3.getBugReport()); 607 assertEquals("Incorrect log", LOGCAT, moduleBTest3.getLog()); 608 assertEquals("Incorrect screenshot", SCREENSHOT, moduleBTest3.getScreenshot()); 609 assertEquals("Incorrect message", MESSAGE, moduleBTest3.getMessage()); 610 assertEquals("Incorrect stack trace", STACK_TRACE, moduleBTest3.getStackTrace()); 611 assertNull("Unexpected report", moduleBTest3.getReportLog()); 612 List<TestResultHistory> resultHistories = moduleBTest3.getTestResultHistories(); 613 // Check if unit tests do parsing result, because tests for CTS Verifier do not parse it. 614 if (checkResultHistories) { 615 // For xTS except CTS Verifier. 616 assertNull("Unexpected test result history list", resultHistories); 617 } else { 618 // For CTS Verifier. 619 assertNotNull("Expected test result history list", resultHistories); 620 assertEquals("Expected 1 test result history", 1, resultHistories.size()); 621 for (TestResultHistory resultHistory : resultHistories) { 622 assertNotNull("Expected test result history", resultHistory); 623 assertEquals( 624 "Incorrect test name", 625 SUB_METHOD_3, 626 resultHistory.getSubTestName(METHOD_3, resultHistory.getTestName())); 627 for (TestResultHistory.ExecutionRecord execRecord : 628 resultHistory.getExecutionRecords()) { 629 assertEquals( 630 "Incorrect test start time", TEST_START_MS, execRecord.getStartTime()); 631 assertEquals("Incorrect test end time", TEST_END_MS, execRecord.getEndTime()); 632 assertEquals( 633 "Incorrect test is automated", 634 TEST_IS_AUTOMATED, 635 execRecord.getIsAutomated()); 636 } 637 } 638 } 639 ITestResult moduleBTest4 = moduleBResults.get(1); 640 assertEquals("Incorrect name", METHOD_4, moduleBTest4.getName()); 641 assertEquals("Incorrect result", TestStatus.PASS, moduleBTest4.getResultStatus()); 642 assertNull("Unexpected bugreport", moduleBTest4.getBugReport()); 643 assertNull("Unexpected log", moduleBTest4.getLog()); 644 assertNull("Unexpected screenshot", moduleBTest4.getScreenshot()); 645 assertNull("Unexpected message", moduleBTest4.getMessage()); 646 assertNull("Unexpected stack trace", moduleBTest4.getStackTrace()); 647 if (!newTestFormat) { 648 ReportLog report = moduleBTest4.getReportLog(); 649 assertNotNull("Expected report", report); 650 ReportLog.Metric summary = report.getSummary(); 651 assertNotNull("Expected report summary", summary); 652 assertEquals("Incorrect source", SUMMARY_SOURCE, summary.getSource()); 653 assertEquals("Incorrect message", SUMMARY_MESSAGE, summary.getMessage()); 654 assertEquals("Incorrect type", ResultType.HIGHER_BETTER, summary.getType()); 655 assertEquals("Incorrect unit", ResultUnit.SCORE, summary.getUnit()); 656 assertTrue( 657 "Incorrect values", 658 Arrays.equals(new double[] {SUMMARY_VALUE}, summary.getValues())); 659 } 660 ITestResult moduleBTest5 = moduleBResults.get(2); 661 assertEquals("Incorrect name", METHOD_5, moduleBTest5.getName()); 662 assertEquals("Incorrect result", TestStatus.PASS, moduleBTest5.getResultStatus()); 663 assertTrue("Expected skipped", moduleBTest5.isSkipped()); 664 assertNull("Unexpected bugreport", moduleBTest5.getBugReport()); 665 assertNull("Unexpected log", moduleBTest5.getLog()); 666 assertNull("Unexpected screenshot", moduleBTest5.getScreenshot()); 667 assertNull("Unexpected message", moduleBTest5.getMessage()); 668 assertNull("Unexpected stack trace", moduleBTest5.getStackTrace()); 669 assertNull("Unexpected report", moduleBTest5.getReportLog()); 670 if (!checkResultHistories) { 671 // CTS Verifier needs to check the condition of the test name with bracket, 672 // so adds one more test with failure result. 673 ITestResult moduleBTest6 = moduleBResults.get(3); 674 assertEquals("Incorrect name", METHOD_6_BRACKETS, moduleBTest6.getName()); 675 assertEquals("Incorrect result", TestStatus.FAIL, moduleBTest6.getResultStatus()); 676 List<TestResultHistory> resultHistories2 = moduleBTest6.getTestResultHistories(); 677 assertNotNull("Expected test result history list", resultHistories2); 678 assertEquals("Expected 1 test result history", 1, resultHistories2.size()); 679 for (TestResultHistory resultHistory : resultHistories2) { 680 assertNotNull("Expected test result history", resultHistory); 681 assertEquals( 682 "Incorrect test name", 683 SUB_METHOD_6_BRACKETS, 684 resultHistory.getSubTestName( 685 METHOD_6_BRACKETS, resultHistory.getTestName())); 686 for (TestResultHistory.ExecutionRecord execRecord : 687 resultHistory.getExecutionRecords()) { 688 assertEquals( 689 "Incorrect test start time", TEST_START_MS, execRecord.getStartTime()); 690 assertEquals("Incorrect test end time", TEST_END_MS, execRecord.getEndTime()); 691 assertEquals( 692 "Incorrect test is automated", 693 TEST_IS_AUTOMATED, 694 execRecord.getIsAutomated()); 695 } 696 } 697 } 698 } 699 700 /** Return all XML nodes that match the given xPathExpression. */ getXmlNodes(String xml, String xPathExpression)701 private NodeList getXmlNodes(String xml, String xPathExpression) 702 throws XPathExpressionException { 703 704 InputSource inputSource = new InputSource(new StringReader(xml)); 705 XPath xpath = XPathFactory.newInstance().newXPath(); 706 return (NodeList) xpath.evaluate(xPathExpression, inputSource, XPathConstants.NODESET); 707 } 708 709 /** Assert that the XML contains a node matching the given xPathExpression. */ assertXmlContainsNode(String xml, String xPathExpression)710 private NodeList assertXmlContainsNode(String xml, String xPathExpression) 711 throws XPathExpressionException { 712 NodeList nodes = getXmlNodes(xml, xPathExpression); 713 assertNotNull( 714 String.format("XML '%s' returned null for xpath '%s'.", xml, xPathExpression), 715 nodes); 716 assertTrue( 717 String.format( 718 "XML '%s' should have returned at least 1 node for xpath '%s', " 719 + "but returned %s nodes instead.", 720 xml, xPathExpression, nodes.getLength()), 721 nodes.getLength() >= 1); 722 return nodes; 723 } 724 725 /** 726 * Assert that the XML contains a node matching the given xPathExpression and that the node has 727 * a given value. 728 */ assertXmlContainsAttribute( String xml, String xPathExpression, String attributeName, String attributeValue)729 private void assertXmlContainsAttribute( 730 String xml, String xPathExpression, String attributeName, String attributeValue) 731 throws XPathExpressionException { 732 NodeList nodes = assertXmlContainsNode(xml, xPathExpression); 733 boolean found = false; 734 735 for (int i = 0; i < nodes.getLength(); i++) { 736 Element element = (Element) nodes.item(i); 737 String value = element.getAttribute(attributeName); 738 if (attributeValue.equals(value)) { 739 found = true; 740 break; 741 } 742 } 743 744 assertTrue( 745 String.format( 746 "xPath '%s' should contain attribute '%s' but does not. XML: '%s'", 747 xPathExpression, attributeName, xml), 748 found); 749 } 750 } 751