• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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.messaging.datamodel.action;
18 
19 import android.content.Intent;
20 import android.os.Bundle;
21 import android.os.Parcel;
22 import android.os.Parcelable;
23 import android.test.suitebuilder.annotation.MediumTest;
24 import android.util.Log;
25 
26 import com.android.messaging.BugleTestCase;
27 import com.android.messaging.Factory;
28 import com.android.messaging.FakeContext;
29 import com.android.messaging.FakeContext.FakeContextHost;
30 import com.android.messaging.FakeFactory;
31 import com.android.messaging.datamodel.BugleServiceTestCase;
32 import com.android.messaging.datamodel.DataModel;
33 import com.android.messaging.datamodel.FakeDataModel;
34 import com.android.messaging.datamodel.action.ActionMonitor.ActionCompletedListener;
35 import com.android.messaging.datamodel.action.ActionMonitor.ActionExecutedListener;
36 import com.android.messaging.datamodel.action.ActionTestHelpers.ResultTracker;
37 import com.android.messaging.datamodel.action.ActionTestHelpers.StubBackgroundWorker;
38 import com.android.messaging.datamodel.action.ActionTestHelpers.StubConnectivityUtil;
39 import com.android.messaging.datamodel.action.ActionTestHelpers.StubLoader;
40 
41 import java.util.ArrayList;
42 
43 @MediumTest
44 public class ActionServiceSystemTest extends BugleServiceTestCase<ActionServiceImpl>
45         implements ActionCompletedListener, ActionExecutedListener, FakeContextHost {
46     private static final String TAG = "ActionServiceSystemTest";
47 
48     static {
49         // Set flag during loading of test cases to prevent application initialization starting
BugleTestCase.setTestsRunning()50         BugleTestCase.setTestsRunning();
51     }
52 
53     @Override
onActionSucceeded(final ActionMonitor monitor, final Action action, final Object data, final Object result)54     public void onActionSucceeded(final ActionMonitor monitor,
55             final Action action, final Object data, final Object result) {
56         final TestChatAction test = (TestChatAction) action;
57         assertEquals("Expect correct action parameter", parameter, test.parameter);
58         final ResultTracker tracker = (ResultTracker) data;
59         tracker.completionResult = result;
60         synchronized(tracker) {
61             tracker.notifyAll();
62         }
63     }
64 
65     @Override
onActionFailed(final ActionMonitor monitor, final Action action, final Object data, final Object result)66     public void onActionFailed(final ActionMonitor monitor, final Action action,
67             final Object data, final Object result) {
68         final TestChatAction test = (TestChatAction) action;
69         assertEquals("Expect correct action parameter", parameter, test.parameter);
70         final ResultTracker tracker = (ResultTracker) data;
71         tracker.completionResult = result;
72         synchronized(tracker) {
73             tracker.notifyAll();
74         }
75     }
76 
77     @Override
onActionExecuted(final ActionMonitor monitor, final Action action, final Object data, final Object result)78     public void onActionExecuted(final ActionMonitor monitor, final Action action,
79             final Object data, final Object result) {
80         final TestChatAction test = (TestChatAction) action;
81         assertEquals("Expect correct action parameter", parameter, test.parameter);
82         final ResultTracker tracker = (ResultTracker) data;
83         tracker.executionResult = result;
84     }
85 
ActionServiceSystemTest()86     public ActionServiceSystemTest() {
87         super(ActionServiceImpl.class);
88     }
89 
testChatActionSucceeds()90     public void testChatActionSucceeds() {
91         final ResultTracker tracker = new ResultTracker();
92 
93         final ActionService service = DataModel.get().getActionService();
94         final TestChatActionMonitor monitor = new TestChatActionMonitor(null, tracker, this, this);
95         final TestChatAction initial = new TestChatAction(monitor.getActionKey(), parameter);
96 
97         assertNull("Expect completion result to start null", tracker.completionResult);
98         assertNull("Expect execution result to start null", tracker.executionResult);
99 
100         final Parcel parcel = Parcel.obtain();
101         parcel.writeParcelable(initial, 0);
102         parcel.setDataPosition(0);
103         final TestChatAction action = parcel.readParcelable(mContext.getClassLoader());
104 
105         synchronized(mWorker) {
106             try {
107                 action.start(monitor);
108                 // Wait for callback across threads
109                 mWorker.wait(2000);
110             } catch (final InterruptedException e) {
111                 assertTrue("Interrupted waiting for execution", false);
112             }
113         }
114 
115         assertEquals("Expect to see 1 server request queued", 1,
116                 mWorker.getRequestsMade().size());
117         final Action request = mWorker.getRequestsMade().get(0);
118         assertTrue("Expect Test type", request instanceof TestChatAction);
119 
120         final Bundle response = new Bundle();
121         response.putString(TestChatAction.RESPONSE_TEST, processResponseResult);
122         synchronized(tracker) {
123             try {
124                 request.markBackgroundWorkStarting();
125                 request.markBackgroundWorkQueued();
126 
127                 request.markBackgroundWorkStarting();
128                 request.markBackgroundCompletionQueued();
129                 service.handleResponseFromBackgroundWorker(request, response);
130                 // Wait for callback across threads
131                 tracker.wait(2000);
132             } catch (final InterruptedException e) {
133                 assertTrue("Interrupted waiting for response processing", false);
134             }
135         }
136 
137         // TODO
138         //assertEquals("Expect execution result set", executeActionResult, tracker.executionResult);
139         assertEquals("Expect completion result set", processResponseResult,
140                 tracker.completionResult);
141     }
142 
testChatActionFails()143     public void testChatActionFails() {
144         final ResultTracker tracker = new ResultTracker();
145 
146         final ActionService service = DataModel.get().getActionService();
147         final TestChatActionMonitor monitor = new TestChatActionMonitor(null, tracker, this, this);
148         final TestChatAction action = new TestChatAction(monitor.getActionKey(), parameter);
149 
150         assertNull("Expect completion result to start null", tracker.completionResult);
151         assertNull("Expect execution result to start null", tracker.executionResult);
152 
153         synchronized(mWorker) {
154             try {
155                 action.start(monitor);
156                 // Wait for callback across threads
157                 mWorker.wait(2000);
158             } catch (final InterruptedException e) {
159                 assertTrue("Interrupted waiting for requests", false);
160             }
161         }
162 
163         final ArrayList<Intent> intents = mContext.extractIntents();
164         assertNotNull(intents);
165         assertEquals("Expect to see one intent", intents.size(), 1);
166 
167         assertEquals("Expect to see 1 server request queued", 1,
168                 mWorker.getRequestsMade().size());
169         final Action request = mWorker.getRequestsMade().get(0);
170         assertTrue("Expect Test type", request instanceof TestChatAction);
171 
172         synchronized(tracker) {
173             try {
174                 request.markBackgroundWorkStarting();
175                 request.markBackgroundWorkQueued();
176 
177                 request.markBackgroundWorkStarting();
178                 request.markBackgroundCompletionQueued();
179                 service.handleFailureFromBackgroundWorker(request, new Exception("It went wrong"));
180                 // Wait for callback across threads
181                 tracker.wait(2000);
182             } catch (final InterruptedException e) {
183                 assertTrue("Interrupted waiting for response processing", false);
184             }
185         }
186 
187         // TODO
188         //assertEquals("Expect execution result set", executeActionResult, tracker.executionResult);
189         assertEquals("Expect completion result set", processFailureResult,
190                 tracker.completionResult);
191     }
192 
testChatActionNoMonitor()193     public void testChatActionNoMonitor() {
194         final ActionService service = DataModel.get().getActionService();
195         final TestChatAction action =
196                 new TestChatAction(Action.generateUniqueActionKey(null), parameter);
197 
198         synchronized(mWorker) {
199             try {
200                 action.start();
201                 // Wait for callback across threads
202                 mWorker.wait(2000);
203             } catch (final InterruptedException e) {
204                 assertTrue("Interrupted waiting for execution", false);
205             }
206         }
207 
208         assertEquals("Expect to see 1 server request queued", 1,
209                 mWorker.getRequestsMade().size());
210         Action request = mWorker.getRequestsMade().get(0);
211         assertTrue("Expect Test type", request instanceof TestChatAction);
212 
213         final Bundle response = new Bundle();
214         response.putString(TestChatAction.RESPONSE_TEST, processResponseResult);
215         synchronized(mWorker) {
216             try {
217                 service.handleResponseFromBackgroundWorker(request, response);
218                 // Wait for callback across threads
219                 mWorker.wait(2000);
220             } catch (final InterruptedException e) {
221                 assertTrue("Interrupted waiting for response processing", false);
222             }
223         }
224 
225         assertEquals("Expect to see second server request queued",
226                 2, mWorker.getRequestsMade().size());
227         request = mWorker.getRequestsMade().get(1);
228         assertTrue("Expect other type",
229                 request instanceof TestChatActionOther);
230     }
231 
testChatActionUnregisterListener()232     public void testChatActionUnregisterListener() {
233         final ResultTracker tracker = new ResultTracker();
234 
235         final ActionService service = DataModel.get().getActionService();
236         final TestChatActionMonitor monitor = new TestChatActionMonitor(null, tracker, this, this);
237         final TestChatAction action = new TestChatAction(monitor.getActionKey(), parameter);
238 
239         assertNull("Expect completion result to start null", tracker.completionResult);
240         assertNull("Expect execution result to start null", tracker.executionResult);
241 
242         synchronized(mWorker) {
243             try {
244                 action.start(monitor);
245                 // Wait for callback across threads
246                 mWorker.wait(2000);
247             } catch (final InterruptedException e) {
248                 assertTrue("Interrupted waiting for execution", false);
249             }
250         }
251 
252         assertEquals("Expect to see 1 server request queued", 1,
253                 mWorker.getRequestsMade().size());
254         final Action request = mWorker.getRequestsMade().get(0);
255         assertTrue("Expect Test type", request instanceof TestChatAction);
256 
257         monitor.unregister();
258 
259         final Bundle response = new Bundle();
260         synchronized(mWorker) {
261             try {
262                 request.markBackgroundWorkStarting();
263                 request.markBackgroundWorkQueued();
264 
265                 request.markBackgroundWorkStarting();
266                 request.markBackgroundCompletionQueued();
267                 service.handleResponseFromBackgroundWorker(request, response);
268                 // Wait for callback across threads
269                 mWorker.wait(2000);
270             } catch (final InterruptedException e) {
271                 assertTrue("Interrupted waiting for response processing", false);
272             }
273         }
274 
275         //assertEquals("Expect execution result set", executeActionResult, tracker.executionResult);
276         assertEquals("Expect completion never called", null, tracker.completionResult);
277     }
278 
279     StubBackgroundWorker mWorker;
280     FakeContext mContext;
281     StubLoader mLoader;
282 
283     private static final String parameter = "parameter";
284     private static final Object executeActionResult = "executeActionResult";
285     private static final String processResponseResult = "processResponseResult";
286     private static final Object processFailureResult = "processFailureResult";
287 
288     @Override
setUp()289     public void setUp() throws Exception {
290         super.setUp();
291         Log.d(TAG, "ChatActionTest setUp");
292 
293         mContext = new FakeContext(getContext(), this);
294         mWorker = new StubBackgroundWorker();
295         FakeFactory.registerWithFakeContext(getContext(), mContext)
296                 .withDataModel(new FakeDataModel(mContext)
297                 .withBackgroundWorkerForActionService(mWorker)
298                 .withActionService(new ActionService())
299                 .withConnectivityUtil(new StubConnectivityUtil(mContext)));
300 
301         mLoader = new StubLoader();
302         setContext(Factory.get().getApplicationContext());
303     }
304 
305     @Override
getServiceClassName()306     public String getServiceClassName() {
307         return ActionServiceImpl.class.getName();
308     }
309 
310     @Override
startServiceForStub(final Intent intent)311     public void startServiceForStub(final Intent intent) {
312         this.startService(intent);
313     }
314 
315     @Override
onStartCommandForStub(final Intent intent, final int flags, final int startId)316     public void onStartCommandForStub(final Intent intent, final int flags, final int startId) {
317         this.getService().onStartCommand(intent, flags, startId);
318     }
319 
320     public static class TestChatAction extends Action implements Parcelable {
321         public static String RESPONSE_TEST = "response_test";
322         public static String KEY_PARAMETER = "parameter";
323 
TestChatAction(final String key, final String parameter)324         protected TestChatAction(final String key, final String parameter) {
325             super(key);
326             this.actionParameters.putString(KEY_PARAMETER, parameter);
327             // Cache parameter as a member variable
328             this.parameter = parameter;
329         }
330 
331         // An example parameter
332         public final String parameter;
333 
334         /**
335          * Process the action locally - runs on datamodel service thread
336          */
337         @Override
executeAction()338         protected Object executeAction() {
339             requestBackgroundWork();
340             return executeActionResult;
341         }
342 
343         /**
344          * Process the response from the server - runs on datamodel service thread
345          */
346         @Override
processBackgroundResponse(final Bundle response)347         protected Object processBackgroundResponse(final Bundle response) {
348             requestBackgroundWork(new TestChatActionOther(null, parameter));
349             return response.get(RESPONSE_TEST);
350         }
351 
352         /**
353          * Called in case of failures when sending requests - runs on datamodel service thread
354          */
355         @Override
processBackgroundFailure()356         protected Object processBackgroundFailure() {
357             return processFailureResult;
358         }
359 
TestChatAction(final Parcel in)360         private TestChatAction(final Parcel in) {
361             super(in);
362             // Cache parameter as a member variable
363             parameter = actionParameters.getString(KEY_PARAMETER);
364         }
365 
366         public static final Parcelable.Creator<TestChatAction> CREATOR
367                 = new Parcelable.Creator<TestChatAction>() {
368             @Override
369             public TestChatAction createFromParcel(final Parcel in) {
370                 return new TestChatAction(in);
371             }
372 
373             @Override
374             public TestChatAction[] newArray(final int size) {
375                 return new TestChatAction[size];
376             }
377         };
378 
379         @Override
writeToParcel(final Parcel parcel, final int flags)380         public void writeToParcel(final Parcel parcel, final int flags) {
381             writeActionToParcel(parcel, flags);
382         }
383     }
384 
385     public static class TestChatActionOther extends Action implements Parcelable {
TestChatActionOther(final String key, final String parameter)386         protected TestChatActionOther(final String key, final String parameter) {
387             super(generateUniqueActionKey(key));
388             this.parameter = parameter;
389         }
390 
391         public final String parameter;
392 
TestChatActionOther(final Parcel in)393         private TestChatActionOther(final Parcel in) {
394             super(in);
395             parameter = in.readString();
396         }
397 
398         public static final Parcelable.Creator<TestChatActionOther> CREATOR
399                 = new Parcelable.Creator<TestChatActionOther>() {
400             @Override
401             public TestChatActionOther createFromParcel(final Parcel in) {
402                 return new TestChatActionOther(in);
403             }
404 
405             @Override
406             public TestChatActionOther[] newArray(final int size) {
407                 return new TestChatActionOther[size];
408             }
409         };
410 
411         @Override
writeToParcel(final Parcel parcel, final int flags)412         public void writeToParcel(final Parcel parcel, final int flags) {
413             writeActionToParcel(parcel, flags);
414             parcel.writeString(parameter);
415         }
416     }
417 
418     /**
419      * An operation that notifies a listener upon completion
420      */
421     public static class TestChatActionMonitor extends ActionMonitor {
422         /**
423          * Create action state wrapping an BlockUserAction instance
424          * @param account - account in which to block the user
425          * @param baseKey - suggested action key from BlockUserAction
426          * @param data - optional action specific data that is handed back to listener
427          * @param listener - action completed listener
428          */
TestChatActionMonitor(final String baseKey, final Object data, final ActionCompletedListener completed, final ActionExecutedListener executed)429         public TestChatActionMonitor(final String baseKey, final Object data,
430                 final ActionCompletedListener completed, final ActionExecutedListener executed) {
431             super(STATE_CREATED, Action.generateUniqueActionKey(baseKey), data);
432             setCompletedListener(completed);
433             setExecutedListener(executed);
434         }
435     }
436 }
437