Update AppCompatSpinner popup color tests
* Use android:colorBackground instead of android:background for
default popup theming
* Only query the center pixel of the combined background to eliminate
need for checking rounded corners and drop shadow
* Also mark the entire buildSrc to be ignored by Git
Change-Id: Ida519ddb4091e5263f94b22b6461b9bb56669875
diff --git a/.gitignore b/.gitignore
index a72b3dc..e1876f9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,4 @@
**/gen
*.iml
**/out
+buildSrc/
diff --git a/v7/appcompat/tests/res/values/styles.xml b/v7/appcompat/tests/res/values/styles.xml
index 0232a2b..1b416a4 100644
--- a/v7/appcompat/tests/res/values/styles.xml
+++ b/v7/appcompat/tests/res/values/styles.xml
@@ -43,11 +43,11 @@
</style>
<style name="MagentaSpinnerPopupTheme">
- <item name="android:background">@color/test_magenta</item>
+ <item name="android:colorBackground">@color/test_magenta</item>
</style>
<style name="OceanSpinnerPopupTheme">
- <item name="android:background">@color/ocean_default</item>
+ <item name="android:colorBackground">@color/ocean_default</item>
</style>
<style name="PopupEmptyStyle" />
diff --git a/v7/appcompat/tests/src/android/support/v7/testutils/TestUtils.java b/v7/appcompat/tests/src/android/support/v7/testutils/TestUtils.java
index d258e1f..686bfb5 100644
--- a/v7/appcompat/tests/src/android/support/v7/testutils/TestUtils.java
+++ b/v7/appcompat/tests/src/android/support/v7/testutils/TestUtils.java
@@ -14,14 +14,8 @@
* limitations under the License.
*/
-
package android.support.v7.testutils;
-import android.support.v4.util.Pair;
-import android.view.View;
-import android.view.ViewParent;
-import junit.framework.Assert;
-
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
@@ -29,6 +23,10 @@
import android.os.SystemClock;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
+import android.support.v4.util.Pair;
+import android.view.View;
+import android.view.ViewParent;
+import junit.framework.Assert;
import java.util.ArrayList;
import java.util.List;
@@ -113,17 +111,17 @@
public static void assertAllPixelsOfColor(String failMessagePrefix, @NonNull Drawable drawable,
int drawableWidth, int drawableHeight, boolean callSetBounds, @ColorInt int color,
int allowedComponentVariance, boolean throwExceptionIfFails) {
- // Create a bitmap
- Bitmap bitmap = Bitmap.createBitmap(drawableWidth, drawableHeight,
- Bitmap.Config.ARGB_8888);
- // Create a canvas that wraps the bitmap
- Canvas canvas = new Canvas(bitmap);
- if (callSetBounds) {
- // Configure the drawable to have bounds that match the passed size
- drawable.setBounds(0, 0, drawableWidth, drawableHeight);
- }
- // And ask the drawable to draw itself to the canvas / bitmap
- drawable.draw(canvas);
+ // Create a bitmap
+ Bitmap bitmap = Bitmap.createBitmap(drawableWidth, drawableHeight,
+ Bitmap.Config.ARGB_8888);
+ // Create a canvas that wraps the bitmap
+ Canvas canvas = new Canvas(bitmap);
+ if (callSetBounds) {
+ // Configure the drawable to have bounds that match the passed size
+ drawable.setBounds(0, 0, drawableWidth, drawableHeight);
+ }
+ // And ask the drawable to draw itself to the canvas / bitmap
+ drawable.draw(canvas);
try {
assertAllPixelsOfColor(failMessagePrefix, bitmap, drawableWidth, drawableHeight, color,
@@ -148,35 +146,15 @@
for (int row = 0; row < bitmapHeight; row++) {
bitmap.getPixels(rowPixels, 0, bitmapWidth, 0, row, bitmapWidth, 1);
for (int column = 0; column < bitmapWidth; column++) {
- int sourceAlpha = Color.alpha(rowPixels[column]);
- int sourceRed = Color.red(rowPixels[column]);
- int sourceGreen = Color.green(rowPixels[column]);
- int sourceBlue = Color.blue(rowPixels[column]);
-
- int expectedAlpha = Color.alpha(color);
- int expectedRed = Color.red(color);
- int expectedGreen = Color.green(color);
- int expectedBlue = Color.blue(color);
-
- int varianceAlpha = Math.abs(sourceAlpha - expectedAlpha);
- int varianceRed = Math.abs(sourceRed - expectedRed);
- int varianceGreen = Math.abs(sourceGreen - expectedGreen);
- int varianceBlue = Math.abs(sourceBlue - expectedBlue);
-
- boolean isColorMatch = (varianceAlpha <= allowedComponentVariance)
- && (varianceRed <= allowedComponentVariance)
- && (varianceGreen <= allowedComponentVariance)
- && (varianceBlue <= allowedComponentVariance);
-
- if (!isColorMatch) {
+ @ColorInt int colorAtCurrPixel = rowPixels[column];
+ if (!areColorsTheSameWithTolerance(color, colorAtCurrPixel,
+ allowedComponentVariance)) {
String mismatchDescription = failMessagePrefix
- + ": expected all drawable colors to be ["
- + expectedAlpha + "," + expectedRed + ","
- + expectedGreen + "," + expectedBlue
- + "] but at position (" + row + "," + column + ") out of ("
- + bitmapWidth + "," + bitmapHeight + ") found ["
- + sourceAlpha + "," + sourceRed + ","
- + sourceGreen + "," + sourceBlue + "]";
+ + ": expected all drawable colors to be "
+ + formatColorToHex(color)
+ + " but at position (" + row + "," + column + ") out of ("
+ + bitmapWidth + "," + bitmapHeight + ") found "
+ + formatColorToHex(colorAtCurrPixel);
if (throwExceptionIfFails) {
throw new RuntimeException(mismatchDescription);
} else {
@@ -187,6 +165,73 @@
}
}
+ /**
+ * Checks whether the center pixel in the specified bitmap is of the same specified color.
+ *
+ * In case there is a color mismatch, the behavior of this method depends on the
+ * <code>throwExceptionIfFails</code> parameter. If it is <code>true</code>, this method will
+ * throw an <code>Exception</code> describing the mismatch. Otherwise this method will call
+ * <code>Assert.fail</code> with detailed description of the mismatch.
+ */
+ public static void assertCenterPixelOfColor(String failMessagePrefix, @NonNull Bitmap bitmap,
+ @ColorInt int color,
+ int allowedComponentVariance, boolean throwExceptionIfFails) {
+ final int centerX = bitmap.getWidth() / 2;
+ final int centerY = bitmap.getHeight() / 2;
+ final @ColorInt int colorAtCenterPixel = bitmap.getPixel(centerX, centerY);
+ if (!areColorsTheSameWithTolerance(color, colorAtCenterPixel,
+ allowedComponentVariance)) {
+ String mismatchDescription = failMessagePrefix
+ + ": expected all drawable colors to be "
+ + formatColorToHex(color)
+ + " but at position (" + centerX + "," + centerY + ") out of ("
+ + bitmap.getWidth() + "," + bitmap.getHeight() + ") found"
+ + formatColorToHex(colorAtCenterPixel);
+ if (throwExceptionIfFails) {
+ throw new RuntimeException(mismatchDescription);
+ } else {
+ Assert.fail(mismatchDescription);
+ }
+ }
+ }
+
+ /**
+ * Formats the passed integer-packed color into the #AARRGGBB format.
+ */
+ private static String formatColorToHex(@ColorInt int color) {
+ return String.format("#%08X", (0xFFFFFFFF & color));
+ }
+
+ /**
+ * Compares two integer-packed colors to be equal, each component within the specified
+ * allowed variance. Returns <code>true</code> if the two colors are sufficiently equal
+ * and <code>false</code> otherwise.
+ */
+ private static boolean areColorsTheSameWithTolerance(@ColorInt int expectedColor,
+ @ColorInt int actualColor, int allowedComponentVariance) {
+ int sourceAlpha = Color.alpha(actualColor);
+ int sourceRed = Color.red(actualColor);
+ int sourceGreen = Color.green(actualColor);
+ int sourceBlue = Color.blue(actualColor);
+
+ int expectedAlpha = Color.alpha(expectedColor);
+ int expectedRed = Color.red(expectedColor);
+ int expectedGreen = Color.green(expectedColor);
+ int expectedBlue = Color.blue(expectedColor);
+
+ int varianceAlpha = Math.abs(sourceAlpha - expectedAlpha);
+ int varianceRed = Math.abs(sourceRed - expectedRed);
+ int varianceGreen = Math.abs(sourceGreen - expectedGreen);
+ int varianceBlue = Math.abs(sourceBlue - expectedBlue);
+
+ boolean isColorMatch = (varianceAlpha <= allowedComponentVariance)
+ && (varianceRed <= allowedComponentVariance)
+ && (varianceGreen <= allowedComponentVariance)
+ && (varianceBlue <= allowedComponentVariance);
+
+ return isColorMatch;
+ }
+
public static void waitForActivityDestroyed(BaseTestActivity activity) {
while (!activity.isDestroyed()) {
SystemClock.sleep(30);
diff --git a/v7/appcompat/tests/src/android/support/v7/testutils/TestUtilsMatchers.java b/v7/appcompat/tests/src/android/support/v7/testutils/TestUtilsMatchers.java
index 2c20aa8..ac10d3b 100644
--- a/v7/appcompat/tests/src/android/support/v7/testutils/TestUtilsMatchers.java
+++ b/v7/appcompat/tests/src/android/support/v7/testutils/TestUtilsMatchers.java
@@ -117,7 +117,8 @@
* Returns a matcher that matches <code>View</code>s whose combined background starting
* from the view and up its ancestor chain matches the specified color.
*/
- public static Matcher isCombinedBackground(@ColorInt final int color) {
+ public static Matcher isCombinedBackground(@ColorInt final int color,
+ final boolean onlyTestCenterPixel) {
return new BoundedMatcher<View, View>(View.class) {
private String failedComparisonDescription;
@@ -133,9 +134,14 @@
// Create a bitmap with combined backgrounds of the view and its ancestors.
Bitmap combinedBackgroundBitmap = TestUtils.getCombinedBackgroundBitmap(view);
try {
- TestUtils.assertAllPixelsOfColor("", combinedBackgroundBitmap,
- combinedBackgroundBitmap.getWidth(),
- combinedBackgroundBitmap.getHeight(), color, 0, true);
+ if (onlyTestCenterPixel) {
+ TestUtils.assertCenterPixelOfColor("", combinedBackgroundBitmap,
+ color, 0, true);
+ } else {
+ TestUtils.assertAllPixelsOfColor("", combinedBackgroundBitmap,
+ combinedBackgroundBitmap.getWidth(),
+ combinedBackgroundBitmap.getHeight(), color, 0, true);
+ }
// If we are here, the color comparison has passed.
failedComparisonDescription = null;
return true;
diff --git a/v7/appcompat/tests/src/android/support/v7/widget/AppCompatSpinnerTest.java b/v7/appcompat/tests/src/android/support/v7/widget/AppCompatSpinnerTest.java
index 1d9ea9f..52dd727 100644
--- a/v7/appcompat/tests/src/android/support/v7/widget/AppCompatSpinnerTest.java
+++ b/v7/appcompat/tests/src/android/support/v7/widget/AppCompatSpinnerTest.java
@@ -77,8 +77,11 @@
// matching background.
String itemText = (String) spinner.getAdapter().getItem(2);
Matcher popupContentMatcher = hasChild(withText(itemText));
+ // Note that we are only testing the center pixel of the combined popup background. This
+ // is to "eliminate" otherwise hacky code that would need to skip over rounded corners and
+ // drop shadow of the combined visual appearance of a popup.
onView(popupContentMatcher).inRoot(isPlatformPopup()).check(
- matches(isCombinedBackground(expectedPopupColor)));
+ matches(isCombinedBackground(expectedPopupColor, true)));
// Click an entry in the popup to dismiss it
onView(withText(itemText)).perform(click());