| /* |
| * Copyright (C) 2008 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.cts; |
| |
| import com.android.cts.TestDevice.DeviceParameterCollector; |
| |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.ProcessingInstruction; |
| |
| import java.io.File; |
| import java.net.InetAddress; |
| import java.net.UnknownHostException; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Date; |
| import java.util.regex.Matcher; |
| import java.util.regex.Pattern; |
| |
| import javax.xml.parsers.DocumentBuilderFactory; |
| |
| /** |
| * Store the information of a test plan. |
| */ |
| public class TestSessionLog extends XMLResourceHandler { |
| private static final String EXPR_TEST_FAILED = ".+\\((\\S+):(\\d+)\\)"; |
| private static Pattern mTestFailedPattern = Pattern.compile(EXPR_TEST_FAILED); |
| private static final String ATTRIBUTE_NAME = "name"; |
| static final String ATTRIBUTE_RESULT = "result"; |
| private static final String ATTRIBUTE_VERSION = "version"; |
| private static final String ATTRIBUTE_DIGEST = "digest"; |
| private static final String ATTRIBUTE_KNOWN_FAILURE = "KnownFailure"; |
| |
| public static final String CTS_RESULT_FILE_NAME = "testResult.xml"; |
| private static final String CTS_RESULT_FILE_VERSION = "1.5"; |
| |
| static final String ATTRIBUTE_STARTTIME = "starttime"; |
| static final String ATTRIBUTE_ENDTIME = "endtime"; |
| static final String ATTRIBUTE_TESTPLAN = "testPlan"; |
| static final String ATTRIBUTE_RESOLUTION = "resolution"; |
| static final String ATTRIBUTE_SUBSCRIBER_ID = "subscriberId"; |
| static final String ATTRIBUTE_DEVICE_ID = "deviceID"; |
| static final String ATTRIBUTE_BUILD_ID = "buildID"; |
| static final String ATTRIBUTE_BUILD_VERSION = "buildVersion"; |
| static final String ATTRIBUTE_ANDROID_PLATFORM_VERSION = "androidPlatformVersion"; |
| static final String ATTRIBUTE_LOCALES = "locales"; |
| static final String ATTRIBUTE_XDPI = "Xdpi"; |
| static final String ATTRIBUTE_YDPI = "Ydpi"; |
| static final String ATTRIBUTE_TOUCH = "touch"; |
| static final String ATTRIBUTE_NAVIGATION = "navigation"; |
| static final String ATTRIBUTE_KEYPAD = "keypad"; |
| static final String ATTRIBUTE_NETWORK = "network"; |
| static final String ATTRIBUTE_IMEI = "imei"; |
| static final String ATTRIBUTE_IMSI = "imsi"; |
| static final String ATTRIBUTE_BUILD_NAME = "buildName"; |
| static final String ATTRIBUTE_ARCH = "arch"; |
| static final String ATTRIBUTE_VALUE = "value"; |
| static final String ATTRIBUTE_AVAILABLE = "available"; |
| static final String ATTRIBUTE_TYPE = "type"; |
| static final String ATTRIBUTE_UID = "uid"; |
| static final String ATTRIBUTE_OPEN_GL_ES_VERSION = "openGlEsVersion"; |
| |
| static final String ATTRIBUTE_PASS = "pass"; |
| static final String ATTRIBUTE_FAILED = "failed"; |
| static final String ATTRIBUTE_TIMEOUT = "timeout"; |
| static final String ATTRIBUTE_NOT_EXECUTED = "notExecuted"; |
| |
| static final String TAG_DEVICEINFO = "DeviceInfo"; |
| static final String TAG_HOSTINFO = "HostInfo"; |
| static final String TAG_OSINFO = "Os"; |
| static final String TAG_JAVA = "Java"; |
| static final String TAG_CTS = "Cts"; |
| static final String TAG_INTVALUE = "IntValue"; |
| static final String TAG_SUMMARY = "Summary"; |
| static final String TAG_SCREEN = "Screen"; |
| static final String TAG_BUILD_INFO = "BuildInfo"; |
| static final String TAG_FEATURE_INFO = "FeatureInfo"; |
| static final String TAG_FEATURE = "Feature"; |
| static final String TAG_PROCESS_INFO = "ProcessInfo"; |
| static final String TAG_PROCESS = "Process"; |
| static final String TAG_PHONE_SUB_INFO = "PhoneSubInfo"; |
| static final String TAG_TEST_RESULT = "TestResult"; |
| static final String TAG_TESTPACKAGE = "TestPackage"; |
| static final String TAG_TESTSUITE = "TestSuite"; |
| static final String TAG_TESTCASE = "TestCase"; |
| static final String TAG_FAILED_SCENE = "FailedScene"; |
| static final String TAG_STACK_TRACE = "StackTrace"; |
| static final String TAG_FAILED_MESSAGE = "message"; |
| |
| private Collection<TestPackage> mTestPackages; |
| private Date mSessionStartTime; |
| private Date mSessionEndTime; |
| private String mResultPath; |
| private String mResultDir; |
| private String mTestPlanName; |
| |
| private ArrayList<DeviceParameterCollector> mDeviceParameterBase; |
| |
| public TestSessionLog(final Collection<TestPackage> packages, final String testPlanName) { |
| mTestPackages = packages; |
| |
| mDeviceParameterBase = new ArrayList<TestDevice.DeviceParameterCollector>(); |
| mTestPlanName = testPlanName; |
| |
| mSessionStartTime = new Date(); |
| mSessionEndTime = new Date(); |
| } |
| |
| /** |
| * Get the test plan name. |
| * |
| * @return The test plan name. |
| */ |
| public String getTestPlanName() { |
| return mTestPlanName; |
| } |
| |
| /** |
| * Get all result of this session. |
| * |
| * @return All the tests with a result code of this session. |
| */ |
| public Collection<Test> getAllResults() { |
| if (mTestPackages == null || mTestPackages.size() == 0) { |
| return null; |
| } |
| |
| ArrayList<Test> results = new ArrayList<Test>(); |
| for (TestPackage p : mTestPackages) { |
| results.addAll(p.getTests()); |
| } |
| |
| return results; |
| } |
| |
| /** |
| * Get test list according to the result type code. |
| * |
| * @param resCode The result code. |
| * @return The list of {@link Test}. |
| */ |
| public Collection<Test> getTestList(int resCode) { |
| if ((resCode < CtsTestResult.CODE_FIRST) |
| || (resCode > CtsTestResult.CODE_LAST)) { |
| return null; |
| } |
| |
| ArrayList<Test> tests = new ArrayList<Test>(); |
| for (Test test : getAllResults()) { |
| if (resCode == test.getResult().getResultCode()) { |
| tests.add(test); |
| } |
| } |
| |
| return tests; |
| } |
| |
| /** |
| * Get TestSession start time |
| * |
| * @return The start time. |
| */ |
| public Date getStartTime() { |
| return mSessionStartTime; |
| } |
| |
| /** |
| * Get TestSession end time |
| * |
| * @return The end time. |
| */ |
| public Date getEndTime() { |
| return mSessionEndTime; |
| } |
| |
| /** |
| * Get test packages. |
| * |
| * @return The test packages. |
| */ |
| public Collection<TestPackage> getTestPackages() { |
| return mTestPackages; |
| } |
| |
| /** |
| * Get the path to the XML result file. |
| * |
| * @return The result path. |
| */ |
| public String getResultPath() { |
| return mResultPath; |
| } |
| |
| /** |
| * Get the result directory. This is the directory that all result files |
| * should go into. |
| */ |
| public String getResultDir() { |
| return mResultDir; |
| } |
| |
| /** |
| * set TestSession start time |
| * |
| * @param time The start time. |
| */ |
| public void setStartTime(final long time) { |
| mSessionStartTime.setTime(time); |
| |
| String startTimeStr = HostUtils.getFormattedTimeString(time, "_", ".", "."); |
| mResultDir = HostConfig.getInstance().getResultRepository().getRoot() |
| + File.separator + startTimeStr; |
| mResultPath = mResultDir + File.separator + CTS_RESULT_FILE_NAME; |
| // Make sure the result directory exists |
| new File(mResultDir).mkdirs(); |
| } |
| |
| /** |
| * set TestSession end time |
| * |
| * @param time The end time. |
| */ |
| public void setEndTime(final long time) { |
| mSessionEndTime.setTime(time); |
| } |
| |
| /** |
| * Calling this functions indicates that the TestSession is complete. This |
| * indicates to the TestSessionLog that it is time to store the results |
| * to the filesystem. |
| */ |
| public void sessionComplete() { |
| try { |
| writeToFile(new File(mResultPath), createResultDoc()); |
| // Now zip up the results directory so we have something nice |
| // that people can upload. |
| HostUtils.zipUpDirectory(mResultDir, |
| mResultDir + ".zip", |
| new HostUtils.ZipFilenameTransformer() { |
| public String transform(String filename) { |
| if (filename.startsWith(mResultDir)) { |
| return filename.substring(mResultDir.length() + 1); |
| } |
| return filename; |
| } |
| }); |
| } catch (Exception e) { |
| Log.e("Got exception when trying to write to result file", e); |
| } |
| HostConfig.getInstance().extractResultResources(mResultDir); |
| } |
| |
| /** |
| * Create result Doc in XML format. |
| * |
| * @return Result document. |
| */ |
| protected Document createResultDoc() { |
| try { |
| |
| Document doc = DocumentBuilderFactory.newInstance() |
| .newDocumentBuilder().newDocument(); |
| ProcessingInstruction pr = doc.createProcessingInstruction( |
| "xml-stylesheet", "type=\"text/xsl\" href=\"cts_result.xsl\""); |
| doc.appendChild(pr); |
| Node root = doc.createElement(TAG_TEST_RESULT); |
| doc.appendChild(root); |
| |
| setAttribute(doc, root, ATTRIBUTE_VERSION, CTS_RESULT_FILE_VERSION); |
| setAttribute(doc, root, ATTRIBUTE_STARTTIME, HostUtils.dateToString(mSessionStartTime)); |
| setAttribute(doc, root, ATTRIBUTE_ENDTIME, HostUtils.dateToString(mSessionEndTime)); |
| setAttribute(doc, root, ATTRIBUTE_TESTPLAN, mTestPlanName); |
| |
| // set device information |
| for (int i = 0; i < mDeviceParameterBase.size(); i ++) { |
| DeviceParameterCollector bldInfo = mDeviceParameterBase.get(i); |
| // set device setting |
| Node deviceSettingNode = doc.createElement(TAG_DEVICEINFO); |
| |
| Node screenNode = doc.createElement(TAG_SCREEN); |
| setAttribute(doc, screenNode, ATTRIBUTE_RESOLUTION, bldInfo.getScreenResolution()); |
| deviceSettingNode.appendChild(screenNode); |
| Node simCardNode = doc.createElement(TAG_PHONE_SUB_INFO); |
| setAttribute(doc, simCardNode, ATTRIBUTE_SUBSCRIBER_ID, bldInfo.getPhoneNumber()); |
| deviceSettingNode.appendChild(simCardNode); |
| root.appendChild(deviceSettingNode); |
| |
| Node devInfoNode = doc.createElement(TAG_BUILD_INFO); |
| setAttribute(doc, devInfoNode, ATTRIBUTE_DEVICE_ID, bldInfo.getSerialNumber()); |
| setAttribute(doc, devInfoNode, ATTRIBUTE_BUILD_ID, bldInfo.getBuildId()); |
| setAttribute(doc, devInfoNode, ATTRIBUTE_BUILD_NAME, bldInfo.getProductName()); |
| setAttribute(doc, devInfoNode, ATTRIBUTE_BUILD_VERSION, |
| bldInfo.getBuildVersion()); |
| setAttribute(doc, devInfoNode, ATTRIBUTE_ANDROID_PLATFORM_VERSION, |
| bldInfo.getAndroidPlatformVersion()); |
| setAttribute(doc, devInfoNode, ATTRIBUTE_LOCALES, bldInfo.getLocales()); |
| setAttribute(doc, devInfoNode, ATTRIBUTE_XDPI, bldInfo.getXdpi()); |
| setAttribute(doc, devInfoNode, ATTRIBUTE_YDPI, bldInfo.getYdpi()); |
| setAttribute(doc, devInfoNode, ATTRIBUTE_TOUCH, bldInfo.getTouchInfo()); |
| setAttribute(doc, devInfoNode, ATTRIBUTE_NAVIGATION, bldInfo.getNavigation()); |
| setAttribute(doc, devInfoNode, ATTRIBUTE_KEYPAD, bldInfo.getKeypad()); |
| setAttribute(doc, devInfoNode, ATTRIBUTE_NETWORK, bldInfo.getNetwork()); |
| setAttribute(doc, devInfoNode, ATTRIBUTE_IMEI, bldInfo.getIMEI()); |
| setAttribute(doc, devInfoNode, ATTRIBUTE_IMSI, bldInfo.getIMSI()); |
| setAttribute(doc, devInfoNode, ATTRIBUTE_OPEN_GL_ES_VERSION, |
| bldInfo.getOpenGlEsVersion()); |
| |
| setAttribute(doc, devInfoNode, |
| DeviceParameterCollector.BUILD_FINGERPRINT, bldInfo.getBuildFingerPrint()); |
| setAttribute(doc, devInfoNode, |
| DeviceParameterCollector.BUILD_TYPE, bldInfo.getBuildType()); |
| setAttribute(doc, devInfoNode, |
| DeviceParameterCollector.BUILD_MODEL, bldInfo.getBuildModel()); |
| setAttribute(doc, devInfoNode, |
| DeviceParameterCollector.BUILD_BRAND, bldInfo.getBuildBrand()); |
| setAttribute(doc, devInfoNode, |
| DeviceParameterCollector.BUILD_BOARD, bldInfo.getBuildBoard()); |
| setAttribute(doc, devInfoNode, |
| DeviceParameterCollector.BUILD_DEVICE, bldInfo.getBuildDevice()); |
| setAttribute(doc, devInfoNode, |
| DeviceParameterCollector.BUILD_ABI, bldInfo.getBuildAbi()); |
| setAttribute(doc, devInfoNode, |
| DeviceParameterCollector.BUILD_ABI2, bldInfo.getBuildAbi2()); |
| |
| deviceSettingNode.appendChild(devInfoNode); |
| |
| addFeatureInfo(doc, deviceSettingNode, bldInfo); |
| addProcessInfo(doc, deviceSettingNode, bldInfo); |
| } |
| |
| Node hostInfo = doc.createElement(TAG_HOSTINFO); |
| root.appendChild(hostInfo); |
| String hostName = ""; |
| try { |
| hostName = InetAddress.getLocalHost().getHostName(); |
| } catch (UnknownHostException ignored) {} |
| setAttribute(doc, hostInfo, ATTRIBUTE_NAME, hostName); |
| Node osInfo = doc.createElement(TAG_OSINFO); |
| hostInfo.appendChild(osInfo); |
| setAttribute(doc, osInfo, ATTRIBUTE_NAME, System.getProperty("os.name")); |
| setAttribute(doc, osInfo, ATTRIBUTE_VERSION, System.getProperty("os.version")); |
| setAttribute(doc, osInfo, ATTRIBUTE_ARCH, System.getProperty("os.arch")); |
| Node javaInfo = doc.createElement(TAG_JAVA); |
| hostInfo.appendChild(javaInfo); |
| setAttribute(doc, javaInfo, ATTRIBUTE_NAME, System.getProperty("java.vendor")); |
| setAttribute(doc, javaInfo, ATTRIBUTE_VERSION, System.getProperty("java.version")); |
| Node ctsInfo = doc.createElement(TAG_CTS); |
| hostInfo.appendChild(ctsInfo); |
| setAttribute(doc, ctsInfo, ATTRIBUTE_VERSION, Version.asString()); |
| for (HostConfig.Ints i : HostConfig.Ints.values()) { |
| Node intValue = doc.createElement(TAG_INTVALUE); |
| ctsInfo.appendChild(intValue); |
| setAttribute(doc, intValue, ATTRIBUTE_NAME, i.name()); |
| setAttribute(doc, intValue, ATTRIBUTE_VALUE, i.value()); |
| } |
| |
| int passNum = getTestList(CtsTestResult.CODE_PASS).size(); |
| int failNum = getTestList(CtsTestResult.CODE_FAIL).size(); |
| int notExecutedNum = getTestList(CtsTestResult.CODE_NOT_EXECUTED).size(); |
| int timeOutNum = getTestList(CtsTestResult.CODE_TIMEOUT).size(); |
| Node summaryNode = doc.createElement(TAG_SUMMARY); |
| root.appendChild(summaryNode); |
| setAttribute(doc, summaryNode, ATTRIBUTE_PASS, passNum); |
| setAttribute(doc, summaryNode, ATTRIBUTE_FAILED, failNum); |
| setAttribute(doc, summaryNode, ATTRIBUTE_NOT_EXECUTED, notExecutedNum); |
| setAttribute(doc, summaryNode, ATTRIBUTE_TIMEOUT, timeOutNum); |
| |
| for (TestPackage testPackage : mTestPackages) { |
| Node testPackageNode = doc.createElement(TAG_TESTPACKAGE); |
| setAttribute(doc, testPackageNode, ATTRIBUTE_NAME, testPackage.getAppBinaryName()); |
| setAttribute(doc, testPackageNode, TestSessionBuilder.ATTRIBUTE_APP_PACKAGE_NAME, |
| testPackage.getAppPackageName()); |
| setAttribute(doc, testPackageNode, ATTRIBUTE_DIGEST, |
| testPackage.getMessageDigest()); |
| |
| if (testPackage instanceof SignatureCheckPackage) { |
| setAttribute(doc, testPackageNode, |
| TestSessionBuilder.ATTRIBUTE_SIGNATURE_CHECK, "true"); |
| } |
| |
| for (TestSuite testSuite : testPackage.getTestSuites()) { |
| outputTestSuite(doc, testPackage, testPackageNode, testSuite); |
| } |
| root.appendChild(testPackageNode); |
| } |
| |
| return doc; |
| } catch (Exception e) { |
| Log.e("create result doc failed", e); |
| } |
| return null; |
| } |
| |
| /** |
| * Creates a {@link #TAG_FEATURE_INFO} tag with {@link #TAG_FEATURE} elements indicating |
| * what features are supported by the device. It parses a string from the deviceInfo argument |
| * that is in the form of "feature1:true;feature2:false;featuer3;true;" with a trailing |
| * semi-colon. |
| * |
| * <pre> |
| * <FeatureInfo> |
| * <Feature name="android.name.of.feature" available="true" /> |
| * ... |
| * </FeatureInfo> |
| * </pre> |
| * @param document used to create elements |
| * @param parentNode to attach the FeatureInfo element to |
| * @param deviceInfo to get the feature data from |
| */ |
| private void addFeatureInfo(Document document, Node parentNode, |
| DeviceParameterCollector deviceInfo) { |
| Node featureInfo = document.createElement(TAG_FEATURE_INFO); |
| parentNode.appendChild(featureInfo); |
| |
| String features = deviceInfo.getFeatures(); |
| if (features == null) { |
| features = ""; |
| } |
| |
| String[] featurePairs = features.split(";"); |
| for (String featurePair : featurePairs) { |
| String[] nameTypeAvailability = featurePair.split(":"); |
| if (nameTypeAvailability.length >= 3) { |
| Node feature = document.createElement(TAG_FEATURE); |
| featureInfo.appendChild(feature); |
| |
| setAttribute(document, feature, ATTRIBUTE_NAME, nameTypeAvailability[0]); |
| setAttribute(document, feature, ATTRIBUTE_TYPE, nameTypeAvailability[1]); |
| setAttribute(document, feature, ATTRIBUTE_AVAILABLE, nameTypeAvailability[2]); |
| } |
| } |
| } |
| |
| /** |
| * Creates a {@link #TAG_PROCESS_INFO} tag with {@link #TAG_PROCESS} elements indicating |
| * what particular processes of interest were running on the device. It parses a string from |
| * the deviceInfo argument that is in the form of "processName1;processName2;..." with a |
| * trailing semi-colon. |
| * |
| * <pre> |
| * <ProcessInfo> |
| * <Process name="long_cat_viewer" uid="0" /> |
| * ... |
| * </ProcessInfo> |
| * </pre> |
| * |
| * @param document |
| * @param parentNode |
| * @param deviceInfo |
| */ |
| private void addProcessInfo(Document document, Node parentNode, |
| DeviceParameterCollector deviceInfo) { |
| Node processInfo = document.createElement(TAG_PROCESS_INFO); |
| parentNode.appendChild(processInfo); |
| |
| String rootProcesses = deviceInfo.getProcesses(); |
| if (rootProcesses == null) { |
| rootProcesses = ""; |
| } |
| |
| String[] processNames = rootProcesses.split(";"); |
| for (String processName : processNames) { |
| processName = processName.trim(); |
| if (processName.length() > 0) { |
| Node process = document.createElement(TAG_PROCESS); |
| processInfo.appendChild(process); |
| |
| setAttribute(document, process, ATTRIBUTE_NAME, processName); |
| setAttribute(document, process, ATTRIBUTE_UID, "0"); |
| } |
| } |
| } |
| |
| /** |
| * Output TestSuite and result to XML DOM Document. |
| * |
| * @param doc The document. |
| * @param parentNode The parent node. |
| * @param testSuite The test suite. |
| */ |
| private void outputTestSuite(final Document doc, |
| final TestPackage testPackage, final Node parentNode, |
| TestSuite testSuite) { |
| |
| Collection<TestSuite> subSuites = testSuite.getSubSuites(); |
| Collection<TestCase> testCases = testSuite.getTestCases(); |
| |
| Node testSuiteNode = doc.createElement(TAG_TESTSUITE); |
| setAttribute(doc, testSuiteNode, ATTRIBUTE_NAME, testSuite.getName()); |
| |
| for (TestCase testCase : testCases) { |
| Node testCaseNode = doc.createElement(TAG_TESTCASE); |
| testSuiteNode.appendChild(testCaseNode); |
| setAttribute(doc, testCaseNode, ATTRIBUTE_NAME, testCase.getName()); |
| setAttribute(doc, testCaseNode, TestSessionBuilder.ATTRIBUTE_PRIORITY, |
| testCase.getPriority()); |
| |
| Collection<Test> tests = testCase.getTests(); |
| for (Test test : tests) { |
| Node testNode = doc.createElement(TestSessionBuilder.TAG_TEST); |
| testCaseNode.appendChild(testNode); |
| |
| if (test.isKnownFailure()) { |
| setAttribute(doc, testNode, ATTRIBUTE_KNOWN_FAILURE, test.getKnownFailure()); |
| } |
| |
| CtsTestResult result = test.getResult(); |
| setAttribute(doc, testNode, ATTRIBUTE_NAME, test.getName()); |
| setAttribute(doc, testNode, ATTRIBUTE_RESULT, result.getResultString()); |
| setAttribute(doc, testNode, ATTRIBUTE_STARTTIME, |
| new Date(test.getStartTime()).toString()); |
| setAttribute(doc, testNode, ATTRIBUTE_ENDTIME, |
| new Date(test.getEndTime()).toString()); |
| |
| String failedMessage = result.getFailedMessage(); |
| |
| if (failedMessage != null) { |
| // failure message may contain control characters < 0x20 that get translated |
| // into illegal XML character entities. Replace them first. |
| failedMessage = HostUtils.replaceControlChars(failedMessage); |
| Node failedMessageNode = doc.createElement(TAG_FAILED_SCENE); |
| testNode.appendChild(failedMessageNode); |
| setAttribute(doc, failedMessageNode,TAG_FAILED_MESSAGE, failedMessage); |
| |
| String stackTrace = sanitizeStackTrace(result.getStackTrace()); |
| if (stackTrace != null) { |
| Node stackTraceNode = doc.createElement(TAG_STACK_TRACE); |
| failedMessageNode.appendChild(stackTraceNode); |
| Node stackTraceTextNode = doc.createTextNode(stackTrace); |
| stackTraceNode.appendChild(stackTraceTextNode); |
| } |
| } |
| } |
| } |
| |
| for (TestSuite subSuite : subSuites) { |
| outputTestSuite(doc, testPackage, testSuiteNode, subSuite); |
| parentNode.appendChild(testSuiteNode); |
| } |
| parentNode.appendChild(testSuiteNode); |
| } |
| |
| /** |
| * Strip out any invalid XML characters that might cause the report to be unviewable. |
| * http://www.w3.org/TR/REC-xml/#dt-character |
| */ |
| private static String sanitizeStackTrace(String trace) { |
| if (trace != null) { |
| return trace.replaceAll("[^\\u0009\\u000A\\u000D\\u0020-\\uD7FF\\uE000-\\uFFFD]", ""); |
| } else { |
| return null; |
| } |
| } |
| |
| /** |
| * Fetch failed file name and line number |
| * |
| * @param failedResult failed message |
| * @return failed file name and line number |
| */ |
| public final static String[] getFailedLineNumber(final String failedResult) { |
| Matcher m = mTestFailedPattern.matcher(failedResult); |
| if (m.matches()) { |
| return new String[]{m.group(1), m.group(2)}; |
| } |
| return null; |
| } |
| |
| /** |
| * set the device information of a specific device |
| * |
| * @param dInfo The device information. |
| */ |
| public void setDeviceInfo(final TestDevice.DeviceParameterCollector dInfo) { |
| for (DeviceParameterCollector collector : mDeviceParameterBase) { |
| if (collector.getSerialNumber().equals(dInfo.getSerialNumber())) { |
| //if there has information for the device with given serial number, |
| //replace it with the new information. |
| mDeviceParameterBase.remove(collector); |
| break; |
| } |
| } |
| mDeviceParameterBase.add(dInfo); |
| } |
| } |