TestSuite.java revision a4e46484cb5df4323bc8a3b76dee9a95de3c34c9
1/*
2 * Copyright (C) 2011 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 */
16package com.android.cts.tradefed.result;
17
18import com.android.ddmlib.testrunner.TestIdentifier;
19
20import org.kxml2.io.KXmlSerializer;
21import org.xmlpull.v1.XmlPullParser;
22import org.xmlpull.v1.XmlPullParserException;
23
24import java.io.IOException;
25import java.util.Collection;
26import java.util.Deque;
27import java.util.LinkedHashMap;
28import java.util.List;
29import java.util.Map;
30
31/**
32 * Data structure that represents a "TestSuite" XML element and its children.
33 */
34class TestSuite extends AbstractXmlPullParser {
35
36    static final String TAG = "TestSuite";
37
38    private String mName;
39
40    // use linked hash map for predictable iteration order
41    Map<String, TestSuite> mChildSuiteMap = new LinkedHashMap<String, TestSuite>();
42    Map<String, TestCase> mChildTestCaseMap = new LinkedHashMap<String, TestCase>();
43
44    /**
45     * @param testSuite
46     */
47    public TestSuite(String suiteName) {
48        mName = suiteName;
49    }
50
51    public TestSuite() {
52    }
53
54    /**
55     * @return the name of this suite
56     */
57    public String getName() {
58        return mName;
59    }
60
61    /**
62     * Set the name of this suite
63     */
64    public void setName(String name) {
65        mName = name;
66    }
67
68    /**
69     * Insert the given test result into this suite.
70     *
71     * @param suiteNames list of remaining suite names for this test
72     * @param testClassName the test class name
73     * @param testName the test method name
74     * @param testResult the {@link TestResult}
75     */
76    public Test findTest(List<String> suiteNames, String testClassName, String testName,
77            boolean insertIfMissing) {
78        if (suiteNames.size() <= 0) {
79            // no more package segments
80            TestCase testCase = getTestCase(testClassName);
81            return testCase.findTest(testName, insertIfMissing);
82        } else {
83            String rootName = suiteNames.remove(0);
84            TestSuite suite = getTestSuite(rootName);
85            return suite.findTest(suiteNames, testClassName, testName, insertIfMissing);
86        }
87    }
88
89    /**
90     * Gets all the child {@link TestSuite}s
91     */
92    public Collection<TestSuite> getTestSuites() {
93        return mChildSuiteMap.values();
94    }
95
96    /**
97     * Gets all the child {@link TestCase}s
98     */
99    public Collection<TestCase> getTestCases() {
100        return mChildTestCaseMap.values();
101    }
102
103    /**
104     * Get the child {@link TestSuite} with given name, creating if necessary.
105     *
106     * @param suiteName
107     * @return the {@link TestSuite}
108     */
109    private TestSuite getTestSuite(String suiteName) {
110        TestSuite testSuite = mChildSuiteMap.get(suiteName);
111        if (testSuite == null) {
112            testSuite = new TestSuite(suiteName);
113            mChildSuiteMap.put(suiteName, testSuite);
114        }
115        return testSuite;
116    }
117
118    /**
119     * Get the child {@link TestCase} with given name, creating if necessary.
120     * @param testCaseName
121     * @return
122     */
123    private TestCase getTestCase(String testCaseName) {
124        TestCase testCase = mChildTestCaseMap.get(testCaseName);
125        if (testCase == null) {
126            testCase = new TestCase(testCaseName);
127            mChildTestCaseMap.put(testCaseName, testCase);
128        }
129        return testCase;
130    }
131
132    /**
133     * Serialize this object and all its contents to XML.
134     *
135     * @param serializer
136     * @throws IOException
137     */
138    public void serialize(KXmlSerializer serializer) throws IOException {
139        if (mName != null) {
140            serializer.startTag(CtsXmlResultReporter.ns, TAG);
141            serializer.attribute(CtsXmlResultReporter.ns, "name", mName);
142        }
143        for (TestSuite childSuite : mChildSuiteMap.values()) {
144            childSuite.serialize(serializer);
145        }
146        for (TestCase childCase : mChildTestCaseMap.values()) {
147            childCase.serialize(serializer);
148        }
149        if (mName != null) {
150            serializer.endTag(CtsXmlResultReporter.ns, TAG);
151        }
152    }
153
154    /**
155     * Populates this class with suite result data parsed from XML.
156     *
157     * @param parser the {@link XmlPullParser}. Expected to be pointing at start
158     *            of a TestSuite tag
159     */
160    @Override
161    void parse(XmlPullParser parser) throws XmlPullParserException, IOException {
162        if (!parser.getName().equals(TAG)) {
163            throw new XmlPullParserException(String.format(
164                    "invalid XML: Expected %s tag but received %s", TAG, parser.getName()));
165        }
166        setName(getAttribute(parser, "name"));
167        int eventType = parser.next();
168        while (eventType != XmlPullParser.END_DOCUMENT) {
169            if (eventType == XmlPullParser.START_TAG && parser.getName().equals(TestSuite.TAG)) {
170                TestSuite suite = new TestSuite();
171                suite.parse(parser);
172                insertSuite(suite);
173            } else if (eventType == XmlPullParser.START_TAG && parser.getName().equals(
174                    TestCase.TAG)) {
175                TestCase testCase = new TestCase();
176                testCase.parse(parser);
177                insertTestCase(testCase);
178            } else if (eventType == XmlPullParser.END_TAG && parser.getName().equals(TAG)) {
179                return;
180            }
181            eventType = parser.next();
182        }
183    }
184
185    /**
186     * Adds a child {@link TestCase}.
187     */
188    public void insertTestCase(TestCase testCase) {
189        mChildTestCaseMap.put(testCase.getName(), testCase);
190    }
191
192    /**
193     * Adds a child {@link TestSuite}.
194     */
195    public void insertSuite(TestSuite suite) {
196        mChildSuiteMap.put(suite.getName(), suite);
197    }
198
199
200    /**
201     * Adds tests contained in this result that have the given <var>resultFilter</var>
202     *
203     * @param tests the {@link Collection} of {@link TestIdentifier}s to add to
204     * @param parentSuiteNames a {@link Deque} of parent suite names. Used to construct the full
205     * class name of the test
206     * @param resultFilter the {@link CtsTestStatus} to filter by
207     */
208    void addTestsWithStatus(Collection<TestIdentifier> tests, Deque<String> parentSuiteNames,
209            CtsTestStatus resultFilter) {
210        if (getName() != null) {
211            parentSuiteNames.addLast(getName());
212        }
213        for (TestSuite suite : mChildSuiteMap.values()) {
214            suite.addTestsWithStatus(tests, parentSuiteNames, resultFilter);
215        }
216        for (TestCase testCase : mChildTestCaseMap.values()) {
217            testCase.addTestsWithStatus(tests, parentSuiteNames, resultFilter);
218        }
219        if (getName() != null) {
220            parentSuiteNames.removeLast();
221        }
222    }
223
224    /**
225     * Count the number of tests in this {@link TestSuite} with given status.
226     *
227     * @param status
228     * @return the test count
229     */
230    public int countTests(CtsTestStatus status) {
231        int total = 0;
232        for (TestSuite suite : mChildSuiteMap.values()) {
233            total += suite.countTests(status);
234        }
235        for (TestCase testCase : mChildTestCaseMap.values()) {
236            total += testCase.countTests(status);
237        }
238        return total;
239    }
240}
241