| /* |
| * Copyright (C) 2015 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package com.android.compatibility.common.util; |
| |
| import org.xmlpull.v1.XmlPullParser; |
| import org.xmlpull.v1.XmlPullParserException; |
| import org.xmlpull.v1.XmlPullParserFactory; |
| import org.xmlpull.v1.XmlSerializer; |
| |
| import java.io.File; |
| import java.io.FileNotFoundException; |
| import java.io.FileOutputStream; |
| import java.io.FileReader; |
| import java.io.IOException; |
| import java.io.OutputStream; |
| import java.net.InetAddress; |
| import java.net.UnknownHostException; |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.Map.Entry; |
| import java.util.Set; |
| |
| /** |
| * Handles conversion of results to/from files. |
| */ |
| public class ResultHandler { |
| |
| private static final String ENCODING = "UTF-8"; |
| private static final String TYPE = "org.kxml2.io.KXmlParser,org.kxml2.io.KXmlSerializer"; |
| private static final String NS = null; |
| private static final String RESULT_FILE_VERSION = "5.0"; |
| /* package */ static final String TEST_RESULT_FILE_NAME = "test_result.xml"; |
| |
| // XML constants |
| private static final String ABI_ATTR = "abi"; |
| private static final String BUGREPORT_TAG = "BugReport"; |
| private static final String BUILD_TAG = "Build"; |
| private static final String CASE_TAG = "TestCase"; |
| private static final String DEVICES_ATTR = "devices"; |
| private static final String END_TIME_ATTR = "end"; |
| private static final String FAILED_ATTR = "failed"; |
| private static final String FAILURE_TAG = "Failure"; |
| private static final String HOST_NAME_ATTR = "host_name"; |
| private static final String JAVA_VENDOR_ATTR = "java_vendor"; |
| private static final String JAVA_VERSION_ATTR = "java_version"; |
| private static final String LOGCAT_TAG = "Logcat"; |
| private static final String MESSAGE_ATTR = "message"; |
| private static final String MODULE_TAG = "Module"; |
| private static final String NAME_ATTR = "name"; |
| private static final String NOT_EXECUTED_ATTR = "not_executed"; |
| private static final String OS_ARCH_ATTR = "os_arch"; |
| private static final String OS_NAME_ATTR = "os_name"; |
| private static final String OS_VERSION_ATTR = "os_version"; |
| private static final String PASS_ATTR = "pass"; |
| private static final String REPORT_VERSION_ATTR = "report_version"; |
| private static final String REFERENCE_URL_ATTR = "reference_url"; |
| private static final String RESULT_ATTR = "result"; |
| private static final String RESULT_TAG = "Result"; |
| private static final String SCREENSHOT_TAG = "Screenshot"; |
| private static final String STACK_TAG = "StackTrace"; |
| private static final String START_TIME_ATTR = "start"; |
| private static final String SUITE_NAME_ATTR = "suite_name"; |
| private static final String SUITE_PLAN_ATTR = "suite_plan"; |
| private static final String SUITE_VERSION_ATTR = "suite_version"; |
| private static final String SUMMARY_TAG = "Summary"; |
| private static final String TEST_TAG = "Test"; |
| |
| /** |
| * @param resultsDir |
| */ |
| public static List<IInvocationResult> getResults(File resultsDir) { |
| List<IInvocationResult> results = new ArrayList<>(); |
| File[] files = resultsDir.listFiles(); |
| if (files == null || files.length == 0) { |
| // No results, just return the empty list |
| return results; |
| } |
| for (File resultDir : files) { |
| if (!resultDir.isDirectory()) { |
| continue; |
| } |
| try { |
| File resultFile = new File(resultDir, TEST_RESULT_FILE_NAME); |
| if (!resultFile.exists()) { |
| continue; |
| } |
| IInvocationResult invocation = new InvocationResult(resultDir); |
| XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); |
| XmlPullParser parser = factory.newPullParser(); |
| parser.setInput(new FileReader(resultFile)); |
| parser.nextTag(); |
| parser.require(XmlPullParser.START_TAG, NS, RESULT_TAG); |
| invocation.setStartTime(Long.valueOf( |
| parser.getAttributeValue(NS, START_TIME_ATTR))); |
| invocation.setTestPlan(parser.getAttributeValue(NS, SUITE_PLAN_ATTR)); |
| String deviceList = parser.getAttributeValue(NS, DEVICES_ATTR); |
| for (String device : deviceList.split(",")) { |
| invocation.addDeviceSerial(device); |
| } |
| parser.nextTag(); |
| parser.require(XmlPullParser.START_TAG, NS, BUILD_TAG); |
| // TODO(stuartscott): may want to reload these incase the retry was done with |
| // --skip-device-info flag |
| parser.nextTag(); |
| parser.require(XmlPullParser.END_TAG, NS, BUILD_TAG); |
| parser.nextTag(); |
| parser.require(XmlPullParser.START_TAG, NS, SUMMARY_TAG); |
| parser.nextTag(); |
| parser.require(XmlPullParser.END_TAG, NS, SUMMARY_TAG); |
| while (parser.nextTag() == XmlPullParser.START_TAG) { |
| parser.require(XmlPullParser.START_TAG, NS, MODULE_TAG); |
| String name = parser.getAttributeValue(NS, NAME_ATTR); |
| String abi = parser.getAttributeValue(NS, ABI_ATTR); |
| String id = AbiUtils.createId(abi, name); |
| IModuleResult module = invocation.getOrCreateModule(id); |
| while (parser.nextTag() == XmlPullParser.START_TAG) { |
| parser.require(XmlPullParser.START_TAG, NS, CASE_TAG); |
| String caseName = parser.getAttributeValue(NS, NAME_ATTR); |
| ICaseResult testCase = module.getOrCreateResult(caseName); |
| while (parser.nextTag() == XmlPullParser.START_TAG) { |
| parser.require(XmlPullParser.START_TAG, NS, TEST_TAG); |
| String testName = parser.getAttributeValue(NS, NAME_ATTR); |
| ITestResult test = testCase.getOrCreateResult(testName); |
| String result = parser.getAttributeValue(NS, RESULT_ATTR); |
| test.setResultStatus(TestStatus.getStatus(result)); |
| if (parser.nextTag() == XmlPullParser.START_TAG) { |
| if (parser.getName().equals(FAILURE_TAG)) { |
| test.setMessage(parser.getAttributeValue(NS, MESSAGE_ATTR)); |
| if (parser.nextTag() == XmlPullParser.START_TAG) { |
| parser.require(XmlPullParser.START_TAG, NS, STACK_TAG); |
| test.setStackTrace(parser.nextText()); |
| parser.require(XmlPullParser.END_TAG, NS, STACK_TAG); |
| parser.nextTag(); |
| } |
| parser.require(XmlPullParser.END_TAG, NS, FAILURE_TAG); |
| parser.nextTag(); |
| } else if (parser.getName().equals(BUGREPORT_TAG)) { |
| test.setBugReport(parser.nextText()); |
| parser.nextTag(); |
| } else if (parser.getName().equals(LOGCAT_TAG)) { |
| test.setLog(parser.nextText()); |
| parser.nextTag(); |
| } else if (parser.getName().equals(SCREENSHOT_TAG)) { |
| test.setScreenshot(parser.nextText()); |
| parser.nextTag(); |
| } else { |
| test.setReportLog(ReportLog.parse(parser)); |
| parser.nextTag(); |
| } |
| } |
| parser.require(XmlPullParser.END_TAG, NS, TEST_TAG); |
| } |
| parser.require(XmlPullParser.END_TAG, NS, CASE_TAG); |
| } |
| parser.require(XmlPullParser.END_TAG, NS, MODULE_TAG); |
| } |
| parser.require(XmlPullParser.END_TAG, NS, RESULT_TAG); |
| results.add(invocation); |
| } catch (XmlPullParserException e) { |
| e.printStackTrace(); |
| } catch (FileNotFoundException e) { |
| e.printStackTrace(); |
| } catch (IOException e) { |
| e.printStackTrace(); |
| } |
| } |
| return results; |
| } |
| |
| /** |
| * @param result |
| * @param resultDir |
| * @param startTime |
| * @param referenceUrl A nullable string that can contain a URL to a related data |
| * @return The result file created. |
| * @throws IOException |
| * @throws XmlPullParserException |
| */ |
| public static File writeResults(String suiteName, String suiteVersion, String suitePlan, |
| IInvocationResult result, File resultDir, long startTime, long endTime, |
| String referenceUrl) throws IOException, XmlPullParserException { |
| int passed = result.countResults(TestStatus.PASS); |
| int failed = result.countResults(TestStatus.FAIL); |
| int notExecuted = result.countResults(TestStatus.NOT_EXECUTED); |
| File resultFile = new File(resultDir, TEST_RESULT_FILE_NAME); |
| OutputStream stream = new FileOutputStream(resultFile); |
| XmlSerializer serializer = XmlPullParserFactory.newInstance(TYPE, null).newSerializer(); |
| serializer.setOutput(stream, ENCODING); |
| serializer.startDocument(ENCODING, false); |
| serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); |
| serializer.processingInstruction( |
| "xml-stylesheet type=\"text/xsl\" href=\"compatibility-result.xsl\""); |
| serializer.startTag(NS, RESULT_TAG); |
| serializer.attribute(NS, START_TIME_ATTR, String.valueOf(startTime)); |
| serializer.attribute(NS, END_TIME_ATTR, String.valueOf(endTime)); |
| serializer.attribute(NS, SUITE_NAME_ATTR, suiteName); |
| serializer.attribute(NS, SUITE_VERSION_ATTR, suiteVersion); |
| serializer.attribute(NS, SUITE_PLAN_ATTR, suitePlan); |
| serializer.attribute(NS, REPORT_VERSION_ATTR, RESULT_FILE_VERSION); |
| if (referenceUrl != null) { |
| serializer.attribute(NS, REFERENCE_URL_ATTR, referenceUrl); |
| } |
| |
| // Device Info |
| Set<String> devices = result.getDeviceSerials(); |
| StringBuilder deviceList = new StringBuilder(); |
| boolean first = true; |
| for (String device : devices) { |
| if (first) { |
| first = false; |
| } else { |
| deviceList.append(","); |
| } |
| deviceList.append(device); |
| } |
| serializer.attribute(NS, DEVICES_ATTR, deviceList.toString()); |
| |
| // Host Info |
| String hostName = ""; |
| try { |
| hostName = InetAddress.getLocalHost().getHostName(); |
| } catch (UnknownHostException ignored) {} |
| serializer.attribute(NS, HOST_NAME_ATTR, hostName); |
| serializer.attribute(NS, OS_NAME_ATTR, System.getProperty("os.name")); |
| serializer.attribute(NS, OS_VERSION_ATTR, System.getProperty("os.version")); |
| serializer.attribute(NS, OS_ARCH_ATTR, System.getProperty("os.arch")); |
| serializer.attribute(NS, JAVA_VENDOR_ATTR, System.getProperty("java.vendor")); |
| serializer.attribute(NS, JAVA_VERSION_ATTR, System.getProperty("java.version")); |
| |
| // Build Info |
| serializer.startTag(NS, BUILD_TAG); |
| for (Entry<String, String> entry : result.getBuildInfo().entrySet()) { |
| serializer.attribute(NS, entry.getKey(), entry.getValue()); |
| } |
| serializer.endTag(NS, BUILD_TAG); |
| |
| // Summary |
| serializer.startTag(NS, SUMMARY_TAG); |
| serializer.attribute(NS, PASS_ATTR, Integer.toString(passed)); |
| serializer.attribute(NS, FAILED_ATTR, Integer.toString(failed)); |
| serializer.attribute(NS, NOT_EXECUTED_ATTR, Integer.toString(notExecuted)); |
| serializer.endTag(NS, SUMMARY_TAG); |
| |
| // Results |
| for (IModuleResult module : result.getModules()) { |
| serializer.startTag(NS, MODULE_TAG); |
| serializer.attribute(NS, NAME_ATTR, module.getName()); |
| serializer.attribute(NS, ABI_ATTR, module.getAbi()); |
| for (ICaseResult cr : module.getResults()) { |
| serializer.startTag(NS, CASE_TAG); |
| serializer.attribute(NS, NAME_ATTR, cr.getName()); |
| for (ITestResult r : cr.getResults()) { |
| serializer.startTag(NS, TEST_TAG); |
| serializer.attribute(NS, RESULT_ATTR, r.getResultStatus().getValue()); |
| serializer.attribute(NS, NAME_ATTR, r.getName()); |
| String message = r.getMessage(); |
| if (message != null) { |
| serializer.startTag(NS, FAILURE_TAG); |
| serializer.attribute(NS, MESSAGE_ATTR, message); |
| String stackTrace = r.getStackTrace(); |
| if (stackTrace != null) { |
| serializer.startTag(NS, STACK_TAG); |
| serializer.text(stackTrace); |
| serializer.endTag(NS, STACK_TAG); |
| } |
| serializer.endTag(NS, FAILURE_TAG); |
| } |
| String bugreport = r.getBugReport(); |
| if (bugreport != null) { |
| serializer.startTag(NS, BUGREPORT_TAG); |
| serializer.text(bugreport); |
| serializer.endTag(NS, BUGREPORT_TAG); |
| } |
| String logcat = r.getLog(); |
| if (logcat != null) { |
| serializer.startTag(NS, LOGCAT_TAG); |
| serializer.text(logcat); |
| serializer.endTag(NS, LOGCAT_TAG); |
| } |
| String screenshot = r.getScreenshot(); |
| if (screenshot != null) { |
| serializer.startTag(NS, SCREENSHOT_TAG); |
| serializer.text(screenshot); |
| serializer.endTag(NS, SCREENSHOT_TAG); |
| } |
| ReportLog report = r.getReportLog(); |
| if (report != null) { |
| ReportLog.serialize(serializer, report); |
| } |
| serializer.endTag(NS, TEST_TAG); |
| } |
| serializer.endTag(NS, CASE_TAG); |
| } |
| serializer.endTag(NS, MODULE_TAG); |
| } |
| serializer.endDocument(); |
| return resultFile; |
| } |
| |
| } |