• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 android.mediapc.cts.common;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 import static com.google.common.truth.Truth.assertWithMessage;
21 
22 import static org.junit.Assume.assumeTrue;
23 
24 import android.util.Log;
25 
26 import androidx.annotation.NonNull;
27 import androidx.annotation.VisibleForTesting;
28 import androidx.test.platform.app.InstrumentationRegistry;
29 
30 import com.android.compatibility.common.util.DeviceReportLog;
31 import com.android.cts.verifier.CtsVerifierReportLog;
32 
33 import com.google.common.base.Preconditions;
34 
35 import org.junit.rules.TestName;
36 
37 import java.util.HashSet;
38 import java.util.Map;
39 import java.util.Set;
40 import java.util.stream.Collectors;
41 
42 /**
43  * Logs a set of measurements and results for defined performance class requirements.
44  *
45  * <p> Nested classes are organized alphabetically, add[Requirement] functions are organized by
46  * their requirement number in the order they appear in the Android CDD
47  */
48 public class PerformanceClassEvaluator {
49     private static final String TAG = PerformanceClassEvaluator.class.getSimpleName();
50 
51     private final String mTestName;
52     private Set<Requirement> mRequirements;
53 
PerformanceClassEvaluator(TestName testName)54     public PerformanceClassEvaluator(TestName testName) {
55         Preconditions.checkNotNull(testName);
56         String baseTestName = testName.getMethodName() != null ? testName.getMethodName() : "";
57         this.mTestName = baseTestName.replace("{", "(").replace("}", ")");
58         this.mRequirements = new HashSet<Requirement>();
59     }
60 
getTestName()61     String getTestName() {
62         return mTestName;
63     }
64 
addRequirement(R req)65     public <R extends Requirement> R addRequirement(R req) {
66         if (!this.mRequirements.add(req)) {
67             throw new IllegalStateException("Requirement " + req.id() + " already added");
68         }
69         return req;
70     }
71 
72     /**
73      * Returns if the PerformanceClassEvaluator is ready to be submitted.
74      *
75      * <p>The PerformanceClassEvaluator is ready for submission if: all added requirements have all
76      * their required measurements recorded AND there is at least one requirement added.
77      *
78      * <p>Note: this function is ONLY meant to be used by ITS. Other tests should attempt to submit
79      * and make sure an exception is not thrown during submission.
80      */
isReadyToSubmitItsResults()81     public boolean isReadyToSubmitItsResults() {
82         boolean allMeasuredValuesSet =
83                 mRequirements.stream().allMatch(r -> r.allMeasuredValuesSet());
84         boolean hasRequirements = !mRequirements.isEmpty();
85         return allMeasuredValuesSet && hasRequirements;
86     }
87 
88     private enum SubmitType {
89         TRADEFED, VERIFIER
90     }
91 
92 
submitAndCheck()93     public void submitAndCheck() {
94         // submit clears the requirements so compute before submitting
95         Map<Requirement, Integer> idToGrade = computeGrades();
96         boolean perfClassMet = submit(SubmitType.TRADEFED);
97         // check performance class
98         assumeTrue("Build.VERSION.MEDIA_PERFORMANCE_CLASS is not declared", Utils.isPerfClass());
99         if (!perfClassMet) {
100             idToGrade.forEach(
101                     (r, grade) -> {
102                         int pc = Utils.getPerfClass();
103                         if (r.appliesToPerformanceClass(pc)) {
104                             assertWithMessage("%s performance class", r).that(grade).isAtLeast(pc);
105                         }
106                     });
107         }
108         // Safety catch.
109         assertThat(perfClassMet).isTrue();
110     }
111 
submitAndVerify()112     public void submitAndVerify() {
113         // submit clears the requirements so compute before submitting
114         Map<Requirement, Integer> grades = computeGrades();
115         boolean perfClassMet = submit(SubmitType.VERIFIER);
116         int declaredPc = Utils.getPerfClass();
117 
118         if (!perfClassMet && Utils.isPerfClass()) {
119             String msg = "Declared performance class %s but requirement [%s] grades as %s";
120             grades.forEach((r, grade) -> Log.w(TAG, msg.formatted(declaredPc, r, grade)));
121         }
122     }
123 
124     @NonNull
125     @VisibleForTesting // Prevents warning about using computePerformanceClass
computeGrades()126     private Map<Requirement, Integer> computeGrades() {
127         return mRequirements.stream()
128                 .collect(Collectors.toMap(r -> r, Requirement::computePerformanceClass));
129     }
130 
submit(SubmitType type)131     private boolean submit(SubmitType type) {
132         boolean perfClassMet = true;
133         for (Requirement req : this.mRequirements) {
134             switch (type) {
135                 case VERIFIER:
136                     CtsVerifierReportLog verifierLog = new CtsVerifierReportLog(
137                             RequirementConstants.REPORT_LOG_NAME, req.id());
138                     perfClassMet &= req.writeLogAndCheck(verifierLog, this.mTestName);
139                     verifierLog.submit();
140                     break;
141 
142                 case TRADEFED:
143                 default:
144                     DeviceReportLog tradefedLog = new DeviceReportLog(
145                             RequirementConstants.REPORT_LOG_NAME, req.id());
146                     perfClassMet &= req.writeLogAndCheck(tradefedLog, this.mTestName);
147                     tradefedLog.submit(InstrumentationRegistry.getInstrumentation());
148                     break;
149             }
150         }
151         this.mRequirements.clear(); // makes sure report isn't submitted twice
152         return perfClassMet;
153     }
154 }
155