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.cts.tradefed.testtype;
17 
18 import com.android.cts.tradefed.UnitTests;
19 import com.android.cts.tradefed.build.StubCtsBuildHelper;
20 import com.android.cts.tradefed.result.PlanCreator;
21 import com.android.cts.util.AbiUtils;
22 import com.android.ddmlib.testrunner.TestIdentifier;
23 import com.android.tradefed.device.DeviceNotAvailableException;
24 import com.android.tradefed.device.ITestDevice;
25 import com.android.tradefed.result.ITestInvocationListener;
26 import com.android.tradefed.targetprep.ITargetPreparer;
27 import com.android.tradefed.testtype.IRemoteTest;
28 import com.android.tradefed.util.xml.AbstractXmlParser.ParseException;
29 
30 import junit.framework.TestCase;
31 
32 import org.easymock.EasyMock;
33 
34 import java.io.ByteArrayInputStream;
35 import java.io.File;
36 import java.io.FileNotFoundException;
37 import java.io.InputStream;
38 import java.util.Arrays;
39 import java.util.ArrayList;
40 import java.util.HashMap;
41 import java.util.HashSet;
42 import java.util.List;
43 import java.util.Map;
44 import java.util.Set;
45 
46 /**
47  * Unit tests for {@link CtsTest}.
48  */
49 public class CtsTestTest extends TestCase {
50 
51     private static final String PLAN_NAME = "CTS";
52     private static final String PACKAGE_NAME = "test-name";
53     private static final String ID = AbiUtils.createId(UnitTests.ABI.getName(), PACKAGE_NAME);
54     private static final TestIdentifier TEST_IDENTIFIER =
55             new TestIdentifier("CLASS_NAME", "TEST_NAME");
56     private static final List<String> NAMES = new ArrayList<>();
57     private static final List<String> IDS = new ArrayList<>();
58     private static final List<TestIdentifier> TEST_IDENTIFIER_LIST = new ArrayList<>();
59 
60     static {
61         NAMES.add(PACKAGE_NAME);
62         IDS.add(ID);
63         TEST_IDENTIFIER_LIST.add(TEST_IDENTIFIER);
64     }
65 
66     /** the test fixture under test, with all external dependencies mocked out */
67     private CtsTest mCtsTest;
68     private ITestPackageRepo mMockRepo;
69     private ITestPlan mMockPlan;
70     private ITestDevice mMockDevice;
71     private ITestInvocationListener mMockListener;
72     private StubCtsBuildHelper mStubBuildHelper;
73     private ITestPackageDef mMockPackageDef;
74     private Set<ITestPackageDef> mMockPackageDefs;
75     private IRemoteTest mMockTest;
76 
77     /**
78      * {@inheritDoc}
79      */
80     @Override
setUp()81     protected void setUp() throws Exception {
82         super.setUp();
83         mMockRepo = EasyMock.createMock(ITestPackageRepo.class);
84         mMockPlan = EasyMock.createMock(ITestPlan.class);
85         mMockDevice = EasyMock.createMock(ITestDevice.class);
86         mMockListener = EasyMock.createNiceMock(ITestInvocationListener.class);
87         mStubBuildHelper = new StubCtsBuildHelper();
88         mMockPackageDefs = new HashSet<>();
89         mMockPackageDef = EasyMock.createMock(ITestPackageDef.class);
90         mMockPackageDefs.add(mMockPackageDef);
91         EasyMock.expect(mMockPackageDef.getTargetApkName()).andStubReturn(null);
92         EasyMock.expect(mMockPackageDef.getTargetPackageName()).andStubReturn(null);
93         mMockTest = EasyMock.createMock(IRemoteTest.class);
94 
95         mCtsTest = new CtsTest() {
96             @Override
97             ITestPackageRepo createTestCaseRepo() {
98                 return mMockRepo;
99             }
100 
101             @Override
102             ITestPlan createPlan(String planName) {
103                 return mMockPlan;
104             }
105 
106             @Override
107             ITestPlan createPlan(PlanCreator planCreator) {
108                 return mMockPlan;
109             }
110 
111             @Override
112             InputStream createXmlStream(File xmlFile) throws FileNotFoundException {
113                 // return empty stream, not used
114                 return new ByteArrayInputStream(new byte[0]);
115             }
116         };
117         mCtsTest.setDevice(mMockDevice);
118         mCtsTest.setBuildHelper(mStubBuildHelper);
119         // turn off device collection for simplicity
120         mCtsTest.setSkipDeviceInfo(true);
121         // only run tests on one ABI
122         EasyMock.expect(mMockDevice.getProperty("ro.product.cpu.abilist"))
123                 .andReturn(UnitTests.ABI.getName()).anyTimes();
124     }
125 
126     /**
127      * Test normal case {@link CtsTest#run(ITestInvocationListener)} when running a plan.
128      */
129     @SuppressWarnings("unchecked")
testRun_plan()130     public void testRun_plan() throws DeviceNotAvailableException, ParseException {
131         setParsePlanExpectations();
132 
133         setCreateAndRunTestExpectations();
134 
135         replayMocks();
136         mCtsTest.run(mMockListener);
137         verifyMocks();
138     }
139 
140     /**
141      * Test normal case {@link CtsTest#run(ITestInvocationListener)} when running a package.
142      */
143     @SuppressWarnings("unchecked")
testRun_package()144     public void testRun_package() throws DeviceNotAvailableException {
145         mCtsTest.addPackageName(PACKAGE_NAME);
146         Map<String, List<ITestPackageDef>> nameMap = new HashMap<>();
147         List<ITestPackageDef> testPackageDefList = new ArrayList<>();
148         testPackageDefList.add(mMockPackageDef);
149         nameMap.put(PACKAGE_NAME, testPackageDefList);
150 
151         EasyMock.expect(mMockRepo.getTestPackageDefsByName()).andReturn(nameMap);
152 
153         setCreateAndRunTestExpectations();
154 
155         replayMocks();
156         mCtsTest.run(mMockListener);
157         verifyMocks();
158     }
159 
160     /**
161      * Test a resumed run
162      */
163     @SuppressWarnings("unchecked")
testRun_resume()164     public void testRun_resume() throws DeviceNotAvailableException {
165         mCtsTest.addPackageName(PACKAGE_NAME);
166         Map<String, List<ITestPackageDef>> nameMap = new HashMap<>();
167         List<ITestPackageDef> testPackageDefList = new ArrayList<>();
168         testPackageDefList.add(mMockPackageDef);
169         nameMap.put(PACKAGE_NAME, testPackageDefList);
170 
171         EasyMock.expect(mMockRepo.getTestPackageDefsByName()).andReturn(nameMap);
172         setCreateAndRunTestExpectations();
173         // abort the first run
174         EasyMock.expectLastCall().andThrow(new DeviceNotAvailableException());
175 
176         // now expect test to be resumed
177         mMockTest.run((ITestInvocationListener)EasyMock.anyObject());
178 
179         replayMocks();
180         try {
181             mCtsTest.run(mMockListener);
182             fail("Did not throw DeviceNotAvailableException");
183         } catch (DeviceNotAvailableException e) {
184             // expected
185         }
186         // now resume, and expect same test's run method to be called again
187         mCtsTest.run(mMockListener);
188         verifyMocks();
189     }
190 
191     /**
192      * Test normal case {@link CtsTest#run(ITestInvocationListener)} when running a class.
193      */
194     @SuppressWarnings("unchecked")
testRun_class()195     public void testRun_class() throws DeviceNotAvailableException {
196         final String className = "className";
197         final String methodName = "methodName";
198         mCtsTest.setClassName(className);
199         mCtsTest.setMethodName(methodName);
200 
201         EasyMock.expect(mMockRepo.findPackageIdsForTest(className)).andReturn(IDS);
202         mMockPackageDef.setClassName(className, methodName);
203 
204         setCreateAndRunTestExpectations();
205 
206         replayMocks();
207         mCtsTest.run(mMockListener);
208         verifyMocks();
209     }
210 
211     /**
212      * Test normal case {@link CtsTest#run(ITestInvocationListener)} when running a class.
213      */
214     @SuppressWarnings("unchecked")
testRun_test()215     public void testRun_test() throws DeviceNotAvailableException {
216         final String className = "className";
217         final String methodName = "methodName";
218         final String testName = String.format("%s#%s", className, methodName);
219         mCtsTest.setTestName(testName);
220 
221         EasyMock.expect(mMockRepo.findPackageIdsForTest(className)).andReturn(IDS);
222         mMockPackageDef.setClassName(className, methodName);
223 
224         setCreateAndRunTestExpectations();
225 
226         replayMocks();
227         mCtsTest.run(mMockListener);
228         verifyMocks();
229     }
230 
231     /**
232      * Test {@link CtsTest#run(ITestInvocationListener)} when --excluded-package is specified
233      */
testRun_excludedPackage()234     public void testRun_excludedPackage() throws DeviceNotAvailableException, ParseException {
235         mCtsTest.setPlanName(PLAN_NAME);
236         mMockPlan.parse((InputStream) EasyMock.anyObject());
237         EasyMock.expect(mMockPlan.getTestIds()).andReturn(IDS);
238 
239         mCtsTest.addExcludedPackageName(PACKAGE_NAME);
240 
241         // PACKAGE_NAME would normally be run, but it has been excluded. Expect nothing to happen
242         replayMocks();
243         mCtsTest.run(mMockListener);
244         verifyMocks();
245     }
246 
247     /**
248      * Test {@link CtsTest#run(ITestInvocationListener)} when --continue-session is specified
249      */
testRun_continueSession()250     public void testRun_continueSession() throws DeviceNotAvailableException {
251         mCtsTest.setContinueSessionId(1);
252         EasyMock.expect(mMockPlan.getTestIds()).andReturn(IDS);
253         TestFilter filter = new TestFilter();
254         EasyMock.expect(mMockPlan.getTestFilter(ID)).andReturn(filter);
255 
256         mMockPackageDef.setTestFilter(filter);
257 
258         setCreateAndRunTestExpectations();
259 
260         replayMocks();
261         mCtsTest.run(mMockListener);
262         verifyMocks();
263     }
264 
265     /**
266      * Set EasyMock expectations for parsing {@link #PLAN_NAME}
267      */
setParsePlanExpectations()268     private void setParsePlanExpectations() throws ParseException {
269         mCtsTest.setPlanName(PLAN_NAME);
270         mMockPlan.parse((InputStream) EasyMock.anyObject());
271         EasyMock.expect(mMockPlan.getTestIds()).andReturn(IDS);
272         TestFilter filter = new TestFilter();
273         EasyMock.expect(mMockPlan.getTestFilter(ID)).andReturn(filter);
274         mMockPackageDef.setTestFilter(filter);
275     }
276 
277     /**
278      * Set EasyMock expectations for creating and running a package with PACKAGE_NAME
279      */
setCreateAndRunTestExpectations()280     private void setCreateAndRunTestExpectations() throws DeviceNotAvailableException {
281         EasyMock.expect(mMockRepo.getPackageNames()).andReturn(NAMES).anyTimes();
282         EasyMock.expect(mMockRepo.getPackageIds()).andReturn(IDS).anyTimes();
283         EasyMock.expect(mMockRepo.getTestPackage(ID)).andReturn(mMockPackageDef).anyTimes();
284         EasyMock.expect(mMockPackageDef.createTest((File) EasyMock.anyObject())).andReturn(mMockTest);
285         EasyMock.expect(mMockPackageDef.getTests()).andReturn(TEST_IDENTIFIER_LIST).times(2);
286         EasyMock.expect(mMockPackageDef.getName()).andReturn(PACKAGE_NAME).atLeastOnce();
287         EasyMock.expect(mMockPackageDef.getAbi()).andReturn(UnitTests.ABI).atLeastOnce();
288         EasyMock.expect(mMockPackageDef.getId()).andReturn(ID).atLeastOnce();
289         EasyMock.expect(mMockPackageDef.getDigest()).andReturn("digest").atLeastOnce();
290         EasyMock.expect(mMockPackageDef.getPackagePreparers()).andReturn(
291                     new ArrayList<ITargetPreparer>()).atLeastOnce();
292         mMockTest.run((ITestInvocationListener) EasyMock.anyObject());
293     }
294 
295     /**
296      * Test {@link CtsTest#run(ITestInvocationListener)} when --plan and --package options have not
297      * been specified
298      */
testRun_nothingToRun()299     public void testRun_nothingToRun() throws DeviceNotAvailableException {
300         replayMocks();
301         try {
302             mCtsTest.run(mMockListener);
303             fail("IllegalArgumentException not thrown");
304         } catch (IllegalArgumentException e) {
305             // expected
306         }
307     }
308 
309     /**
310      * Test {@link CtsTest#run(ITestInvocationListener)} when --plan and --package options have
311      * been specified.
312      */
testRun_packagePlan()313     public void testRun_packagePlan() throws DeviceNotAvailableException {
314         mCtsTest.setPlanName(PLAN_NAME);
315         mCtsTest.addPackageName(PACKAGE_NAME);
316         replayMocks();
317         try {
318             mCtsTest.run(mMockListener);
319             fail("IllegalArgumentException not thrown");
320         } catch (IllegalArgumentException e) {
321             // expected
322         }
323     }
324 
325     /**
326      * Test {@link CtsTest#run(ITestInvocationListener)} when --plan and --class options have been
327      * specified
328      */
testRun_planClass()329     public void testRun_planClass() throws DeviceNotAvailableException {
330         mCtsTest.setPlanName(PLAN_NAME);
331         mCtsTest.setClassName("class");
332         replayMocks();
333         try {
334             mCtsTest.run(mMockListener);
335             fail("IllegalArgumentException not thrown");
336         } catch (IllegalArgumentException e) {
337             // expected
338         }
339     }
340 
341     /**
342      * Test {@link CtsTest#run(ITestInvocationListener)} when --package and --class options have
343      * been specified
344      */
testRun_packageClass()345     public void testRun_packageClass() throws DeviceNotAvailableException {
346         mCtsTest.addPackageName(PACKAGE_NAME);
347         mCtsTest.setClassName("class");
348         replayMocks();
349         try {
350             mCtsTest.run(mMockListener);
351             fail("IllegalArgumentException not thrown");
352         } catch (IllegalArgumentException e) {
353             // expected
354         }
355     }
356 
357     /**
358      * Test {@link CtsTest#run(ITestInvocationListener)} when --plan, --package and --class options
359      * have been specified
360      */
testRun_planPackageClass()361     public void testRun_planPackageClass() throws DeviceNotAvailableException {
362         mCtsTest.setPlanName(PLAN_NAME);
363         mCtsTest.addPackageName(PACKAGE_NAME);
364         mCtsTest.setClassName("class");
365         replayMocks();
366         try {
367             mCtsTest.run(mMockListener);
368             fail("IllegalArgumentException not thrown");
369         } catch (IllegalArgumentException e) {
370             // expected
371         }
372     }
373 
374     /**
375      * Test {@link CtsTest#run(ITestInvocationListener)} when --plan, --continue-option options
376      * have been specified
377      */
testRun_planContinue()378     public void testRun_planContinue() throws DeviceNotAvailableException {
379         mCtsTest.setPlanName(PLAN_NAME);
380         mCtsTest.setContinueSessionId(1);
381         replayMocks();
382         try {
383             mCtsTest.run(mMockListener);
384             fail("IllegalArgumentException not thrown");
385         } catch (IllegalArgumentException e) {
386             // expected
387         }
388     }
389 
390     /**
391      * Test {@link CtsTestTest#join} works.
392      * @throws DeviceNotAvailableException
393      */
testJoin()394     public void testJoin() throws DeviceNotAvailableException {
395         String expected = "a@b@c";
396         String actual = mCtsTest.join(new ArrayList<String>(Arrays.asList("a", "b", "c")), "@");
397         assertEquals(expected, actual);
398     }
399 
400     /**
401      * Test {@link CtsTestTest#join} for a single element list.
402      * @throws DeviceNotAvailableException
403      */
testSingleJoin()404     public void testSingleJoin() throws DeviceNotAvailableException {
405         String actual = mCtsTest.join(new ArrayList<String>(Arrays.asList("foo")), "@");
406         assertEquals("foo", actual);
407     }
408 
409     /**
410      * Test {@link CtsTestTest#join} for an empty list.
411      * @throws DeviceNotAvailableException
412      */
testEmptyJoin()413     public void testEmptyJoin() throws DeviceNotAvailableException {
414         String actual = mCtsTest.join(new ArrayList<String>(), "@");
415         assertEquals("", actual);
416     }
417 
replayMocks(Object... mocks)418     private void replayMocks(Object... mocks) {
419         EasyMock.replay(mMockRepo, mMockPlan, mMockDevice, mMockPackageDef, mMockListener, mMockTest);
420         EasyMock.replay(mocks);
421     }
422 
verifyMocks(Object... mocks)423     private void verifyMocks(Object... mocks) {
424         EasyMock.verify(mMockRepo, mMockPlan, mMockDevice, mMockPackageDef, mMockListener, mMockTest);
425         EasyMock.verify(mocks);
426     }
427 }
428