1 /*
2  * Copyright (C) 2018 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.tradefed.result;
17 
18 import com.android.ddmlib.testrunner.TestResult.TestStatus;
19 import com.android.tradefed.metrics.proto.MetricMeasurement.Metric;
20 
21 import java.util.Arrays;
22 import java.util.HashMap;
23 import java.util.LinkedHashMap;
24 import java.util.Map;
25 
26 /** Container for a result of a single test. */
27 public class TestResult {
28 
29     private TestStatus mStatus;
30     private String mStackTrace;
31     private Map<String, String> mMetrics;
32     private HashMap<String, Metric> mProtoMetrics;
33     private Map<String, LogFile> mLoggedFiles;
34     // the start and end time of the test, measured via {@link System#currentTimeMillis()}
35     private long mStartTime = 0;
36     private long mEndTime = 0;
37 
TestResult()38     public TestResult() {
39         mStatus = TestStatus.INCOMPLETE;
40         mStartTime = System.currentTimeMillis();
41         mLoggedFiles = new LinkedHashMap<String, LogFile>();
42         mProtoMetrics = new HashMap<>();
43     }
44 
45     /** Get the {@link TestStatus} result of the test. */
getStatus()46     public TestStatus getStatus() {
47         return mStatus;
48     }
49 
50     /**
51      * Get the associated {@link String} stack trace. Should be <code>null</code> if {@link
52      * #getStatus()} is {@link TestStatus#PASSED}.
53      */
getStackTrace()54     public String getStackTrace() {
55         return mStackTrace;
56     }
57 
58     /** Get the associated test metrics. */
getMetrics()59     public Map<String, String> getMetrics() {
60         return mMetrics;
61     }
62 
63     /** Get the associated test metrics in proto format. */
getProtoMetrics()64     public HashMap<String, Metric> getProtoMetrics() {
65         return mProtoMetrics;
66     }
67 
68     /** Set the test metrics, overriding any previous values. */
setMetrics(Map<String, String> metrics)69     public void setMetrics(Map<String, String> metrics) {
70         mMetrics = metrics;
71     }
72 
73     /** Set the test proto metrics format, overriding any previous values. */
setProtoMetrics(HashMap<String, Metric> metrics)74     public void setProtoMetrics(HashMap<String, Metric> metrics) {
75         mProtoMetrics = metrics;
76     }
77 
78     /** Add a logged file tracking associated with that test case */
addLoggedFile(String dataName, LogFile loggedFile)79     public void addLoggedFile(String dataName, LogFile loggedFile) {
80         mLoggedFiles.put(dataName, loggedFile);
81     }
82 
83     /** Returns a copy of the map containing all the logged file associated with that test case. */
getLoggedFiles()84     public Map<String, LogFile> getLoggedFiles() {
85         return new LinkedHashMap<>(mLoggedFiles);
86     }
87 
88     /**
89      * Return the {@link System#currentTimeMillis()} time that the {@link
90      * ITestInvocationListener#testStarted(TestDescription)} event was received.
91      */
getStartTime()92     public long getStartTime() {
93         return mStartTime;
94     }
95 
96     /**
97      * Allows to set the time when the test was started, to be used with {@link
98      * ITestInvocationListener#testStarted(TestDescription, long)}.
99      */
setStartTime(long startTime)100     public void setStartTime(long startTime) {
101         mStartTime = startTime;
102     }
103 
104     /**
105      * Return the {@link System#currentTimeMillis()} time that the {@link
106      * ITestInvocationListener#testEnded(TestDescription, Map)} event was received.
107      */
getEndTime()108     public long getEndTime() {
109         return mEndTime;
110     }
111 
112     /** Set the {@link TestStatus}. */
setStatus(TestStatus status)113     public TestResult setStatus(TestStatus status) {
114         mStatus = status;
115         return this;
116     }
117 
118     /** Set the stack trace. */
setStackTrace(String trace)119     public void setStackTrace(String trace) {
120         mStackTrace = trace;
121     }
122 
123     /** Sets the end time */
setEndTime(long currentTimeMillis)124     public void setEndTime(long currentTimeMillis) {
125         mEndTime = currentTimeMillis;
126     }
127 
128     @Override
hashCode()129     public int hashCode() {
130         return Arrays.hashCode(new Object[] {mMetrics, mStackTrace, mStatus});
131     }
132 
133     @Override
equals(Object obj)134     public boolean equals(Object obj) {
135         if (this == obj) {
136             return true;
137         }
138         if (obj == null) {
139             return false;
140         }
141         if (getClass() != obj.getClass()) {
142             return false;
143         }
144         TestResult other = (TestResult) obj;
145         return equal(mMetrics, other.mMetrics)
146                 && equal(mStackTrace, other.mStackTrace)
147                 && equal(mStatus, other.mStatus);
148     }
149 
equal(Object a, Object b)150     private static boolean equal(Object a, Object b) {
151         return a == b || (a != null && a.equals(b));
152     }
153 
154     /**
155      * Create an exact copy of given TestResult.
156      *
157      * @param result The TestResult to copy from.
158      */
clone(TestResult result)159     public static TestResult clone(TestResult result) {
160         TestResult newResult = new TestResult();
161         newResult.setStatus(result.getStatus());
162         newResult.setStackTrace(result.getStackTrace());
163         newResult.setMetrics(result.getMetrics());
164         newResult.setProtoMetrics(result.getProtoMetrics());
165         newResult.setStartTime(result.getStartTime());
166         newResult.setEndTime(result.getEndTime());
167         // The LoggedFiles map contains the log file info whenever testLogSaved is called.
168         // e.g. testLogSaved("coverage", new LogFile("/fake/path", "fake//url", LogDataType.TEXT))
169         for (Map.Entry<String, LogFile> logFile : result.getLoggedFiles().entrySet()) {
170             newResult.addLoggedFile(logFile.getKey(), logFile.getValue());
171         }
172         return newResult;
173     }
174 }
175