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 =
77                 new BusinessLogicHostExecutor(
78                         mMockDevice, mMockBuild, this, new ArrayList<String>());
79         // reset the instance variables tracking the method invoked and the args used
80         mInvoked = null;
81         mArgsUsed = null;
82         // reset the OtherClass class variable tracking the method invoked
83         OtherClass.otherInvoked = null;
84     }
85 
86     @Test
testInvokeMethodInThisClass()87     public void testInvokeMethodInThisClass() throws Exception {
88         mExecutor.invokeMethod(METHOD_1);
89         // assert that mInvoked was set for this BusinessLogicDeviceExecutorTest instance
90         assertEquals("Failed to invoke method in this class", mInvoked, METHOD_1);
91     }
92 
93         @Test
testInvokeMethodInOtherClass()94     public void testInvokeMethodInOtherClass() throws Exception {
95         mExecutor.invokeMethod(OTHER_METHOD_1);
96         // assert that OtherClass.method1 was invoked, and static field of OtherClass was changed
97         assertEquals("Failed to invoke method in other class", OtherClass.otherInvoked,
98                 OTHER_METHOD_1);
99     }
100 
101     @Test
testInvokeMethodWithStringArgs()102     public void testInvokeMethodWithStringArgs() throws Exception {
103         mExecutor.invokeMethod(METHOD_2, ARG_STRING_1, ARG_STRING_2);
104         assertEquals("Failed to invoke method in this class", mInvoked, METHOD_2);
105         // assert both String arguments were correctly set for method2
106         assertEquals("Failed to set first argument", mArgsUsed[0], ARG_STRING_1);
107         assertEquals("Failed to set second argument", mArgsUsed[1], ARG_STRING_2);
108     }
109 
110     @Test
testInvokeMethodWithStringAndDeviceArgs()111     public void testInvokeMethodWithStringAndDeviceArgs() throws Exception {
112         mExecutor.invokeMethod(METHOD_3, ARG_STRING_1);
113         assertEquals("Failed to invoke method in this class", mInvoked, METHOD_3);
114         // assert that String arg and ITestDevice arg were correctly set for method3
115         assertEquals("Failed to set first argument", mArgsUsed[0], ARG_STRING_1);
116         assertEquals("Failed to set second argument", mArgsUsed[1], mMockDevice);
117     }
118 
119     @Test
testInvokeMethodWithDeviceAndStringArgs()120     public void testInvokeMethodWithDeviceAndStringArgs() throws Exception {
121         mExecutor.invokeMethod(METHOD_4, ARG_STRING_1);
122         assertEquals("Failed to invoke method in this class", mInvoked, METHOD_4);
123         // Like testInvokeMethodWithStringAndDeviceArgs, but flip the args for method4
124         assertEquals("Failed to set first argument", mArgsUsed[0], mMockDevice);
125         assertEquals("Failed to set second argument", mArgsUsed[1], ARG_STRING_1);
126     }
127 
128     @Test
testInvokeMethodWithStringArrayArg()129     public void testInvokeMethodWithStringArrayArg() throws Exception {
130         mExecutor.invokeMethod(METHOD_5, ARG_STRING_1, ARG_STRING_2);
131         assertEquals("Failed to invoke method in this class", mInvoked, METHOD_5);
132         // assert both String arguments were correctly set for method5
133         assertEquals("Failed to set first argument", mArgsUsed[0], ARG_STRING_1);
134         assertEquals("Failed to set second argument", mArgsUsed[1], ARG_STRING_2);
135     }
136 
137     @Test
testInvokeMethodWithEmptyStringArrayArg()138     public void testInvokeMethodWithEmptyStringArrayArg() throws Exception {
139         mExecutor.invokeMethod(METHOD_5);
140         assertEquals("Failed to invoke method in this class", mInvoked, METHOD_5);
141         // assert no String arguments were set for method5
142         assertEquals("Incorrectly set args", mArgsUsed.length, 0);
143     }
144 
145     @Test
testInvokeMethodWithStringAndStringArrayArgs()146     public void testInvokeMethodWithStringAndStringArrayArgs() throws Exception {
147         mExecutor.invokeMethod(METHOD_6, ARG_STRING_1, ARG_STRING_2);
148         assertEquals("Failed to invoke method in this class", mInvoked, METHOD_6);
149         // assert both String arguments were correctly set for method6
150         assertEquals("Failed to set first argument", mArgsUsed[0], ARG_STRING_1);
151         assertEquals("Failed to set second argument", mArgsUsed[1], ARG_STRING_2);
152     }
153 
154     @Test
testInvokeMethodWithAllArgTypes()155     public void testInvokeMethodWithAllArgTypes() throws Exception {
156         mExecutor.invokeMethod(METHOD_7, ARG_STRING_1, ARG_STRING_2);
157         assertEquals("Failed to invoke method in this class", mInvoked, METHOD_7);
158         // assert all arguments were correctly set for method7
159         assertEquals("Failed to set first argument", mArgsUsed[0], ARG_STRING_1);
160         assertEquals("Failed to set second argument", mArgsUsed[1], mMockBuild);
161         assertEquals("Failed to set second argument", mArgsUsed[2], mMockDevice);
162         assertEquals("Failed to set third argument", mArgsUsed[3], ARG_STRING_2);
163     }
164 
165     @Test
testInvokeOverloadedMethodOneArg()166     public void testInvokeOverloadedMethodOneArg() throws Exception {
167         mExecutor.invokeMethod(METHOD_1, ARG_STRING_1);
168         assertEquals("Failed to invoke method in this class", mInvoked, METHOD_1);
169         assertEquals("Set wrong number of arguments", mArgsUsed.length, 1);
170         assertEquals("Failed to set first argument", mArgsUsed[0], ARG_STRING_1);
171     }
172 
173     @Test
testInvokeOverloadedMethodTwoArgs()174     public void testInvokeOverloadedMethodTwoArgs() throws Exception {
175         mExecutor.invokeMethod(METHOD_1, ARG_STRING_1, ARG_STRING_2);
176         assertEquals("Failed to invoke method in this class", mInvoked, METHOD_1);
177         assertEquals("Set wrong number of arguments", mArgsUsed.length, 2);
178         assertEquals("Failed to set first argument", mArgsUsed[0], ARG_STRING_1);
179         assertEquals("Failed to set second argument", mArgsUsed[1], ARG_STRING_2);
180     }
181 
182     @Test(expected = RuntimeException.class)
testInvokeNonExistentMethod()183     public void testInvokeNonExistentMethod() throws Exception {
184         mExecutor.invokeMethod(FAKE_METHOD, ARG_STRING_1, ARG_STRING_2);
185     }
186 
187     @Test(expected = RuntimeException.class)
testInvokeMethodTooManyArgs()188     public void testInvokeMethodTooManyArgs() throws Exception {
189         mExecutor.invokeMethod(METHOD_3, ARG_STRING_1, ARG_STRING_2);
190     }
191 
192     @Test(expected = RuntimeException.class)
testInvokeMethodTooFewArgs()193     public void testInvokeMethodTooFewArgs() throws Exception {
194         mExecutor.invokeMethod(METHOD_2, ARG_STRING_1);
195     }
196 
197     @Test(expected = RuntimeException.class)
testInvokeMethodIncompatibleArgs()198     public void testInvokeMethodIncompatibleArgs() throws Exception {
199         mExecutor.invokeMethod(METHOD_8, ARG_STRING_1);
200     }
201 
202     @Test
testExecuteConditionCheckReturnValue()203     public void testExecuteConditionCheckReturnValue() throws Exception {
204         assertTrue("Wrong return value",
205                 mExecutor.executeCondition(METHOD_2, ARG_STRING_1, ARG_STRING_1));
206         assertFalse("Wrong return value",
207                 mExecutor.executeCondition(METHOD_2, ARG_STRING_1, ARG_STRING_2));
208     }
209 
210     @Test(expected = RuntimeException.class)
testExecuteInvalidCondition()211     public void testExecuteInvalidCondition() throws Exception {
212         mExecutor.executeCondition(METHOD_1); // method1 does not return type boolean
213     }
214 
215     @Test
testExecuteAction()216     public void testExecuteAction() throws Exception {
217         mExecutor.executeAction(METHOD_2, ARG_STRING_1, ARG_STRING_2);
218         assertEquals("Failed to invoke method in this class", mInvoked, METHOD_2);
219         // assert both String arguments were correctly set for method2
220         assertEquals("Failed to set first argument", mArgsUsed[0], ARG_STRING_1);
221         assertEquals("Failed to set second argument", mArgsUsed[1], ARG_STRING_2);
222     }
223 
224     @Test(expected = RuntimeException.class)
testExecuteActionThrowException()225     public void testExecuteActionThrowException() throws Exception {
226         mExecutor.executeAction(METHOD_9);
227     }
228 
229     @Test
testExecuteActionViolateAssumption()230     public void testExecuteActionViolateAssumption() throws Exception {
231         try {
232             mExecutor.executeAction(METHOD_10);
233             // JUnit4 doesn't support expecting AssumptionViolatedException with "expected"
234             // attribute on @Test annotation, so test using Assert.fail()
235             fail("Expected assumption failure");
236         } catch (AssumptionViolatedException e) {
237             // expected
238         }
239     }
240 
method1()241     public void method1() {
242         mInvoked = METHOD_1;
243     }
244 
245     // overloaded method with one arg
method1(String arg1)246     public void method1(String arg1) {
247         mInvoked = METHOD_1;
248         mArgsUsed = new Object[]{arg1};
249     }
250 
251     // overloaded method with two args
method1(String arg1, String arg2)252     public void method1(String arg1, String arg2) {
253         mInvoked = METHOD_1;
254         mArgsUsed = new Object[]{arg1, arg2};
255     }
256 
method2(String arg1, String arg2)257     public boolean method2(String arg1, String arg2) {
258         mInvoked = METHOD_2;
259         mArgsUsed = new Object[]{arg1, arg2};
260         return arg1.equals(arg2);
261     }
262 
method3(String arg1, ITestDevice arg2)263     public void method3(String arg1, ITestDevice arg2) {
264         mInvoked = METHOD_3;
265 
266         mArgsUsed = new Object[]{arg1, arg2};
267     }
268 
269     // Same as method3, but flipped args
method4(ITestDevice arg1, String arg2)270     public void method4(ITestDevice arg1, String arg2) {
271         mInvoked = METHOD_4;
272         mArgsUsed = new Object[]{arg1, arg2};
273     }
274 
method5(String... args)275     public void method5(String... args) {
276         mInvoked = METHOD_5;
277         mArgsUsed = args;
278     }
279 
method6(String arg1, String... moreArgs)280     public void method6(String arg1, String... moreArgs) {
281         mInvoked = METHOD_6;
282         List<String> allArgs = new ArrayList<>();
283         allArgs.add(arg1);
284         allArgs.addAll(Arrays.asList(moreArgs));
285         mArgsUsed = allArgs.toArray(new String[0]);
286     }
287 
method7(String arg1, IBuildInfo arg2, ITestDevice arg3, String... moreArgs)288     public void method7(String arg1, IBuildInfo arg2, ITestDevice arg3, String... moreArgs) {
289         mInvoked = METHOD_7;
290         List<Object> allArgs = new ArrayList<>();
291         allArgs.add(arg1);
292         allArgs.add(arg2);
293         allArgs.add(arg3);
294         allArgs.addAll(Arrays.asList(moreArgs));
295         mArgsUsed = allArgs.toArray(new Object[0]);
296     }
297 
method8(String arg1, Integer arg2)298     public void method8(String arg1, Integer arg2) {
299         // This method should never be successfully invoked, since Integer parameter types are
300         // unsupported for the BusinessLogic service
301     }
302 
303     // throw AssertionFailedError
304     @Ignore
method9()305     public void method9() throws AssertionFailedError {
306         assertTrue(false);
307     }
308 
309     // throw AssumptionViolatedException
method10()310     public void method10() throws AssumptionViolatedException {
311         assumeTrue(false);
312     }
313 
314     public static class OtherClass {
315 
316         public static String otherInvoked = null;
317 
method1()318         public void method1() {
319             otherInvoked = OTHER_METHOD_1;
320         }
321     }
322 }
323