1 /*
2  * Copyright (C) 2010 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.cts.tradefed.testtype;
17 
18 import com.android.cts.tradefed.testtype.CtsTest.TestPackage;
19 import com.android.ddmlib.testrunner.TestIdentifier;
20 import com.android.tradefed.log.LogUtil.CLog;
21 import com.android.tradefed.result.ITestInvocationListener;
22 import com.android.tradefed.result.ResultForwarder;
23 
24 import java.util.Collection;
25 import java.util.HashMap;
26 import java.util.HashSet;
27 import java.util.LinkedHashSet;
28 import java.util.Map;
29 import java.util.Set;
30 
31 /**
32  * A {@link ITestInvocationListener} that filters test results based on the set of expected tests
33  * in CTS test package xml files.
34  * <p/>
35  * It will only report test results for expected tests, and at end of invocation, will report the
36  * set of expected tests that were not executed.
37  */
38 class ResultFilter extends ResultForwarder {
39 
40     private final Set<TestIdentifier> mKnownTests;
41     private final Set<TestIdentifier> mRemainingTests;
42     private final String mTestRun;
43 
44     /**
45      * Create a {@link ResultFilter}.
46      *
47      * @param listener the real {@link ITestInvocationListener} to forward results to
48      */
ResultFilter(ITestInvocationListener listener, TestPackage testPackage)49     ResultFilter(ITestInvocationListener listener, TestPackage testPackage) {
50         super(listener);
51         mTestRun = testPackage.getTestRunName();
52         Collection<TestIdentifier> tests = testPackage.getKnownTests();
53         mKnownTests = new HashSet<TestIdentifier>(tests);
54         // use LinkedHashMap for predictable test order
55         mRemainingTests = new LinkedHashSet<TestIdentifier>(tests);
56     }
57 
58 
59     /**
60      * {@inheritDoc}
61      */
62     @Override
testRunStarted(String runName, int testCount)63     public void testRunStarted(String runName, int testCount) {
64         if (mTestRun.equals(runName)) {
65             super.testRunStarted(runName, testCount);
66         } else {
67             CLog.d("Skipping reporting unknown test run %s", runName);
68         }
69     }
70 
71     /**
72      * {@inheritDoc}
73      */
74     @Override
testStarted(TestIdentifier test)75     public void testStarted(TestIdentifier test) {
76         if (isKnownTest(test)) {
77             super.testStarted(test);
78         } else {
79             CLog.d("Skipping reporting unknown test %s", test);
80         }
81     }
82 
83     /**
84      * {@inheritDoc}
85      */
86     @Override
testFailed(TestIdentifier test, String trace)87     public void testFailed(TestIdentifier test, String trace) {
88         if (isKnownTest(test)) {
89             super.testFailed(test, trace);
90         }
91     }
92 
93     /**
94      * {@inheritDoc}
95      */
96     @Override
testEnded(TestIdentifier test, Map<String, String> testMetrics)97     public void testEnded(TestIdentifier test, Map<String, String> testMetrics) {
98         if (isKnownTest(test)) {
99             super.testEnded(test, testMetrics);
100             removeExecutedTest(test);
101         }
102     }
103 
104     /**
105      * @param test
106      * @return
107      */
isKnownTest(TestIdentifier test)108     private boolean isKnownTest(TestIdentifier test) {
109         return mKnownTests.contains(test);
110     }
111 
112     /**
113      * Remove given test from the 'remaining tests' data structure.
114      * @param test
115      */
removeExecutedTest(TestIdentifier test)116     private void removeExecutedTest(TestIdentifier test) {
117         mRemainingTests.remove(test);
118     }
119 
120     /**
121      * Report the set of expected tests that were not executed
122      */
reportUnexecutedTests()123     public void reportUnexecutedTests() {
124         if (mRemainingTests.isEmpty()) {
125             return;
126         }
127         super.testRunStarted(mTestRun, mRemainingTests.size());
128         for (TestIdentifier test : mRemainingTests) {
129             // an unexecuted test is currently reported as a 'testStarted' event without a
130             // 'testEnded'. TODO: consider adding an explict API for reporting an unexecuted
131             // test
132             super.testStarted(test);
133         }
134         super.testRunEnded(0, new HashMap<String, String>());
135     }
136 
137     /** @return the number of known tests */
getKnownTestCount()138     public int getKnownTestCount() {
139         return mKnownTests.size();
140     }
141 }
142