PorcessPendingMessagesAction queues one message for sending/downloading associated with a subscription triggering current action at a time. And the ConnectivityUtil also works based on subscriptions so that pending messages can be processed regardless of other phones' state in multi-sim case. It includes cleanup code as well. Test: Manual Change-Id: Id6b4f4a0aa6a3291e7a4d8a5d3f0fbb9db3c5b86 Signed-off-by: Taesu Lee <taesu82.lee@samsung.com>
431 lines
17 KiB
Java
431 lines
17 KiB
Java
/*
|
|
* Copyright (C) 2015 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package com.android.messaging.datamodel.action;
|
|
|
|
import android.content.Intent;
|
|
import android.os.Bundle;
|
|
import android.os.Parcel;
|
|
import android.os.Parcelable;
|
|
import android.test.suitebuilder.annotation.MediumTest;
|
|
import android.util.Log;
|
|
|
|
import com.android.messaging.BugleTestCase;
|
|
import com.android.messaging.Factory;
|
|
import com.android.messaging.FakeContext;
|
|
import com.android.messaging.FakeContext.FakeContextHost;
|
|
import com.android.messaging.FakeFactory;
|
|
import com.android.messaging.datamodel.BugleServiceTestCase;
|
|
import com.android.messaging.datamodel.DataModel;
|
|
import com.android.messaging.datamodel.FakeDataModel;
|
|
import com.android.messaging.datamodel.action.ActionMonitor.ActionCompletedListener;
|
|
import com.android.messaging.datamodel.action.ActionMonitor.ActionExecutedListener;
|
|
import com.android.messaging.datamodel.action.ActionTestHelpers.ResultTracker;
|
|
import com.android.messaging.datamodel.action.ActionTestHelpers.StubBackgroundWorker;
|
|
import com.android.messaging.datamodel.action.ActionTestHelpers.StubLoader;
|
|
|
|
import java.util.ArrayList;
|
|
|
|
@MediumTest
|
|
public class ActionServiceSystemTest extends BugleServiceTestCase<ActionServiceImpl>
|
|
implements ActionCompletedListener, ActionExecutedListener, FakeContextHost {
|
|
private static final String TAG = "ActionServiceSystemTest";
|
|
|
|
static {
|
|
// Set flag during loading of test cases to prevent application initialization starting
|
|
BugleTestCase.setTestsRunning();
|
|
}
|
|
|
|
@Override
|
|
public void onActionSucceeded(final ActionMonitor monitor,
|
|
final Action action, final Object data, final Object result) {
|
|
final TestChatAction test = (TestChatAction) action;
|
|
assertEquals("Expect correct action parameter", parameter, test.parameter);
|
|
final ResultTracker tracker = (ResultTracker) data;
|
|
tracker.completionResult = result;
|
|
synchronized(tracker) {
|
|
tracker.notifyAll();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onActionFailed(final ActionMonitor monitor, final Action action,
|
|
final Object data, final Object result) {
|
|
final TestChatAction test = (TestChatAction) action;
|
|
assertEquals("Expect correct action parameter", parameter, test.parameter);
|
|
final ResultTracker tracker = (ResultTracker) data;
|
|
tracker.completionResult = result;
|
|
synchronized(tracker) {
|
|
tracker.notifyAll();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void onActionExecuted(final ActionMonitor monitor, final Action action,
|
|
final Object data, final Object result) {
|
|
final TestChatAction test = (TestChatAction) action;
|
|
assertEquals("Expect correct action parameter", parameter, test.parameter);
|
|
final ResultTracker tracker = (ResultTracker) data;
|
|
tracker.executionResult = result;
|
|
}
|
|
|
|
public ActionServiceSystemTest() {
|
|
super(ActionServiceImpl.class);
|
|
}
|
|
|
|
public void testChatActionSucceeds() {
|
|
final ResultTracker tracker = new ResultTracker();
|
|
|
|
final ActionService service = DataModel.get().getActionService();
|
|
final TestChatActionMonitor monitor = new TestChatActionMonitor(null, tracker, this, this);
|
|
final TestChatAction initial = new TestChatAction(monitor.getActionKey(), parameter);
|
|
|
|
assertNull("Expect completion result to start null", tracker.completionResult);
|
|
assertNull("Expect execution result to start null", tracker.executionResult);
|
|
|
|
final Parcel parcel = Parcel.obtain();
|
|
parcel.writeParcelable(initial, 0);
|
|
parcel.setDataPosition(0);
|
|
final TestChatAction action = parcel.readParcelable(mContext.getClassLoader());
|
|
|
|
synchronized(mWorker) {
|
|
try {
|
|
action.start(monitor);
|
|
// Wait for callback across threads
|
|
mWorker.wait(2000);
|
|
} catch (final InterruptedException e) {
|
|
assertTrue("Interrupted waiting for execution", false);
|
|
}
|
|
}
|
|
|
|
assertEquals("Expect to see 1 server request queued", 1,
|
|
mWorker.getRequestsMade().size());
|
|
final Action request = mWorker.getRequestsMade().get(0);
|
|
assertTrue("Expect Test type", request instanceof TestChatAction);
|
|
|
|
final Bundle response = new Bundle();
|
|
response.putString(TestChatAction.RESPONSE_TEST, processResponseResult);
|
|
synchronized(tracker) {
|
|
try {
|
|
request.markBackgroundWorkStarting();
|
|
request.markBackgroundWorkQueued();
|
|
|
|
request.markBackgroundWorkStarting();
|
|
request.markBackgroundCompletionQueued();
|
|
service.handleResponseFromBackgroundWorker(request, response);
|
|
// Wait for callback across threads
|
|
tracker.wait(2000);
|
|
} catch (final InterruptedException e) {
|
|
assertTrue("Interrupted waiting for response processing", false);
|
|
}
|
|
}
|
|
|
|
// TODO
|
|
//assertEquals("Expect execution result set", executeActionResult, tracker.executionResult);
|
|
assertEquals("Expect completion result set", processResponseResult,
|
|
tracker.completionResult);
|
|
}
|
|
|
|
public void testChatActionFails() {
|
|
final ResultTracker tracker = new ResultTracker();
|
|
|
|
final ActionService service = DataModel.get().getActionService();
|
|
final TestChatActionMonitor monitor = new TestChatActionMonitor(null, tracker, this, this);
|
|
final TestChatAction action = new TestChatAction(monitor.getActionKey(), parameter);
|
|
|
|
assertNull("Expect completion result to start null", tracker.completionResult);
|
|
assertNull("Expect execution result to start null", tracker.executionResult);
|
|
|
|
synchronized(mWorker) {
|
|
try {
|
|
action.start(monitor);
|
|
// Wait for callback across threads
|
|
mWorker.wait(2000);
|
|
} catch (final InterruptedException e) {
|
|
assertTrue("Interrupted waiting for requests", false);
|
|
}
|
|
}
|
|
|
|
assertEquals("Expect to see 1 server request queued", 1,
|
|
mWorker.getRequestsMade().size());
|
|
final Action request = mWorker.getRequestsMade().get(0);
|
|
assertTrue("Expect Test type", request instanceof TestChatAction);
|
|
|
|
synchronized(tracker) {
|
|
try {
|
|
request.markBackgroundWorkStarting();
|
|
request.markBackgroundWorkQueued();
|
|
|
|
request.markBackgroundWorkStarting();
|
|
request.markBackgroundCompletionQueued();
|
|
service.handleFailureFromBackgroundWorker(request, new Exception("It went wrong"));
|
|
// Wait for callback across threads
|
|
tracker.wait(2000);
|
|
} catch (final InterruptedException e) {
|
|
assertTrue("Interrupted waiting for response processing", false);
|
|
}
|
|
}
|
|
|
|
// TODO
|
|
//assertEquals("Expect execution result set", executeActionResult, tracker.executionResult);
|
|
assertEquals("Expect completion result set", processFailureResult,
|
|
tracker.completionResult);
|
|
}
|
|
|
|
public void testChatActionNoMonitor() {
|
|
final ActionService service = DataModel.get().getActionService();
|
|
final TestChatAction action =
|
|
new TestChatAction(Action.generateUniqueActionKey(null), parameter);
|
|
|
|
synchronized(mWorker) {
|
|
try {
|
|
action.start();
|
|
// Wait for callback across threads
|
|
mWorker.wait(2000);
|
|
} catch (final InterruptedException e) {
|
|
assertTrue("Interrupted waiting for execution", false);
|
|
}
|
|
}
|
|
|
|
assertEquals("Expect to see 1 server request queued", 1,
|
|
mWorker.getRequestsMade().size());
|
|
Action request = mWorker.getRequestsMade().get(0);
|
|
assertTrue("Expect Test type", request instanceof TestChatAction);
|
|
|
|
final Bundle response = new Bundle();
|
|
response.putString(TestChatAction.RESPONSE_TEST, processResponseResult);
|
|
synchronized(mWorker) {
|
|
try {
|
|
service.handleResponseFromBackgroundWorker(request, response);
|
|
// Wait for callback across threads
|
|
mWorker.wait(2000);
|
|
} catch (final InterruptedException e) {
|
|
assertTrue("Interrupted waiting for response processing", false);
|
|
}
|
|
}
|
|
|
|
assertEquals("Expect to see second server request queued",
|
|
2, mWorker.getRequestsMade().size());
|
|
request = mWorker.getRequestsMade().get(1);
|
|
assertTrue("Expect other type",
|
|
request instanceof TestChatActionOther);
|
|
}
|
|
|
|
public void testChatActionUnregisterListener() {
|
|
final ResultTracker tracker = new ResultTracker();
|
|
|
|
final ActionService service = DataModel.get().getActionService();
|
|
final TestChatActionMonitor monitor = new TestChatActionMonitor(null, tracker, this, this);
|
|
final TestChatAction action = new TestChatAction(monitor.getActionKey(), parameter);
|
|
|
|
assertNull("Expect completion result to start null", tracker.completionResult);
|
|
assertNull("Expect execution result to start null", tracker.executionResult);
|
|
|
|
synchronized(mWorker) {
|
|
try {
|
|
action.start(monitor);
|
|
// Wait for callback across threads
|
|
mWorker.wait(2000);
|
|
} catch (final InterruptedException e) {
|
|
assertTrue("Interrupted waiting for execution", false);
|
|
}
|
|
}
|
|
|
|
assertEquals("Expect to see 1 server request queued", 1,
|
|
mWorker.getRequestsMade().size());
|
|
final Action request = mWorker.getRequestsMade().get(0);
|
|
assertTrue("Expect Test type", request instanceof TestChatAction);
|
|
|
|
monitor.unregister();
|
|
|
|
final Bundle response = new Bundle();
|
|
synchronized(mWorker) {
|
|
try {
|
|
request.markBackgroundWorkStarting();
|
|
request.markBackgroundWorkQueued();
|
|
|
|
request.markBackgroundWorkStarting();
|
|
request.markBackgroundCompletionQueued();
|
|
service.handleResponseFromBackgroundWorker(request, response);
|
|
// Wait for callback across threads
|
|
mWorker.wait(2000);
|
|
} catch (final InterruptedException e) {
|
|
assertTrue("Interrupted waiting for response processing", false);
|
|
}
|
|
}
|
|
|
|
//assertEquals("Expect execution result set", executeActionResult, tracker.executionResult);
|
|
assertEquals("Expect completion never called", null, tracker.completionResult);
|
|
}
|
|
|
|
StubBackgroundWorker mWorker;
|
|
FakeContext mContext;
|
|
StubLoader mLoader;
|
|
|
|
private static final String parameter = "parameter";
|
|
private static final Object executeActionResult = "executeActionResult";
|
|
private static final String processResponseResult = "processResponseResult";
|
|
private static final Object processFailureResult = "processFailureResult";
|
|
|
|
@Override
|
|
public void setUp() throws Exception {
|
|
super.setUp();
|
|
Log.d(TAG, "ChatActionTest setUp");
|
|
|
|
mContext = new FakeContext(getContext(), this);
|
|
mWorker = new StubBackgroundWorker();
|
|
FakeFactory.registerWithFakeContext(getContext(), mContext)
|
|
.withDataModel(new FakeDataModel(mContext)
|
|
.withBackgroundWorkerForActionService(mWorker)
|
|
.withActionService(new ActionService()));
|
|
|
|
mLoader = new StubLoader();
|
|
setContext(Factory.get().getApplicationContext());
|
|
}
|
|
|
|
@Override
|
|
public String getServiceClassName() {
|
|
return ActionServiceImpl.class.getName();
|
|
}
|
|
|
|
@Override
|
|
public void startServiceForStub(final Intent intent) {
|
|
this.startService(intent);
|
|
}
|
|
|
|
@Override
|
|
public void onStartCommandForStub(final Intent intent, final int flags, final int startId) {
|
|
this.getService().onStartCommand(intent, flags, startId);
|
|
}
|
|
|
|
public static class TestChatAction extends Action implements Parcelable {
|
|
public static String RESPONSE_TEST = "response_test";
|
|
public static String KEY_PARAMETER = "parameter";
|
|
|
|
protected TestChatAction(final String key, final String parameter) {
|
|
super(key);
|
|
this.actionParameters.putString(KEY_PARAMETER, parameter);
|
|
// Cache parameter as a member variable
|
|
this.parameter = parameter;
|
|
}
|
|
|
|
// An example parameter
|
|
public final String parameter;
|
|
|
|
/**
|
|
* Process the action locally - runs on datamodel service thread
|
|
*/
|
|
@Override
|
|
protected Object executeAction() {
|
|
requestBackgroundWork();
|
|
return executeActionResult;
|
|
}
|
|
|
|
/**
|
|
* Process the response from the server - runs on datamodel service thread
|
|
*/
|
|
@Override
|
|
protected Object processBackgroundResponse(final Bundle response) {
|
|
requestBackgroundWork(new TestChatActionOther(null, parameter));
|
|
return response.get(RESPONSE_TEST);
|
|
}
|
|
|
|
/**
|
|
* Called in case of failures when sending requests - runs on datamodel service thread
|
|
*/
|
|
@Override
|
|
protected Object processBackgroundFailure() {
|
|
return processFailureResult;
|
|
}
|
|
|
|
private TestChatAction(final Parcel in) {
|
|
super(in);
|
|
// Cache parameter as a member variable
|
|
parameter = actionParameters.getString(KEY_PARAMETER);
|
|
}
|
|
|
|
public static final Parcelable.Creator<TestChatAction> CREATOR
|
|
= new Parcelable.Creator<TestChatAction>() {
|
|
@Override
|
|
public TestChatAction createFromParcel(final Parcel in) {
|
|
return new TestChatAction(in);
|
|
}
|
|
|
|
@Override
|
|
public TestChatAction[] newArray(final int size) {
|
|
return new TestChatAction[size];
|
|
}
|
|
};
|
|
|
|
@Override
|
|
public void writeToParcel(final Parcel parcel, final int flags) {
|
|
writeActionToParcel(parcel, flags);
|
|
}
|
|
}
|
|
|
|
public static class TestChatActionOther extends Action implements Parcelable {
|
|
protected TestChatActionOther(final String key, final String parameter) {
|
|
super(generateUniqueActionKey(key));
|
|
this.parameter = parameter;
|
|
}
|
|
|
|
public final String parameter;
|
|
|
|
private TestChatActionOther(final Parcel in) {
|
|
super(in);
|
|
parameter = in.readString();
|
|
}
|
|
|
|
public static final Parcelable.Creator<TestChatActionOther> CREATOR
|
|
= new Parcelable.Creator<TestChatActionOther>() {
|
|
@Override
|
|
public TestChatActionOther createFromParcel(final Parcel in) {
|
|
return new TestChatActionOther(in);
|
|
}
|
|
|
|
@Override
|
|
public TestChatActionOther[] newArray(final int size) {
|
|
return new TestChatActionOther[size];
|
|
}
|
|
};
|
|
|
|
@Override
|
|
public void writeToParcel(final Parcel parcel, final int flags) {
|
|
writeActionToParcel(parcel, flags);
|
|
parcel.writeString(parameter);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* An operation that notifies a listener upon completion
|
|
*/
|
|
public static class TestChatActionMonitor extends ActionMonitor {
|
|
/**
|
|
* Create action state wrapping an BlockUserAction instance
|
|
* @param account - account in which to block the user
|
|
* @param baseKey - suggested action key from BlockUserAction
|
|
* @param data - optional action specific data that is handed back to listener
|
|
* @param listener - action completed listener
|
|
*/
|
|
public TestChatActionMonitor(final String baseKey, final Object data,
|
|
final ActionCompletedListener completed, final ActionExecutedListener executed) {
|
|
super(STATE_CREATED, Action.generateUniqueActionKey(baseKey), data);
|
|
setCompletedListener(completed);
|
|
setExecutedListener(executed);
|
|
}
|
|
}
|
|
}
|