Add test for Validators

Test: cts-tradefed run cts-dev -m CtsAutoFillServiceTestCases
           --test=android.autofillservice.cts.ValidatorTest
Bug: 62534917
Change-Id: I02790a7db209683dcb005d39f3fbeaa143fc4b1e
diff --git a/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java b/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java
index 07d4721..89e3969 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/CannedFillResponse.java
@@ -26,6 +26,7 @@
 import android.service.autofill.FillCallback;
 import android.service.autofill.FillResponse;
 import android.service.autofill.SaveInfo;
+import android.service.autofill.Validator;
 import android.view.autofill.AutofillId;
 import android.view.autofill.AutofillValue;
 import android.widget.RemoteViews;
@@ -58,6 +59,7 @@
     private final List<CannedDataset> mDatasets;
     private final String mFailureMessage;
     private final int mSaveType;
+    private final Validator mValidator;
     private final String[] mRequiredSavableIds;
     private final String[] mOptionalSavableIds;
     private final String mSaveDescription;
@@ -74,6 +76,7 @@
         mResponseType = builder.mResponseType;
         mDatasets = builder.mDatasets;
         mFailureMessage = builder.mFailureMessage;
+        mValidator = builder.mValidator;
         mRequiredSavableIds = builder.mRequiredSavableIds;
         mOptionalSavableIds = builder.mOptionalSavableIds;
         mSaveDescription = builder.mSaveDescription;
@@ -129,6 +132,9 @@
 
             saveInfo.setFlags(mFlags);
 
+            if (mValidator != null) {
+                saveInfo.setValidator(mValidator);
+            }
             if (mOptionalSavableIds != null) {
                 saveInfo.setOptionalIds(getAutofillIds(nodeResolver, mOptionalSavableIds));
             }
@@ -176,6 +182,7 @@
         private final List<CannedDataset> mDatasets = new ArrayList<>();
         private final ResponseType mResponseType;
         private String mFailureMessage;
+        private Validator mValidator;
         private String[] mRequiredSavableIds;
         private String[] mOptionalSavableIds;
         private String mSaveDescription;
@@ -204,6 +211,14 @@
         }
 
         /**
+         * Sets the validator for this request
+         */
+        public Builder setValidator(Validator validator) {
+            mValidator = validator;
+            return this;
+        }
+
+        /**
          * Sets the required savable ids based on they {@code resourceId}.
          */
         public Builder setRequiredSavableIds(int type, String... ids) {
diff --git a/tests/autofillservice/src/android/autofillservice/cts/ValidatorTest.java b/tests/autofillservice/src/android/autofillservice/cts/ValidatorTest.java
new file mode 100644
index 0000000..b94064a
--- /dev/null
+++ b/tests/autofillservice/src/android/autofillservice/cts/ValidatorTest.java
@@ -0,0 +1,139 @@
+/*
+ * 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 static android.autofillservice.cts.Helper.ID_PASSWORD;
+import static android.autofillservice.cts.Helper.ID_USERNAME;
+import static android.autofillservice.cts.Helper.assertNoDanglingSessions;
+import static android.service.autofill.SaveInfo.SAVE_DATA_TYPE_GENERIC;
+
+import android.service.autofill.LuhnChecksumValidator;
+import android.service.autofill.SimpleRegexValidator;
+import android.service.autofill.Validator;
+import android.service.autofill.Validators;
+import android.support.annotation.NonNull;
+import android.support.test.rule.ActivityTestRule;
+import android.view.View;
+import android.view.autofill.AutofillId;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import java.util.function.BiFunction;
+
+public class ValidatorTest extends AutoFillServiceTestCase {
+    @Rule
+    public final ActivityTestRule<LoginActivity> mActivityRule = new ActivityTestRule<>(
+            LoginActivity.class);
+
+    private LoginActivity mActivity;
+
+    @Before
+    public void setActivity() {
+        mActivity = mActivityRule.getActivity();
+    }
+
+    @After
+    public void finishWelcomeActivity() {
+        WelcomeActivity.finishIt();
+    }
+
+    /**
+     * Base test
+     *
+     * @param validatorBuilder method to build a validator
+     * @param willSaveBeShown  Whether the save pop-up will be shown
+     */
+    private void testValidator(
+            @NonNull BiFunction<AutofillId, AutofillId, Validator> validatorBuilder,
+            boolean willSaveBeShown) throws Exception {
+        enableService();
+
+        AutofillId usernameId = mActivity.getUsername().getAutofillId();
+        AutofillId passwordId = mActivity.getPassword().getAutofillId();
+
+        // Set response
+        sReplier.addResponse(new CannedFillResponse.Builder()
+                .setRequiredSavableIds(SAVE_DATA_TYPE_GENERIC, ID_USERNAME, ID_PASSWORD)
+                .setValidator(validatorBuilder.apply(usernameId, passwordId))
+                .build());
+
+        // Trigger auto-fill
+        mActivity.onPassword(View::requestFocus);
+
+        // Wait for onFill() before proceeding.
+        sReplier.getNextFillRequest();
+
+        // Trigger save.
+        mActivity.onUsername((v) -> v.setText("7992739871-3"));
+        mActivity.onPassword((v) -> v.setText("passwd"));
+        mActivity.tapLogin();
+
+        if (willSaveBeShown) {
+            sUiBot.saveForAutofill(true, SAVE_DATA_TYPE_GENERIC);
+            sReplier.getNextSaveRequest();
+        } else {
+            sUiBot.assertSaveNotShowing(SAVE_DATA_TYPE_GENERIC);
+        }
+
+        assertNoDanglingSessions();
+    }
+
+    @Test
+    public void checkForInvalidField() throws Exception {
+        testValidator((usernameId, passwordId) -> Validators.or(
+                new LuhnChecksumValidator(new AutofillId(-1)),
+                new SimpleRegexValidator(passwordId, "pass.*")), true);
+    }
+
+    @Test
+    public void checkBoth() throws Exception {
+        testValidator((usernameId, passwordId) -> Validators.and(
+                new LuhnChecksumValidator(usernameId),
+                new SimpleRegexValidator(passwordId, "pass.*")), true);
+    }
+
+    @Test
+    public void checkEither1() throws Exception {
+        testValidator((usernameId, passwordId) -> Validators.or(
+                new SimpleRegexValidator(usernameId, "7.*"),
+                new SimpleRegexValidator(passwordId, "pass.*")), true);
+    }
+
+    @Test
+    public void checkEither2() throws Exception {
+        testValidator((usernameId, passwordId) -> Validators.or(
+                new SimpleRegexValidator(usernameId, "invalid"),
+                new SimpleRegexValidator(passwordId, "pass.*")), true);
+    }
+
+    @Test
+    public void checkBothButFail() throws Exception {
+        testValidator((usernameId, passwordId) -> Validators.and(
+                new SimpleRegexValidator(usernameId, "7.*"),
+                new SimpleRegexValidator(passwordId, "invalid")), false);
+    }
+
+    @Test
+    public void checkEitherButFail() throws Exception {
+        testValidator((usernameId, passwordId) -> Validators.or(
+                new SimpleRegexValidator(usernameId, "invalid"),
+                new SimpleRegexValidator(passwordId, "invalid")), false);
+    }
+}