Merge "Support non-disposed render in tests am: d84e1ead52 am: 165bb7ded3" into rvc-d1-dev-plus-aosp
diff --git a/bridge/tests/res/testApp/MyApplication/golden/a11y_test1.png b/bridge/tests/res/testApp/MyApplication/golden/a11y_test1.png
new file mode 100644
index 0000000..067a193
--- /dev/null
+++ b/bridge/tests/res/testApp/MyApplication/golden/a11y_test1.png
Binary files differ
diff --git a/bridge/tests/res/testApp/MyApplication/src/main/res/layout/a11y_test1.xml b/bridge/tests/res/testApp/MyApplication/src/main/res/layout/a11y_test1.xml
new file mode 100644
index 0000000..3af420c
--- /dev/null
+++ b/bridge/tests/res/testApp/MyApplication/src/main/res/layout/a11y_test1.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2020 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.
+  -->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <android.widget.TextView
+        android:layout_width="100dp"
+        android:layout_height="100dp"
+        android:background="#000000"
+        android:gravity="center"
+        android:text="Hello!"
+        android:textColor="#000000" />
+
+
+    <Button
+        android:layout_width="10dp"
+        android:layout_height="10dp"
+        android:text="Hello World!!!"
+    />
+    <View
+        android:layout_width="100dp"
+        android:layout_height="100dp"
+        android:background="#000000"
+        android:importantForAccessibility="yes"
+        android:focusable="true"
+        android:clickable="true"
+    />
+</LinearLayout>
diff --git a/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java b/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
index 3db0644..9229d0d 100644
--- a/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
+++ b/bridge/tests/src/com/android/layoutlib/bridge/intensive/Main.java
@@ -22,6 +22,7 @@
 import com.android.layoutlib.bridge.android.BridgeXmlBlockParserTest;
 import com.android.layoutlib.bridge.impl.LayoutParserWrapperTest;
 import com.android.layoutlib.bridge.impl.ResourceHelperTest;
+import com.android.tools.idea.validator.LayoutValidatorTests;
 
 import org.junit.runner.RunWith;
 import org.junit.runners.Suite;
@@ -44,7 +45,8 @@
         Matrix_DelegateTest.class, TestDelegates.class,
         BridgeRenderSessionTest.class, ResourceHelperTest.class, BridgeContextTest.class,
         Resources_DelegateTest.class, Color_DelegateTest.class, ImagePoolHelperTest.class,
-        ImagePoolImplTest.class, HighQualityShadowsRenderTests.class
+        ImagePoolImplTest.class, HighQualityShadowsRenderTests.class,
+        LayoutValidatorTests.class
 })
 public class Main {
 }
diff --git a/bridge/tests/src/com/android/layoutlib/bridge/intensive/util/SessionParamsBuilder.java b/bridge/tests/src/com/android/layoutlib/bridge/intensive/util/SessionParamsBuilder.java
index 6fbb955..b7f5bb0 100644
--- a/bridge/tests/src/com/android/layoutlib/bridge/intensive/util/SessionParamsBuilder.java
+++ b/bridge/tests/src/com/android/layoutlib/bridge/intensive/util/SessionParamsBuilder.java
@@ -63,6 +63,7 @@
     private IImageFactory mImageFactory = null;
     private boolean enableShadows = true;
     private boolean highQualityShadows = true;
+    private boolean enableLayoutValidator = false;
 
     @NonNull
     public SessionParamsBuilder setParser(@NonNull LayoutPullParser layoutParser) {
@@ -176,6 +177,12 @@
     }
 
     @NonNull
+    public SessionParamsBuilder enableLayoutValidation() {
+        this.enableLayoutValidator = true;
+        return this;
+    }
+
+    @NonNull
     public SessionParams build() {
         assert mFrameworkResources != null;
         assert mProjectResources != null;
@@ -198,6 +205,7 @@
                 mMinSdk, mTargetSdk, mLayoutLog);
         params.setFlag(RenderParamsFlags.FLAG_ENABLE_SHADOW, enableShadows);
         params.setFlag(RenderParamsFlags.FLAG_RENDER_HIGH_QUALITY_SHADOW, highQualityShadows);
+        params.setFlag(RenderParamsFlags.FLAG_ENABLE_LAYOUT_VALIDATOR, enableLayoutValidator);
         if (mImageFactory != null) {
             params.setImageFactory(mImageFactory);
         }
diff --git a/bridge/tests/src/com/android/tools/idea/validator/LayoutValidatorTests.java b/bridge/tests/src/com/android/tools/idea/validator/LayoutValidatorTests.java
new file mode 100644
index 0000000..3de6bae
--- /dev/null
+++ b/bridge/tests/src/com/android/tools/idea/validator/LayoutValidatorTests.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2020 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.tools.idea.validator;
+
+import com.android.ide.common.rendering.api.SessionParams;
+import com.android.layoutlib.bridge.intensive.RenderTestBase;
+import com.android.layoutlib.bridge.intensive.setup.ConfigGenerator;
+import com.android.layoutlib.bridge.intensive.setup.LayoutLibTestCallback;
+import com.android.layoutlib.bridge.intensive.setup.LayoutPullParser;
+import com.android.tools.idea.validator.ValidatorData.Issue;
+import com.android.tools.idea.validator.ValidatorData.Level;
+import com.android.tools.idea.validator.ValidatorData.Type;
+
+import org.junit.Test;
+
+import android.view.View;
+
+import static org.junit.Assert.assertEquals;
+
+public class LayoutValidatorTests extends RenderTestBase {
+
+    @Test
+    public void testRenderAndVerify() throws Exception {
+        LayoutPullParser parser = createParserFromPath("a11y_test1.xml");
+        LayoutLibTestCallback layoutLibCallback =
+                new LayoutLibTestCallback(getLogger(), mDefaultClassLoader);
+        layoutLibCallback.initResources();
+        SessionParams params = getSessionParamsBuilder()
+                .setParser(parser)
+                .setConfigGenerator(ConfigGenerator.NEXUS_5)
+                .setCallback(layoutLibCallback)
+                .disableDecoration()
+                .enableLayoutValidation()
+                .build();
+
+        renderAndVerify(params, "a11y_test1.png");
+    }
+
+    @Test
+    public void testValidation() throws Exception {
+        LayoutPullParser parser = createParserFromPath("a11y_test1.xml");
+        LayoutLibTestCallback layoutLibCallback =
+                new LayoutLibTestCallback(getLogger(), mDefaultClassLoader);
+        layoutLibCallback.initResources();
+        SessionParams params = getSessionParamsBuilder()
+                .setParser(parser)
+                .setConfigGenerator(ConfigGenerator.NEXUS_5)
+                .setCallback(layoutLibCallback)
+                .disableDecoration()
+                .enableLayoutValidation()
+                .build();
+
+        render(sBridge, params, -1, session -> {
+            ValidatorResult result = LayoutValidator
+                    .validate(((View) session.getRootViews().get(0).getViewObject()));
+            assertEquals(2, result.getIssues().size());
+            for (Issue issue : result.getIssues()) {
+                assertEquals(Type.ACCESSIBILITY, issue.mType);
+                assertEquals(Level.ERROR, issue.mLevel);
+            }
+
+            assertEquals("This item may not have a label readable by screen readers.",
+                    result.getIssues().get(0).mMsg);
+            assertEquals(
+                    "The item's text contrast ratio is 1.00. This ratio is based on a text color " +
+                            "of #000000 and background color of #000000. Consider increasing this item's" +
+                            " text contrast ratio to 3.00 or greater.",
+                    result.getIssues().get(1).mMsg);
+            // TODO: It should recognize 10dp x 10dp button. Investigate why it's not.
+        });
+    }
+}