1 /*
2  * Copyright (C) 2015 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 com.android.compatibility.common.tradefed.testtype;
18 
19 import com.android.compatibility.common.tradefed.build.CompatibilityBuildProvider;
20 import com.android.compatibility.common.tradefed.testtype.ModuleRepo.ConfigFilter;
21 import com.android.compatibility.common.tradefed.testtype.IModuleDef;
22 import com.android.compatibility.common.util.AbiUtils;
23 import com.android.tradefed.build.IBuildInfo;
24 import com.android.tradefed.testtype.IAbi;
25 import com.android.tradefed.testtype.IRemoteTest;
26 import com.android.tradefed.testtype.IShardableTest;
27 import com.android.tradefed.util.FileUtil;
28 
29 import junit.framework.TestCase;
30 
31 import java.io.File;
32 import java.io.IOException;
33 import java.util.Arrays;
34 import java.util.ArrayList;
35 import java.util.HashSet;
36 import java.util.List;
37 import java.util.Map;
38 import java.util.Set;
39 
40 public class ModuleRepoTest extends TestCase {
41 
42     private static final String TOKEN =
43             "<target_preparer class=\"com.android.compatibility.common.tradefed.targetprep.TokenRequirement\">\n"
44             + "<option name=\"token\" value=\"%s\" />\n"
45             + "</target_preparer>\n";
46     private static final String CONFIG =
47             "<configuration description=\"Auto Generated File\">\n" +
48             "%s" +
49             "<test class=\"com.android.compatibility.common.tradefed.testtype.%s\">\n" +
50             "<option name=\"module\" value=\"%s\" />" +
51             "</test>\n" +
52             "</configuration>";
53     private static final String FOOBAR_TOKEN = "foobar";
54     private static final String SERIAL1 = "abc";
55     private static final String SERIAL2 = "def";
56     private static final String SERIAL3 = "ghi";
57     private static final Set<String> SERIALS = new HashSet<>();
58     private static final Set<IAbi> ABIS = new HashSet<>();
59     private static final List<String> DEVICE_TOKENS = new ArrayList<>();
60     private static final List<String> TEST_ARGS= new ArrayList<>();
61     private static final List<String> MODULE_ARGS = new ArrayList<>();
62     private static final List<String> INCLUDES = new ArrayList<>();
63     private static final List<String> EXCLUDES = new ArrayList<>();
64     private static final Set<String> FILES = new HashSet<>();
65     private static final String FILENAME = "%s.config";
66     private static final String ABI_32 = "armeabi-v7a";
67     private static final String ABI_64 = "arm64-v8a";
68     private static final String MODULE_NAME_A = "FooModuleA";
69     private static final String MODULE_NAME_B = "FooModuleB";
70     private static final String MODULE_NAME_C = "FooModuleC";
71     private static final String ID_A_32 = AbiUtils.createId(ABI_32, MODULE_NAME_A);
72     private static final String ID_A_64 = AbiUtils.createId(ABI_64, MODULE_NAME_A);
73     private static final String ID_B_32 = AbiUtils.createId(ABI_32, MODULE_NAME_B);
74     private static final String ID_B_64 = AbiUtils.createId(ABI_64, MODULE_NAME_B);
75     private static final String ID_C_32 = AbiUtils.createId(ABI_32, MODULE_NAME_C);
76     private static final String ID_C_64 = AbiUtils.createId(ABI_64, MODULE_NAME_C);
77     private static final String TEST_ARG = TestStub.class.getName() + ":foo:bar";
78     private static final String MODULE_ARG = "%s:blah:foobar";
79     private static final String TEST_STUB = "TestStub"; // Trivial test stub
80     private static final String SHARDABLE_TEST_STUB = "ShardableTestStub"; // Shardable and IBuildReceiver
81     private static final String [] EXPECTED_MODULE_IDS = new String[] {
82         "arm64-v8a FooModuleB",
83         "arm64-v8a FooModuleC",
84         "armeabi-v7a FooModuleA",
85         "arm64-v8a FooModuleA",
86         "armeabi-v7a FooModuleC",
87         "armeabi-v7a FooModuleB"
88     };
89 
90     static {
91         SERIALS.add(SERIAL1);
92         SERIALS.add(SERIAL2);
93         SERIALS.add(SERIAL3);
ABIS.add(new Abi(ABI_32, "32"))94         ABIS.add(new Abi(ABI_32, "32"));
ABIS.add(new Abi(ABI_64, "64"))95         ABIS.add(new Abi(ABI_64, "64"));
96         DEVICE_TOKENS.add(String.format("%s:%s", SERIAL3, FOOBAR_TOKEN));
97         TEST_ARGS.add(TEST_ARG);
String.format(MODULE_ARG, MODULE_NAME_A)98         MODULE_ARGS.add(String.format(MODULE_ARG, MODULE_NAME_A));
String.format(MODULE_ARG, MODULE_NAME_B)99         MODULE_ARGS.add(String.format(MODULE_ARG, MODULE_NAME_B));
String.format(MODULE_ARG, MODULE_NAME_C)100         MODULE_ARGS.add(String.format(MODULE_ARG, MODULE_NAME_C));
String.format(FILENAME, MODULE_NAME_A)101         FILES.add(String.format(FILENAME, MODULE_NAME_A));
String.format(FILENAME, MODULE_NAME_B)102         FILES.add(String.format(FILENAME, MODULE_NAME_B));
String.format(FILENAME, MODULE_NAME_C)103         FILES.add(String.format(FILENAME, MODULE_NAME_C));
104     }
105     private IModuleRepo mRepo;
106     private File mTestsDir;
107     private IBuildInfo mBuild;
108 
109     @Override
setUp()110     public void setUp() throws Exception {
111         mTestsDir = setUpConfigs();
112         mRepo = new ModuleRepo();
113         mBuild = new CompatibilityBuildProvider().getBuild();
114     }
115 
setUpConfigs()116     private File setUpConfigs() throws IOException {
117         File testsDir = FileUtil.createNamedTempDir("testcases");
118         createConfig(testsDir, MODULE_NAME_A, null);
119         createConfig(testsDir, MODULE_NAME_B, null);
120         createConfig(testsDir, MODULE_NAME_C, FOOBAR_TOKEN);
121         return testsDir;
122     }
123 
createConfig(File testsDir, String name, String token)124     private void createConfig(File testsDir, String name, String token) throws IOException {
125         createConfig(testsDir, name, token, TEST_STUB);
126     }
127 
createConfig(File testsDir, String name, String token, String moduleClass)128     private void createConfig(File testsDir, String name, String token, String moduleClass) throws IOException {
129         File config = new File(testsDir, String.format(FILENAME, name));
130         String preparer = "";
131         if (token != null) {
132             preparer = String.format(TOKEN, token);
133         }
134         FileUtil.writeToFile(String.format(CONFIG, preparer, moduleClass, name), config);
135     }
136 
137     @Override
tearDown()138     public void tearDown() throws Exception {
139         tearDownConfigs(mTestsDir);
140     }
141 
tearDownConfigs(File testsDir)142     private void tearDownConfigs(File testsDir) {
143         FileUtil.recursiveDelete(testsDir);
144     }
145 
testInitialization()146     public void testInitialization() throws Exception {
147         mRepo.initialize(3, mTestsDir, ABIS, DEVICE_TOKENS, TEST_ARGS, MODULE_ARGS, INCLUDES,
148                 EXCLUDES, mBuild);
149         assertTrue("Should be initialized", mRepo.isInitialized());
150         assertEquals("Wrong number of shards", 3, mRepo.getNumberOfShards());
151         assertEquals("Wrong number of modules per shard", 2, mRepo.getModulesPerShard());
152         Map<String, Set<String>> deviceTokens = mRepo.getDeviceTokens();
153         assertEquals("Wrong number of devices with tokens", 1, deviceTokens.size());
154         Set<String> tokens = deviceTokens.get(SERIAL3);
155         assertEquals("Wrong number of tokens", 1, tokens.size());
156         assertTrue("Unexpected device token", tokens.contains(FOOBAR_TOKEN));
157         assertEquals("Wrong number of modules", 0, mRepo.getLargeModules().size());
158         assertEquals("Wrong number of modules", 0, mRepo.getMediumModules().size());
159         assertEquals("Wrong number of modules", 4, mRepo.getSmallModules().size());
160         List<IModuleDef> tokenModules = mRepo.getTokenModules();
161         assertEquals("Wrong number of modules with tokens", 2, tokenModules.size());
162         List<IModuleDef> serial1Modules = mRepo.getModules(SERIAL1);
163         assertEquals("Wrong number of modules", 2, serial1Modules.size());
164         List<IModuleDef> serial2Modules = mRepo.getModules(SERIAL2);
165         assertEquals("Wrong number of modules", 2, serial2Modules.size());
166         List<IModuleDef> serial3Modules = mRepo.getModules(SERIAL3);
167         assertEquals("Wrong number of modules", 2, serial3Modules.size());
168         // Serial 3 should have the modules with tokens
169         for (IModuleDef module : serial3Modules) {
170             assertEquals("Wrong module", MODULE_NAME_C, module.getName());
171         }
172         Set<String> serials = mRepo.getSerials();
173         assertEquals("Wrong number of serials", 3, serials.size());
174         assertTrue("Unexpected device serial", serials.containsAll(SERIALS));
175     }
176 
testConfigFilter()177     public void testConfigFilter() throws Exception {
178         File[] configFiles = mTestsDir.listFiles(new ConfigFilter());
179         assertEquals("Wrong number of config files found.", 3, configFiles.length);
180         for (File file : configFiles) {
181             assertTrue(String.format("Unrecognised file: %s", file.getAbsolutePath()),
182                     FILES.contains(file.getName()));
183         }
184     }
185 
testFiltering()186     public void testFiltering() throws Exception {
187         List<String> includeFilters = new ArrayList<>();
188         includeFilters.add(MODULE_NAME_A);
189         List<String> excludeFilters = new ArrayList<>();
190         excludeFilters.add(ID_A_32);
191         excludeFilters.add(MODULE_NAME_B);
192         mRepo.initialize(1, mTestsDir, ABIS, DEVICE_TOKENS, TEST_ARGS, MODULE_ARGS, includeFilters,
193                 excludeFilters, mBuild);
194         List<IModuleDef> modules = mRepo.getModules(SERIAL1);
195         assertEquals("Incorrect number of modules", 1, modules.size());
196         IModuleDef module = modules.get(0);
197         assertEquals("Incorrect ID", ID_A_64, module.getId());
198         checkArgs(module);
199     }
200 
testParsing()201     public void testParsing() throws Exception {
202         mRepo.initialize(1, mTestsDir, ABIS, DEVICE_TOKENS, TEST_ARGS, MODULE_ARGS, INCLUDES,
203                 EXCLUDES, mBuild);
204         List<IModuleDef> modules = mRepo.getModules(SERIAL3);
205         Set<String> idSet = new HashSet<>();
206         for (IModuleDef module : modules) {
207             idSet.add(module.getId());
208         }
209         assertEquals("Incorrect number of IDs", 6, idSet.size());
210         assertTrue("Missing ID_A_32", idSet.contains(ID_A_32));
211         assertTrue("Missing ID_A_64", idSet.contains(ID_A_64));
212         assertTrue("Missing ID_B_32", idSet.contains(ID_B_32));
213         assertTrue("Missing ID_B_64", idSet.contains(ID_B_64));
214         assertTrue("Missing ID_C_32", idSet.contains(ID_C_32));
215         assertTrue("Missing ID_C_64", idSet.contains(ID_C_64));
216         for (IModuleDef module : modules) {
217             checkArgs(module);
218         }
219     }
220 
checkArgs(IModuleDef module)221     private void checkArgs(IModuleDef module) {
222         IRemoteTest test = module.getTest();
223         assertTrue("Incorrect test type", test instanceof TestStub);
224         TestStub stub = (TestStub) test;
225         assertEquals("Incorrect test arg", "bar", stub.mFoo);
226         assertEquals("Incorrect module arg", "foobar", stub.mBlah);
227     }
228 
testSplit()229     public void testSplit() throws Exception {
230         createConfig(mTestsDir, "sharder_1", null, SHARDABLE_TEST_STUB);
231         createConfig(mTestsDir, "sharder_2", null, SHARDABLE_TEST_STUB);
232         createConfig(mTestsDir, "sharder_3", null, SHARDABLE_TEST_STUB);
233         Set<IAbi> abis = new HashSet<>();
234         abis.add(new Abi(ABI_64, "64"));
235         ArrayList<String> emptyList = new ArrayList<>();
236 
237         mRepo.initialize(3, mTestsDir, abis, DEVICE_TOKENS, emptyList, emptyList, emptyList,
238                          emptyList, mBuild);
239 
240         List<IModuleDef> modules = new ArrayList<>();
241         modules.addAll(mRepo.getLargeModules());
242         modules.addAll(mRepo.getMediumModules());
243         modules.addAll(mRepo.getSmallModules());
244         modules.addAll(mRepo.getTokenModules());
245 
246         int shardableCount = 0;
247         for (IModuleDef def : modules) {
248             IRemoteTest test = def.getTest();
249             if (test instanceof IShardableTest) {
250                 assertNotNull("Build not set", ((ShardableTestStub)test).mBuildInfo);
251                 shardableCount++;
252             }
253         }
254         assertEquals("Shards wrong", 3*3, shardableCount);
255     }
256 
testGetModuleIds()257     public void testGetModuleIds() {
258         mRepo.initialize(3, mTestsDir, ABIS, DEVICE_TOKENS, TEST_ARGS, MODULE_ARGS, INCLUDES,
259                 EXCLUDES, mBuild);
260         assertTrue("Should be initialized", mRepo.isInitialized());
261 
262         assertArrayEquals(EXPECTED_MODULE_IDS, mRepo.getModuleIds());
263     }
264 
assertArrayEquals(Object[] expected, Object[] actual)265     private void assertArrayEquals(Object[] expected, Object[] actual) {
266         assertEquals(Arrays.asList(expected), Arrays.asList(actual));
267     }
268 }
269