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