DO NOT MERGE - Moar Autofill CTS improvements:
- Created a MultipleExceptionsCatcher used to throw multiple exceptions.
- Ignore fillRequests() when the service is not enabled.
- Created a custom ActivityTestRule that cleans up autofill state before
starting the activity.
- Moved some helpers from AutoFillServiceTestCase to Helper.
Test: CtsAutoFillServiceTestCases pass
Test: AutoFinishSessionTest doesn't fail anymore when started after a previous failed test
Bug: 37566627
Fixes: 62717612
Change-Id: Ia6016267b07dfeaf1fc5e349dfa7f12e31f1f27b
Merged-In: Ia6016267b07dfeaf1fc5e349dfa7f12e31f1f27b
(cherry picked from commit b8b8363684c8a2d5ad02c7e36bd6bba6e6dc2f00)
diff --git a/tests/autofillservice/Android.mk b/tests/autofillservice/Android.mk
index f4437f7..27a8cb5 100644
--- a/tests/autofillservice/Android.mk
+++ b/tests/autofillservice/Android.mk
@@ -23,6 +23,7 @@
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
LOCAL_STATIC_JAVA_LIBRARIES := \
+ android-support-annotations \
compatibility-device-util \
ctstestrunner \
truth-prebuilt \
diff --git a/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.java b/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.java
index 15d1052..209b043 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.java
@@ -16,16 +16,17 @@
package android.autofillservice.cts;
+import static android.autofillservice.cts.Helper.getContext;
import static android.autofillservice.cts.Helper.getLoggingLevel;
import static android.autofillservice.cts.Helper.hasAutofillFeature;
import static android.autofillservice.cts.Helper.runShellCommand;
import static android.autofillservice.cts.Helper.setLoggingLevel;
+import static android.autofillservice.cts.InstrumentedAutoFillService.SERVICE_NAME;
import static android.provider.Settings.Secure.AUTOFILL_SERVICE;
import static com.google.common.truth.Truth.assertWithMessage;
import android.autofillservice.cts.InstrumentedAutoFillService.Replier;
-import android.content.Context;
import android.content.pm.PackageManager;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
@@ -39,6 +40,8 @@
import org.junit.Rule;
import org.junit.runner.RunWith;
+import java.util.List;
+
/**
* Base class for all other tests.
*/
@@ -46,10 +49,6 @@
abstract class AutoFillServiceTestCase {
private static final String TAG = "AutoFillServiceTestCase";
- private static final String SERVICE_NAME =
- InstrumentedAutoFillService.class.getPackage().getName()
- + "/." + InstrumentedAutoFillService.class.getSimpleName();
-
protected static UiBot sUiBot;
protected static final Replier sReplier = InstrumentedAutoFillService.getReplier();
@@ -82,30 +81,16 @@
@AfterClass
public static void resetSettings() {
- runShellCommand("settings delete secure %s", AUTOFILL_SERVICE);
- }
-
- @Before
- public void disableService() {
if (!hasAutofillFeature()) return;
- if (!isServiceEnabled()) return;
-
- final OneTimeSettingsListener observer = new OneTimeSettingsListener(getContext(),
- AUTOFILL_SERVICE);
+ // Clean up only - no need to call disableService() because it doesn't need to fail if
+ // it's not reset.
runShellCommand("settings delete secure %s", AUTOFILL_SERVICE);
- observer.assertCalled();
- assertServiceDisabled();
-
- InstrumentedAutoFillService.setIgnoreUnexpectedRequests(false);
}
@Before
public void reset() {
- destroyAllSessions();
sReplier.reset();
- InstrumentedAutoFillService.resetStaticState();
- AuthenticationActivity.resetStaticState();
}
@Before
@@ -136,9 +121,18 @@
// exceptions would mask the real cause. A better approach might be using a @Rule or some other
// visitor pattern.
@After
- public void assertNoPendingRequests() {
- sReplier.assertNumberUnhandledFillRequests(0);
- sReplier.assertNumberUnhandledSaveRequests(0);
+ public void assertNothingIsPending() throws Exception {
+ final MultipleExceptionsCatcher catcher = new MultipleExceptionsCatcher()
+ .run(() -> sReplier.assertNumberUnhandledFillRequests(0))
+ .run(() -> sReplier.assertNumberUnhandledSaveRequests(0));
+
+ final List<Exception> replierExceptions = sReplier.getExceptions();
+ if (replierExceptions != null) {
+ for (Exception e : replierExceptions) {
+ catcher.add(e);
+ }
+ }
+ catcher.throwIfAny();
}
@After
@@ -150,13 +144,18 @@
* Enables the {@link InstrumentedAutoFillService} for autofill for the current user.
*/
protected void enableService() {
- if (isServiceEnabled()) return;
+ Helper.enableAutofillService(getContext(), SERVICE_NAME);
+ InstrumentedAutoFillService.setIgnoreUnexpectedRequests(false);
+ }
- final OneTimeSettingsListener observer = new OneTimeSettingsListener(getContext(),
- AUTOFILL_SERVICE);
- runShellCommand("settings put secure %s %s default", AUTOFILL_SERVICE, SERVICE_NAME);
- observer.assertCalled();
- assertServiceEnabled();
+ /**
+ * Disables the {@link InstrumentedAutoFillService} for autofill for the current user.
+ */
+ protected void disableService() {
+ if (!hasAutofillFeature()) return;
+
+ Helper.disableAutofillService(getContext(), SERVICE_NAME);
+ InstrumentedAutoFillService.setIgnoreUnexpectedRequests(true);
}
/**
@@ -182,19 +181,7 @@
assertWithMessage("Dangling sessions ('%s'): %s'", command, result).that(result).isEmpty();
}
- /**
- * Destroys all sessions.
- */
- protected void destroyAllSessions() {
- runShellCommand("cmd autofill destroy sessions");
- assertNoDanglingSessions();
- }
-
- protected static Context getContext() {
- return InstrumentationRegistry.getInstrumentation().getContext();
- }
-
- protected static RemoteViews createPresentation(String message) {
+ protected RemoteViews createPresentation(String message) {
final RemoteViews presentation = new RemoteViews(getContext()
.getPackageName(), R.layout.list_item);
presentation.setTextViewText(R.id.text1, message);
diff --git a/tests/autofillservice/src/android/autofillservice/cts/AutoFinishSessionTest.java b/tests/autofillservice/src/android/autofillservice/cts/AutoFinishSessionTest.java
index ab1c0ea..b966078 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/AutoFinishSessionTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/AutoFinishSessionTest.java
@@ -18,6 +18,7 @@
import static android.autofillservice.cts.FragmentContainerActivity.FRAGMENT_TAG;
import static android.autofillservice.cts.Helper.findNodeByResourceId;
+import static android.autofillservice.cts.Helper.getContext;
import static android.service.autofill.SaveInfo.SAVE_DATA_TYPE_GENERIC;
import static com.google.common.truth.Truth.assertThat;
@@ -28,7 +29,6 @@
import android.service.autofill.SaveInfo;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
-import android.support.test.rule.ActivityTestRule;
import android.view.ViewGroup;
import android.widget.EditText;
@@ -41,8 +41,8 @@
*/
public class AutoFinishSessionTest extends AutoFillServiceTestCase {
@Rule
- public final ActivityTestRule<FragmentContainerActivity> mActivityRule =
- new ActivityTestRule<>(FragmentContainerActivity.class);
+ public final AutofillActivityTestRule<FragmentContainerActivity> mActivityRule =
+ new AutofillActivityTestRule<>(FragmentContainerActivity.class);
private FragmentContainerActivity mActivity;
private EditText mEditText1;
private EditText mEditText2;
diff --git a/tests/autofillservice/src/android/autofillservice/cts/AutofillActivityTestRule.java b/tests/autofillservice/src/android/autofillservice/cts/AutofillActivityTestRule.java
new file mode 100644
index 0000000..7cf3c64
--- /dev/null
+++ b/tests/autofillservice/src/android/autofillservice/cts/AutofillActivityTestRule.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2017 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 android.autofillservice.cts;
+
+import android.app.Activity;
+import android.support.test.rule.ActivityTestRule;
+
+/**
+ * Custom {@link ActivityTestRule} that cleans up the autofill state before the activity is
+ * launched.
+ */
+public class AutofillActivityTestRule<T extends Activity> extends ActivityTestRule<T> {
+
+ public AutofillActivityTestRule(Class<T> activityClass) {
+ super(activityClass);
+ }
+
+ @Override
+ protected void beforeActivityLaunched() {
+ Helper.preTestCleanup();
+
+ super.beforeActivityLaunched();
+ }
+}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/AutofillValueTest.java b/tests/autofillservice/src/android/autofillservice/cts/AutofillValueTest.java
index 0ed3c86..ff18003 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/AutofillValueTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/AutofillValueTest.java
@@ -26,7 +26,6 @@
import android.icu.util.Calendar;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
-import android.support.test.rule.ActivityTestRule;
import android.view.View;
import android.view.autofill.AutofillValue;
import android.widget.CompoundButton;
@@ -57,8 +56,8 @@
*/
public class AutofillValueTest extends AutoFillServiceTestCase {
@Rule
- public final ActivityTestRule<AllAutofillableViewsActivity> mActivityRule =
- new ActivityTestRule<>(AllAutofillableViewsActivity.class);
+ public final AutofillActivityTestRule<AllAutofillableViewsActivity> mActivityRule =
+ new AutofillActivityTestRule<>(AllAutofillableViewsActivity.class);
private AllAutofillableViewsActivity mActivity;
private EditText mEditText;
diff --git a/tests/autofillservice/src/android/autofillservice/cts/CheckoutActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/CheckoutActivityTest.java
index c3809a0..6ba5431 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/CheckoutActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/CheckoutActivityTest.java
@@ -31,6 +31,7 @@
import static android.autofillservice.cts.Helper.assertToggleIsSanitized;
import static android.autofillservice.cts.Helper.assertToggleValue;
import static android.autofillservice.cts.Helper.findNodeByResourceId;
+import static android.autofillservice.cts.Helper.getContext;
import static android.service.autofill.SaveInfo.SAVE_DATA_TYPE_CREDIT_CARD;
import static android.view.View.AUTOFILL_TYPE_LIST;
@@ -41,7 +42,6 @@
import android.autofillservice.cts.CannedFillResponse.CannedDataset;
import android.autofillservice.cts.InstrumentedAutoFillService.FillRequest;
import android.autofillservice.cts.InstrumentedAutoFillService.SaveRequest;
-import android.support.test.rule.ActivityTestRule;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
@@ -58,8 +58,8 @@
public class CheckoutActivityTest extends AutoFillServiceTestCase {
@Rule
- public final ActivityTestRule<CheckoutActivity> mActivityRule =
- new ActivityTestRule<CheckoutActivity>(CheckoutActivity.class);
+ public final AutofillActivityTestRule<CheckoutActivity> mActivityRule =
+ new AutofillActivityTestRule<CheckoutActivity>(CheckoutActivity.class);
private CheckoutActivity mActivity;
diff --git a/tests/autofillservice/src/android/autofillservice/cts/DatePickerCalendarActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/DatePickerCalendarActivityTest.java
index a51a00c..40c11d3 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/DatePickerCalendarActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/DatePickerCalendarActivityTest.java
@@ -15,15 +15,13 @@
*/
package android.autofillservice.cts;
-import android.support.test.rule.ActivityTestRule;
-
import org.junit.Rule;
public class DatePickerCalendarActivityTest extends DatePickerTestCase<DatePickerCalendarActivity> {
@Rule
- public final ActivityTestRule<DatePickerCalendarActivity> mActivityRule =
- new ActivityTestRule<DatePickerCalendarActivity>(DatePickerCalendarActivity.class);
+ public final AutofillActivityTestRule<DatePickerCalendarActivity> mActivityRule =
+ new AutofillActivityTestRule<DatePickerCalendarActivity>(DatePickerCalendarActivity.class);
@Override
protected DatePickerCalendarActivity getDatePickerActivity() {
diff --git a/tests/autofillservice/src/android/autofillservice/cts/DatePickerSpinnerActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/DatePickerSpinnerActivityTest.java
index 10851cd..0497f87 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/DatePickerSpinnerActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/DatePickerSpinnerActivityTest.java
@@ -15,15 +15,13 @@
*/
package android.autofillservice.cts;
-import android.support.test.rule.ActivityTestRule;
-
import org.junit.Rule;
public class DatePickerSpinnerActivityTest extends DatePickerTestCase<DatePickerSpinnerActivity> {
@Rule
- public final ActivityTestRule<DatePickerSpinnerActivity> mActivityRule =
- new ActivityTestRule<DatePickerSpinnerActivity>(DatePickerSpinnerActivity.class);
+ public final AutofillActivityTestRule<DatePickerSpinnerActivity> mActivityRule =
+ new AutofillActivityTestRule<DatePickerSpinnerActivity>(DatePickerSpinnerActivity.class);
@Override
protected DatePickerSpinnerActivity getDatePickerActivity() {
diff --git a/tests/autofillservice/src/android/autofillservice/cts/FatActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/FatActivityTest.java
index a2edf4d..b2dd1d4 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/FatActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/FatActivityTest.java
@@ -18,18 +18,18 @@
import static android.autofillservice.cts.CannedFillResponse.NO_RESPONSE;
import static android.autofillservice.cts.FatActivity.ID_CAPTCHA;
import static android.autofillservice.cts.FatActivity.ID_IMAGE;
-import static android.autofillservice.cts.FatActivity.ID_IMPORTANT_IMAGE;
-import static android.autofillservice.cts.FatActivity.ID_INPUT;
-import static android.autofillservice.cts.FatActivity.ID_INPUT_CONTAINER;
import static android.autofillservice.cts.FatActivity.ID_IMPORTANT_CONTAINER_EXCLUDING_DESCENDANTS;
import static android.autofillservice.cts.FatActivity.ID_IMPORTANT_CONTAINER_EXCLUDING_DESCENDANTS_CHILD;
import static android.autofillservice.cts.FatActivity.ID_IMPORTANT_CONTAINER_EXCLUDING_DESCENDANTS_GRAND_CHILD;
-import static android.autofillservice.cts.FatActivity.ID_NOT_IMPORTANT_CONTAINER_MIXED_DESCENDANTS;
-import static android.autofillservice.cts.FatActivity.ID_NOT_IMPORTANT_CONTAINER_MIXED_DESCENDANTS_CHILD;
-import static android.autofillservice.cts.FatActivity.ID_NOT_IMPORTANT_CONTAINER_MIXED_DESCENDANTS_GRAND_CHILD;
+import static android.autofillservice.cts.FatActivity.ID_IMPORTANT_IMAGE;
+import static android.autofillservice.cts.FatActivity.ID_INPUT;
+import static android.autofillservice.cts.FatActivity.ID_INPUT_CONTAINER;
import static android.autofillservice.cts.FatActivity.ID_NOT_IMPORTANT_CONTAINER_EXCLUDING_DESCENDANTS;
import static android.autofillservice.cts.FatActivity.ID_NOT_IMPORTANT_CONTAINER_EXCLUDING_DESCENDANTS_CHILD;
import static android.autofillservice.cts.FatActivity.ID_NOT_IMPORTANT_CONTAINER_EXCLUDING_DESCENDANTS_GRAND_CHILD;
+import static android.autofillservice.cts.FatActivity.ID_NOT_IMPORTANT_CONTAINER_MIXED_DESCENDANTS;
+import static android.autofillservice.cts.FatActivity.ID_NOT_IMPORTANT_CONTAINER_MIXED_DESCENDANTS_CHILD;
+import static android.autofillservice.cts.FatActivity.ID_NOT_IMPORTANT_CONTAINER_MIXED_DESCENDANTS_GRAND_CHILD;
import static android.autofillservice.cts.Helper.assertNumberOfChildren;
import static android.autofillservice.cts.Helper.findNodeByResourceId;
import static android.autofillservice.cts.Helper.findNodeByText;
@@ -38,7 +38,6 @@
import android.app.assist.AssistStructure.ViewNode;
import android.autofillservice.cts.InstrumentedAutoFillService.FillRequest;
-import android.support.test.rule.ActivityTestRule;
import org.junit.Before;
import org.junit.Rule;
@@ -50,8 +49,8 @@
public class FatActivityTest extends AutoFillServiceTestCase {
@Rule
- public final ActivityTestRule<FatActivity> mActivityRule =
- new ActivityTestRule<FatActivity>(FatActivity.class);
+ public final AutofillActivityTestRule<FatActivity> mActivityRule =
+ new AutofillActivityTestRule<FatActivity>(FatActivity.class);
private FatActivity mFatActivity;
diff --git a/tests/autofillservice/src/android/autofillservice/cts/Helper.java b/tests/autofillservice/src/android/autofillservice/cts/Helper.java
index cf383a1..7c91578 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/Helper.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/Helper.java
@@ -17,6 +17,7 @@
package android.autofillservice.cts;
import static android.autofillservice.cts.Helper.runShellCommand;
+import static android.autofillservice.cts.InstrumentedAutoFillService.SERVICE_NAME;
import static android.provider.Settings.Secure.AUTOFILL_SERVICE;
import static com.google.common.truth.Truth.assertThat;
@@ -696,6 +697,92 @@
runShellCommand("cmd autofill set log_level %s", level);
}
+ /**
+ * Uses Settings to enable the given autofill service for the default user, and checks the
+ * value was properly check, throwing an exception if it was not.
+ */
+ public static void enableAutofillService(Context context, String serviceName) {
+ if (isAutofillServiceEnabled(serviceName)) return;
+
+ final OneTimeSettingsListener observer = new OneTimeSettingsListener(context,
+ AUTOFILL_SERVICE);
+ runShellCommand("settings put secure %s %s default", AUTOFILL_SERVICE, serviceName);
+ observer.assertCalled();
+ assertAutofillServiceStatus(serviceName, true);
+ }
+
+ /**
+ * Uses Settings to disable the given autofill service for the default user, and checks the
+ * value was properly check, throwing an exception if it was not.
+ */
+ public static void disableAutofillService(Context context, String serviceName) {
+ if (!isAutofillServiceEnabled(serviceName)) return;
+
+ final OneTimeSettingsListener observer = new OneTimeSettingsListener(context,
+ AUTOFILL_SERVICE);
+ runShellCommand("settings delete secure %s", AUTOFILL_SERVICE);
+ observer.assertCalled();
+ assertAutofillServiceStatus(serviceName, false);
+ }
+
+ /**
+ * Checks whether the given service is set as the autofill service for the default user.
+ */
+ public static boolean isAutofillServiceEnabled(String serviceName) {
+ final String actualName = runShellCommand("settings get secure %s", AUTOFILL_SERVICE);
+ return serviceName.equals(actualName);
+ }
+
+ /**
+ * Asserts whether the given service is enabled as the autofill service for the default user.
+ */
+ public static void assertAutofillServiceStatus(String serviceName, boolean enabled) {
+ final String actual = runShellCommand("settings get secure %s", AUTOFILL_SERVICE);
+ final String expected = enabled ? serviceName : "null";
+ assertWithMessage("Invalid value for secure setting %s", AUTOFILL_SERVICE)
+ .that(actual).isEqualTo(expected);
+ }
+
+ /**
+ * Asserts that there is no session left in the service.
+ */
+ public static void assertNoDanglingSessions() {
+ final String command = "cmd autofill list sessions";
+ final String result = runShellCommand(command);
+ assertWithMessage("Dangling sessions ('%s'): %s'", command, result).that(result).isEmpty();
+ }
+
+ /**
+ * Destroys all sessions.
+ */
+ public static void destroyAllSessions() {
+ runShellCommand("cmd autofill destroy sessions");
+ assertNoDanglingSessions();
+ }
+
+ /**
+ * Gets the instrumentation context.
+ */
+ public static Context getContext() {
+ return InstrumentationRegistry.getInstrumentation().getContext();
+ }
+
+ /**
+ * Cleans up the autofill state; should be called before pretty much any test.
+ */
+ public static void preTestCleanup() {
+ if (!hasAutofillFeature()) return;
+
+ Log.d(TAG, "preTestCleanup()");
+
+ disableAutofillService(getContext(), SERVICE_NAME);
+ InstrumentedAutoFillService.setIgnoreUnexpectedRequests(true);
+
+ destroyAllSessions();
+ InstrumentedAutoFillService.resetStaticState();
+ AuthenticationActivity.resetStaticState();
+ }
+
private Helper() {
}
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/InitializedCheckoutActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/InitializedCheckoutActivityTest.java
index cfdb6e4..07c67eb9 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/InitializedCheckoutActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/InitializedCheckoutActivityTest.java
@@ -28,7 +28,6 @@
import static android.autofillservice.cts.Helper.findNodeByResourceId;
import android.autofillservice.cts.InstrumentedAutoFillService.FillRequest;
-import android.support.test.rule.ActivityTestRule;
import org.junit.Before;
import org.junit.Rule;
@@ -40,8 +39,8 @@
public class InitializedCheckoutActivityTest extends AutoFillServiceTestCase {
@Rule
- public final ActivityTestRule<InitializedCheckoutActivity> mActivityRule =
- new ActivityTestRule<InitializedCheckoutActivity>(InitializedCheckoutActivity.class);
+ public final AutofillActivityTestRule<InitializedCheckoutActivity> mActivityRule =
+ new AutofillActivityTestRule<InitializedCheckoutActivity>(InitializedCheckoutActivity.class);
private InitializedCheckoutActivity mCheckoutActivity;
diff --git a/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java b/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java
index 81e3387..12fec5a 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/InstrumentedAutoFillService.java
@@ -38,8 +38,10 @@
import android.service.autofill.FillContext;
import android.service.autofill.FillResponse;
import android.service.autofill.SaveCallback;
+import android.support.annotation.Nullable;
import android.util.Log;
+import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
@@ -51,6 +53,9 @@
*/
public class InstrumentedAutoFillService extends AutofillService {
+ static final String SERVICE_NAME = InstrumentedAutoFillService.class.getPackage()
+ .getName() + "/." + InstrumentedAutoFillService.class.getSimpleName();
+
private static final String TAG = "InstrumentedAutoFillService";
private static final boolean DUMP_FILL_REQUESTS = false;
@@ -64,6 +69,9 @@
private static final Replier sReplier = new Replier();
private static final BlockingQueue<String> sConnectionStates = new LinkedBlockingQueue<>();
+ private static final Object sLock = new Object();
+
+ // @GuardedBy("sLock")
private static boolean sIgnoreUnexpectedRequests = false;
public InstrumentedAutoFillService() {
@@ -89,9 +97,11 @@
@Override
public void onFillRequest(android.service.autofill.FillRequest request,
CancellationSignal cancellationSignal, FillCallback callback) {
- if (sIgnoreUnexpectedRequests || !fromSamePackage(request.getFillContexts())) {
- Log.w(TAG, "Ignoring onFillRequest()");
- return;
+ synchronized (sLock) {
+ if (sIgnoreUnexpectedRequests || !fromSamePackage(request.getFillContexts())) {
+ Log.w(TAG, "Ignoring onFillRequest()");
+ return;
+ }
}
if (DUMP_FILL_REQUESTS) dumpStructure("onFillRequest()", request.getFillContexts());
sReplier.onFillRequest(request.getFillContexts(), request.getClientState(),
@@ -101,9 +111,11 @@
@Override
public void onSaveRequest(android.service.autofill.SaveRequest request,
SaveCallback callback) {
- if (sIgnoreUnexpectedRequests || !fromSamePackage(request.getFillContexts())) {
- Log.w(TAG, "Ignoring onSaveRequest()");
- return;
+ synchronized (sLock) {
+ if (sIgnoreUnexpectedRequests || !fromSamePackage(request.getFillContexts())) {
+ Log.w(TAG, "Ignoring onSaveRequest()");
+ return;
+ }
}
if (DUMP_SAVE_REQUESTS) dumpStructure("onSaveRequest()", request.getFillContexts());
sReplier.onSaveRequest(request.getFillContexts(), request.getClientState(), callback);
@@ -126,7 +138,9 @@
* should throw an exception.
*/
public static void setIgnoreUnexpectedRequests(boolean ignore) {
- sIgnoreUnexpectedRequests = ignore;
+ synchronized (sLock) {
+ sIgnoreUnexpectedRequests = ignore;
+ }
}
/**
@@ -231,10 +245,28 @@
private final BlockingQueue<FillRequest> mFillRequests = new LinkedBlockingQueue<>();
private final BlockingQueue<SaveRequest> mSaveRequests = new LinkedBlockingQueue<>();
+ private List<Exception> mExceptions;
+
private Replier() {
}
/**
+ * Gets the exceptions thrown asynchronously, if any.
+ */
+ @Nullable List<Exception> getExceptions() {
+ return mExceptions;
+ }
+
+ private void addException(@Nullable Exception e) {
+ if (e == null) return;
+
+ if (mExceptions == null) {
+ mExceptions = new ArrayList<>();
+ }
+ mExceptions.add(e);
+ }
+
+ /**
* Sets the expectation for the next {@code onFillRequest} as {@link FillResponse} with just
* one {@link Dataset}.
*/
@@ -280,6 +312,13 @@
}
/**
+ * Gets the current number of unhandled requests.
+ */
+ int getNumberUnhandledFillRequests() {
+ return mFillRequests.size();
+ }
+
+ /**
* Gets the next save request, in the order received.
*
* <p>Typically called at the end of a test case, to assert the initial request.
@@ -310,6 +349,7 @@
mResponses.clear();
mFillRequests.clear();
mSaveRequests.clear();
+ mExceptions = null;
}
private void onFillRequest(List<FillContext> contexts, Bundle data,
@@ -321,11 +361,14 @@
} catch (InterruptedException e) {
Log.w(TAG, "Interrupted getting CannedResponse: " + e);
Thread.currentThread().interrupt();
+ addException(e);
return;
}
if (response == null) {
- dumpStructure("onFillRequest() without response", contexts);
- throw new RetryableException("No CannedResponse");
+ final String msg = "onFillRequest() received when no CannedResponse was set";
+ dumpStructure(msg, contexts);
+ addException(new RetryableException(msg));
+ return;
}
if (response.getResponseType() == NULL) {
Log.d(TAG, "onFillRequest(): replying with null");
@@ -350,6 +393,8 @@
Log.v(TAG, "onFillRequest(): fillResponse = " + fillResponse);
callback.onSuccess(fillResponse);
+ } catch (Exception e) {
+ addException(e);
} finally {
mFillRequests.offer(new FillRequest(contexts, data, cancellationSignal, callback,
flags));
diff --git a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
index 686a056..72f5197 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/LoginActivityTest.java
@@ -18,12 +18,13 @@
import static android.app.Activity.RESULT_CANCELED;
import static android.app.Activity.RESULT_OK;
+import static android.autofillservice.cts.CannedFillResponse.DO_NOT_REPLY_RESPONSE;
import static android.autofillservice.cts.CannedFillResponse.NO_RESPONSE;
import static android.autofillservice.cts.CheckoutActivity.ID_CC_NUMBER;
-import static android.autofillservice.cts.CannedFillResponse.DO_NOT_REPLY_RESPONSE;
import static android.autofillservice.cts.Helper.ID_PASSWORD;
import static android.autofillservice.cts.Helper.ID_PASSWORD_LABEL;
import static android.autofillservice.cts.Helper.ID_USERNAME;
+import static android.autofillservice.cts.Helper.assertNoDanglingSessions;
import static android.autofillservice.cts.Helper.assertNumberOfChildren;
import static android.autofillservice.cts.Helper.assertTextAndValue;
import static android.autofillservice.cts.Helper.assertTextIsSanitized;
@@ -31,6 +32,7 @@
import static android.autofillservice.cts.Helper.dumpStructure;
import static android.autofillservice.cts.Helper.eventually;
import static android.autofillservice.cts.Helper.findNodeByResourceId;
+import static android.autofillservice.cts.Helper.getContext;
import static android.autofillservice.cts.Helper.runShellCommand;
import static android.autofillservice.cts.Helper.setUserComplete;
import static android.autofillservice.cts.InstrumentedAutoFillService.waitUntilConnected;
@@ -72,7 +74,6 @@
import android.service.autofill.FillEventHistory;
import android.service.autofill.FillResponse;
import android.service.autofill.SaveInfo;
-import android.support.test.rule.ActivityTestRule;
import android.support.test.uiautomator.UiObject2;
import android.view.View;
import android.view.View.AccessibilityDelegate;
@@ -99,8 +100,8 @@
public class LoginActivityTest extends AutoFillServiceTestCase {
@Rule
- public final ActivityTestRule<LoginActivity> mActivityRule = new ActivityTestRule<LoginActivity>(
- LoginActivity.class);
+ public final AutofillActivityTestRule<LoginActivity> mActivityRule =
+ new AutofillActivityTestRule<LoginActivity>(LoginActivity.class);
private LoginActivity mActivity;
@@ -1172,7 +1173,7 @@
throw e;
}
- // Sanity check: once saved, the session should be finsihed.
+ // Sanity check: once saved, the session should be finished.
assertNoDanglingSessions();
}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/MultipleExceptionsCatcher.java b/tests/autofillservice/src/android/autofillservice/cts/MultipleExceptionsCatcher.java
new file mode 100644
index 0000000..3750c30
--- /dev/null
+++ b/tests/autofillservice/src/android/autofillservice/cts/MultipleExceptionsCatcher.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2017 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 android.autofillservice.cts;
+
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.util.Log;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Helper used to catch multiple exceptions that might have happened in a test case.
+ */
+// TODO: move to common CTS code (and add test cases to it)
+public final class MultipleExceptionsCatcher {
+
+ private static final String TAG = "MultipleExceptionsCatcher";
+
+ private final List<Throwable> mThrowables = new ArrayList<>();
+
+ /**
+ * Runs {@code r} postponing any thrown exception to {@link #throwIfAny()}.
+ */
+ public MultipleExceptionsCatcher run(@NonNull Runnable r) {
+ try {
+ r.run();
+ } catch (Throwable t) {
+ mThrowables.add(t);
+ }
+ return this;
+ }
+
+ /**
+ * Adds an exception - if it's not {@code null} to the exceptions thrown by
+ * {@link #throwIfAny()}.
+ */
+ public MultipleExceptionsCatcher add(@Nullable Throwable t) {
+ if (t != null) {
+ mThrowables.add(t);
+ }
+ return this;
+ }
+
+ /**
+ * Throws one exception merging all exceptions thrown or added so far, if any.
+ */
+ public void throwIfAny() throws Exception {
+ if (mThrowables.isEmpty()) return;
+
+ if (mThrowables.size() == 1) {
+ final Throwable t = mThrowables.get(0);
+ if (t instanceof Exception) {
+ throw (Exception) t;
+ }
+ }
+
+ String msg = "D'OH!";
+ try {
+ try (StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw)) {
+ sw.write("Caught " + mThrowables.size() + " exceptions\n");
+ for (int i = 0; i < mThrowables.size(); i++) {
+ sw.write("\n---- Begin of exception #" + (i + 1) + " ----\n");
+ final Throwable exception = mThrowables.get(i);
+ exception.printStackTrace(pw);
+ sw.write("---- End of exception #" + (i + 1) + " ----\n\n");
+ }
+ msg = sw.toString();
+ }
+ } catch (IOException e) {
+ // ignore close() errors - should not happen...
+ Log.e(TAG, "Exception closing StringWriter: " + e);
+ }
+ throw new AssertionError(msg);
+ }
+}
diff --git a/tests/autofillservice/src/android/autofillservice/cts/MultipleFragmentLoginTest.java b/tests/autofillservice/src/android/autofillservice/cts/MultipleFragmentLoginTest.java
index ac7ae34..3e30b9b 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/MultipleFragmentLoginTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/MultipleFragmentLoginTest.java
@@ -28,7 +28,6 @@
import android.app.assist.AssistStructure;
import android.app.assist.AssistStructure.ViewNode;
import android.os.Bundle;
-import android.support.test.rule.ActivityTestRule;
import android.util.Log;
import android.view.autofill.AutofillValue;
import android.widget.EditText;
@@ -40,8 +39,8 @@
public class MultipleFragmentLoginTest extends AutoFillServiceTestCase {
private static final String LOG_TAG = MultipleFragmentLoginTest.class.getSimpleName();
@Rule
- public final ActivityTestRule<FragmentContainerActivity> mActivityRule =
- new ActivityTestRule<>(FragmentContainerActivity.class);
+ public final AutofillActivityTestRule<FragmentContainerActivity> mActivityRule =
+ new AutofillActivityTestRule<>(FragmentContainerActivity.class);
private FragmentContainerActivity mActivity;
private EditText mEditText1;
private EditText mEditText2;
diff --git a/tests/autofillservice/src/android/autofillservice/cts/OptionalSaveActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/OptionalSaveActivityTest.java
index b1250de..d1b8400 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/OptionalSaveActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/OptionalSaveActivityTest.java
@@ -28,7 +28,6 @@
import android.app.assist.AssistStructure;
import android.autofillservice.cts.CannedFillResponse.CannedDataset;
import android.autofillservice.cts.InstrumentedAutoFillService.SaveRequest;
-import android.support.test.rule.ActivityTestRule;
import org.junit.After;
import org.junit.Before;
@@ -49,8 +48,8 @@
public class OptionalSaveActivityTest extends AutoFillServiceTestCase {
@Rule
- public final ActivityTestRule<OptionalSaveActivity> mActivityRule =
- new ActivityTestRule<OptionalSaveActivity>(OptionalSaveActivity.class);
+ public final AutofillActivityTestRule<OptionalSaveActivity> mActivityRule =
+ new AutofillActivityTestRule<OptionalSaveActivity>(OptionalSaveActivity.class);
private OptionalSaveActivity mActivity;
diff --git a/tests/autofillservice/src/android/autofillservice/cts/PartitionedActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/PartitionedActivityTest.java
index cd854c8..d458940 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/PartitionedActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/PartitionedActivityTest.java
@@ -25,6 +25,7 @@
import static android.autofillservice.cts.GridActivity.ID_L4C2;
import static android.autofillservice.cts.Helper.assertTextIsSanitized;
import static android.autofillservice.cts.Helper.assertValue;
+import static android.autofillservice.cts.Helper.getContext;
import static android.autofillservice.cts.Helper.getMaxPartitions;
import static android.autofillservice.cts.Helper.setMaxPartitions;
import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST;
@@ -45,7 +46,6 @@
import android.content.IntentSender;
import android.os.Bundle;
import android.service.autofill.FillResponse;
-import android.support.test.rule.ActivityTestRule;
import android.widget.RemoteViews;
import org.junit.Before;
@@ -58,8 +58,8 @@
public class PartitionedActivityTest extends AutoFillServiceTestCase {
@Rule
- public final ActivityTestRule<GridActivity> mActivityRule =
- new ActivityTestRule<GridActivity>(GridActivity.class);
+ public final AutofillActivityTestRule<GridActivity> mActivityRule =
+ new AutofillActivityTestRule<GridActivity>(GridActivity.class);
private GridActivity mActivity;
diff --git a/tests/autofillservice/src/android/autofillservice/cts/PreFilledLoginActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/PreFilledLoginActivityTest.java
index 349149f..75c742f 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/PreFilledLoginActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/PreFilledLoginActivityTest.java
@@ -27,7 +27,6 @@
import android.autofillservice.cts.InstrumentedAutoFillService.FillRequest;
import android.autofillservice.cts.InstrumentedAutoFillService.SaveRequest;
-import android.support.test.rule.ActivityTestRule;
import org.junit.After;
import org.junit.Before;
@@ -40,8 +39,8 @@
public class PreFilledLoginActivityTest extends AutoFillServiceTestCase {
@Rule
- public final ActivityTestRule<PreFilledLoginActivity> mActivityRule =
- new ActivityTestRule<PreFilledLoginActivity>(PreFilledLoginActivity.class);
+ public final AutofillActivityTestRule<PreFilledLoginActivity> mActivityRule =
+ new AutofillActivityTestRule<PreFilledLoginActivity>(PreFilledLoginActivity.class);
private PreFilledLoginActivity mActivity;
diff --git a/tests/autofillservice/src/android/autofillservice/cts/SessionLifecycleTest.java b/tests/autofillservice/src/android/autofillservice/cts/SessionLifecycleTest.java
index c5a0105..1601512 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/SessionLifecycleTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/SessionLifecycleTest.java
@@ -24,6 +24,7 @@
import static android.autofillservice.cts.Helper.assertTextAndValue;
import static android.autofillservice.cts.Helper.eventually;
import static android.autofillservice.cts.Helper.findNodeByResourceId;
+import static android.autofillservice.cts.Helper.getContext;
import static android.autofillservice.cts.Helper.getOutOfProcessPid;
import static android.autofillservice.cts.Helper.runShellCommand;
import static android.autofillservice.cts.Helper.setOrientation;
@@ -56,8 +57,8 @@
private static final String CANCEL_FULL_ID = "android.autofillservice.cts:id/cancel";
@Before
- public void removeAllSessions() {
- destroyAllSessions();
+ public void cleanUpState() {
+ Helper.preTestCleanup();
}
/**
diff --git a/tests/autofillservice/src/android/autofillservice/cts/TimePickerClockActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/TimePickerClockActivityTest.java
index d8651b6..8135eba 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/TimePickerClockActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/TimePickerClockActivityTest.java
@@ -15,15 +15,13 @@
*/
package android.autofillservice.cts;
-import android.support.test.rule.ActivityTestRule;
-
import org.junit.Rule;
public class TimePickerClockActivityTest extends TimePickerTestCase<TimePickerClockActivity> {
@Rule
- public final ActivityTestRule<TimePickerClockActivity> mActivityRule =
- new ActivityTestRule<TimePickerClockActivity>(TimePickerClockActivity.class);
+ public final AutofillActivityTestRule<TimePickerClockActivity> mActivityRule =
+ new AutofillActivityTestRule<TimePickerClockActivity>(TimePickerClockActivity.class);
@Override
protected TimePickerClockActivity getTimePickerActivity() {
diff --git a/tests/autofillservice/src/android/autofillservice/cts/TimePickerSpinnerActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/TimePickerSpinnerActivityTest.java
index ab86255..2d97f03 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/TimePickerSpinnerActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/TimePickerSpinnerActivityTest.java
@@ -15,15 +15,13 @@
*/
package android.autofillservice.cts;
-import android.support.test.rule.ActivityTestRule;
-
import org.junit.Rule;
public class TimePickerSpinnerActivityTest extends TimePickerTestCase<TimePickerSpinnerActivity> {
@Rule
- public final ActivityTestRule<TimePickerSpinnerActivity> mActivityRule =
- new ActivityTestRule<TimePickerSpinnerActivity>(TimePickerSpinnerActivity.class);
+ public final AutofillActivityTestRule<TimePickerSpinnerActivity> mActivityRule =
+ new AutofillActivityTestRule<TimePickerSpinnerActivity>(TimePickerSpinnerActivity.class);
@Override
protected TimePickerSpinnerActivity getTimePickerActivity() {
diff --git a/tests/autofillservice/src/android/autofillservice/cts/ViewAttributesTest.java b/tests/autofillservice/src/android/autofillservice/cts/ViewAttributesTest.java
index f33d6fe..541250b 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/ViewAttributesTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/ViewAttributesTest.java
@@ -24,7 +24,6 @@
import android.support.annotation.IdRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
-import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.view.View;
import android.view.autofill.AutofillValue;
@@ -40,8 +39,8 @@
@RunWith(AndroidJUnit4.class)
public class ViewAttributesTest extends AutoFillServiceTestCase {
@Rule
- public final ActivityTestRule<ViewAttributesTestActivity> mActivityRule =
- new ActivityTestRule<>(ViewAttributesTestActivity.class);
+ public final AutofillActivityTestRule<ViewAttributesTestActivity> mActivityRule =
+ new AutofillActivityTestRule<>(ViewAttributesTestActivity.class);
private ViewAttributesTestActivity mActivity;
diff --git a/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivityTest.java
index f5e6832..a4d827d 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/VirtualContainerActivityTest.java
@@ -36,7 +36,8 @@
import android.autofillservice.cts.InstrumentedAutoFillService.FillRequest;
import android.autofillservice.cts.VirtualContainerView.Line;
import android.graphics.Rect;
-import android.support.test.rule.ActivityTestRule;
+import android.os.SystemClock;
+import android.service.autofill.SaveInfo;
import android.support.test.uiautomator.UiObject2;
import android.view.autofill.AutofillManager;
@@ -51,8 +52,8 @@
public class VirtualContainerActivityTest extends AutoFillServiceTestCase {
@Rule
- public final ActivityTestRule<VirtualContainerActivity> mActivityRule =
- new ActivityTestRule<VirtualContainerActivity>(VirtualContainerActivity.class);
+ public final AutofillActivityTestRule<VirtualContainerActivity> mActivityRule =
+ new AutofillActivityTestRule<VirtualContainerActivity>(VirtualContainerActivity.class);
private VirtualContainerActivity mActivity;