Home | History | Annotate | Download | only in suite
      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.suite;
     17 
     18 import static org.junit.Assert.assertEquals;
     19 import static org.junit.Assert.assertNotNull;
     20 import static org.junit.Assert.assertTrue;
     21 
     22 import com.android.tradefed.invoker.IInvocationContext;
     23 import com.android.tradefed.invoker.InvocationContext;
     24 import com.android.tradefed.metrics.proto.MetricMeasurement.Metric;
     25 import com.android.tradefed.result.LogDataType;
     26 import com.android.tradefed.result.LogFile;
     27 import com.android.tradefed.result.TestDescription;
     28 import com.android.tradefed.result.TestRunResult;
     29 import com.android.tradefed.testtype.Abi;
     30 import com.android.tradefed.testtype.IAbi;
     31 import com.android.tradefed.util.FileUtil;
     32 
     33 import org.junit.After;
     34 import org.junit.Before;
     35 import org.junit.Test;
     36 import org.junit.runner.RunWith;
     37 import org.junit.runners.JUnit4;
     38 import org.w3c.dom.Element;
     39 import org.w3c.dom.NodeList;
     40 import org.xml.sax.InputSource;
     41 
     42 import java.io.File;
     43 import java.io.StringReader;
     44 import java.util.ArrayList;
     45 import java.util.Collection;
     46 import java.util.HashMap;
     47 import java.util.Map;
     48 
     49 import javax.xml.xpath.XPath;
     50 import javax.xml.xpath.XPathConstants;
     51 import javax.xml.xpath.XPathExpressionException;
     52 import javax.xml.xpath.XPathFactory;
     53 
     54 /** Unit tests for {@link XmlSuiteResultFormatter}. */
     55 @RunWith(JUnit4.class)
     56 public class XmlSuiteResultFormatterTest {
     57     private XmlSuiteResultFormatter mFormatter;
     58     private SuiteResultHolder mResultHolder;
     59     private IInvocationContext mContext;
     60     private File mResultDir;
     61 
     62     @Before
     63     public void setUp() throws Exception {
     64         mFormatter = new XmlSuiteResultFormatter();
     65         mResultHolder = new SuiteResultHolder();
     66         mContext = new InvocationContext();
     67         mResultDir = FileUtil.createTempDir("result-dir");
     68     }
     69 
     70     @After
     71     public void tearDown() throws Exception {
     72         FileUtil.recursiveDelete(mResultDir);
     73     }
     74 
     75     /** Check that the basic overall structure is good an contains all the information. */
     76     @Test
     77     public void testBasicFormat() throws Exception {
     78         mResultHolder.context = mContext;
     79 
     80         Collection<TestRunResult> runResults = new ArrayList<>();
     81         runResults.add(createFakeResult("module1", 2, 0));
     82         runResults.add(createFakeResult("module2", 1, 0));
     83         mResultHolder.runResults = runResults;
     84 
     85         Map<String, IAbi> modulesAbi = new HashMap<>();
     86         modulesAbi.put("module1", new Abi("armeabi-v7a", "32"));
     87         modulesAbi.put("module2", new Abi("armeabi-v7a", "32"));
     88         mResultHolder.modulesAbi = modulesAbi;
     89 
     90         mResultHolder.completeModules = 2;
     91         mResultHolder.totalModules = 2;
     92         mResultHolder.passedTests = 2;
     93         mResultHolder.failedTests = 0;
     94         mResultHolder.startTime = 0L;
     95         mResultHolder.endTime = 10L;
     96         File res = mFormatter.writeResults(mResultHolder, mResultDir);
     97         String content = FileUtil.readStringFromFile(res);
     98         assertXmlContainsNode(content, "Result");
     99         // Verify that the summary has been populated
    100         assertXmlContainsNode(content, "Result/Summary");
    101         assertXmlContainsAttribute(content, "Result/Summary", "pass", "2");
    102         assertXmlContainsAttribute(content, "Result/Summary", "failed", "0");
    103         assertXmlContainsAttribute(content, "Result/Summary", "modules_done", "2");
    104         assertXmlContainsAttribute(content, "Result/Summary", "modules_total", "2");
    105         // Verify that each module results are available
    106         assertXmlContainsNode(content, "Result/Module");
    107         assertXmlContainsAttribute(content, "Result/Module", "name", "module1");
    108         assertXmlContainsAttribute(content, "Result/Module", "abi", "armeabi-v7a");
    109         assertXmlContainsAttribute(content, "Result/Module", "runtime", "10");
    110         assertXmlContainsAttribute(content, "Result/Module", "done", "true");
    111         assertXmlContainsAttribute(content, "Result/Module", "pass", "2");
    112         // Verify the test cases that passed are present
    113         assertXmlContainsNode(content, "Result/Module/TestCase");
    114         assertXmlContainsAttribute(content, "Result/Module/TestCase", "name", "com.class.module1");
    115         assertXmlContainsAttribute(
    116                 content, "Result/Module/TestCase/Test", "name", "module1.method0");
    117         assertXmlContainsAttribute(
    118                 content, "Result/Module/TestCase/Test", "name", "module1.method1");
    119 
    120         assertXmlContainsAttribute(content, "Result/Module", "name", "module2");
    121         assertXmlContainsAttribute(content, "Result/Module", "pass", "1");
    122         assertXmlContainsAttribute(content, "Result/Module/TestCase", "name", "com.class.module2");
    123         assertXmlContainsAttribute(
    124                 content, "Result/Module/TestCase/Test", "name", "module2.method0");
    125     }
    126 
    127     /** Check that the test failures are properly reported. */
    128     @Test
    129     public void testFailuresReporting() throws Exception {
    130         mResultHolder.context = mContext;
    131 
    132         Collection<TestRunResult> runResults = new ArrayList<>();
    133         runResults.add(createFakeResult("module1", 2, 1));
    134         mResultHolder.runResults = runResults;
    135 
    136         Map<String, IAbi> modulesAbi = new HashMap<>();
    137         modulesAbi.put("module1", new Abi("armeabi-v7a", "32"));
    138         mResultHolder.modulesAbi = modulesAbi;
    139 
    140         mResultHolder.completeModules = 2;
    141         mResultHolder.totalModules = 1;
    142         mResultHolder.passedTests = 2;
    143         mResultHolder.failedTests = 1;
    144         mResultHolder.startTime = 0L;
    145         mResultHolder.endTime = 10L;
    146         File res = mFormatter.writeResults(mResultHolder, mResultDir);
    147         String content = FileUtil.readStringFromFile(res);
    148 
    149         assertXmlContainsNode(content, "Result/Module");
    150         assertXmlContainsAttribute(content, "Result/Module/TestCase", "name", "com.class.module1");
    151         assertXmlContainsAttribute(
    152                 content, "Result/Module/TestCase/Test", "name", "module1.method0");
    153         assertXmlContainsAttribute(
    154                 content, "Result/Module/TestCase/Test", "name", "module1.method1");
    155         // Check that failures are showing in the xml for the test cases
    156         assertXmlContainsAttribute(
    157                 content, "Result/Module/TestCase/Test", "name", "module1.failed0");
    158         assertXmlContainsAttribute(
    159                 content, "Result/Module/TestCase/Test/Failure", "message", "module1 failed.");
    160         assertXmlContainsValue(
    161                 content,
    162                 "Result/Module/TestCase/Test/Failure/StackTrace",
    163                 "module1 failed.\nstack\nstack");
    164         // Test that we can read back the informations
    165         SuiteResultHolder holder = mFormatter.parseResults(mResultDir);
    166         assertEquals(holder.completeModules, mResultHolder.completeModules);
    167         assertEquals(holder.totalModules, mResultHolder.totalModules);
    168         assertEquals(holder.passedTests, mResultHolder.passedTests);
    169         assertEquals(holder.failedTests, mResultHolder.failedTests);
    170         assertEquals(holder.startTime, mResultHolder.startTime);
    171         assertEquals(holder.endTime, mResultHolder.endTime);
    172         assertEquals(
    173                 holder.modulesAbi.get("armeabi-v7a module1"),
    174                 mResultHolder.modulesAbi.get("module1"));
    175         assertEquals(holder.runResults.size(), mResultHolder.runResults.size());
    176     }
    177 
    178     /** Check that the logs for each test case are reported. */
    179     @Test
    180     public void testLogReporting() throws Exception {
    181         mResultHolder.context = mContext;
    182 
    183         Collection<TestRunResult> runResults = new ArrayList<>();
    184         runResults.add(createResultWithLog("armeabi-v7a module1", 1, LogDataType.LOGCAT));
    185         runResults.add(createResultWithLog("module2", 1, LogDataType.BUGREPORT));
    186         runResults.add(createResultWithLog("module3", 1, LogDataType.PNG));
    187         mResultHolder.runResults = runResults;
    188 
    189         Map<String, IAbi> modulesAbi = new HashMap<>();
    190         modulesAbi.put("armeabi-v7a module1", new Abi("armeabi-v7a", "32"));
    191         mResultHolder.modulesAbi = modulesAbi;
    192 
    193         mResultHolder.completeModules = 2;
    194         mResultHolder.totalModules = 2;
    195         mResultHolder.passedTests = 2;
    196         mResultHolder.failedTests = 0;
    197         mResultHolder.startTime = 0L;
    198         mResultHolder.endTime = 10L;
    199         File res = mFormatter.writeResults(mResultHolder, mResultDir);
    200         String content = FileUtil.readStringFromFile(res);
    201         // One logcat and one bugreport are found in the report
    202         assertXmlContainsValue(
    203                 content, "Result/Module/TestCase/Test/Logcat", "http:url/armeabi-v7a module1");
    204         assertXmlContainsValue(
    205                 content, "Result/Module/TestCase/Test/BugReport", "http:url/module2");
    206         assertXmlContainsValue(
    207                 content, "Result/Module/TestCase/Test/Screenshot", "http:url/module3");
    208 
    209         // Test that we can read back the informations for log files
    210         SuiteResultHolder holder = mFormatter.parseResults(mResultDir);
    211         assertEquals(
    212                 holder.modulesAbi.get("armeabi-v7a module1"),
    213                 mResultHolder.modulesAbi.get("armeabi-v7a module1"));
    214         assertEquals(holder.runResults.size(), mResultHolder.runResults.size());
    215         for (TestRunResult result : holder.runResults) {
    216             TestDescription description =
    217                     new TestDescription(
    218                             "com.class." + result.getName(), result.getName() + ".method0");
    219             // Check that we reloaded the logged files.
    220             assertTrue(
    221                     result.getTestResults()
    222                                     .get(description)
    223                                     .getLoggedFiles()
    224                                     .get(result.getName() + "log0")
    225                             != null);
    226         }
    227     }
    228 
    229     private TestRunResult createResultWithLog(String runName, int count, LogDataType type) {
    230         TestRunResult fakeRes = new TestRunResult();
    231         fakeRes.testRunStarted(runName, count);
    232         for (int i = 0; i < count; i++) {
    233             TestDescription description =
    234                     new TestDescription("com.class." + runName, runName + ".method" + i);
    235             fakeRes.testStarted(description);
    236             fakeRes.testLogSaved(
    237                     runName + "log" + i, new LogFile("path", "http:url/" + runName, type));
    238             fakeRes.testEnded(description, new HashMap<String, Metric>());
    239         }
    240         fakeRes.testRunEnded(10L, new HashMap<String, String>());
    241         return fakeRes;
    242     }
    243 
    244     private TestRunResult createFakeResult(String runName, int passed, int failed) {
    245         TestRunResult fakeRes = new TestRunResult();
    246         fakeRes.testRunStarted(runName, passed + failed);
    247         for (int i = 0; i < passed; i++) {
    248             TestDescription description =
    249                     new TestDescription("com.class." + runName, runName + ".method" + i);
    250             fakeRes.testStarted(description);
    251             fakeRes.testEnded(description, new HashMap<String, Metric>());
    252         }
    253         for (int i = 0; i < failed; i++) {
    254             TestDescription description =
    255                     new TestDescription("com.class." + runName, runName + ".failed" + i);
    256             fakeRes.testStarted(description);
    257             fakeRes.testFailed(description, runName + " failed.\nstack\nstack");
    258             fakeRes.testEnded(description, new HashMap<String, Metric>());
    259         }
    260         fakeRes.testRunEnded(10L, new HashMap<String, Metric>());
    261         return fakeRes;
    262     }
    263 
    264     /** Return all XML nodes that match the given xPathExpression. */
    265     private NodeList getXmlNodes(String xml, String xPathExpression)
    266             throws XPathExpressionException {
    267 
    268         InputSource inputSource = new InputSource(new StringReader(xml));
    269         XPath xpath = XPathFactory.newInstance().newXPath();
    270         return (NodeList) xpath.evaluate(xPathExpression, inputSource, XPathConstants.NODESET);
    271     }
    272 
    273     /** Assert that the XML contains a node matching the given xPathExpression. */
    274     private NodeList assertXmlContainsNode(String xml, String xPathExpression)
    275             throws XPathExpressionException {
    276         NodeList nodes = getXmlNodes(xml, xPathExpression);
    277         assertNotNull(
    278                 String.format("XML '%s' returned null for xpath '%s'.", xml, xPathExpression),
    279                 nodes);
    280         assertTrue(
    281                 String.format(
    282                         "XML '%s' should have returned at least 1 node for xpath '%s', "
    283                                 + "but returned %s nodes instead.",
    284                         xml, xPathExpression, nodes.getLength()),
    285                 nodes.getLength() >= 1);
    286         return nodes;
    287     }
    288 
    289     /**
    290      * Assert that the XML contains a node matching the given xPathExpression and that the node has
    291      * a given value.
    292      */
    293     private void assertXmlContainsValue(String xml, String xPathExpression, String value)
    294             throws XPathExpressionException {
    295         NodeList nodes = assertXmlContainsNode(xml, xPathExpression);
    296         boolean found = false;
    297 
    298         for (int i = 0; i < nodes.getLength(); i++) {
    299             Element element = (Element) nodes.item(i);
    300             if (element.getTextContent().equals(value)) {
    301                 found = true;
    302                 break;
    303             }
    304         }
    305 
    306         assertTrue(
    307                 String.format(
    308                         "xPath '%s' should contain value '%s' but does not. XML: '%s'",
    309                         xPathExpression, value, xml),
    310                 found);
    311     }
    312 
    313     /**
    314      * Assert that the XML contains a node matching the given xPathExpression and that the node has
    315      * a given value.
    316      */
    317     private void assertXmlContainsAttribute(
    318             String xml, String xPathExpression, String attributeName, String attributeValue)
    319             throws XPathExpressionException {
    320         NodeList nodes = assertXmlContainsNode(xml, xPathExpression);
    321         boolean found = false;
    322 
    323         for (int i = 0; i < nodes.getLength(); i++) {
    324             Element element = (Element) nodes.item(i);
    325             String value = element.getAttribute(attributeName);
    326             if (attributeValue.equals(value)) {
    327                 found = true;
    328                 break;
    329             }
    330         }
    331 
    332         assertTrue(
    333                 String.format(
    334                         "xPath '%s' should contain attribute '%s' but does not. XML: '%s'",
    335                         xPathExpression, attributeName, xml),
    336                 found);
    337     }
    338 }
    339