1 /*
2  * Copyright (C) 2015 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.compatibility.common.util;
17 
18 import java.util.ArrayList;
19 import java.util.Collections;
20 import java.util.HashMap;
21 import java.util.List;
22 import java.util.Map;
23 
24 /**
25  * Data structure for a Compatibility test module result.
26  */
27 public class ModuleResult implements IModuleResult {
28 
29     private String mId;
30     private long mRuntime = 0;
31 
32     /* Variables related to completion of the module */
33     private boolean mDone = false;
34     private boolean mHaveSetDone = false;
35     private boolean mInProgress = false;
36     private int mExpectedTestRuns = 0;
37     private int mActualTestRuns = 0;
38     private int mNotExecuted = 0;
39     private boolean mIsFailed = false;
40 
41     private Map<String, ICaseResult> mResults = new HashMap<>();
42 
43     /**
44      * Creates a {@link ModuleResult} for the given id, created with
45      * {@link AbiUtils#createId(String, String)}
46      */
ModuleResult(String id)47     public ModuleResult(String id) {
48         mId = id;
49     }
50 
51     /**
52      * {@inheritDoc}
53      */
54     @Override
isDone()55     public boolean isDone() {
56         // If module is failed, it cannot be marked done.
57         if (isFailed()) {
58             return false;
59         }
60         return mDone && !mInProgress && (mActualTestRuns >= mExpectedTestRuns);
61     }
62 
63     /**
64      * {@inheritDoc}
65      */
66     @Override
isDoneSoFar()67     public boolean isDoneSoFar() {
68         return mDone && !mInProgress;
69     }
70 
71     /**
72      * {@inheritDoc}
73      */
74     @Override
initializeDone(boolean done)75     public void initializeDone(boolean done) {
76         mDone = done;
77         mHaveSetDone = false;
78         if (mDone) {
79             mNotExecuted = 0;
80         }
81     }
82 
83     /**
84      * {@inheritDoc}
85      */
86     @Override
setDone(boolean done)87     public void setDone(boolean done) {
88         if (mHaveSetDone) {
89             mDone &= done; // If we've already set done for this instance, AND the received value
90         } else {
91             mDone = done; // If done has only been initialized, overwrite the existing value
92         }
93         mHaveSetDone = true;
94         if (mDone) {
95             mNotExecuted = 0;
96         }
97     }
98 
99     /**
100      * {@inheritDoc}
101      */
102     @Override
inProgress(boolean inProgress)103     public void inProgress(boolean inProgress) {
104         mInProgress = inProgress;
105     }
106 
107     /**
108      * {@inheritDoc}
109      */
110     @Override
getExpectedTestRuns()111     public int getExpectedTestRuns() {
112         return mExpectedTestRuns;
113     }
114 
115     /**
116      * {@inheritDoc}
117      */
118     @Override
setExpectedTestRuns(int numRuns)119     public void setExpectedTestRuns(int numRuns) {
120         mExpectedTestRuns = numRuns;
121     }
122 
123     /**
124      * {@inheritDoc}
125      */
126     @Override
getTestRuns()127     public int getTestRuns() {
128         return mActualTestRuns;
129     }
130 
131     /**
132      * {@inheritDoc}
133      */
134     @Override
addTestRun()135     public void addTestRun() {
136         mActualTestRuns++;
137     }
138 
139     /**
140      * {@inheritDoc}
141      */
142     @Override
resetTestRuns()143     public void resetTestRuns() {
144         mActualTestRuns = 0;
145     }
146 
147     /**
148      * {@inheritDoc}
149      */
150     @Override
getNotExecuted()151     public int getNotExecuted() {
152         return mNotExecuted;
153     }
154 
155     /**
156      * {@inheritDoc}
157      */
158     @Override
setNotExecuted(int numTests)159     public void setNotExecuted(int numTests) {
160         mNotExecuted = numTests;
161     }
162 
163     /**
164      * {@inheritDoc}
165      */
166     @Override
getId()167     public String getId() {
168         return mId;
169     }
170 
171     /**
172      * {@inheritDoc}
173      */
174     @Override
getName()175     public String getName() {
176         return AbiUtils.parseTestName(mId);
177     }
178 
179     /**
180      * {@inheritDoc}
181      */
182     @Override
getAbi()183     public String getAbi() {
184         return AbiUtils.parseAbi(mId);
185     }
186 
187     /**
188      * {@inheritDoc}
189      */
190     @Override
addRuntime(long elapsedTime)191     public void addRuntime(long elapsedTime) {
192         mRuntime += elapsedTime;
193     }
194 
195     /**
196      * {@inheritDoc}
197      */
198     @Override
resetRuntime()199     public void resetRuntime() {
200         mRuntime = 0;
201     }
202 
203     /**
204      * {@inheritDoc}
205      */
206     @Override
getRuntime()207     public long getRuntime() {
208         return mRuntime;
209     }
210 
211     /**
212      * {@inheritDoc}
213      */
214     @Override
getOrCreateResult(String caseName)215     public ICaseResult getOrCreateResult(String caseName) {
216         ICaseResult result = mResults.get(caseName);
217         if (result == null) {
218             result = new CaseResult(caseName);
219             mResults.put(caseName, result);
220         }
221         return result;
222     }
223 
224     /**
225      * {@inheritDoc}
226      */
227     @Override
getResult(String caseName)228     public ICaseResult getResult(String caseName) {
229         return mResults.get(caseName);
230     }
231 
232     /**
233      * {@inheritDoc}
234      */
235     @Override
getResults()236     public List<ICaseResult> getResults() {
237         ArrayList<ICaseResult> results = new ArrayList<>(mResults.values());
238         Collections.sort(results);
239         return results;
240     }
241 
242     /**
243      * {@inheritDoc}
244      */
245     @Override
countResults(TestStatus status)246     public int countResults(TestStatus status) {
247         int total = 0;
248         for (ICaseResult result : mResults.values()) {
249             total += result.countResults(status);
250         }
251         return total;
252     }
253 
254     /**
255      * {@inheritDoc}
256      */
257     @Override
compareTo(IModuleResult another)258     public int compareTo(IModuleResult another) {
259         return getId().compareTo(another.getId());
260     }
261 
262     @Override
setFailed()263     public void setFailed() {
264         mIsFailed = true;
265     }
266 
267     @Override
isFailed()268     public boolean isFailed() {
269         return mIsFailed;
270     }
271 
272     /**
273      * {@inheritDoc}
274      */
275     @Override
mergeFrom(IModuleResult otherModuleResult)276     public void mergeFrom(IModuleResult otherModuleResult) {
277         if (!otherModuleResult.getId().equals(getId())) {
278             throw new IllegalArgumentException(String.format(
279                 "Cannot merge module result with mismatched id. Expected %s, Found %s",
280                         otherModuleResult.getId(), getId()));
281         }
282 
283         this.mRuntime += otherModuleResult.getRuntime();
284         this.mNotExecuted += otherModuleResult.getNotExecuted();
285         // Only touch variables related to 'done' status if this module is not already done
286         if (!isDone()) {
287             this.setDone(otherModuleResult.isDoneSoFar());
288             this.mActualTestRuns += otherModuleResult.getTestRuns();
289             // expected test runs are the same across shards, except for shards that do not run
290             // this module at least once (for which the value is not yet set).
291             this.mExpectedTestRuns += otherModuleResult.getExpectedTestRuns();
292         }
293         // If something failed, then the aggregation is failed
294         if (!this.isFailed()) {
295             this.mIsFailed = otherModuleResult.isFailed();
296         }
297         for (ICaseResult otherCaseResult : otherModuleResult.getResults()) {
298             ICaseResult caseResult = getOrCreateResult(otherCaseResult.getName());
299             caseResult.mergeFrom(otherCaseResult);
300         }
301     }
302 }
303