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