1 /*
2  * Copyright (C) 2010 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;
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 
23 import com.android.ddmlib.FileListingService;
24 import com.android.ddmlib.IShellOutputReceiver;
25 import com.android.tradefed.config.Configuration;
26 import com.android.tradefed.config.OptionSetter;
27 import com.android.tradefed.device.CollectingOutputReceiver;
28 import com.android.tradefed.device.DeviceNotAvailableException;
29 import com.android.tradefed.device.ITestDevice;
30 import com.android.tradefed.device.MockFileUtil;
31 import com.android.tradefed.invoker.TestInformation;
32 import com.android.tradefed.result.ITestInvocationListener;
33 import com.android.tradefed.testtype.coverage.CoverageOptions;
34 
35 import org.easymock.EasyMock;
36 import org.junit.Before;
37 import org.junit.Test;
38 import org.junit.runner.RunWith;
39 import org.junit.runners.JUnit4;
40 
41 import java.io.File;
42 import java.util.ArrayList;
43 import java.util.List;
44 import java.util.concurrent.TimeUnit;
45 
46 
47 /** Unit tests for {@link GTest}. */
48 @RunWith(JUnit4.class)
49 public class GTestTest {
50     private static final String GTEST_FLAG_FILTER = "--gtest_filter";
51     private ITestInvocationListener mMockInvocationListener = null;
52     private IShellOutputReceiver mMockReceiver = null;
53     private ITestDevice mMockITestDevice = null;
54     private GTest mGTest;
55     private OptionSetter mSetter;
56 
57     private TestInformation mTestInfo;
58     private Configuration mConfiguration;
59     private CoverageOptions mCoverageOptions;
60     private OptionSetter mCoverageOptionsSetter;
61 
62     /** Helper to initialize the various EasyMocks we'll need. */
63     @Before
setUp()64     public void setUp() throws Exception {
65         mMockInvocationListener = EasyMock.createMock(ITestInvocationListener.class);
66         mMockReceiver = EasyMock.createMock(IShellOutputReceiver.class);
67         mMockITestDevice = EasyMock.createMock(ITestDevice.class);
68         mMockReceiver.flush();
69         EasyMock.expectLastCall().anyTimes();
70         EasyMock.expect(mMockITestDevice.getSerialNumber()).andStubReturn("serial");
71         mGTest =
72                 new GTest() {
73                     @Override
74                     IShellOutputReceiver createResultParser(
75                             String runName, ITestInvocationListener listener) {
76                         return mMockReceiver;
77                     }
78 
79                     @Override
80                     GTestXmlResultParser createXmlParser(
81                             String testRunName, ITestInvocationListener listener) {
82                         return new GTestXmlResultParser(testRunName, listener) {
83                             @Override
84                             public void parseResult(File f, CollectingOutputReceiver output) {
85                                 return;
86                             }
87                         };
88                     }
89                 };
90         mGTest.setDevice(mMockITestDevice);
91         mSetter = new OptionSetter(mGTest);
92 
93         // Set up the coverage options
94         mConfiguration = new Configuration("", "");
95         mCoverageOptions = new CoverageOptions();
96         mCoverageOptionsSetter = new OptionSetter(mCoverageOptions);
97 
98         mConfiguration.setCoverageOptions(mCoverageOptions);
99         mGTest.setConfiguration(mConfiguration);
100 
101         mTestInfo = TestInformation.newBuilder().build();
102     }
103 
104     /**
105      * Helper that replays all mocks.
106      */
replayMocks()107     private void replayMocks() {
108       EasyMock.replay(mMockInvocationListener, mMockITestDevice, mMockReceiver);
109     }
110 
111     /**
112      * Helper that verifies all mocks.
113      */
verifyMocks()114     private void verifyMocks() {
115       EasyMock.verify(mMockInvocationListener, mMockITestDevice, mMockReceiver);
116     }
117 
118     /** Test run when the test dir is not found on the device. */
119     @Test
testRun_noTestDir()120     public void testRun_noTestDir() throws DeviceNotAvailableException {
121         EasyMock.expect(mMockITestDevice.doesFileExist(GTest.DEFAULT_NATIVETEST_PATH))
122                 .andReturn(false);
123         replayMocks();
124         mGTest.run(mTestInfo, mMockInvocationListener);
125         verifyMocks();
126     }
127 
128     /** Test run when no device is set should throw an exception. */
129     @Test
testRun_noDevice()130     public void testRun_noDevice() throws DeviceNotAvailableException {
131         mGTest.setDevice(null);
132         replayMocks();
133         try {
134             mGTest.run(mTestInfo, mMockInvocationListener);
135             fail("an exception should have been thrown");
136         } catch (IllegalArgumentException e) {
137             // expected
138         }
139         verifyMocks();
140     }
141 
142     /** Test the run method for a couple tests */
143     @Test
testRun()144     public void testRun() throws DeviceNotAvailableException {
145         final String nativeTestPath = GTest.DEFAULT_NATIVETEST_PATH;
146         final String test1 = "test1";
147         final String test2 = "test2";
148         final String testPath1 = String.format("%s/%s", nativeTestPath, test1);
149         final String testPath2 = String.format("%s/%s", nativeTestPath, test2);
150 
151 
152         MockFileUtil.setMockDirContents(mMockITestDevice, nativeTestPath, test1, test2);
153         EasyMock.expect(mMockITestDevice.doesFileExist(nativeTestPath)).andReturn(true);
154         EasyMock.expect(mMockITestDevice.isDirectory(nativeTestPath)).andReturn(true);
155         EasyMock.expect(mMockITestDevice.isDirectory(testPath1)).andReturn(false);
156         // report the file as executable
157         EasyMock.expect(mMockITestDevice.isExecutable(testPath1)).andReturn(true);
158         EasyMock.expect(mMockITestDevice.isDirectory(testPath2)).andReturn(false);
159         // report the file as executable
160         EasyMock.expect(mMockITestDevice.isExecutable(testPath2)).andReturn(true);
161 
162         String[] files = new String[] {"test1", "test2"};
163         EasyMock.expect(mMockITestDevice.getChildren(nativeTestPath)).andReturn(files);
164         mMockITestDevice.executeShellCommand(
165                 EasyMock.contains(test1),
166                 EasyMock.same(mMockReceiver),
167                 EasyMock.anyLong(),
168                 (TimeUnit) EasyMock.anyObject(),
169                 EasyMock.anyInt());
170         mMockITestDevice.executeShellCommand(
171                 EasyMock.contains(test2),
172                 EasyMock.same(mMockReceiver),
173                 EasyMock.anyLong(),
174                 (TimeUnit) EasyMock.anyObject(),
175                 EasyMock.anyInt());
176 
177         replayMocks();
178 
179         mGTest.run(mTestInfo, mMockInvocationListener);
180         verifyMocks();
181     }
182 
183     @Test
testRunFilterAbiPath()184     public void testRunFilterAbiPath() throws DeviceNotAvailableException {
185         final String nativeTestPath = GTest.DEFAULT_NATIVETEST_PATH;
186         final String test1 = "arm/test1";
187         final String test2 = "arm64/test2";
188         final String testPath2 = String.format("%s/%s", nativeTestPath, test2);
189         MockFileUtil.setMockDirContents(mMockITestDevice, nativeTestPath, test1, test2);
190         mGTest.setAbi(new Abi("arm64-v8a", "64"));
191 
192         EasyMock.expect(mMockITestDevice.doesFileExist(nativeTestPath)).andReturn(true);
193         EasyMock.expect(mMockITestDevice.isDirectory(nativeTestPath)).andReturn(true);
194         EasyMock.expect(mMockITestDevice.isDirectory(nativeTestPath + "/arm")).andReturn(true);
195 
196         EasyMock.expect(mMockITestDevice.isDirectory(nativeTestPath + "/arm64")).andReturn(true);
197         EasyMock.expect(mMockITestDevice.isDirectory(testPath2)).andReturn(false);
198         // report the file as executable
199         EasyMock.expect(mMockITestDevice.isExecutable(testPath2)).andReturn(true);
200 
201         String[] dirs = new String[] {"arm", "arm64"};
202         EasyMock.expect(mMockITestDevice.getChildren(nativeTestPath)).andReturn(dirs);
203         String[] testFiles = new String[] {"test2"};
204         EasyMock.expect(mMockITestDevice.getChildren(nativeTestPath + "/arm64"))
205                 .andReturn(testFiles);
206         mMockITestDevice.executeShellCommand(
207                 EasyMock.contains(test2),
208                 EasyMock.same(mMockReceiver),
209                 EasyMock.anyLong(),
210                 (TimeUnit) EasyMock.anyObject(),
211                 EasyMock.anyInt());
212 
213         replayMocks();
214 
215         mGTest.run(mTestInfo, mMockInvocationListener);
216         verifyMocks();
217     }
218 
219     /** Test the run method when module name is specified */
220     @Test
testRun_moduleName()221     public void testRun_moduleName() throws DeviceNotAvailableException {
222         final String module = "test1";
223         final String modulePath = String.format("%s%s%s",
224                 GTest.DEFAULT_NATIVETEST_PATH, FileListingService.FILE_SEPARATOR, module);
225         MockFileUtil.setMockDirContents(mMockITestDevice, modulePath, new String[] {});
226 
227         mGTest.setModuleName(module);
228 
229         EasyMock.expect(mMockITestDevice.doesFileExist(modulePath)).andReturn(true);
230         EasyMock.expect(mMockITestDevice.isDirectory(modulePath)).andReturn(false);
231         mMockITestDevice.executeShellCommand(EasyMock.contains(modulePath),
232                 EasyMock.same(mMockReceiver),
233                 EasyMock.anyLong(), (TimeUnit)EasyMock.anyObject(), EasyMock.anyInt());
234         // report the file as executable
235         EasyMock.expect(mMockITestDevice.isExecutable(modulePath)).andReturn(true);
236 
237         replayMocks();
238 
239         mGTest.run(mTestInfo, mMockInvocationListener);
240         verifyMocks();
241     }
242 
243     /** Test the run method for a test in a subdirectory */
244     @Test
testRun_nested()245     public void testRun_nested() throws DeviceNotAvailableException {
246         final String nativeTestPath = GTest.DEFAULT_NATIVETEST_PATH;
247         final String subFolderName = "subFolder";
248         final String test1 = "test1";
249         final String test1Path = String.format("%s%s%s%s%s", nativeTestPath,
250                 FileListingService.FILE_SEPARATOR,
251                 subFolderName,
252                 FileListingService.FILE_SEPARATOR, test1);
253         MockFileUtil.setMockDirPath(mMockITestDevice, nativeTestPath, subFolderName, test1);
254         EasyMock.expect(mMockITestDevice.doesFileExist(nativeTestPath)).andReturn(true);
255         EasyMock.expect(mMockITestDevice.isDirectory(nativeTestPath)).andReturn(true);
256         EasyMock.expect(mMockITestDevice.isDirectory(nativeTestPath + "/" + subFolderName))
257                 .andReturn(true);
258         EasyMock.expect(mMockITestDevice.isDirectory(test1Path)).andReturn(false);
259         // report the file as executable
260         EasyMock.expect(mMockITestDevice.isExecutable(test1Path)).andReturn(true);
261         String[] files = new String[] {subFolderName};
262         EasyMock.expect(mMockITestDevice.getChildren(nativeTestPath)).andReturn(files);
263         String[] files2 = new String[] {"test1"};
264         EasyMock.expect(mMockITestDevice.getChildren(nativeTestPath + "/" + subFolderName))
265                 .andReturn(files2);
266         mMockITestDevice.executeShellCommand(EasyMock.contains(test1Path),
267                 EasyMock.same(mMockReceiver),
268                 EasyMock.anyLong(), (TimeUnit)EasyMock.anyObject(), EasyMock.anyInt());
269 
270         replayMocks();
271 
272         mGTest.run(mTestInfo, mMockInvocationListener);
273         verifyMocks();
274     }
275 
276     /**
277      * Helper function to do the actual filtering test.
278      *
279      * @param filterString The string to search for in the Mock, to verify filtering was called
280      * @throws DeviceNotAvailableException
281      */
doTestFilter(String filterString)282     private void doTestFilter(String filterString) throws DeviceNotAvailableException {
283         String nativeTestPath = GTest.DEFAULT_NATIVETEST_PATH;
284         String testPath = nativeTestPath + "/test1";
285         // configure the mock file system to have a single test
286         MockFileUtil.setMockDirContents(mMockITestDevice, nativeTestPath, "test1");
287         EasyMock.expect(mMockITestDevice.doesFileExist(nativeTestPath)).andReturn(true);
288         EasyMock.expect(mMockITestDevice.isDirectory(nativeTestPath)).andReturn(true);
289         EasyMock.expect(mMockITestDevice.isDirectory(testPath)).andReturn(false);
290         // report the file as executable
291         EasyMock.expect(mMockITestDevice.isExecutable(testPath)).andReturn(true);
292         String[] files = new String[] {"test1"};
293         EasyMock.expect(mMockITestDevice.getChildren(nativeTestPath)).andReturn(files);
294         mMockITestDevice.executeShellCommand(EasyMock.contains(filterString),
295                 EasyMock.same(mMockReceiver), EasyMock.anyLong(), (TimeUnit)EasyMock.anyObject(),
296                 EasyMock.anyInt());
297         replayMocks();
298         mGTest.run(mTestInfo, mMockInvocationListener);
299 
300         verifyMocks();
301     }
302 
303     /** Test the include filtering of test methods. */
304     @Test
testIncludeFilter()305     public void testIncludeFilter() throws DeviceNotAvailableException {
306         String includeFilter1 = "abc";
307         String includeFilter2 = "def";
308         mGTest.addIncludeFilter(includeFilter1);
309         mGTest.addIncludeFilter(includeFilter2);
310         doTestFilter(String.format("%s=%s:%s", GTEST_FLAG_FILTER, includeFilter1, includeFilter2));
311     }
312 
313     /** Test that large filters are converted to flagfile. */
314     @Test
testLargeFilters()315     public void testLargeFilters() throws DeviceNotAvailableException {
316         StringBuilder includeFilter1 = new StringBuilder("abc");
317         for (int i = 0; i < 550; i++) {
318             includeFilter1.append("a");
319         }
320         String includeFilter2 = "def";
321         mGTest.addIncludeFilter(includeFilter1.toString());
322         mGTest.addIncludeFilter(includeFilter2);
323 
324         EasyMock.expect(mMockITestDevice.pushFile(EasyMock.anyObject(), EasyMock.anyObject()))
325                 .andReturn(true);
326 
327         doTestFilter(String.format("%s=/data/local/tmp/flagfile", GTestBase.GTEST_FLAG_FILE));
328     }
329 
330     /** Test the exclude filtering of test methods. */
331     @Test
testExcludeFilter()332     public void testExcludeFilter() throws DeviceNotAvailableException {
333         String excludeFilter1 = "*don?tRunMe*";
334         mGTest.addExcludeFilter(excludeFilter1);
335 
336         doTestFilter(String.format(
337                 "%s=-%s", GTEST_FLAG_FILTER, excludeFilter1));
338     }
339 
340     /** Test simultaneous include and exclude filtering of test methods. */
341     @Test
testIncludeAndExcludeFilters()342     public void testIncludeAndExcludeFilters() throws DeviceNotAvailableException {
343         String includeFilter1 = "pleaseRunMe";
344         String includeFilter2 = "andMe";
345         String excludeFilter1 = "dontRunMe";
346         String excludeFilter2 = "orMe";
347         mGTest.addIncludeFilter(includeFilter1);
348         mGTest.addExcludeFilter(excludeFilter1);
349         mGTest.addIncludeFilter(includeFilter2);
350         mGTest.addExcludeFilter(excludeFilter2);
351 
352         doTestFilter(String.format("%s=%s:%s-%s:%s", GTEST_FLAG_FILTER,
353               includeFilter1, includeFilter2, excludeFilter1, excludeFilter2));
354     }
355 
356     /** Test behavior for command lines too long to be run by ADB */
357     @Test
testCommandTooLong()358     public void testCommandTooLong() throws DeviceNotAvailableException {
359         String deviceScriptPath = "/data/local/tmp/gtest_script.sh";
360         StringBuilder testNameBuilder = new StringBuilder();
361         for (int i = 0; i < 1005; i++) {
362             testNameBuilder.append("a");
363         }
364         String testName = testNameBuilder.toString();
365         // filter string will be longer than GTest.GTEST_CMD_CHAR_LIMIT
366 
367         String nativeTestPath = GTest.DEFAULT_NATIVETEST_PATH;
368         String testPath = nativeTestPath + "/" + testName;
369         // configure the mock file system to have a single test
370         MockFileUtil.setMockDirContents(mMockITestDevice, nativeTestPath, "test1");
371         EasyMock.expect(mMockITestDevice.doesFileExist(nativeTestPath)).andReturn(true);
372         EasyMock.expect(mMockITestDevice.isDirectory(nativeTestPath)).andReturn(true);
373         EasyMock.expect(mMockITestDevice.isDirectory(testPath)).andReturn(false);
374         // report the file as executable
375         EasyMock.expect(mMockITestDevice.isExecutable(testPath)).andReturn(true);
376         String[] files = new String[] {testName};
377         EasyMock.expect(mMockITestDevice.getChildren(nativeTestPath)).andReturn(files);
378         // Expect push of script file
379         EasyMock.expect(mMockITestDevice.pushString(EasyMock.<String>anyObject(),
380                 EasyMock.eq(deviceScriptPath))).andReturn(Boolean.TRUE);
381         // chmod 755 for the shell script
382         EasyMock.expect(mMockITestDevice.executeShellCommand(EasyMock.contains("chmod")))
383                 .andReturn("")
384                 .times(1);
385         // Expect command to run shell script, rather than direct adb command
386         mMockITestDevice.executeShellCommand(EasyMock.eq(String.format("sh %s", deviceScriptPath)),
387                 EasyMock.same(mMockReceiver), EasyMock.anyLong(), (TimeUnit)EasyMock.anyObject(),
388                 EasyMock.anyInt());
389         // Expect deletion of file on device
390         mMockITestDevice.deleteFile(deviceScriptPath);
391         replayMocks();
392         mGTest.run(mTestInfo, mMockInvocationListener);
393 
394         verifyMocks();
395     }
396 
397     /** Empty file exclusion regex filter should not skip any files */
398     @Test
testFileExclusionRegexFilter_emptyfilters()399     public void testFileExclusionRegexFilter_emptyfilters() throws Exception {
400         // report /test_file as executable
401         ITestDevice mockDevice = EasyMock.createMock(ITestDevice.class);
402         EasyMock.expect(mockDevice.isExecutable("/test_file")).andReturn(true);
403         EasyMock.replay(mockDevice);
404         mGTest.setDevice(mockDevice);
405         assertFalse(mGTest.shouldSkipFile("/test_file"));
406         EasyMock.verify(mockDevice);
407     }
408 
409     /** File exclusion regex filter should skip invalid filepath. */
410     @Test
testFileExclusionRegexFilter_invalidInputString()411     public void testFileExclusionRegexFilter_invalidInputString() throws Exception {
412         assertTrue(mGTest.shouldSkipFile(null));
413         assertTrue(mGTest.shouldSkipFile(""));
414     }
415 
416     /** File exclusion regex filter should skip matched filepaths. */
417     @Test
testFileExclusionRegexFilter_skipMatched()418     public void testFileExclusionRegexFilter_skipMatched() throws Exception {
419         // report all files as executable
420         ITestDevice mockDevice = EasyMock.createMock(ITestDevice.class);
421         EasyMock.expect(mockDevice.isExecutable("/some/path/file/run_me")).andReturn(true);
422         EasyMock.expect(mockDevice.isExecutable("/some/path/file/run_me2")).andReturn(true);
423         EasyMock.expect(mockDevice.isExecutable("/some/path/file/run_me.not")).andReturn(true);
424         EasyMock.expect(mockDevice.isExecutable("/some/path/file/run_me.so")).andReturn(true);
425         EasyMock.replay(mockDevice);
426         mGTest.setDevice(mockDevice);
427         // Skip files ending in .not
428         mGTest.addFileExclusionFilterRegex(".*\\.not");
429         assertFalse(mGTest.shouldSkipFile("/some/path/file/run_me"));
430         assertFalse(mGTest.shouldSkipFile("/some/path/file/run_me2"));
431         assertTrue(mGTest.shouldSkipFile("/some/path/file/run_me.not"));
432         // Ensure that the default .so filter is present.
433         assertTrue(mGTest.shouldSkipFile("/some/path/file/run_me.so"));
434         EasyMock.verify(mockDevice);
435     }
436 
437     /** File exclusion regex filter for multi filters. */
438     @Test
testFileExclusionRegexFilter_skipMultiMatched()439     public void testFileExclusionRegexFilter_skipMultiMatched() throws Exception {
440         // report all files as executable
441         ITestDevice mockDevice = EasyMock.createMock(ITestDevice.class);
442         EasyMock.expect(mockDevice.isExecutable("/some/path/file/run_me")).andReturn(true);
443         EasyMock.expect(mockDevice.isExecutable("/some/path/file/run_me.not")).andReturn(true);
444         EasyMock.expect(mockDevice.isExecutable("/some/path/file/run_me.not2")).andReturn(true);
445         EasyMock.replay(mockDevice);
446         mGTest.setDevice(mockDevice);
447         // Skip files ending in .not
448         mGTest.addFileExclusionFilterRegex(".*\\.not");
449         // Also skip files ending in .not2
450         mGTest.addFileExclusionFilterRegex(".*\\.not2");
451         assertFalse(mGTest.shouldSkipFile("/some/path/file/run_me"));
452         assertTrue(mGTest.shouldSkipFile("/some/path/file/run_me.not"));
453         assertTrue(mGTest.shouldSkipFile("/some/path/file/run_me.not2"));
454     }
455 
456     /** Test the run method for a couple tests */
457     @Test
testRunXml()458     public void testRunXml() throws Exception {
459         mSetter.setOptionValue("xml-output", "true");
460 
461         final String nativeTestPath = GTest.DEFAULT_NATIVETEST_PATH;
462         final String test1 = "test1";
463         final String test2 = "test2";
464         final String testPath1 = String.format("%s/%s", nativeTestPath, test1);
465         final String testPath2 = String.format("%s/%s", nativeTestPath, test2);
466 
467         MockFileUtil.setMockDirContents(mMockITestDevice, nativeTestPath, test1, test2);
468         EasyMock.expect(mMockITestDevice.doesFileExist(nativeTestPath)).andReturn(true);
469         EasyMock.expect(mMockITestDevice.isDirectory(nativeTestPath)).andReturn(true);
470         EasyMock.expect(mMockITestDevice.isDirectory(testPath1)).andReturn(false);
471         EasyMock.expect(mMockITestDevice.isExecutable(testPath1)).andReturn(true);
472         EasyMock.expect(mMockITestDevice.isDirectory(testPath2)).andReturn(false);
473         EasyMock.expect(mMockITestDevice.isExecutable(testPath2)).andReturn(true);
474         String[] files = new String[] {"test1", "test2"};
475         EasyMock.expect(mMockITestDevice.getChildren(nativeTestPath)).andReturn(files);
476         mMockITestDevice.deleteFile(testPath1 + "_res.xml");
477         mMockITestDevice.deleteFile(testPath2 + "_res.xml");
478         EasyMock.expect(mMockITestDevice.pullFile((String)EasyMock.anyObject(),
479                 (File)EasyMock.anyObject())).andStubReturn(true);
480         mMockITestDevice.executeShellCommand(EasyMock.contains(test1),
481                 (CollectingOutputReceiver) EasyMock.anyObject(),
482                 EasyMock.anyLong(), (TimeUnit)EasyMock.anyObject(), EasyMock.anyInt());
483         mMockITestDevice.executeShellCommand(EasyMock.contains(test2),
484                 (CollectingOutputReceiver) EasyMock.anyObject(),
485                 EasyMock.anyLong(), (TimeUnit)EasyMock.anyObject(), EasyMock.anyInt());
486         replayMocks();
487 
488         mGTest.run(mTestInfo, mMockInvocationListener);
489         verifyMocks();
490     }
491 
492     /** Test cross-process coverage dump for all native processes */
493     @Test
testNativeCoverageAllProcesses()494     public void testNativeCoverageAllProcesses() throws Exception {
495         mCoverageOptionsSetter.setOptionValue("coverage", "true");
496         mCoverageOptionsSetter.setOptionValue("coverage-toolchain", "GCOV");
497         mCoverageOptionsSetter.setOptionValue("coverage-flush", "true");
498 
499         final String nativeTestPath = GTest.DEFAULT_NATIVETEST_PATH;
500         final String test1 = "test1";
501         final String test2 = "test2";
502         final String testPath1 = String.format("%s/%s", nativeTestPath, test1);
503         final String testPath2 = String.format("%s/%s", nativeTestPath, test2);
504 
505         MockFileUtil.setMockDirContents(mMockITestDevice, nativeTestPath, test1, test2);
506         EasyMock.expect(mMockITestDevice.enableAdbRoot()).andReturn(true);
507         EasyMock.expect(mMockITestDevice.executeShellCommand("mkdir /data/misc/trace/testcoverage"))
508                 .andReturn("");
509         EasyMock.expect(mMockITestDevice.isAdbRoot()).andReturn(true);
510         EasyMock.expect(mMockITestDevice.executeShellCommand("kill -37 -1")).andReturn("");
511         // Wait up to 5 minutes for the device to be available after flushing coverage data.
512         mMockITestDevice.waitForDeviceAvailable(5 * 60 * 1000);
513         EasyMock.expect(mMockITestDevice.executeShellCommand("rm -rf /data/misc/trace/*"))
514                 .andReturn("");
515         EasyMock.expect(mMockITestDevice.doesFileExist(nativeTestPath)).andReturn(true);
516         EasyMock.expect(mMockITestDevice.isDirectory(nativeTestPath)).andReturn(true);
517         EasyMock.expect(mMockITestDevice.isDirectory(testPath1)).andReturn(false);
518         // report the file as executable
519         EasyMock.expect(mMockITestDevice.isExecutable(testPath1)).andReturn(true);
520         EasyMock.expect(mMockITestDevice.isDirectory(testPath2)).andReturn(false);
521         // report the file as executable
522         EasyMock.expect(mMockITestDevice.isExecutable(testPath2)).andReturn(true);
523 
524         String[] files = new String[] {"test1", "test2"};
525         EasyMock.expect(mMockITestDevice.getChildren(nativeTestPath)).andReturn(files);
526         mMockITestDevice.executeShellCommand(
527                 EasyMock.contains(test1),
528                 EasyMock.same(mMockReceiver),
529                 EasyMock.anyLong(),
530                 (TimeUnit) EasyMock.anyObject(),
531                 EasyMock.anyInt());
532         mMockITestDevice.executeShellCommand(
533                 EasyMock.contains(test2),
534                 EasyMock.same(mMockReceiver),
535                 EasyMock.anyLong(),
536                 (TimeUnit) EasyMock.anyObject(),
537                 EasyMock.anyInt());
538 
539         replayMocks();
540 
541         mGTest.run(mTestInfo, mMockInvocationListener);
542         verifyMocks();
543     }
544 
545     /** Test cross-process coverage dump for specific processes */
546     @Test
testNativeCoverageSpecificProcesses()547     public void testNativeCoverageSpecificProcesses() throws Exception {
548         final List<String> processNames = new ArrayList<>();
549         processNames.add("init");
550         processNames.add("surfaceflinger");
551 
552         mCoverageOptionsSetter.setOptionValue("coverage", "true");
553         mCoverageOptionsSetter.setOptionValue("coverage-toolchain", "GCOV");
554         mCoverageOptionsSetter.setOptionValue("coverage-flush", "true");
555         for (String processName : processNames) {
556             mCoverageOptionsSetter.setOptionValue("coverage-processes", processName);
557         }
558 
559         final String nativeTestPath = GTest.DEFAULT_NATIVETEST_PATH;
560         final String test1 = "test1";
561         final String test2 = "test2";
562         final String testPath1 = String.format("%s/%s", nativeTestPath, test1);
563         final String testPath2 = String.format("%s/%s", nativeTestPath, test2);
564 
565         MockFileUtil.setMockDirContents(mMockITestDevice, nativeTestPath, test1, test2);
566         EasyMock.expect(mMockITestDevice.enableAdbRoot()).andReturn(true);
567         EasyMock.expect(mMockITestDevice.executeShellCommand("mkdir /data/misc/trace/testcoverage"))
568                 .andReturn("");
569         // Get the pids to flush coverage data.
570         EasyMock.expect(mMockITestDevice.isAdbRoot()).andReturn(true);
571         EasyMock.expect(mMockITestDevice.getProcessPid(processNames.get(0))).andReturn("1");
572         EasyMock.expect(mMockITestDevice.getProcessPid(processNames.get(1))).andReturn("1000");
573         EasyMock.expect(mMockITestDevice.executeShellCommand("kill -37 1 1000")).andReturn("");
574         // Wait up to 5 minutes for the device to be available after flushing coverage data.
575         mMockITestDevice.waitForDeviceAvailable(5 * 60 * 1000);
576 
577         // Clear the coverage data.
578         EasyMock.expect(mMockITestDevice.executeShellCommand("rm -rf /data/misc/trace/*"))
579                 .andReturn("");
580         EasyMock.expect(mMockITestDevice.doesFileExist(nativeTestPath)).andReturn(true);
581         EasyMock.expect(mMockITestDevice.isDirectory(nativeTestPath)).andReturn(true);
582         EasyMock.expect(mMockITestDevice.isDirectory(testPath1)).andReturn(false);
583         // report the file as executable
584         EasyMock.expect(mMockITestDevice.isExecutable(testPath1)).andReturn(true);
585         EasyMock.expect(mMockITestDevice.isDirectory(testPath2)).andReturn(false);
586         // report the file as executable
587         EasyMock.expect(mMockITestDevice.isExecutable(testPath2)).andReturn(true);
588 
589         String[] files = new String[] {"test1", "test2"};
590         EasyMock.expect(mMockITestDevice.getChildren(nativeTestPath)).andReturn(files);
591         mMockITestDevice.executeShellCommand(
592                 EasyMock.contains(test1),
593                 EasyMock.same(mMockReceiver),
594                 EasyMock.anyLong(),
595                 (TimeUnit) EasyMock.anyObject(),
596                 EasyMock.anyInt());
597         mMockITestDevice.executeShellCommand(
598                 EasyMock.contains(test2),
599                 EasyMock.same(mMockReceiver),
600                 EasyMock.anyLong(),
601                 (TimeUnit) EasyMock.anyObject(),
602                 EasyMock.anyInt());
603 
604         replayMocks();
605 
606         mGTest.run(mTestInfo, mMockInvocationListener);
607         verifyMocks();
608     }
609 
610     @Test
testGetFileName()611     public void testGetFileName() {
612         String expected = "bar";
613         String s1 = "/foo/" + expected;
614         String s2 = expected;
615         String s3 = "/foo/";
616         assertEquals(expected, mGTest.getFileName(s1));
617         assertEquals(expected, mGTest.getFileName(s2));
618         try {
619             mGTest.getFileName(s3);
620             fail("Expected IllegalArgumentException not thrown");
621         } catch (IllegalArgumentException iae) {
622             // expected
623         }
624     }
625 
626     /** Test the include filtering by file of test methods. */
627     @Test
testFileFilter()628     public void testFileFilter() throws Exception {
629         String fileFilter = "presubmit";
630         mSetter.setOptionValue("test-filter-key", fileFilter);
631         String expectedFilterFile = String.format("%s/test1%s",
632                 GTest.DEFAULT_NATIVETEST_PATH, GTest.FILTER_EXTENSION);
633         String fakeContent = "{\n" +
634                              "    \"presubmit\": {\n" +
635                              "        \"filter\": \"Foo1.*:Foo2.*\"\n" +
636                              "    },\n" +
637                              "    \"continuous\": {\n" +
638                              "        \"filter\": \"Foo1.*:Foo2.*:Bar.*\"\n" +
639                              "    }\n" +
640                              "}\n";
641         EasyMock.expect(mMockITestDevice.doesFileExist(expectedFilterFile)).andReturn(true);
642         EasyMock.expect(mMockITestDevice.executeShellCommand("cat \"" + expectedFilterFile + "\""))
643                 .andReturn(fakeContent);
644         doTestFilter(String.format("%s=%s", GTEST_FLAG_FILTER, "Foo1.*:Foo2.*"));
645     }
646 
647     @Test
testFileFilter_negative()648     public void testFileFilter_negative() throws Exception {
649         String fileFilter = "presubmit";
650         mSetter.setOptionValue("test-filter-key", fileFilter);
651         String expectedFilterFile =
652                 String.format("%s/test1%s", GTest.DEFAULT_NATIVETEST_PATH, GTest.FILTER_EXTENSION);
653         String fakeContent =
654                 "{\n"
655                         + "    \"presubmit\": {\n"
656                         + "        \"filter\": \"Foo1.*-Foo2.*\"\n"
657                         + "    },\n"
658                         + "    \"continuous\": {\n"
659                         + "        \"filter\": \"Foo1.*:Foo2.*:Bar.*\"\n"
660                         + "    }\n"
661                         + "}\n";
662         EasyMock.expect(mMockITestDevice.doesFileExist(expectedFilterFile)).andReturn(true);
663         EasyMock.expect(mMockITestDevice.executeShellCommand("cat \"" + expectedFilterFile + "\""))
664                 .andReturn(fakeContent);
665         doTestFilter(String.format("%s=%s", GTEST_FLAG_FILTER, "Foo1.*-Foo2.*"));
666     }
667 
668     @Test
testFileFilter_negativeOnly()669     public void testFileFilter_negativeOnly() throws Exception {
670         String fileFilter = "presubmit";
671         mSetter.setOptionValue("test-filter-key", fileFilter);
672         String expectedFilterFile =
673                 String.format("%s/test1%s", GTest.DEFAULT_NATIVETEST_PATH, GTest.FILTER_EXTENSION);
674         String fakeContent =
675                 "{\n"
676                         + "    \"presubmit\": {\n"
677                         + "        \"filter\": \"-Foo1.*:Foo2.*\"\n"
678                         + "    },\n"
679                         + "    \"continuous\": {\n"
680                         + "        \"filter\": \"Foo1.*:Foo2.*:Bar.*\"\n"
681                         + "    }\n"
682                         + "}\n";
683         EasyMock.expect(mMockITestDevice.doesFileExist(expectedFilterFile)).andReturn(true);
684         EasyMock.expect(mMockITestDevice.executeShellCommand("cat \"" + expectedFilterFile + "\""))
685                 .andReturn(fakeContent);
686         doTestFilter(String.format("%s=%s", GTEST_FLAG_FILTER, "-Foo1.*:Foo2.*"));
687     }
688 
689     /**
690      * Test the include filtering by providing a non existing filter. No filter will be applied in
691      * this case.
692      */
693     @Test
testFileFilter_notfound()694     public void testFileFilter_notfound() throws Exception {
695         String fileFilter = "garbage";
696         mSetter.setOptionValue("test-filter-key", fileFilter);
697         String expectedFilterFile = String.format("%s/test1%s",
698                 GTest.DEFAULT_NATIVETEST_PATH, GTest.FILTER_EXTENSION);
699         String fakeContent = "{\n" +
700                              "    \"presubmit\": {\n" +
701                              "        \"filter\": \"Foo1.*:Foo2.*\"\n" +
702                              "    },\n" +
703                              "    \"continuous\": {\n" +
704                              "        \"filter\": \"Foo1.*:Foo2.*:Bar.*\"\n" +
705                              "    }\n" +
706                              "}\n";
707         EasyMock.expect(mMockITestDevice.doesFileExist(expectedFilterFile)).andReturn(true);
708         EasyMock.expect(mMockITestDevice.executeShellCommand("cat \"" + expectedFilterFile + "\""))
709                 .andReturn(fakeContent);
710         doTestFilter("");
711     }
712 
713     /** Test {@link GTest#getGTestCmdLine(String, String)} with default options. */
714     @Test
testGetGTestCmdLine_defaults()715     public void testGetGTestCmdLine_defaults() {
716         String cmd_line = mGTest.getGTestCmdLine("test_path", "flags");
717         assertEquals("test_path flags", cmd_line);
718     }
719 
720     /**
721      * Test {@link GTest#getGTestFilters(String)} When the push to file fails, in this case we use
722      * the original filter arguments instead of hte flagfile.
723      */
724     @Test
testGetGTestFilters_largeFilters_pushFail()725     public void testGetGTestFilters_largeFilters_pushFail() throws Exception {
726         StringBuilder includeFilter1 = new StringBuilder("abc");
727         for (int i = 0; i < 550; i++) {
728             includeFilter1.append("a");
729         }
730         mGTest.addIncludeFilter(includeFilter1.toString());
731         // Fail to push
732         EasyMock.expect(mMockITestDevice.pushFile(EasyMock.anyObject(), EasyMock.anyObject()))
733                 .andReturn(false);
734 
735         EasyMock.replay(mMockITestDevice);
736         String flag = mGTest.getGTestFilters("/path/");
737         // We fallback to the original command line filter
738         assertEquals("--gtest_filter=" + includeFilter1.toString(), flag);
739         EasyMock.verify(mMockITestDevice);
740     }
741 
742     /** Test {@link GTest#getGTestCmdLine(String, String)} with non-default user. */
743     @Test
testGetGTestCmdLine_runAs()744     public void testGetGTestCmdLine_runAs() throws Exception {
745         mSetter.setOptionValue("run-test-as", "shell");
746 
747         String cmd_line = mGTest.getGTestCmdLine("test_path", "flags");
748         assertEquals("su shell test_path flags", cmd_line);
749     }
750 
751     /** Test GTest command line string for sharded tests. */
752     @Test
testGetGTestCmdLine_testShard()753     public void testGetGTestCmdLine_testShard() {
754         mGTest.setShardIndex(1);
755         mGTest.setShardCount(3);
756 
757         String cmd_line = mGTest.getGTestCmdLine("test_path", "flags");
758         assertEquals("GTEST_SHARD_INDEX=1 GTEST_TOTAL_SHARDS=3 test_path flags", cmd_line);
759     }
760 }
761