Home | History | Annotate | Download | only in action
      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
     50         BugleTestCase.setTestsRunning();
     51     }
     52 
     53     @Override
     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
     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
     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 
     86     public ActionServiceSystemTest() {
     87         super(ActionServiceImpl.class);
     88     }
     89 
     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 
    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 
    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 
    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
    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
    306     public String getServiceClassName() {
    307         return ActionServiceImpl.class.getName();
    308     }
    309 
    310     @Override
    311     public void startServiceForStub(final Intent intent) {
    312         this.startService(intent);
    313     }
    314 
    315     @Override
    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 
    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
    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
    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
    356         protected Object processBackgroundFailure() {
    357             return processFailureResult;
    358         }
    359 
    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
    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 {
    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 
    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
    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          */
    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