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