• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.util.testmapping;
17 
18 import static org.junit.Assert.assertEquals;
19 import static org.junit.Assert.assertFalse;
20 import static org.junit.Assert.assertTrue;
21 import static org.junit.Assert.fail;
22 import static org.mockito.Mockito.mock;
23 import static org.mockito.Mockito.times;
24 import static org.mockito.Mockito.verify;
25 import static org.mockito.Mockito.when;
26 
27 import com.android.tradefed.build.IBuildInfo;
28 import com.android.tradefed.error.HarnessRuntimeException;
29 import com.android.tradefed.util.FileUtil;
30 import com.android.tradefed.util.ZipUtil;
31 
32 import com.google.common.collect.Sets;
33 
34 import org.junit.Before;
35 import org.junit.Test;
36 import org.junit.runner.RunWith;
37 import org.junit.runners.JUnit4;
38 
39 import java.io.File;
40 import java.io.InputStream;
41 import java.nio.charset.StandardCharsets;
42 import java.nio.file.Files;
43 import java.nio.file.Path;
44 import java.nio.file.Paths;
45 import java.util.ArrayList;
46 import java.util.Arrays;
47 import java.util.HashSet;
48 import java.util.List;
49 import java.util.Map;
50 import java.util.Set;
51 
52 /** Unit tests for {@link TestMapping}. */
53 @RunWith(JUnit4.class)
54 public class TestMappingTest {
55 
56     private static final String TEST_DATA_DIR = "testdata";
57     private static final String TEST_MAPPING = "TEST_MAPPING";
58     private static final String TEST_MAPPINGS_ZIP = "test_mappings.zip";
59     private static final String DISABLED_PRESUBMIT_TESTS = "disabled-presubmit-tests";
60     private static final Set<String> NO_MATCHED_PATTERNS = new HashSet<>();
61     private static final boolean IGNORE_IMPORTS = true;
62     private TestMapping mTestMapping;
63 
64     @Before
setUp()65     public void setUp() throws Exception {
66         mTestMapping = new TestMapping();
67     }
68 
69     /** Test for {@link TestMapping#getTests()} implementation. */
70     @Test
testparseTestMapping()71     public void testparseTestMapping() throws Exception {
72         File tempDir = null;
73         File testMappingFile = null;
74 
75         try {
76             tempDir = FileUtil.createTempDir("test_mapping");
77             String srcFile = File.separator + TEST_DATA_DIR + File.separator + "test_mapping_1";
78             InputStream resourceStream = this.getClass().getResourceAsStream(srcFile);
79             File testMappingRootDir = FileUtil.createTempDir("subdir", tempDir);
80             String rootDirName = testMappingRootDir.getName();
81             testMappingFile =
82                     FileUtil.saveResourceFile(resourceStream, testMappingRootDir, TEST_MAPPING);
83             Set<TestInfo> tests =
84                     mTestMapping.getTests(
85                             mTestMapping.getTestCollection(
86                                     testMappingFile.toPath(),
87                                     Paths.get(tempDir.getAbsolutePath()),
88                                     NO_MATCHED_PATTERNS),
89                             "presubmit",
90                             null,
91                             true,
92                             null,
93                             new HashSet<String>());
94             assertEquals(1, tests.size());
95             Set<String> names = new HashSet<String>();
96             for (TestInfo test : tests) {
97                 names.add(test.getName());
98             }
99             assertTrue(names.contains("test1"));
100 
101             tests =
102                     mTestMapping.getTests(
103                             mTestMapping.getTestCollection(
104                                     testMappingFile.toPath(),
105                                     Paths.get(tempDir.getAbsolutePath()),
106                                     NO_MATCHED_PATTERNS),
107                             "presubmit",
108                             null,
109                             false,
110                             null,
111                             new HashSet<String>());
112             assertEquals(1, tests.size());
113             names = new HashSet<String>();
114             for (TestInfo test : tests) {
115                 names.add(test.getName());
116             }
117             assertTrue(names.contains("suite/stub1"));
118 
119             tests =
120                     mTestMapping.getTests(
121                             mTestMapping.getTestCollection(
122                                     testMappingFile.toPath(),
123                                     Paths.get(tempDir.getAbsolutePath()),
124                                     NO_MATCHED_PATTERNS),
125                             "postsubmit",
126                             null,
127                             false,
128                             null,
129                             new HashSet<String>());
130             assertEquals(2, tests.size());
131             TestOption testOption =
132                     new TestOption(
133                             "instrumentation-arg",
134                             "annotation=android.platform.test.annotations.Presubmit");
135             names = new HashSet<String>();
136             Set<TestOption> testOptions = new HashSet<TestOption>();
137             for (TestInfo test : tests) {
138                 names.add(test.getName());
139                 testOptions.addAll(test.getOptions());
140             }
141             assertTrue(names.contains("test2"));
142             assertTrue(names.contains("instrument"));
143             assertTrue(testOptions.contains(testOption));
144 
145             tests =
146                     mTestMapping.getTests(
147                             mTestMapping.getTestCollection(
148                                     testMappingFile.toPath(),
149                                     Paths.get(tempDir.getAbsolutePath()),
150                                     NO_MATCHED_PATTERNS),
151                             "othertype",
152                             null,
153                             false,
154                             null,
155                             new HashSet<String>());
156             assertEquals(1, tests.size());
157             names = new HashSet<String>();
158             testOptions = new HashSet<TestOption>();
159             Set<String> sources = new HashSet<String>();
160             for (TestInfo test : tests) {
161                 names.add(test.getName());
162                 testOptions.addAll(test.getOptions());
163                 sources.addAll(test.getSources());
164             }
165             assertTrue(names.contains("test3"));
166             assertEquals(1, testOptions.size());
167             assertTrue(sources.contains(rootDirName));
168         } finally {
169             FileUtil.recursiveDelete(tempDir);
170         }
171     }
172 
173     /** Test for {@link TestMapping#getTests()} throw exception for malformatted json file. */
174     @Test(expected = RuntimeException.class)
testparseTestMapping_BadJson()175     public void testparseTestMapping_BadJson() throws Exception {
176         File tempDir = null;
177 
178         try {
179             tempDir = FileUtil.createTempDir("test_mapping");
180             File testMappingFile = Paths.get(tempDir.getAbsolutePath(), TEST_MAPPING).toFile();
181             FileUtil.writeToFile("bad format json file", testMappingFile);
182             mTestMapping.getTests(
183                     mTestMapping.getTestCollection(
184                             testMappingFile.toPath(),
185                             Paths.get(tempDir.getAbsolutePath()),
186                             NO_MATCHED_PATTERNS),
187                     "presubmit",
188                     null,
189                     false,
190                     null,
191                     new HashSet<String>());
192         } finally {
193             FileUtil.recursiveDelete(tempDir);
194         }
195     }
196 
197     /** Test for {@link TestMapping#getTests()} for loading tests from test_mappings.zip. */
198     @Test
testGetTests()199     public void testGetTests() throws Exception {
200         File tempDir = null;
201         IBuildInfo mockBuildInfo = mock(IBuildInfo.class);
202         try {
203             tempDir = FileUtil.createTempDir("test_mapping");
204 
205             File srcDir = FileUtil.createTempDir("src", tempDir);
206             String srcFile = File.separator + TEST_DATA_DIR + File.separator + "test_mapping_1";
207             InputStream resourceStream = this.getClass().getResourceAsStream(srcFile);
208             FileUtil.saveResourceFile(resourceStream, srcDir, TEST_MAPPING);
209             File subDir = FileUtil.createTempDir("sub_dir", srcDir);
210             srcFile = File.separator + TEST_DATA_DIR + File.separator + "test_mapping_2";
211             resourceStream = this.getClass().getResourceAsStream(srcFile);
212             FileUtil.saveResourceFile(resourceStream, subDir, TEST_MAPPING);
213             srcFile = File.separator + TEST_DATA_DIR + File.separator + DISABLED_PRESUBMIT_TESTS;
214             resourceStream = this.getClass().getResourceAsStream(srcFile);
215             FileUtil.saveResourceFile(resourceStream, tempDir, DISABLED_PRESUBMIT_TESTS);
216             List<File> filesToZip =
217                     Arrays.asList(srcDir, new File(tempDir, DISABLED_PRESUBMIT_TESTS));
218 
219             File zipFile = Paths.get(tempDir.getAbsolutePath(), TEST_MAPPINGS_ZIP).toFile();
220             ZipUtil.createZip(filesToZip, zipFile);
221             when(mockBuildInfo.getFile(TEST_MAPPINGS_ZIP)).thenReturn(zipFile);
222 
223             // Ensure the static variable doesn't have any relative path configured.
224             Set<TestInfo> tests =
225                     mTestMapping.getTests(
226                             mockBuildInfo, "presubmit", false, null, new HashSet<String>());
227             assertEquals(0, tests.size());
228 
229             tests =
230                     mTestMapping.getTests(
231                             mockBuildInfo, "presubmit", true, null, new HashSet<String>());
232             assertEquals(2, tests.size());
233             Set<String> names = new HashSet<String>();
234             for (TestInfo test : tests) {
235                 names.add(test.getName());
236                 if (test.getName().equals("test1")) {
237                     assertTrue(test.getHostOnly());
238                 } else {
239                     assertFalse(test.getHostOnly());
240                 }
241             }
242             assertTrue(!names.contains("suite/stub1"));
243             assertTrue(names.contains("test1"));
244             verify(mockBuildInfo, times(2)).getFile(TEST_MAPPINGS_ZIP);
245         } finally {
246             FileUtil.recursiveDelete(tempDir);
247         }
248     }
249 
250     /**
251      * Test for {@link TestMapping#getTests()} for loading tests from test_mappings.zip for matching
252      * keywords.
253      */
254     @Test
testGetTests_matchKeywords()255     public void testGetTests_matchKeywords() throws Exception {
256         File tempDir = null;
257         IBuildInfo mockBuildInfo = mock(IBuildInfo.class);
258         try {
259             tempDir = FileUtil.createTempDir("test_mapping");
260 
261             File srcDir = FileUtil.createTempDir("src", tempDir);
262             String srcFile = File.separator + TEST_DATA_DIR + File.separator + "test_mapping_1";
263             InputStream resourceStream = this.getClass().getResourceAsStream(srcFile);
264             FileUtil.saveResourceFile(resourceStream, srcDir, TEST_MAPPING);
265             File subDir = FileUtil.createTempDir("sub_dir", srcDir);
266             srcFile = File.separator + TEST_DATA_DIR + File.separator + "test_mapping_2";
267             resourceStream = this.getClass().getResourceAsStream(srcFile);
268             FileUtil.saveResourceFile(resourceStream, subDir, TEST_MAPPING);
269             srcFile = File.separator + TEST_DATA_DIR + File.separator + DISABLED_PRESUBMIT_TESTS;
270             resourceStream = this.getClass().getResourceAsStream(srcFile);
271             FileUtil.saveResourceFile(resourceStream, tempDir, DISABLED_PRESUBMIT_TESTS);
272             List<File> filesToZip =
273                     Arrays.asList(srcDir, new File(tempDir, DISABLED_PRESUBMIT_TESTS));
274 
275             File zipFile = Paths.get(tempDir.getAbsolutePath(), TEST_MAPPINGS_ZIP).toFile();
276             ZipUtil.createZip(filesToZip, zipFile);
277             when(mockBuildInfo.getFile(TEST_MAPPINGS_ZIP)).thenReturn(zipFile);
278 
279             Set<TestInfo> tests =
280                     mTestMapping.getTests(
281                             mockBuildInfo,
282                             "presubmit",
283                             false,
284                             Sets.newHashSet("key_1"),
285                             new HashSet<String>());
286             assertEquals(1, tests.size());
287             assertEquals("suite/stub2", tests.iterator().next().getName());
288             verify(mockBuildInfo, times(1)).getFile(TEST_MAPPINGS_ZIP);
289         } finally {
290             FileUtil.recursiveDelete(tempDir);
291         }
292     }
293 
294     /**
295      * Test for {@link TestMapping#getTests()} for loading tests from test_mappings.zip for matching
296      * keywords.
297      */
298     @Test
testGetTests_withIgnoreKeywords()299     public void testGetTests_withIgnoreKeywords() throws Exception {
300         File tempDir = null;
301         IBuildInfo mockBuildInfo = mock(IBuildInfo.class);
302         try {
303             tempDir = FileUtil.createTempDir("test_mapping");
304 
305             File srcDir = FileUtil.createTempDir("src", tempDir);
306             String srcFile = File.separator + TEST_DATA_DIR + File.separator + "test_mapping_1";
307             InputStream resourceStream = this.getClass().getResourceAsStream(srcFile);
308             FileUtil.saveResourceFile(resourceStream, srcDir, TEST_MAPPING);
309             File subDir = FileUtil.createTempDir("sub_dir", srcDir);
310             srcFile = File.separator + TEST_DATA_DIR + File.separator + "test_mapping_2";
311             resourceStream = this.getClass().getResourceAsStream(srcFile);
312             FileUtil.saveResourceFile(resourceStream, subDir, TEST_MAPPING);
313             List<File> filesToZip = Arrays.asList(srcDir);
314 
315             File zipFile = Paths.get(tempDir.getAbsolutePath(), TEST_MAPPINGS_ZIP).toFile();
316             ZipUtil.createZip(filesToZip, zipFile);
317             when(mockBuildInfo.getFile(TEST_MAPPINGS_ZIP)).thenReturn(zipFile);
318 
319             Set<TestInfo> tests =
320                     mTestMapping.getTests(
321                             mockBuildInfo,
322                             "presubmit",
323                             false,
324                             new HashSet<String>(),
325                             Sets.newHashSet("key_1"));
326             assertEquals(3, tests.size());
327             verify(mockBuildInfo, times(1)).getFile(TEST_MAPPINGS_ZIP);
328         } finally {
329             FileUtil.recursiveDelete(tempDir);
330         }
331     }
332 
333     /**
334      * Test for {@link TestMapping#getAllTestMappingPaths(Path)} to get TEST_MAPPING files from
335      * child directory.
336      */
337     @Test
testGetAllTestMappingPaths_FromChildDirectory()338     public void testGetAllTestMappingPaths_FromChildDirectory() throws Exception {
339         File tempDir = null;
340         try {
341             tempDir = FileUtil.createTempDir("test_mapping");
342             Path testMappingsRootPath = Paths.get(tempDir.getAbsolutePath());
343             File srcDir = FileUtil.createTempDir("src", tempDir);
344             String srcFile = File.separator + TEST_DATA_DIR + File.separator + "test_mapping_1";
345             InputStream resourceStream = this.getClass().getResourceAsStream(srcFile);
346             FileUtil.saveResourceFile(resourceStream, srcDir, TEST_MAPPING);
347             File subDir = FileUtil.createTempDir("sub_dir", srcDir);
348             srcFile = File.separator + TEST_DATA_DIR + File.separator + "test_mapping_2";
349             resourceStream = this.getClass().getResourceAsStream(srcFile);
350             FileUtil.saveResourceFile(resourceStream, subDir, TEST_MAPPING);
351 
352             List<String> testMappingRelativePaths = new ArrayList<>();
353             Path relPath = testMappingsRootPath.relativize(Paths.get(subDir.getAbsolutePath()));
354             testMappingRelativePaths.add(relPath.toString());
355             TestMapping testMapping = new TestMapping(testMappingRelativePaths, true);
356             Set<Path> paths = testMapping.getAllTestMappingPaths(testMappingsRootPath);
357             assertEquals(2, paths.size());
358         } finally {
359             FileUtil.recursiveDelete(tempDir);
360         }
361     }
362 
363     /**
364      * Test for {@link TestMapping#getAllTestMappingPaths(Path)} to get TEST_MAPPING files from
365      * parent directory.
366      */
367     @Test
testGetAllTestMappingPaths_FromParentDirectory()368     public void testGetAllTestMappingPaths_FromParentDirectory() throws Exception {
369         File tempDir = null;
370         try {
371             tempDir = FileUtil.createTempDir("test_mapping");
372             Path testMappingsRootPath = Paths.get(tempDir.getAbsolutePath());
373             File srcDir = FileUtil.createTempDir("src", tempDir);
374             String srcFile = File.separator + TEST_DATA_DIR + File.separator + "test_mapping_1";
375             InputStream resourceStream = this.getClass().getResourceAsStream(srcFile);
376             FileUtil.saveResourceFile(resourceStream, srcDir, TEST_MAPPING);
377             File subDir = FileUtil.createTempDir("sub_dir", srcDir);
378             srcFile = File.separator + TEST_DATA_DIR + File.separator + "test_mapping_2";
379             resourceStream = this.getClass().getResourceAsStream(srcFile);
380             FileUtil.saveResourceFile(resourceStream, subDir, TEST_MAPPING);
381 
382             List<String> testMappingRelativePaths = new ArrayList<>();
383             Path relPath = testMappingsRootPath.relativize(Paths.get(srcDir.getAbsolutePath()));
384             testMappingRelativePaths.add(relPath.toString());
385             TestMapping testMapping = new TestMapping(testMappingRelativePaths, true);
386             Set<Path> paths = testMapping.getAllTestMappingPaths(testMappingsRootPath);
387             assertEquals(1, paths.size());
388         } finally {
389             FileUtil.recursiveDelete(tempDir);
390         }
391     }
392 
393     /**
394      * Test for {@link TestMapping#getAllTestMappingPaths(Path)} to fail when no TEST_MAPPING files
395      * found.
396      */
397     @Test(expected = RuntimeException.class)
testGetAllTestMappingPaths_NoFilesFound()398     public void testGetAllTestMappingPaths_NoFilesFound() throws Exception {
399         File tempDir = null;
400         try {
401             tempDir = FileUtil.createTempDir("test_mapping");
402             Path testMappingsRootPath = Paths.get(tempDir.getAbsolutePath());
403             File srcDir = FileUtil.createTempDir("src", tempDir);
404 
405             List<String> testMappingRelativePaths = new ArrayList<>();
406             Path relPath = testMappingsRootPath.relativize(Paths.get(srcDir.getAbsolutePath()));
407             testMappingRelativePaths.add(relPath.toString());
408             TestMapping testMapping = new TestMapping(testMappingRelativePaths, true);
409             // No TEST_MAPPING files should be found according to the srcDir, getAllTestMappingPaths
410             // method shall raise RuntimeException.
411             testMapping.getAllTestMappingPaths(testMappingsRootPath);
412         } finally {
413             FileUtil.recursiveDelete(tempDir);
414         }
415     }
416 
417     /**
418      * Test for {@link TestInfo#merge()} for merging two TestInfo objects to fail when module names
419      * are different.
420      */
421     @Test(expected = RuntimeException.class)
testMergeFailByName()422     public void testMergeFailByName() throws Exception {
423         TestInfo test1 = new TestInfo("test1", "folder1", false);
424         TestInfo test2 = new TestInfo("test2", "folder1", false);
425         test1.merge(test2);
426     }
427 
428     /**
429      * Test for {@link TestInfo#merge()} for merging two TestInfo objects to fail when device
430      * requirements are different.
431      */
432     @Test(expected = RuntimeException.class)
testMergeFailByHostOnly()433     public void testMergeFailByHostOnly() throws Exception {
434         TestInfo test1 = new TestInfo("test1", "folder1", false);
435         TestInfo test2 = new TestInfo("test2", "folder1", true);
436         test1.merge(test2);
437     }
438 
439     /**
440      * Test for {@link TestInfo#merge()} for merging two TestInfo objects, one of which has no
441      * option.
442      */
443     @Test
testMergeSuccess()444     public void testMergeSuccess() throws Exception {
445         // Check that the test without any option should be the merge result.
446         TestInfo test1 = new TestInfo("test1", "folder1", false);
447         TestInfo test2 = new TestInfo("test1", "folder1", false);
448         test2.addOption(new TestOption("include-filter", "value"));
449         test1.merge(test2);
450         assertTrue(test1.getOptions().isEmpty());
451         assertFalse(test1.getHostOnly());
452 
453         test1 = new TestInfo("test1", "folder1", false);
454         test2 = new TestInfo("test1", "folder1", false);
455         test1.addOption(new TestOption("include-filter", "value"));
456         test1.merge(test2);
457         assertTrue(test1.getOptions().isEmpty());
458         assertFalse(test1.getHostOnly());
459 
460         test1 = new TestInfo("test1", "folder1", true);
461         test2 = new TestInfo("test1", "folder1", true);
462         test1.addOption(new TestOption("include-filter", "value"));
463         test1.merge(test2);
464         assertTrue(test1.getOptions().isEmpty());
465         assertTrue(test1.getHostOnly());
466     }
467 
468     /**
469      * Test for {@link TestInfo#merge()} for merging two TestInfo objects, each has a different
470      * include-filter.
471      */
472     @Test
testMergeSuccess_2Filters()473     public void testMergeSuccess_2Filters() throws Exception {
474         // Check that the test without any option should be the merge result.
475         TestInfo test1 = new TestInfo("test1", "folder1", false);
476         TestInfo test2 = new TestInfo("test1", "folder2", false);
477         TestOption option1 = new TestOption("include-filter", "value1");
478         test1.addOption(option1);
479         TestOption option2 = new TestOption("include-filter", "value2");
480         test2.addOption(option2);
481         test1.merge(test2);
482         assertEquals(2, test1.getOptions().size());
483         assertTrue(new HashSet<TestOption>(test1.getOptions()).contains(option1));
484         assertTrue(new HashSet<TestOption>(test1.getOptions()).contains(option2));
485         assertEquals(2, test1.getSources().size());
486         assertTrue(test1.getSources().contains("folder1"));
487         assertTrue(test1.getSources().contains("folder2"));
488     }
489 
490     /**
491      * Test for {@link TestInfo#merge()} for merging two TestInfo objects, each has mixed
492      * include-filter and exclude-filter.
493      */
494     @Test
testMergeSuccess_multiFilters()495     public void testMergeSuccess_multiFilters() throws Exception {
496         // Check that the test without any option should be the merge result.
497         TestInfo test1 = new TestInfo("test1", "folder1", false);
498         TestInfo test2 = new TestInfo("test1", "folder2", false);
499         TestOption inclusiveOption1 = new TestOption("include-filter", "value1");
500         test1.addOption(inclusiveOption1);
501         TestOption exclusiveOption1 = new TestOption("exclude-filter", "exclude-value1");
502         test1.addOption(exclusiveOption1);
503         TestOption exclusiveOption2 = new TestOption("exclude-filter", "exclude-value2");
504         test1.addOption(exclusiveOption2);
505         TestOption otherOption1 = new TestOption("somefilter", "");
506         test1.addOption(otherOption1);
507 
508         TestOption inclusiveOption2 = new TestOption("include-filter", "value2");
509         test2.addOption(inclusiveOption2);
510         // Same exclusive option as in test1.
511         test2.addOption(exclusiveOption1);
512         TestOption exclusiveOption3 = new TestOption("exclude-filter", "exclude-value1");
513         test2.addOption(exclusiveOption3);
514         TestOption otherOption2 = new TestOption("somefilter2", "value2");
515         test2.addOption(otherOption2);
516 
517         test1.merge(test2);
518         assertEquals(5, test1.getOptions().size());
519         Set<TestOption> mergedOptions = new HashSet<TestOption>(test1.getOptions());
520         // Options from test1.
521         assertTrue(mergedOptions.contains(inclusiveOption1));
522         assertTrue(mergedOptions.contains(otherOption1));
523         // Shared exclusive option between test1 and test2.
524         assertTrue(mergedOptions.contains(exclusiveOption1));
525         // Options from test2.
526         assertTrue(mergedOptions.contains(inclusiveOption2));
527         assertTrue(mergedOptions.contains(otherOption2));
528         // Both folders are in sources
529         assertEquals(2, test1.getSources().size());
530         assertTrue(test1.getSources().contains("folder1"));
531         assertTrue(test1.getSources().contains("folder2"));
532     }
533 
534     /**
535      * Test for {@link TestInfo#merge()} for merging two TestInfo objects, each has a different
536      * include-filter and include-annotation option.
537      */
538     @Test
testMergeSuccess_MultiFilters_dropIncludeAnnotation()539     public void testMergeSuccess_MultiFilters_dropIncludeAnnotation() throws Exception {
540         // Check that the test without all options except include-annotation option should be the
541         // merge result.
542         TestInfo test1 = new TestInfo("test1", "folder1", false);
543         TestInfo test2 = new TestInfo("test1", "folder1", false);
544         TestOption option1 = new TestOption("include-filter", "value1");
545         test1.addOption(option1);
546         TestOption optionIncludeAnnotation =
547                 new TestOption("include-annotation", "androidx.test.filters.FlakyTest");
548         test1.addOption(optionIncludeAnnotation);
549         TestOption option2 = new TestOption("include-filter", "value2");
550         test2.addOption(option2);
551         test1.merge(test2);
552         assertEquals(2, test1.getOptions().size());
553         assertTrue(new HashSet<TestOption>(test1.getOptions()).contains(option1));
554         assertTrue(new HashSet<TestOption>(test1.getOptions()).contains(option2));
555     }
556 
557     /**
558      * Test for {@link TestInfo#merge()} for merging two TestInfo objects, each has a different
559      * include-filter and exclude-annotation option.
560      */
561     @Test
testMergeSuccess_MultiFilters_keepExcludeAnnotation()562     public void testMergeSuccess_MultiFilters_keepExcludeAnnotation() throws Exception {
563         // Check that the test without all options including exclude-annotation option should be the
564         // merge result.
565         TestInfo test1 = new TestInfo("test1", "folder1", false);
566         TestInfo test2 = new TestInfo("test1", "folder1", false);
567         TestOption option1 = new TestOption("include-filter", "value1");
568         test1.addOption(option1);
569         TestOption optionExcludeAnnotation1 =
570                 new TestOption("exclude-annotation", "androidx.test.filters.FlakyTest");
571         test1.addOption(optionExcludeAnnotation1);
572         TestOption optionExcludeAnnotation2 =
573                 new TestOption("exclude-annotation", "another-annotation");
574         test1.addOption(optionExcludeAnnotation2);
575         TestOption option2 = new TestOption("include-filter", "value2");
576         test2.addOption(option2);
577         TestOption optionExcludeAnnotation3 =
578                 new TestOption("exclude-annotation", "androidx.test.filters.FlakyTest");
579         test1.addOption(optionExcludeAnnotation3);
580         test1.merge(test2);
581         assertEquals(4, test1.getOptions().size());
582         assertTrue(new HashSet<TestOption>(test1.getOptions()).contains(option1));
583         assertTrue(new HashSet<TestOption>(test1.getOptions()).contains(optionExcludeAnnotation1));
584         assertTrue(new HashSet<TestOption>(test1.getOptions()).contains(optionExcludeAnnotation2));
585         assertTrue(new HashSet<TestOption>(test1.getOptions()).contains(option2));
586     }
587 
588     /**
589      * Test for {@link TestMapping#getAllTests()} for loading tests from test_mappings directory.
590      */
591     @Test
testGetAllTests()592     public void testGetAllTests() throws Exception {
593         File tempDir = null;
594         try {
595             tempDir = FileUtil.createTempDir("test_mapping");
596 
597             File srcDir = FileUtil.createTempDir("src", tempDir);
598             String srcFile = File.separator + TEST_DATA_DIR + File.separator + "test_mapping_1";
599             InputStream resourceStream = this.getClass().getResourceAsStream(srcFile);
600             FileUtil.saveResourceFile(resourceStream, srcDir, TEST_MAPPING);
601             File subDir = FileUtil.createTempDir("sub_dir", srcDir);
602             srcFile = File.separator + TEST_DATA_DIR + File.separator + "test_mapping_2";
603             resourceStream = this.getClass().getResourceAsStream(srcFile);
604             FileUtil.saveResourceFile(resourceStream, subDir, TEST_MAPPING);
605             srcFile = File.separator + TEST_DATA_DIR + File.separator + DISABLED_PRESUBMIT_TESTS;
606             resourceStream = this.getClass().getResourceAsStream(srcFile);
607             FileUtil.saveResourceFile(resourceStream, tempDir, DISABLED_PRESUBMIT_TESTS);
608             Map<String, Set<TestInfo>> allTests = mTestMapping.getAllTests(tempDir);
609             Set<TestInfo> tests = allTests.get("presubmit");
610             assertEquals(6, tests.size());
611 
612             tests = allTests.get("postsubmit");
613             assertEquals(4, tests.size());
614 
615             tests = allTests.get("othertype");
616             assertEquals(1, tests.size());
617         } finally {
618             FileUtil.recursiveDelete(tempDir);
619         }
620     }
621 
622     /** Test for {@link TestMapping#extractTestMappingsZip()} for extracting test mappings zip. */
623     @Test
testExtractTestMappingsZip()624     public void testExtractTestMappingsZip() throws Exception {
625         File tempDir = null;
626         File extractedFile = null;
627         try {
628             tempDir = FileUtil.createTempDir("test_mapping");
629 
630             File srcDir = FileUtil.createTempDir("src", tempDir);
631             String srcFile = File.separator + TEST_DATA_DIR + File.separator + "test_mapping_1";
632             InputStream resourceStream = this.getClass().getResourceAsStream(srcFile);
633             FileUtil.saveResourceFile(resourceStream, srcDir, TEST_MAPPING);
634             File subDir = FileUtil.createTempDir("sub_dir", srcDir);
635             srcFile = File.separator + TEST_DATA_DIR + File.separator + "test_mapping_2";
636             resourceStream = this.getClass().getResourceAsStream(srcFile);
637             FileUtil.saveResourceFile(resourceStream, subDir, TEST_MAPPING);
638             srcFile = File.separator + TEST_DATA_DIR + File.separator + DISABLED_PRESUBMIT_TESTS;
639             resourceStream = this.getClass().getResourceAsStream(srcFile);
640             FileUtil.saveResourceFile(resourceStream, tempDir, DISABLED_PRESUBMIT_TESTS);
641             List<File> filesToZip =
642                     Arrays.asList(srcDir, new File(tempDir, DISABLED_PRESUBMIT_TESTS));
643 
644             File zipFile = Paths.get(tempDir.getAbsolutePath(), TEST_MAPPINGS_ZIP).toFile();
645             ZipUtil.createZip(filesToZip, zipFile);
646 
647             extractedFile = TestMapping.extractTestMappingsZip(zipFile);
648             Map<String, Set<TestInfo>> allTests = mTestMapping.getAllTests(tempDir);
649             Set<TestInfo> tests = allTests.get("presubmit");
650             assertEquals(6, tests.size());
651 
652             tests = allTests.get("postsubmit");
653             assertEquals(4, tests.size());
654 
655             tests = allTests.get("othertype");
656             assertEquals(1, tests.size());
657         } finally {
658             FileUtil.recursiveDelete(tempDir);
659             FileUtil.recursiveDelete(extractedFile);
660         }
661     }
662 
663     /** Test for {@link TestMapping#getDisabledTests()} for getting disabled tests. */
664     @Test
testGetDisabledTests()665     public void testGetDisabledTests() throws Exception {
666         File tempDir = null;
667         try {
668             tempDir = FileUtil.createTempDir("test_mapping");
669 
670             File srcDir = FileUtil.createTempDir("src", tempDir);
671             String srcFile = File.separator + TEST_DATA_DIR + File.separator + "test_mapping_1";
672             InputStream resourceStream = this.getClass().getResourceAsStream(srcFile);
673             FileUtil.saveResourceFile(resourceStream, srcDir, TEST_MAPPING);
674             File subDir = FileUtil.createTempDir("sub_dir", srcDir);
675             srcFile = File.separator + TEST_DATA_DIR + File.separator + "test_mapping_2";
676             resourceStream = this.getClass().getResourceAsStream(srcFile);
677             FileUtil.saveResourceFile(resourceStream, subDir, TEST_MAPPING);
678             srcFile = File.separator + TEST_DATA_DIR + File.separator + DISABLED_PRESUBMIT_TESTS;
679             resourceStream = this.getClass().getResourceAsStream(srcFile);
680             FileUtil.saveResourceFile(resourceStream, tempDir, DISABLED_PRESUBMIT_TESTS);
681             Path tempDirPath = Paths.get(tempDir.getAbsolutePath());
682             Set<String> disabledTests = mTestMapping.getDisabledTests(tempDirPath, "presubmit");
683             assertEquals(2, disabledTests.size());
684 
685             disabledTests = mTestMapping.getDisabledTests(tempDirPath, "postsubmit");
686             assertEquals(0, disabledTests.size());
687 
688             disabledTests = mTestMapping.getDisabledTests(tempDirPath, "othertype");
689             assertEquals(0, disabledTests.size());
690         } finally {
691             FileUtil.recursiveDelete(tempDir);
692         }
693     }
694 
695     /** Test for {@link TestMapping#removeComments()} for removing comments in TEST_MAPPING file. */
696     @Test
testRemoveComments()697     public void testRemoveComments() throws Exception {
698         String jsonString = getJsonStringByName("test_mapping_with_comments1");
699         String goldenString = getJsonStringByName("test_mapping_golden1");
700         assertEquals(mTestMapping.removeComments(jsonString), goldenString);
701     }
702 
703     /** Test for {@link TestMapping#removeComments()} for removing comments in TEST_MAPPING file. */
704     @Test
testRemoveComments2()705     public void testRemoveComments2() throws Exception {
706         String jsonString = getJsonStringByName("test_mapping_with_comments2");
707         String goldenString = getJsonStringByName("test_mapping_golden2");
708         assertEquals(mTestMapping.removeComments(jsonString), goldenString);
709     }
710 
711     /**
712      * Test for {@link TestMapping#listTestMappingFiles()} for list TEST_MAPPING files, include
713      * import TEST_MAPPING files.
714      */
715     @Test
testIncludeImports()716     public void testIncludeImports() throws Exception {
717         // Test directory structure:
718         // ├── disabled-presubmit-tests
719         // ├── path1
720         // │   └── TEST_MAPPING
721         // ├── path2
722         // │   ├── path3
723         // │   │  └── TEST_MAPPING
724         // │   └── TEST_MAPPING
725         // └── test_mappings.zip
726         File tempDir = null;
727         IBuildInfo mockBuildInfo = mock(IBuildInfo.class);
728         try {
729             tempDir = FileUtil.createTempDir("test_mapping");
730             File path1 = new File(tempDir.getAbsolutePath() + "/path1");
731             path1.mkdir();
732             String srcFile =
733                     File.separator + TEST_DATA_DIR + File.separator + "test_mapping_with_import_1";
734             InputStream resourceStream = this.getClass().getResourceAsStream(srcFile);
735             FileUtil.saveResourceFile(resourceStream, path1, TEST_MAPPING);
736 
737             File path2 = new File(tempDir.getAbsolutePath() + "/path2");
738             path2.mkdir();
739             srcFile =
740                     File.separator + TEST_DATA_DIR + File.separator + "test_mapping_with_import_2";
741             resourceStream = this.getClass().getResourceAsStream(srcFile);
742             FileUtil.saveResourceFile(resourceStream, path2, TEST_MAPPING);
743 
744             File path3 = new File(path2.getAbsolutePath() + "/path3");
745             path3.mkdir();
746             srcFile = File.separator + TEST_DATA_DIR + File.separator + "test_mapping_1";
747             resourceStream = this.getClass().getResourceAsStream(srcFile);
748             FileUtil.saveResourceFile(resourceStream, path3, TEST_MAPPING);
749 
750             srcFile = File.separator + TEST_DATA_DIR + File.separator + DISABLED_PRESUBMIT_TESTS;
751             resourceStream = this.getClass().getResourceAsStream(srcFile);
752             FileUtil.saveResourceFile(resourceStream, tempDir, DISABLED_PRESUBMIT_TESTS);
753             List<File> filesToZip =
754                     Arrays.asList(path1, path2, new File(tempDir, DISABLED_PRESUBMIT_TESTS));
755 
756             File zipFile = Paths.get(tempDir.getAbsolutePath(), TEST_MAPPINGS_ZIP).toFile();
757             ZipUtil.createZip(filesToZip, zipFile);
758             when(mockBuildInfo.getFile(TEST_MAPPINGS_ZIP)).thenReturn(zipFile);
759 
760             Set<String> names = new HashSet<String>();
761             TestMapping testMapping = new TestMapping(new ArrayList<>(), false);
762             Set<TestInfo> testInfos =
763                     testMapping.getTests(
764                             testMapping.getTestCollection(
765                                     path3.toPath().resolve(TEST_MAPPING),
766                                     tempDir.toPath(),
767                                     NO_MATCHED_PATTERNS),
768                             "presubmit",
769                             null,
770                             true,
771                             null,
772                             new HashSet<String>());
773             assertEquals(3, testInfos.size());
774             for (TestInfo test : testInfos) {
775                 names.add(test.getName());
776                 if (test.getName().equals("test1")) {
777                     assertEquals(2, test.getImportPaths().size());
778                     assertTrue(test.getImportPaths().contains("path1"));
779                     assertTrue(test.getImportPaths().contains("path2"));
780                 }
781             }
782             assertTrue(names.contains("import-test1"));
783             assertTrue(names.contains("import-test2"));
784             assertTrue(names.contains("test1"));
785 
786             testInfos =
787                     testMapping.getTests(
788                             testMapping.getTestCollection(
789                                     path3.toPath().resolve(TEST_MAPPING),
790                                     tempDir.toPath(),
791                                     NO_MATCHED_PATTERNS),
792                             "presubmit",
793                             null,
794                             false,
795                             null,
796                             new HashSet<String>());
797             names.clear();
798             for (TestInfo test : testInfos) {
799                 names.add(test.getName());
800             }
801             assertTrue(names.contains("suite/stub1"));
802             assertTrue(names.contains("import-test3"));
803             assertEquals(2, testInfos.size());
804         } finally {
805             FileUtil.recursiveDelete(tempDir);
806         }
807     }
808 
809     /**
810      * Test for {@link TestMapping#listTestMappingFiles()} for list TEST_MAPPING files, ignore
811      * import TEST_MAPPING files.
812      */
813     @Test
testExcludeImports()814     public void testExcludeImports() throws Exception {
815         // Test directory structure:
816         // ├── disabled-presubmit-tests
817         // ├── path1
818         // │   └── TEST_MAPPING
819         // ├── path2
820         // │   ├── path3
821         // │   │  └── TEST_MAPPING
822         // │   └── TEST_MAPPING
823         // └── test_mappings.zip
824         File tempDir = null;
825         IBuildInfo mockBuildInfo = mock(IBuildInfo.class);
826         try {
827             tempDir = FileUtil.createTempDir("test_mapping");
828             File path1 = new File(tempDir.getAbsolutePath() + "/path1");
829             path1.mkdir();
830             String srcFile =
831                     File.separator + TEST_DATA_DIR + File.separator + "test_mapping_with_import_1";
832             InputStream resourceStream = this.getClass().getResourceAsStream(srcFile);
833             FileUtil.saveResourceFile(resourceStream, path1, TEST_MAPPING);
834 
835             File path2 = new File(tempDir.getAbsolutePath() + "/path2");
836             path2.mkdir();
837             srcFile =
838                     File.separator + TEST_DATA_DIR + File.separator + "test_mapping_with_import_2";
839             resourceStream = this.getClass().getResourceAsStream(srcFile);
840             FileUtil.saveResourceFile(resourceStream, path2, TEST_MAPPING);
841 
842             File path3 = new File(path2.getAbsolutePath() + "/path3");
843             path3.mkdir();
844             srcFile = File.separator + TEST_DATA_DIR + File.separator + "test_mapping_1";
845             resourceStream = this.getClass().getResourceAsStream(srcFile);
846             FileUtil.saveResourceFile(resourceStream, path3, TEST_MAPPING);
847 
848             srcFile = File.separator + TEST_DATA_DIR + File.separator + DISABLED_PRESUBMIT_TESTS;
849             resourceStream = this.getClass().getResourceAsStream(srcFile);
850             FileUtil.saveResourceFile(resourceStream, tempDir, DISABLED_PRESUBMIT_TESTS);
851             List<File> filesToZip =
852                     Arrays.asList(path1, path2, new File(tempDir, DISABLED_PRESUBMIT_TESTS));
853 
854             File zipFile = Paths.get(tempDir.getAbsolutePath(), TEST_MAPPINGS_ZIP).toFile();
855             ZipUtil.createZip(filesToZip, zipFile);
856             when(mockBuildInfo.getFile(TEST_MAPPINGS_ZIP)).thenReturn(zipFile);
857 
858             Set<String> names = new HashSet<String>();
859             Set<TestInfo> testInfos =
860                     mTestMapping.getTests(
861                             mTestMapping.getTestCollection(
862                                     path3.toPath().resolve(TEST_MAPPING),
863                                     tempDir.toPath(),
864                                     NO_MATCHED_PATTERNS),
865                             "presubmit",
866                             null,
867                             true,
868                             null,
869                             new HashSet<String>());
870             assertEquals(1, testInfos.size());
871             for (TestInfo test : testInfos) {
872                 names.add(test.getName());
873             }
874 
875             assertFalse(names.contains("import-test1"));
876             assertFalse(names.contains("import-test2"));
877             assertTrue(names.contains("test1"));
878         } finally {
879             FileUtil.recursiveDelete(tempDir);
880         }
881     }
882 
883     /**
884      * Test for {@link TestMapping#getTestMappingSources()} for collecting paths of TEST_MAPPING
885      * files
886      */
887     @Test
testGetTestMappingSources()888     public void testGetTestMappingSources() throws Exception {
889         // Test directory structure:
890         // ├── disabled-presubmit-tests
891         // ├── src1
892         // |   ├── sub_dir1
893         // |   |  └── TEST_MAPPING
894         // │   └── TEST_MAPPING
895         // ├── src2
896         // │   └── TEST_MAPPING
897         // └── test_mappings.zip
898         File tempDir = null;
899         try {
900             tempDir = FileUtil.createTempDir("test_mapping");
901             File srcDir = FileUtil.createNamedTempDir(tempDir, "src1");
902             String srcFile = File.separator + TEST_DATA_DIR + File.separator + "test_mapping_1";
903             InputStream resourceStream = this.getClass().getResourceAsStream(srcFile);
904             FileUtil.saveResourceFile(resourceStream, srcDir, TEST_MAPPING);
905 
906             File subDir = FileUtil.createNamedTempDir(srcDir, "sub_dir1");
907             srcFile = File.separator + TEST_DATA_DIR + File.separator + "test_mapping_2";
908             resourceStream = this.getClass().getResourceAsStream(srcFile);
909             FileUtil.saveResourceFile(resourceStream, subDir, TEST_MAPPING);
910 
911             subDir = FileUtil.createNamedTempDir(tempDir, "src2");
912             srcFile = File.separator + TEST_DATA_DIR + File.separator + "test_mapping_1";
913             resourceStream = this.getClass().getResourceAsStream(srcFile);
914             FileUtil.saveResourceFile(resourceStream, subDir, TEST_MAPPING);
915 
916             srcFile = File.separator + TEST_DATA_DIR + File.separator + DISABLED_PRESUBMIT_TESTS;
917             resourceStream = this.getClass().getResourceAsStream(srcFile);
918             FileUtil.saveResourceFile(resourceStream, tempDir, DISABLED_PRESUBMIT_TESTS);
919             List<File> filesToZip =
920                     Arrays.asList(srcDir, subDir, new File(tempDir, DISABLED_PRESUBMIT_TESTS));
921 
922             File zipFile = Paths.get(tempDir.getAbsolutePath(), TEST_MAPPINGS_ZIP).toFile();
923             ZipUtil.createZip(filesToZip, zipFile);
924 
925             Set<String> sources = mTestMapping.getTestMappingSources(zipFile);
926             assertEquals(3, sources.size());
927             assertTrue(sources.contains("src1/TEST_MAPPING"));
928             assertTrue(sources.contains("src1/sub_dir1/TEST_MAPPING"));
929             assertTrue(sources.contains("src2/TEST_MAPPING"));
930         } finally {
931             FileUtil.recursiveDelete(tempDir);
932         }
933     }
934 
935     /**
936      * Test for {@link TestMapping#getTestMappingSources()} for collecting paths of TEST_MAPPING
937      * files from a zip file and a directory.
938      */
939     @Test
testGetTestMappingSources_Dir()940     public void testGetTestMappingSources_Dir() throws Exception {
941         // Test directory structure:
942         // ├── disabled-presubmit-tests
943         // ├── src1
944         // |   ├── sub_dir1
945         // |   |  └── TEST_MAPPING
946         // │   └── TEST_MAPPING
947         // ├── src2
948         // │   └── TEST_MAPPING
949         // └── test_mappings.zip
950         File tempDir = null;
951         try {
952             tempDir = FileUtil.createTempDir("test_mapping");
953             File srcDir = FileUtil.createNamedTempDir(tempDir, "src1");
954             String srcFile = File.separator + TEST_DATA_DIR + File.separator + "test_mapping_1";
955             InputStream resourceStream = this.getClass().getResourceAsStream(srcFile);
956             FileUtil.saveResourceFile(resourceStream, srcDir, TEST_MAPPING);
957 
958             File subDir = FileUtil.createNamedTempDir(srcDir, "sub_dir1");
959             srcFile = File.separator + TEST_DATA_DIR + File.separator + "test_mapping_2";
960             resourceStream = this.getClass().getResourceAsStream(srcFile);
961             FileUtil.saveResourceFile(resourceStream, subDir, TEST_MAPPING);
962 
963             subDir = FileUtil.createNamedTempDir(tempDir, "src2");
964             srcFile = File.separator + TEST_DATA_DIR + File.separator + "test_mapping_1";
965             resourceStream = this.getClass().getResourceAsStream(srcFile);
966             FileUtil.saveResourceFile(resourceStream, subDir, TEST_MAPPING);
967 
968             srcFile = File.separator + TEST_DATA_DIR + File.separator + DISABLED_PRESUBMIT_TESTS;
969             resourceStream = this.getClass().getResourceAsStream(srcFile);
970             FileUtil.saveResourceFile(resourceStream, tempDir, DISABLED_PRESUBMIT_TESTS);
971 
972             Set<String> sources = mTestMapping.getTestMappingSources(tempDir);
973             assertEquals(3, sources.size());
974             assertTrue(sources.contains("src1/TEST_MAPPING"));
975             assertTrue(sources.contains("src1/sub_dir1/TEST_MAPPING"));
976             assertTrue(sources.contains("src2/TEST_MAPPING"));
977         } finally {
978             FileUtil.recursiveDelete(tempDir);
979         }
980     }
981 
982     /**
983      * Test for {@link TestMapping#mergeTestMappingZips()} for merging a missed test_mappings.zip.
984      */
985     @Test
testMergeMissedTestMappingZips()986     public void testMergeMissedTestMappingZips() throws Exception {
987         // Test directory1 structure:
988         // ├── disabled-presubmit-tests
989         // ├── src1
990         // │   └── TEST_MAPPING
991         // └── test_mappings.zip
992         File tempDir = null;
993         File baseDir = null;
994         IBuildInfo mockBuildInfo = mock(IBuildInfo.class);
995         try {
996             baseDir = FileUtil.createTempDir("base_directory");
997             // Create 1 test_mappings.zip
998             tempDir = FileUtil.createTempDir("test_mapping");
999             File srcDir = FileUtil.createNamedTempDir(tempDir, "src1");
1000             createTestMapping(srcDir, "test_mapping_kernel1");
1001             createTestMapping(tempDir, DISABLED_PRESUBMIT_TESTS);
1002             List<File> filesToZip =
1003                     Arrays.asList(srcDir, new File(tempDir, DISABLED_PRESUBMIT_TESTS));
1004             File zipFile = Paths.get(tempDir.getAbsolutePath(), TEST_MAPPINGS_ZIP).toFile();
1005             ZipUtil.createZip(filesToZip, zipFile);
1006 
1007             when(mockBuildInfo.getFile(TEST_MAPPINGS_ZIP)).thenReturn(zipFile);
1008             when(mockBuildInfo.getFile("extra-zip")).thenReturn(null);
1009             try {
1010                 mTestMapping.mergeTestMappingZips(
1011                         mockBuildInfo, Arrays.asList("extra-zip"), zipFile, baseDir);
1012                 fail("Should have thrown an exception.");
1013             } catch (HarnessRuntimeException expected) {
1014                 // expected
1015                 assertEquals(
1016                         "Missing extra-zip in the BuildInfo file.", expected.getMessage());
1017             }
1018         } finally {
1019             FileUtil.recursiveDelete(tempDir);
1020             FileUtil.recursiveDelete(baseDir);
1021         }
1022     }
1023 
1024     /**
1025      * Test for {@link TestMapping#mergeTestMappingZips()} to ensure no duplicated source of
1026      * TEST_MAPPING files.
1027      */
1028     @Test
testMergeTestMappingZipsWithDuplicateSources()1029     public void testMergeTestMappingZipsWithDuplicateSources() throws Exception {
1030         // 1 test_mappings.zip structure:
1031         // ├── disabled-presubmit-tests
1032         // ├── src1
1033         // │   └── TEST_MAPPING
1034         // └── test_mappings.zip
1035         //
1036         // another test_mappings.zip structure:
1037         // ├── disabled-presubmit-tests
1038         // ├── src1
1039         // │   └── TEST_MAPPING
1040         // └── test_mappings.zip
1041         File tempDir = null;
1042         File baseDir = null;
1043         IBuildInfo mockBuildInfo = mock(IBuildInfo.class);
1044         try {
1045             baseDir = FileUtil.createTempDir("base_directory");
1046             // Create 1 test_mappings.zip
1047             tempDir = FileUtil.createTempDir("test_mapping");
1048             File srcDir = FileUtil.createNamedTempDir(tempDir, "src1");
1049             createTestMapping(srcDir, "test_mapping_kernel1");
1050             createTestMapping(tempDir, DISABLED_PRESUBMIT_TESTS);
1051             List<File> filesToZip =
1052                     Arrays.asList(srcDir, new File(tempDir, DISABLED_PRESUBMIT_TESTS));
1053             File zipFile = Paths.get(tempDir.getAbsolutePath(), TEST_MAPPINGS_ZIP).toFile();
1054             ZipUtil.createZip(filesToZip, zipFile);
1055 
1056             when(mockBuildInfo.getFile(TEST_MAPPINGS_ZIP)).thenReturn(zipFile);
1057             when(mockBuildInfo.getFile("extra-zip")).thenReturn(zipFile);
1058             try {
1059                 mTestMapping.mergeTestMappingZips(
1060                         mockBuildInfo, Arrays.asList("extra-zip"), zipFile, baseDir);
1061                 fail("Should have thrown an exception.");
1062             } catch (HarnessRuntimeException expected) {
1063                 // expected
1064                 assertTrue(expected.getMessage().contains("Collision of Test Mapping file"));
1065             }
1066         } finally {
1067             FileUtil.recursiveDelete(tempDir);
1068             FileUtil.recursiveDelete(baseDir);
1069         }
1070     }
1071 
1072     /** Test for {@link TestMapping#getTests()} for loading tests from 2 test_mappings.zip. */
1073     @Test
testGetTestsWithAdditionalTestMappingZips()1074     public void testGetTestsWithAdditionalTestMappingZips() throws Exception {
1075         // Test directory1 structure:
1076         // ├── disabled-presubmit-tests
1077         // ├── src1
1078         // │   └── TEST_MAPPING
1079         // └── test_mappings.zip
1080         //
1081         // Test directory2 structure:
1082         // ├── disabled-presubmit-tests
1083         // ├── src2
1084         // │   └── TEST_MAPPING
1085         // └── test_mappings.zip
1086         File tempDir = null;
1087         File tempDir2 = null;
1088         IBuildInfo mockBuildInfo = mock(IBuildInfo.class);
1089         try {
1090             // Create 1 test_mappings.zip
1091             tempDir = FileUtil.createTempDir("test_mapping");
1092             File srcDir = FileUtil.createNamedTempDir(tempDir, "src1");
1093             createTestMapping(srcDir, "test_mapping_kernel1");
1094             createTestMapping(tempDir, DISABLED_PRESUBMIT_TESTS);
1095             List<File> filesToZip =
1096                     Arrays.asList(srcDir, new File(tempDir, DISABLED_PRESUBMIT_TESTS));
1097             File zipFile = Paths.get(tempDir.getAbsolutePath(), TEST_MAPPINGS_ZIP).toFile();
1098             ZipUtil.createZip(filesToZip, zipFile);
1099 
1100             // Create another 1 test_mappings.zip
1101             tempDir2 = FileUtil.createTempDir("test_mapping");
1102             File srcDir2 = FileUtil.createNamedTempDir(tempDir2, "src2");
1103             createTestMapping(srcDir2, "test_mapping_kernel2");
1104             createTestMapping(tempDir2, DISABLED_PRESUBMIT_TESTS);
1105             List<File> filesToZip2 =
1106                     Arrays.asList(srcDir2, new File(tempDir2, DISABLED_PRESUBMIT_TESTS));
1107             File zipFile2 = Paths.get(tempDir2.getAbsolutePath(), TEST_MAPPINGS_ZIP).toFile();
1108             ZipUtil.createZip(filesToZip2, zipFile2);
1109 
1110             when(mockBuildInfo.getFile(TEST_MAPPINGS_ZIP)).thenReturn(zipFile);
1111             when(mockBuildInfo.getFile("extra-zip")).thenReturn(zipFile2);
1112             Set<TestInfo> results =
1113                     mTestMapping.getTests(
1114                             mockBuildInfo,
1115                             "presubmit",
1116                             false,
1117                             null,
1118                             new HashSet<String>(),
1119                             Arrays.asList("extra-zip"),
1120                             new HashSet<>());
1121             assertEquals(2, results.size());
1122             Set<String> names = new HashSet<String>();
1123             for (TestInfo test : results) {
1124                 names.add(test.getName());
1125             }
1126             assertTrue(names.contains("test1"));
1127             assertTrue(names.contains("test2"));
1128         } finally {
1129             FileUtil.recursiveDelete(tempDir);
1130             FileUtil.recursiveDelete(tempDir2);
1131         }
1132     }
1133 
1134     /**
1135      * Test for {@link TestMapping#getTests()} for loading tests from a test_mappings.zip and a
1136      * directory
1137      */
1138     @Test
testGetTestsWithAdditionalTestMappingDir()1139     public void testGetTestsWithAdditionalTestMappingDir() throws Exception {
1140         // Test directory1 structure:
1141         // ├── disabled-presubmit-tests
1142         // ├── src1
1143         // │   └── TEST_MAPPING
1144         // └── test_mappings.zip
1145         //
1146         // Test directory2 structure:
1147         // ├── disabled-presubmit-tests
1148         // ├── src2
1149         // │   └── TEST_MAPPING
1150         File tempDir = null;
1151         File tempDir2 = null;
1152         IBuildInfo mockBuildInfo = mock(IBuildInfo.class);
1153         try {
1154             // Create 1 test_mappings.zip
1155             tempDir = FileUtil.createTempDir("test_mapping");
1156             File srcDir = FileUtil.createNamedTempDir(tempDir, "src1");
1157             createTestMapping(srcDir, "test_mapping_kernel1");
1158             createTestMapping(tempDir, DISABLED_PRESUBMIT_TESTS);
1159             List<File> filesToZip =
1160                     Arrays.asList(srcDir, new File(tempDir, DISABLED_PRESUBMIT_TESTS));
1161             File zipFile = Paths.get(tempDir.getAbsolutePath(), TEST_MAPPINGS_ZIP).toFile();
1162             ZipUtil.createZip(filesToZip, zipFile);
1163 
1164             // Create another 1 test_mappings.zip
1165             tempDir2 = FileUtil.createTempDir("test_mapping");
1166             File srcDir2 = FileUtil.createNamedTempDir(tempDir2, "src2");
1167             createTestMapping(srcDir2, "test_mapping_kernel2");
1168 
1169             when(mockBuildInfo.getFile(TEST_MAPPINGS_ZIP)).thenReturn(zipFile);
1170             when(mockBuildInfo.getFile("extra-zip")).thenReturn(tempDir2);
1171             Set<TestInfo> results =
1172                     mTestMapping.getTests(
1173                             mockBuildInfo,
1174                             "presubmit",
1175                             false,
1176                             null,
1177                             new HashSet<String>(),
1178                             Arrays.asList("extra-zip"),
1179                             new HashSet<>());
1180             assertEquals(2, results.size());
1181             Set<String> names = new HashSet<String>();
1182             for (TestInfo test : results) {
1183                 names.add(test.getName());
1184             }
1185             assertTrue(names.contains("test1"));
1186             assertTrue(names.contains("test2"));
1187         } finally {
1188             FileUtil.recursiveDelete(tempDir);
1189             FileUtil.recursiveDelete(tempDir2);
1190         }
1191     }
1192 
1193     /**
1194      * Test for {@link TestMapping#getTests(Map, String, Set, boolean, Set)} for parsing
1195      * TEST_MAPPING with checking file_patterns matched.
1196      */
1197     @Test
testparseTestMappingWithFilePatterns()1198     public void testparseTestMappingWithFilePatterns() throws Exception {
1199         File tempDir = null;
1200         File testMappingFile = null;
1201 
1202         try {
1203             tempDir = FileUtil.createTempDir("test_mapping");
1204             String srcFile =
1205                     File.separator
1206                             + TEST_DATA_DIR
1207                             + File.separator
1208                             + "test_mapping_with_file_patterns_java";
1209             InputStream resourceStream = this.getClass().getResourceAsStream(srcFile);
1210             File testMappingRootDir = FileUtil.createTempDir("subdir", tempDir);
1211             String rootDirName = testMappingRootDir.getName();
1212             Set<String> matchedPatternPaths =
1213                     new HashSet<>(
1214                             Arrays.asList(
1215                                     rootDirName + File.separator + "a/b/c.java",
1216                                     rootDirName + File.separator + "b/c.java"));
1217             testMappingFile =
1218                     FileUtil.saveResourceFile(resourceStream, testMappingRootDir, TEST_MAPPING);
1219             List<String> testMappingPaths =
1220                     new ArrayList<String>(List.of(testMappingRootDir.toString()));
1221             TestMapping testMapping = new TestMapping(testMappingPaths, IGNORE_IMPORTS);
1222             Set<TestInfo> tests =
1223                     testMapping.getTests(
1224                             testMapping.getTestCollection(
1225                                     testMappingFile.toPath(),
1226                                     Paths.get(tempDir.getAbsolutePath()),
1227                                     matchedPatternPaths),
1228                             "presubmit",
1229                             null,
1230                             false,
1231                             null,
1232                             new HashSet<String>());
1233             Set<String> names = new HashSet<String>();
1234             for (TestInfo test : tests) {
1235                 names.add(test.getName());
1236             }
1237             assertTrue(names.contains("test_java"));
1238 
1239             // test with matched file is TEST_MAPPING
1240             matchedPatternPaths.clear();
1241             matchedPatternPaths.add(rootDirName + File.separator + "a/TEST_MAPPING");
1242             tests =
1243                     testMapping.getTests(
1244                             testMapping.getTestCollection(
1245                                     testMappingFile.toPath(),
1246                                     Paths.get(tempDir.getAbsolutePath()),
1247                                     matchedPatternPaths),
1248                             "presubmit",
1249                             null,
1250                             false,
1251                             null,
1252                             new HashSet<String>());
1253             assertEquals(2, tests.size());
1254 
1255             // test with no matched file.
1256             matchedPatternPaths.clear();
1257             matchedPatternPaths.add(rootDirName + File.separator + "a/b/c.jar");
1258             tests =
1259                     testMapping.getTests(
1260                             testMapping.getTestCollection(
1261                                     testMappingFile.toPath(),
1262                                     Paths.get(tempDir.getAbsolutePath()),
1263                                     matchedPatternPaths),
1264                             "presubmit",
1265                             null,
1266                             false,
1267                             null,
1268                             new HashSet<String>());
1269             assertEquals(0, tests.size());
1270 
1271             // Test with no test mapping path passed from TMSR, skip the file patterns checking.
1272             TestMapping testMappingWithEmptyPath = new TestMapping();
1273             tests =
1274                     testMappingWithEmptyPath.getTests(
1275                             testMappingWithEmptyPath.getTestCollection(
1276                                     testMappingFile.toPath(),
1277                                     Paths.get(tempDir.getAbsolutePath()),
1278                                     matchedPatternPaths),
1279                             "presubmit",
1280                             null,
1281                             false,
1282                             null,
1283                             new HashSet<String>());
1284             assertEquals(2, tests.size());
1285         } finally {
1286             FileUtil.recursiveDelete(tempDir);
1287         }
1288     }
1289 
createTestMapping(File srcDir, String srcName)1290     private void createTestMapping(File srcDir, String srcName) throws Exception {
1291         String srcFile = File.separator + TEST_DATA_DIR + File.separator + srcName;
1292         InputStream resourceStream = this.getClass().getResourceAsStream(srcFile);
1293         FileUtil.saveResourceFile(resourceStream, srcDir, TEST_MAPPING);
1294     }
1295 
getJsonStringByName(String fileName)1296     private String getJsonStringByName(String fileName) throws Exception {
1297         File tempDir = null;
1298         try {
1299             tempDir = FileUtil.createTempDir("test_mapping");
1300             File srcDir = FileUtil.createTempDir("src", tempDir);
1301             String srcFile = File.separator + TEST_DATA_DIR + File.separator + fileName;
1302             InputStream resourceStream = this.getClass().getResourceAsStream(srcFile);
1303             FileUtil.saveResourceFile(resourceStream, srcDir, TEST_MAPPING);
1304             Path file = Paths.get(srcDir.getAbsolutePath(), TEST_MAPPING);
1305             return String.join("\n", Files.readAllLines(file, StandardCharsets.UTF_8));
1306         } finally {
1307             FileUtil.recursiveDelete(tempDir);
1308         }
1309     }
1310 }
1311