1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16 
17 package com.android.compatibility.common.util;
18 
19 import static junit.framework.Assert.assertEquals;
20 import static junit.framework.Assert.assertFalse;
21 import static junit.framework.Assert.assertTrue;
22 import static junit.framework.Assert.fail;
23 import static org.junit.Assume.assumeTrue;
24 
25 import com.android.tradefed.build.IBuildInfo;
26 import com.android.tradefed.device.ITestDevice;
27 
28 import org.easymock.EasyMock;
29 import org.junit.AssumptionViolatedException;
30 import org.junit.Before;
31 import org.junit.Ignore;
32 import org.junit.Test;
33 import org.junit.runner.RunWith;
34 import org.junit.runners.JUnit4;
35 
36 import java.util.ArrayList;
37 import java.util.Arrays;
38 import java.util.List;
39 
40 import junit.framework.AssertionFailedError;
41 
42 /**
43  * Tests for {@link BusinessLogicHostExecutor}.
44  */
45 @RunWith(JUnit4.class)
46 public class BusinessLogicHostExecutorTest {
47 
48     private static final String THIS_CLASS =
49             "com.android.compatibility.common.util.BusinessLogicHostExecutorTest";
50     private static final String METHOD_1 = THIS_CLASS + ".method1";
51     private static final String METHOD_2 = THIS_CLASS + ".method2";
52     private static final String METHOD_3 = THIS_CLASS + ".method3";
53     private static final String METHOD_4 = THIS_CLASS + ".method4";
54     private static final String METHOD_5 = THIS_CLASS + ".method5";
55     private static final String METHOD_6 = THIS_CLASS + ".method6";
56     private static final String METHOD_7 = THIS_CLASS + ".method7";
57     private static final String METHOD_8 = THIS_CLASS + ".method8";
58     private static final String METHOD_9 = THIS_CLASS + ".method9";
59     private static final String METHOD_10 = THIS_CLASS + ".method10";
60     private static final String FAKE_METHOD = THIS_CLASS + ".methodDoesntExist";
61     private static final String ARG_STRING_1 = "arg1";
62     private static final String ARG_STRING_2 = "arg2";
63 
64     private static final String OTHER_METHOD_1 = THIS_CLASS + "$OtherClass.method1";
65 
66     private String mInvoked = null;
67     private Object[] mArgsUsed = null;
68     private IBuildInfo mMockBuild;
69     private ITestDevice mMockDevice;
70     private BusinessLogicExecutor mExecutor;
71 
72     @Before
setUp()73     public void setUp() {
74         mMockBuild = EasyMock.createMock(IBuildInfo.class);
75         mMockDevice = EasyMock.createMock(ITestDevice.class);
76         mExecutor = new BusinessLogicHostExecutor(mMockDevice, mMockBuild, this);
77         // reset the instance variables tracking the method invoked and the args used
78         mInvoked = null;
79         mArgsUsed = null;
80         // reset the OtherClass class variable tracking the method invoked
81         OtherClass.otherInvoked = null;
82     }
83 
84     @Test
testInvokeMethodInThisClass()85     public void testInvokeMethodInThisClass() throws Exception {
86         mExecutor.invokeMethod(METHOD_1);
87         // assert that mInvoked was set for this BusinessLogicDeviceExecutorTest instance
88         assertEquals("Failed to invoke method in this class", mInvoked, METHOD_1);
89     }
90 
91         @Test
testInvokeMethodInOtherClass()92     public void testInvokeMethodInOtherClass() throws Exception {
93         mExecutor.invokeMethod(OTHER_METHOD_1);
94         // assert that OtherClass.method1 was invoked, and static field of OtherClass was changed
95         assertEquals("Failed to invoke method in other class", OtherClass.otherInvoked,
96                 OTHER_METHOD_1);
97     }
98 
99     @Test
testInvokeMethodWithStringArgs()100     public void testInvokeMethodWithStringArgs() throws Exception {
101         mExecutor.invokeMethod(METHOD_2, ARG_STRING_1, ARG_STRING_2);
102         assertEquals("Failed to invoke method in this class", mInvoked, METHOD_2);
103         // assert both String arguments were correctly set for method2
104         assertEquals("Failed to set first argument", mArgsUsed[0], ARG_STRING_1);
105         assertEquals("Failed to set second argument", mArgsUsed[1], ARG_STRING_2);
106     }
107 
108     @Test
testInvokeMethodWithStringAndDeviceArgs()109     public void testInvokeMethodWithStringAndDeviceArgs() throws Exception {
110         mExecutor.invokeMethod(METHOD_3, ARG_STRING_1);
111         assertEquals("Failed to invoke method in this class", mInvoked, METHOD_3);
112         // assert that String arg and ITestDevice arg were correctly set for method3
113         assertEquals("Failed to set first argument", mArgsUsed[0], ARG_STRING_1);
114         assertEquals("Failed to set second argument", mArgsUsed[1], mMockDevice);
115     }
116 
117     @Test
testInvokeMethodWithDeviceAndStringArgs()118     public void testInvokeMethodWithDeviceAndStringArgs() throws Exception {
119         mExecutor.invokeMethod(METHOD_4, ARG_STRING_1);
120         assertEquals("Failed to invoke method in this class", mInvoked, METHOD_4);
121         // Like testInvokeMethodWithStringAndDeviceArgs, but flip the args for method4
122         assertEquals("Failed to set first argument", mArgsUsed[0], mMockDevice);
123         assertEquals("Failed to set second argument", mArgsUsed[1], ARG_STRING_1);
124     }
125 
126     @Test
testInvokeMethodWithStringArrayArg()127     public void testInvokeMethodWithStringArrayArg() throws Exception {
128         mExecutor.invokeMethod(METHOD_5, ARG_STRING_1, ARG_STRING_2);
129         assertEquals("Failed to invoke method in this class", mInvoked, METHOD_5);
130         // assert both String arguments were correctly set for method5
131         assertEquals("Failed to set first argument", mArgsUsed[0], ARG_STRING_1);
132         assertEquals("Failed to set second argument", mArgsUsed[1], ARG_STRING_2);
133     }
134 
135     @Test
testInvokeMethodWithEmptyStringArrayArg()136     public void testInvokeMethodWithEmptyStringArrayArg() throws Exception {
137         mExecutor.invokeMethod(METHOD_5);
138         assertEquals("Failed to invoke method in this class", mInvoked, METHOD_5);
139         // assert no String arguments were set for method5
140         assertEquals("Incorrectly set args", mArgsUsed.length, 0);
141     }
142 
143     @Test
testInvokeMethodWithStringAndStringArrayArgs()144     public void testInvokeMethodWithStringAndStringArrayArgs() throws Exception {
145         mExecutor.invokeMethod(METHOD_6, ARG_STRING_1, ARG_STRING_2);
146         assertEquals("Failed to invoke method in this class", mInvoked, METHOD_6);
147         // assert both String arguments were correctly set for method6
148         assertEquals("Failed to set first argument", mArgsUsed[0], ARG_STRING_1);
149         assertEquals("Failed to set second argument", mArgsUsed[1], ARG_STRING_2);
150     }
151 
152     @Test
testInvokeMethodWithAllArgTypes()153     public void testInvokeMethodWithAllArgTypes() throws Exception {
154         mExecutor.invokeMethod(METHOD_7, ARG_STRING_1, ARG_STRING_2);
155         assertEquals("Failed to invoke method in this class", mInvoked, METHOD_7);
156         // assert all arguments were correctly set for method7
157         assertEquals("Failed to set first argument", mArgsUsed[0], ARG_STRING_1);
158         assertEquals("Failed to set second argument", mArgsUsed[1], mMockBuild);
159         assertEquals("Failed to set second argument", mArgsUsed[2], mMockDevice);
160         assertEquals("Failed to set third argument", mArgsUsed[3], ARG_STRING_2);
161     }
162 
163     @Test
testInvokeOverloadedMethodOneArg()164     public void testInvokeOverloadedMethodOneArg() throws Exception {
165         mExecutor.invokeMethod(METHOD_1, ARG_STRING_1);
166         assertEquals("Failed to invoke method in this class", mInvoked, METHOD_1);
167         assertEquals("Set wrong number of arguments", mArgsUsed.length, 1);
168         assertEquals("Failed to set first argument", mArgsUsed[0], ARG_STRING_1);
169     }
170 
171     @Test
testInvokeOverloadedMethodTwoArgs()172     public void testInvokeOverloadedMethodTwoArgs() throws Exception {
173         mExecutor.invokeMethod(METHOD_1, ARG_STRING_1, ARG_STRING_2);
174         assertEquals("Failed to invoke method in this class", mInvoked, METHOD_1);
175         assertEquals("Set wrong number of arguments", mArgsUsed.length, 2);
176         assertEquals("Failed to set first argument", mArgsUsed[0], ARG_STRING_1);
177         assertEquals("Failed to set second argument", mArgsUsed[1], ARG_STRING_2);
178     }
179 
180     @Test(expected = RuntimeException.class)
testInvokeNonExistentMethod()181     public void testInvokeNonExistentMethod() throws Exception {
182         mExecutor.invokeMethod(FAKE_METHOD, ARG_STRING_1, ARG_STRING_2);
183     }
184 
185     @Test(expected = RuntimeException.class)
testInvokeMethodTooManyArgs()186     public void testInvokeMethodTooManyArgs() throws Exception {
187         mExecutor.invokeMethod(METHOD_3, ARG_STRING_1, ARG_STRING_2);
188     }
189 
190     @Test(expected = RuntimeException.class)
testInvokeMethodTooFewArgs()191     public void testInvokeMethodTooFewArgs() throws Exception {
192         mExecutor.invokeMethod(METHOD_2, ARG_STRING_1);
193     }
194 
195     @Test(expected = RuntimeException.class)
testInvokeMethodIncompatibleArgs()196     public void testInvokeMethodIncompatibleArgs() throws Exception {
197         mExecutor.invokeMethod(METHOD_8, ARG_STRING_1);
198     }
199 
200     @Test
testExecuteConditionCheckReturnValue()201     public void testExecuteConditionCheckReturnValue() throws Exception {
202         assertTrue("Wrong return value",
203                 mExecutor.executeCondition(METHOD_2, ARG_STRING_1, ARG_STRING_1));
204         assertFalse("Wrong return value",
205                 mExecutor.executeCondition(METHOD_2, ARG_STRING_1, ARG_STRING_2));
206     }
207 
208     @Test(expected = RuntimeException.class)
testExecuteInvalidCondition()209     public void testExecuteInvalidCondition() throws Exception {
210         mExecutor.executeCondition(METHOD_1); // method1 does not return type boolean
211     }
212 
213     @Test
testExecuteAction()214     public void testExecuteAction() throws Exception {
215         mExecutor.executeAction(METHOD_2, ARG_STRING_1, ARG_STRING_2);
216         assertEquals("Failed to invoke method in this class", mInvoked, METHOD_2);
217         // assert both String arguments were correctly set for method2
218         assertEquals("Failed to set first argument", mArgsUsed[0], ARG_STRING_1);
219         assertEquals("Failed to set second argument", mArgsUsed[1], ARG_STRING_2);
220     }
221 
222     @Test(expected = RuntimeException.class)
testExecuteActionThrowException()223     public void testExecuteActionThrowException() throws Exception {
224         mExecutor.executeAction(METHOD_9);
225     }
226 
227     @Test
testExecuteActionViolateAssumption()228     public void testExecuteActionViolateAssumption() throws Exception {
229         try {
230             mExecutor.executeAction(METHOD_10);
231             // JUnit4 doesn't support expecting AssumptionViolatedException with "expected"
232             // attribute on @Test annotation, so test using Assert.fail()
233             fail("Expected assumption failure");
234         } catch (AssumptionViolatedException e) {
235             // expected
236         }
237     }
238 
method1()239     public void method1() {
240         mInvoked = METHOD_1;
241     }
242 
243     // overloaded method with one arg
method1(String arg1)244     public void method1(String arg1) {
245         mInvoked = METHOD_1;
246         mArgsUsed = new Object[]{arg1};
247     }
248 
249     // overloaded method with two args
method1(String arg1, String arg2)250     public void method1(String arg1, String arg2) {
251         mInvoked = METHOD_1;
252         mArgsUsed = new Object[]{arg1, arg2};
253     }
254 
method2(String arg1, String arg2)255     public boolean method2(String arg1, String arg2) {
256         mInvoked = METHOD_2;
257         mArgsUsed = new Object[]{arg1, arg2};
258         return arg1.equals(arg2);
259     }
260 
method3(String arg1, ITestDevice arg2)261     public void method3(String arg1, ITestDevice arg2) {
262         mInvoked = METHOD_3;
263 
264         mArgsUsed = new Object[]{arg1, arg2};
265     }
266 
267     // Same as method3, but flipped args
method4(ITestDevice arg1, String arg2)268     public void method4(ITestDevice arg1, String arg2) {
269         mInvoked = METHOD_4;
270         mArgsUsed = new Object[]{arg1, arg2};
271     }
272 
method5(String... args)273     public void method5(String... args) {
274         mInvoked = METHOD_5;
275         mArgsUsed = args;
276     }
277 
method6(String arg1, String... moreArgs)278     public void method6(String arg1, String... moreArgs) {
279         mInvoked = METHOD_6;
280         List<String> allArgs = new ArrayList<>();
281         allArgs.add(arg1);
282         allArgs.addAll(Arrays.asList(moreArgs));
283         mArgsUsed = allArgs.toArray(new String[0]);
284     }
285 
method7(String arg1, IBuildInfo arg2, ITestDevice arg3, String... moreArgs)286     public void method7(String arg1, IBuildInfo arg2, ITestDevice arg3, String... moreArgs) {
287         mInvoked = METHOD_7;
288         List<Object> allArgs = new ArrayList<>();
289         allArgs.add(arg1);
290         allArgs.add(arg2);
291         allArgs.add(arg3);
292         allArgs.addAll(Arrays.asList(moreArgs));
293         mArgsUsed = allArgs.toArray(new Object[0]);
294     }
295 
method8(String arg1, Integer arg2)296     public void method8(String arg1, Integer arg2) {
297         // This method should never be successfully invoked, since Integer parameter types are
298         // unsupported for the BusinessLogic service
299     }
300 
301     // throw AssertionFailedError
302     @Ignore
method9()303     public void method9() throws AssertionFailedError {
304         assertTrue(false);
305     }
306 
307     // throw AssumptionViolatedException
method10()308     public void method10() throws AssumptionViolatedException {
309         assumeTrue(false);
310     }
311 
312     public static class OtherClass {
313 
314         public static String otherInvoked = null;
315 
method1()316         public void method1() {
317             otherInvoked = OTHER_METHOD_1;
318         }
319     }
320 }
321