Home | History | Annotate | Download | only in suite
      1 /*
      2  * Copyright (C) 2016 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.testtype.suite;
     17 
     18 import static org.junit.Assert.assertEquals;
     19 import static org.junit.Assert.assertNull;
     20 import static org.junit.Assert.assertTrue;
     21 import static org.junit.Assert.fail;
     22 import static org.mockito.Mockito.mock;
     23 
     24 import com.android.tradefed.build.IBuildInfo;
     25 import com.android.tradefed.build.IDeviceBuildInfo;
     26 import com.android.tradefed.config.ConfigurationException;
     27 import com.android.tradefed.config.IConfiguration;
     28 import com.android.tradefed.config.OptionSetter;
     29 import com.android.tradefed.device.ITestDevice;
     30 import com.android.tradefed.invoker.InvocationContext;
     31 import com.android.tradefed.result.ITestInvocationListener;
     32 import com.android.tradefed.testtype.IRemoteTest;
     33 import com.android.tradefed.testtype.StubTest;
     34 import com.android.tradefed.util.FileUtil;
     35 import com.android.tradefed.util.ZipUtil;
     36 
     37 import org.easymock.EasyMock;
     38 import org.junit.Before;
     39 import org.junit.Test;
     40 import org.junit.runner.RunWith;
     41 import org.junit.runners.JUnit4;
     42 
     43 import java.io.File;
     44 import java.util.ArrayList;
     45 import java.util.Collection;
     46 import java.util.LinkedHashMap;
     47 import java.util.List;
     48 
     49 /**
     50  * Unit tests for {@link TfSuiteRunner}.
     51  */
     52 @RunWith(JUnit4.class)
     53 public class TfSuiteRunnerTest {
     54 
     55     private static final String TEST_CONFIG =
     56             "<configuration description=\"Runs a stub tests part of some suite\">\n"
     57                     + "    <option name=\"test-suite-tag\" value=\"example-suite\" />\n"
     58                     + "    <test class=\"com.android.tradefed.testtype.StubTest\" />\n"
     59                     + "</configuration>";
     60 
     61     private TfSuiteRunner mRunner;
     62 
     63     @Before
     64     public void setUp() {
     65         mRunner = new TfSuiteRunner();
     66     }
     67 
     68     /**
     69      * Test for {@link TfSuiteRunner#loadTests()} implementation, for basic example configurations.
     70      */
     71     @Test
     72     public void testLoadTests() throws Exception {
     73         OptionSetter setter = new OptionSetter(mRunner);
     74         setter.setOptionValue("suite-config-prefix", "suite");
     75         setter.setOptionValue("run-suite-tag", "example-suite");
     76         LinkedHashMap <String, IConfiguration> configMap = mRunner.loadTests();
     77         assertEquals(2, configMap.size());
     78         assertTrue(configMap.containsKey("suite/stub1"));
     79         assertTrue(configMap.containsKey("suite/stub2"));
     80     }
     81 
     82     /**
     83      * Test for {@link TfSuiteRunner#loadTests()} implementation, only stub1.xml is part of this
     84      * suite.
     85      */
     86     @Test
     87     public void testLoadTests_suite2() throws Exception {
     88         OptionSetter setter = new OptionSetter(mRunner);
     89         setter.setOptionValue("suite-config-prefix", "suite");
     90         setter.setOptionValue("run-suite-tag", "example-suite2");
     91         LinkedHashMap <String, IConfiguration> configMap = mRunner.loadTests();
     92         assertEquals(1, configMap.size());
     93         assertTrue(configMap.containsKey("suite/stub1"));
     94     }
     95 
     96     /** Test that when splitting, the instance of the implementation is used. */
     97     @Test
     98     public void testSplit() throws Exception {
     99         OptionSetter setter = new OptionSetter(mRunner);
    100         setter.setOptionValue("suite-config-prefix", "suite");
    101         setter.setOptionValue("run-suite-tag", "example-suite");
    102         Collection<IRemoteTest> tests = mRunner.split(2);
    103         assertEquals(2, tests.size());
    104         for (IRemoteTest test : tests) {
    105             assertTrue(test instanceof TfSuiteRunner);
    106         }
    107     }
    108 
    109     /**
    110      * Test that when {@link TfSuiteRunner} run-suite-tag is not set we cannot shard since there is
    111      * no configuration.
    112      */
    113     @Test
    114     public void testSplit_nothingToLoad() throws Exception {
    115         OptionSetter setter = new OptionSetter(mRunner);
    116         setter.setOptionValue("suite-config-prefix", "doesnotexists");
    117         setter.setOptionValue("run-suite-tag", "doesnotexists");
    118         assertNull(mRunner.split(2));
    119     }
    120 
    121     /**
    122      * Attempt to load a suite from a suite, but the sub-suite does not have a default run-suite-tag
    123      * so it cannot run anything.
    124      */
    125     @Test
    126     public void testLoadSuite_noSubConfigs() throws ConfigurationException {
    127         OptionSetter setter = new OptionSetter(mRunner);
    128         setter.setOptionValue("suite-config-prefix", "suite");
    129         setter.setOptionValue("run-suite-tag", "test-empty");
    130         LinkedHashMap<String, IConfiguration> configMap = mRunner.loadTests();
    131         assertEquals(0, configMap.size());
    132     }
    133 
    134     /**
    135      * Attempt to load a suite from a suite, the sub-suite has a default run-suite-tag that will be
    136      * loaded.
    137      */
    138     @Test
    139     public void testLoadSuite() throws ConfigurationException {
    140         OptionSetter setter = new OptionSetter(mRunner);
    141         setter.setOptionValue("suite-config-prefix", "suite");
    142         setter.setOptionValue("run-suite-tag", "test-sub-suite");
    143         LinkedHashMap<String, IConfiguration> configMap = mRunner.loadTests();
    144         assertEquals(3, configMap.size());
    145         // 2 test configs loaded from the sub-suite
    146         assertTrue(configMap.containsKey("suite/stub1"));
    147         assertTrue(configMap.containsKey("suite/stub2"));
    148         // 1 config from the left over <test> that was not a suite.
    149         assertTrue(configMap.containsKey("suite/sub-suite"));
    150         IConfiguration config = configMap.get("suite/sub-suite");
    151         // assert that the TfSuiteRunner was removed from the config, only the stubTest remains
    152         assertTrue(config.getTests().size() == 1);
    153         assertTrue(config.getTests().get(0) instanceof StubTest);
    154     }
    155 
    156     /**
    157      * In case of cycle include of sub-suite configuration. We throw an exception to prevent any
    158      * weird runs.
    159      */
    160     @Test
    161     public void testLoadSuite_cycle() throws ConfigurationException {
    162         OptionSetter setter = new OptionSetter(mRunner);
    163         setter.setOptionValue("suite-config-prefix", "suite");
    164         setter.setOptionValue("run-suite-tag", "test-cycle-a");
    165         try {
    166             mRunner.loadTests();
    167             fail("Should have thrown an exception.");
    168         } catch (RuntimeException expected) {
    169             // expected
    170         }
    171     }
    172 
    173     /** Test for {@link TfSuiteRunner#run(ITestInvocationListener)} when loading another suite. */
    174     @Test
    175     public void testLoadTests_suite() throws Exception {
    176         OptionSetter setter = new OptionSetter(mRunner);
    177         setter.setOptionValue("suite-config-prefix", "suite");
    178         setter.setOptionValue("run-suite-tag", "example-suite3");
    179         ITestInvocationListener listener = EasyMock.createMock(ITestInvocationListener.class);
    180         mRunner.setDevice(mock(ITestDevice.class));
    181         mRunner.setBuild(mock(IBuildInfo.class));
    182         mRunner.setSystemStatusChecker(new ArrayList<>());
    183         mRunner.setInvocationContext(new InvocationContext());
    184         // runs the expanded suite
    185         listener.testModuleStarted(EasyMock.anyObject());
    186         listener.testRunStarted("suite/stub1", 0);
    187         listener.testRunEnded(EasyMock.anyLong(), EasyMock.anyObject());
    188         listener.testModuleEnded();
    189         EasyMock.replay(listener);
    190         mRunner.run(listener);
    191         EasyMock.verify(listener);
    192     }
    193 
    194     /**
    195      * Test for {@link TfSuiteRunner#run(ITestInvocationListener)} when loading test configs from
    196      * additional-tests-zip.
    197      */
    198     @Test
    199     public void testLoadTests_additionalTestsZip() throws Exception {
    200         File tmpDir = null;
    201         File deviceTestDir = null;
    202         File additionalTestsZipFile = null;
    203         try {
    204             tmpDir = FileUtil.createTempDir("test");
    205             // tests directory for the build.
    206             deviceTestDir = FileUtil.createTempDir("build-info-test-dir");
    207 
    208             File zipDir = FileUtil.getFileForPath(tmpDir, "suite");
    209             FileUtil.mkdirsRWX(zipDir);
    210 
    211             // Create 2 test configs inside a zip.
    212             File testConfig = new File(zipDir, "test1.config");
    213             FileUtil.writeToFile(TEST_CONFIG, testConfig);
    214             File testConfig2 = new File(zipDir, "test2.config");
    215             FileUtil.writeToFile(TEST_CONFIG, testConfig2);
    216             additionalTestsZipFile = ZipUtil.createZip(zipDir);
    217 
    218             OptionSetter setter = new OptionSetter(mRunner);
    219             setter.setOptionValue("suite-config-prefix", "suite");
    220             setter.setOptionValue("run-suite-tag", "example-suite");
    221             setter.setOptionValue("additional-tests-zip", additionalTestsZipFile.getAbsolutePath());
    222 
    223             IDeviceBuildInfo deviceBuildInfo = EasyMock.createMock(IDeviceBuildInfo.class);
    224             EasyMock.expect(deviceBuildInfo.getTestsDir()).andReturn(deviceTestDir);
    225             mRunner.setBuild(deviceBuildInfo);
    226 
    227             EasyMock.replay(deviceBuildInfo);
    228             LinkedHashMap<String, IConfiguration> configMap = mRunner.loadTests();
    229             assertEquals(4, configMap.size());
    230             // The keySet should be stable and always ensure the same order of files.
    231             List<String> keyList = new ArrayList<>(configMap.keySet());
    232             // test1 and test2 name was sanitized to look like the included configs.
    233             assertEquals("suite/test1", keyList.get(0));
    234             assertEquals("suite/test2", keyList.get(1));
    235             assertEquals("suite/stub1", keyList.get(2));
    236             assertEquals("suite/stub2", keyList.get(3));
    237             EasyMock.verify(deviceBuildInfo);
    238         } finally {
    239             FileUtil.recursiveDelete(deviceTestDir);
    240             FileUtil.recursiveDelete(tmpDir);
    241             FileUtil.recursiveDelete(additionalTestsZipFile);
    242         }
    243     }
    244 }
    245