1 /* 2 * Copyright (C) 2019 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.compatibility.common.util; 18 19 import org.xmlpull.v1.XmlSerializer; 20 21 import java.io.IOException; 22 import java.io.Serializable; 23 import java.util.Objects; 24 import java.util.Set; 25 26 /** 27 * Utility class to add test case result history to the report. This class records per-case history 28 * for CTS Verifier. If this field is used for large test suites like CTS, it may cause performance 29 * issues in APFE. Thus please do not use this class in other test suites. 30 */ 31 public class TestResultHistory implements Serializable { 32 33 private static final long serialVersionUID = 10L; 34 35 private static final String ENCODING = "UTF-8"; 36 private static final String TYPE = "org.kxml2.io.KXmlParser,org.kxml2.io.KXmlSerializer"; 37 38 // XML constants 39 private static final String SUB_TEST_ATTR = "subtest"; 40 private static final String RUN_HISTORY_TAG = "RunHistory"; 41 private static final String RUN_TAG = "Run"; 42 private static final String START_TIME_ATTR = "start"; 43 private static final String END_TIME_ATTR = "end"; 44 private static final String IS_AUTOMATED_ATTR = "isAutomated"; 45 46 private final String mTestName; 47 private final Set<ExecutionRecord> mExecutionRecords; 48 49 /** 50 * Constructor of test result history. 51 * 52 * @param testName a string of test name. 53 * @param executionRecords a Set of ExecutionRecords. 54 */ TestResultHistory(String testName, Set<ExecutionRecord> executionRecords)55 public TestResultHistory(String testName, Set<ExecutionRecord> executionRecords) { 56 this.mTestName = testName; 57 this.mExecutionRecords = executionRecords; 58 } 59 60 /** Get test name */ getTestName()61 public String getTestName() { 62 return mTestName; 63 } 64 65 /** Get a set of ExecutionRecords. */ getExecutionRecords()66 public Set<ExecutionRecord> getExecutionRecords() { 67 return mExecutionRecords; 68 } 69 70 /** {@inheritDoc} */ 71 @Override equals(Object o)72 public boolean equals(Object o) { 73 if (this == o) { 74 return true; 75 } 76 if (o == null || getClass() != o.getClass()) { 77 return false; 78 } 79 TestResultHistory that = (TestResultHistory) o; 80 return Objects.equals(mTestName, that.mTestName) 81 && Objects.equals(mExecutionRecords, that.mExecutionRecords); 82 } 83 84 /** {@inheritDoc} */ 85 @Override hashCode()86 public int hashCode() { 87 return Objects.hash(mTestName, mExecutionRecords); 88 } 89 90 /** 91 * Serializes a given {@link TestResultHistory} to XML. 92 * 93 * @param serializer given serializer. 94 * @param resultHistory test result history with test name and execution record. 95 * @param testName top-level test name. 96 * @throws IOException 97 */ serialize( XmlSerializer serializer, TestResultHistory resultHistory, String testName)98 public static void serialize( 99 XmlSerializer serializer, TestResultHistory resultHistory, String testName) 100 throws IOException { 101 if (resultHistory == null) { 102 throw new IllegalArgumentException("Test result history was null"); 103 } 104 105 serializer.startTag(null, RUN_HISTORY_TAG); 106 // Only show sub-test names in test attribute in run history node. 107 String name = resultHistory.getTestName().replaceFirst(testName + ":", ""); 108 if (!name.isEmpty() && !name.equalsIgnoreCase(testName)) { 109 serializer.attribute(null, SUB_TEST_ATTR, name); 110 } 111 112 for (ExecutionRecord execRecord : resultHistory.getExecutionRecords()) { 113 serializer.startTag(null, RUN_TAG); 114 serializer.attribute(null, START_TIME_ATTR, String.valueOf(execRecord.getStartTime())); 115 serializer.attribute(null, END_TIME_ATTR, String.valueOf(execRecord.getEndTime())); 116 serializer.attribute( 117 null, IS_AUTOMATED_ATTR, String.valueOf(execRecord.getIsAutomated())); 118 serializer.endTag(null, RUN_TAG); 119 } 120 serializer.endTag(null, RUN_HISTORY_TAG); 121 } 122 123 /** Execution Record about start time, end time and isAutomated */ 124 public static class ExecutionRecord implements Serializable { 125 126 private static final long serialVersionUID = 0L; 127 // Start time of test case. 128 private final long startTime; 129 // End time of test case. 130 private final long endTime; 131 // Whether test case was executed through automation. 132 private final boolean isAutomated; 133 ExecutionRecord(long startTime, long endTime, boolean isAutomated)134 public ExecutionRecord(long startTime, long endTime, boolean isAutomated) { 135 this.startTime = startTime; 136 this.endTime = endTime; 137 this.isAutomated = isAutomated; 138 } 139 getStartTime()140 public long getStartTime() { 141 return startTime; 142 } 143 getEndTime()144 public long getEndTime() { 145 return endTime; 146 } 147 getIsAutomated()148 public boolean getIsAutomated() { 149 return isAutomated; 150 } 151 152 @Override equals(Object o)153 public boolean equals(Object o) { 154 if (this == o) { 155 return true; 156 } 157 if (o == null || getClass() != o.getClass()) { 158 return false; 159 } 160 ExecutionRecord that = (ExecutionRecord) o; 161 return startTime == that.startTime 162 && endTime == that.endTime 163 && isAutomated == that.isAutomated; 164 } 165 166 @Override hashCode()167 public int hashCode() { 168 return Objects.hash(startTime, endTime, isAutomated); 169 } 170 } 171 } 172