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.os.Bundle;
20 import android.os.Parcel;
21 import android.os.Parcelable;
22 
23 import androidx.test.filters.MediumTest;
24 import androidx.test.filters.SmallTest;
25 
26 import com.android.messaging.BugleTestCase;
27 import com.android.messaging.FakeFactory;
28 import com.android.messaging.datamodel.DataModelImpl;
29 import com.android.messaging.datamodel.action.ActionTestHelpers.StubChatActionMonitor;
30 
31 import java.util.ArrayList;
32 
33 @MediumTest
34 public class ActionTest extends BugleTestCase {
35     private static final String parameter = "parameter";
36     private static final Object executeActionResult = "executeActionResult";
37     private static final Object processResponseResult = "processResponseResult";
38     private static final Object processFailureResult = "processFailureResult";
39 
40     private static final String mActionKey = "TheActionKey";
41     private static final Object mData = "PrivateData";
42     private StubChatActionMonitor mMonitor;
43     private TestChatAction mAction;
44 
45     private ArrayList<StubChatActionMonitor.StateTransition> mTransitions;
46 
47     @Override
setUp()48     public void setUp() throws Exception {
49         super.setUp();
50         FakeFactory.register(getTestContext())
51                 .withDataModel(new DataModelImpl(getContext()));
52 
53         mMonitor = new StubChatActionMonitor(ActionMonitor.STATE_CREATED, mActionKey,
54                 mData);
55         mAction = new TestChatAction(mActionKey, parameter);
56         mTransitions = mMonitor.getTransitions();
57     }
58 
verifyState(final int count, final int from, final int to)59     private void verifyState(final int count, final int from, final int to) {
60         assertEquals(to, mMonitor.getState());
61         assertEquals(mTransitions.size(), count);
62         verifyTransition(count-1, from , to);
63     }
64 
verifyTransition(final int index, final int from, final int to)65     private void verifyTransition(final int index, final int from, final int to) {
66         assertTrue(mTransitions.size() > index);
67         assertEquals(mAction, mTransitions.get(index).action);
68         assertEquals(from, mTransitions.get(index).from);
69         assertEquals(to, mTransitions.get(index).to);
70     }
71 
72     @SmallTest
testActionStartTransitionsCorrectly()73     public void testActionStartTransitionsCorrectly() {
74         mMonitor.setState(ActionMonitor.STATE_CREATED);
75 
76         ActionMonitor.registerActionMonitor(mAction.actionKey, mMonitor);
77         assertTrue(ActionMonitor.sActionMonitors.containsKey(mAction.actionKey));
78         assertTrue(ActionMonitor.sActionMonitors.containsValue(mMonitor));
79         assertEquals(ActionMonitor.sActionMonitors.get(mAction.actionKey), mMonitor);
80 
81         mAction.markStart();
82         assertEquals("After start state: STATE_QUEUED", ActionMonitor.STATE_QUEUED,
83                 mMonitor.getState());
84         verifyState(1, ActionMonitor.STATE_CREATED, ActionMonitor.STATE_QUEUED);
85 
86         ActionMonitor.unregisterActionMonitor(mAction.actionKey, mMonitor);
87 
88         assertFalse(ActionMonitor.sActionMonitors.containsKey(mAction.actionKey));
89         assertFalse(ActionMonitor.sActionMonitors.containsValue(mMonitor));
90     }
91 
92     @SmallTest
testActionStartAssertsFromIncorrectState()93     public void testActionStartAssertsFromIncorrectState() {
94         mMonitor.setState(ActionMonitor.STATE_UNDEFINED);
95 
96         ActionMonitor.registerActionMonitor(mAction.actionKey, mMonitor);
97         assertTrue(ActionMonitor.sActionMonitors.containsKey(mAction.actionKey));
98         assertTrue(ActionMonitor.sActionMonitors.containsValue(mMonitor));
99         assertEquals(ActionMonitor.sActionMonitors.get(mAction.actionKey), mMonitor);
100 
101         try {
102             mAction.markStart();
103             fail("Expect assertion when starting from STATE_UNDEFINED");
104         } catch (final IllegalStateException ex){
105         }
106         ActionMonitor.unregisterActionMonitor(mAction.actionKey, mMonitor);
107 
108         assertFalse(ActionMonitor.sActionMonitors.containsKey(mAction.actionKey));
109         assertFalse(ActionMonitor.sActionMonitors.containsValue(mMonitor));
110     }
111 
testActionTransitionsEndToEndWithRequests()112     public void testActionTransitionsEndToEndWithRequests() {
113         assertEquals("Start state: STATE_CREATED", ActionMonitor.STATE_CREATED,
114                 mMonitor.getState());
115 
116         ActionMonitor.registerActionMonitor(mAction.actionKey, mMonitor);
117         assertTrue(ActionMonitor.sActionMonitors.containsKey(mAction.actionKey));
118         assertTrue(ActionMonitor.sActionMonitors.containsValue(mMonitor));
119         assertEquals(ActionMonitor.sActionMonitors.get(mAction.actionKey), mMonitor);
120 
121         mAction.markStart();
122 
123         verifyState(1, ActionMonitor.STATE_CREATED, ActionMonitor.STATE_QUEUED);
124 
125         mAction.markBeginExecute();
126 
127         verifyState(2, ActionMonitor.STATE_QUEUED, ActionMonitor.STATE_EXECUTING);
128 
129         final Object result = mAction.executeAction();
130         mAction.requestBackgroundWork();
131 
132         assertEquals("Check executeAction result", result, executeActionResult);
133 
134         mAction.markEndExecute(result);
135 
136         verifyState(3, ActionMonitor.STATE_EXECUTING,
137                 ActionMonitor.STATE_BACKGROUND_ACTIONS_QUEUED);
138 
139         mAction.markBackgroundWorkStarting();
140 
141         verifyState(4, ActionMonitor.STATE_BACKGROUND_ACTIONS_QUEUED,
142                 ActionMonitor.STATE_EXECUTING_BACKGROUND_ACTION);
143 
144         mAction.markBackgroundWorkQueued();
145 
146         verifyState(5, ActionMonitor.STATE_EXECUTING_BACKGROUND_ACTION,
147                 ActionMonitor.STATE_BACKGROUND_ACTIONS_QUEUED);
148 
149         mAction.markBackgroundWorkStarting();
150 
151         verifyState(6, ActionMonitor.STATE_BACKGROUND_ACTIONS_QUEUED,
152                 ActionMonitor.STATE_EXECUTING_BACKGROUND_ACTION);
153 
154         final Bundle response = null;
155 
156         mAction.markBackgroundCompletionQueued();
157 
158         verifyState(7, ActionMonitor.STATE_EXECUTING_BACKGROUND_ACTION,
159                 ActionMonitor.STATE_BACKGROUND_COMPLETION_QUEUED);
160 
161         assertTrue(ActionMonitor.sActionMonitors.containsKey(mAction.actionKey));
162         assertTrue(ActionMonitor.sActionMonitors.containsValue(mMonitor));
163         assertEquals(ActionMonitor.sActionMonitors.get(mAction.actionKey), mMonitor);
164 
165         mAction.processBackgroundWorkResponse(response);
166 
167         verifyTransition(7, ActionMonitor.STATE_BACKGROUND_COMPLETION_QUEUED,
168                 ActionMonitor.STATE_PROCESSING_BACKGROUND_RESPONSE);
169 
170         verifyState(9, ActionMonitor.STATE_PROCESSING_BACKGROUND_RESPONSE,
171                 ActionMonitor.STATE_COMPLETE);
172 
173         assertFalse(ActionMonitor.sActionMonitors.containsKey(mAction.actionKey));
174         assertFalse(ActionMonitor.sActionMonitors.containsValue(mMonitor));
175     }
176 
testActionTransitionsEndToEndFailsRequests()177     public void testActionTransitionsEndToEndFailsRequests() {
178         assertEquals("Start state: STATE_CREATED", ActionMonitor.STATE_CREATED,
179                 mMonitor.getState());
180 
181         ActionMonitor.registerActionMonitor(mAction.actionKey, mMonitor);
182         assertTrue(ActionMonitor.sActionMonitors.containsKey(mAction.actionKey));
183         assertTrue(ActionMonitor.sActionMonitors.containsValue(mMonitor));
184         assertEquals(ActionMonitor.sActionMonitors.get(mAction.actionKey), mMonitor);
185 
186         mAction.markStart();
187 
188         verifyState(1, ActionMonitor.STATE_CREATED, ActionMonitor.STATE_QUEUED);
189 
190         mAction.markBeginExecute();
191 
192         verifyState(2, ActionMonitor.STATE_QUEUED, ActionMonitor.STATE_EXECUTING);
193 
194         final Object result = mAction.executeAction();
195         mAction.requestBackgroundWork();
196 
197         assertEquals("Check executeAction result", result, executeActionResult);
198 
199         mAction.markEndExecute(result);
200 
201         verifyState(3, ActionMonitor.STATE_EXECUTING,
202                 ActionMonitor.STATE_BACKGROUND_ACTIONS_QUEUED);
203 
204         mAction.markBackgroundWorkStarting();
205 
206         verifyState(4, ActionMonitor.STATE_BACKGROUND_ACTIONS_QUEUED,
207                 ActionMonitor.STATE_EXECUTING_BACKGROUND_ACTION);
208 
209         mAction.markBackgroundWorkQueued();
210 
211         verifyState(5, ActionMonitor.STATE_EXECUTING_BACKGROUND_ACTION,
212                 ActionMonitor.STATE_BACKGROUND_ACTIONS_QUEUED);
213 
214         mAction.markBackgroundWorkStarting();
215 
216         verifyState(6, ActionMonitor.STATE_BACKGROUND_ACTIONS_QUEUED,
217                 ActionMonitor.STATE_EXECUTING_BACKGROUND_ACTION);
218 
219         assertTrue(ActionMonitor.sActionMonitors.containsKey(mAction.actionKey));
220         assertTrue(ActionMonitor.sActionMonitors.containsValue(mMonitor));
221         assertEquals(ActionMonitor.sActionMonitors.get(mAction.actionKey), mMonitor);
222 
223         mAction.processBackgroundWorkFailure();
224 
225         verifyState(7, ActionMonitor.STATE_EXECUTING_BACKGROUND_ACTION,
226                 ActionMonitor.STATE_COMPLETE);
227 
228         assertFalse(ActionMonitor.sActionMonitors.containsKey(mAction.actionKey));
229         assertFalse(ActionMonitor.sActionMonitors.containsValue(mMonitor));
230     }
231 
testActionTransitionsEndToEndNoRequests()232     public void testActionTransitionsEndToEndNoRequests() {
233         assertEquals("Start state: STATE_CREATED", ActionMonitor.STATE_CREATED,
234                 mMonitor.getState());
235 
236         ActionMonitor.registerActionMonitor(mAction.actionKey, mMonitor);
237         assertTrue(ActionMonitor.sActionMonitors.containsKey(mAction.actionKey));
238         assertTrue(ActionMonitor.sActionMonitors.containsValue(mMonitor));
239         assertEquals(ActionMonitor.sActionMonitors.get(mAction.actionKey), mMonitor);
240 
241         mAction.markStart();
242 
243         verifyState(1, ActionMonitor.STATE_CREATED, ActionMonitor.STATE_QUEUED);
244 
245         mAction.markBeginExecute();
246 
247         verifyState(2, ActionMonitor.STATE_QUEUED, ActionMonitor.STATE_EXECUTING);
248 
249         final Object result = mAction.executeAction();
250 
251         assertEquals("Check executeAction result", result, executeActionResult);
252 
253         assertTrue(ActionMonitor.sActionMonitors.containsKey(mAction.actionKey));
254         assertTrue(ActionMonitor.sActionMonitors.containsValue(mMonitor));
255         assertEquals(ActionMonitor.sActionMonitors.get(mAction.actionKey), mMonitor);
256 
257         mAction.markEndExecute(result);
258 
259         verifyState(3, ActionMonitor.STATE_EXECUTING,
260                 ActionMonitor.STATE_COMPLETE);
261 
262         assertFalse(ActionMonitor.sActionMonitors.containsKey(mAction.actionKey));
263         assertFalse(ActionMonitor.sActionMonitors.containsValue(mMonitor));
264     }
265 
266     public static class TestChatAction extends Action implements Parcelable {
TestChatAction(final String key, final String parameter)267         protected TestChatAction(final String key, final String parameter) {
268             super(key);
269             this.parameter = parameter;
270         }
271 
272         public final String parameter;
273 
274         /**
275          * Process the action locally - runs on service thread
276          */
277         @Override
executeAction()278         protected Object executeAction() {
279             assertEquals("Check parameter", parameter, ActionTest.parameter);
280             return executeActionResult;
281         }
282 
283         /**
284          * Process the response from the server - runs on service thread
285          */
286         @Override
processBackgroundResponse(final Bundle response)287         protected Object processBackgroundResponse(final Bundle response) {
288             assertEquals("Check parameter", parameter, ActionTest.parameter);
289             return processResponseResult;
290         }
291 
292         /**
293          * Called in case of failures when sending requests - runs on service thread
294          */
295         @Override
processBackgroundFailure()296         protected Object processBackgroundFailure() {
297             assertEquals("Check parameter", parameter, ActionTest.parameter);
298             return processFailureResult;
299         }
300 
TestChatAction(final Parcel in)301         private TestChatAction(final Parcel in) {
302             super(in);
303             parameter = in.readString();
304         }
305 
306         public static final Parcelable.Creator<TestChatAction> CREATOR
307                 = new Parcelable.Creator<TestChatAction>() {
308             @Override
309             public TestChatAction createFromParcel(final Parcel in) {
310                 return new TestChatAction(in);
311             }
312 
313             @Override
314             public TestChatAction[] newArray(final int size) {
315                 return new TestChatAction[size];
316             }
317         };
318 
319         @Override
writeToParcel(final Parcel parcel, final int flags)320         public void writeToParcel(final Parcel parcel, final int flags) {
321             writeActionToParcel(parcel, flags);
322             parcel.writeString(parameter);
323         }
324     }
325 }
326