Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(389)

Unified Diff: chrome/test/android/javatests/src/org/chromium/chrome/test/util/RenderUtils.java

Issue 2866103002: Add render test results to the results_details webpage. (Closed)
Patch Set: Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « build/android/test_runner.pydeps ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/test/android/javatests/src/org/chromium/chrome/test/util/RenderUtils.java
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/RenderUtils.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/RenderUtils.java
index 85438516e313581640aba653cd1adc18f68dafb5..221f03c75f5d6ceb79e3facc9fb48dae059bf9a0 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/RenderUtils.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/RenderUtils.java
@@ -7,6 +7,7 @@ package org.chromium.chrome.test.util;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
+import android.graphics.Color;
import android.graphics.Point;
import android.os.Build;
import android.view.View;
@@ -28,8 +29,12 @@ import java.util.concurrent.Callable;
public class RenderUtils {
private static final String TAG = "RenderUtils";
+ private static final String DIFF_FOLDER_RELATIVE = "/diffs";
+
private static final String FAILURE_FOLDER_RELATIVE = "/failures";
+ private static final String GOLDEN_FOLDER_RELATIVE = "/goldens";
+
/**
* This is a list of devices that we maintain golden images for. If render tests are being run
* on a device in this list, golden images should exist and their absence is a test failure.
@@ -45,6 +50,11 @@ public class RenderUtils {
*/
private static final boolean REPORT_ONLY_DO_NOT_FAIL = true;
+ /**
+ * How many pixels can be different in an image before counting the images as different.
+ */
+ private static final int PIXEL_DIFF_THRESHOLD = 0;
+
private enum ComparisonResult { MATCH, MISMATCH, GOLDEN_NOT_FOUND }
/**
@@ -72,11 +82,19 @@ public class RenderUtils {
private final Activity mActivity;
private final String mGoldenFolder;
private final String mTestClass;
+ private String mOutputDirectory;
public ViewRenderer(Activity activity, String goldenFolder, String testClass) {
mActivity = activity;
mGoldenFolder = goldenFolder;
mTestClass = testClass;
+
+ // Render test will output results to subdirectory of |goldenFolder| unless
+ // --render-test-output-dir is passed.
+ mOutputDirectory = CommandLine.getInstance().getSwitchValue("render-test-output-dir");
+ if (mOutputDirectory == null) {
+ mOutputDirectory = UrlUtils.getIsolatedTestFilePath(mGoldenFolder);
+ }
}
/**
@@ -93,20 +111,34 @@ public class RenderUtils {
*/
public void renderAndCompare(final View view, String id) throws IOException {
// Compare the image against the Golden.
- Bitmap bitmap = ThreadUtils.runOnUiThreadBlockingNoException(new Callable<Bitmap>() {
- @Override
- public Bitmap call() throws Exception {
- return UiUtils.generateScaledScreenshot(view, 0, Bitmap.Config.ARGB_8888);
- }
- });
+ Bitmap testBitmap =
+ ThreadUtils.runOnUiThreadBlockingNoException(new Callable<Bitmap>() {
+ @Override
+ public Bitmap call() throws Exception {
+ return UiUtils.generateScaledScreenshot(
+ view, 0, Bitmap.Config.ARGB_8888);
+ }
+ });
String imagename = imageName(mActivity, mTestClass, id);
- File goldenFile = createPath(mGoldenFolder, imagename);
- ComparisonResult result = compareBmpToGolden(bitmap, goldenFile);
- if (REPORT_ONLY_DO_NOT_FAIL && !isGenerateMode()) {
- Log.d(TAG, "Image comparison for %s: %s", id, result.name());
- return;
+ File goldenFile =
+ createPath(UrlUtils.getIsolatedTestFilePath(mGoldenFolder), imagename);
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ options.inPreferredConfig = testBitmap.getConfig();
+ Bitmap goldenBitmap = BitmapFactory.decodeFile(goldenFile.getAbsolutePath(), options);
+
+ Bitmap diffBitmap = null;
+ ComparisonResult result = null;
+
+ if (goldenBitmap == null) {
+ result = ComparisonResult.GOLDEN_NOT_FOUND;
+ } else {
+ diffBitmap = Bitmap.createBitmap(
+ Math.max(testBitmap.getWidth(), goldenBitmap.getWidth()),
+ Math.max(testBitmap.getHeight(), goldenBitmap.getHeight()),
+ testBitmap.getConfig());
+ result = compareBitmapToGolden(testBitmap, goldenBitmap, diffBitmap);
}
if (result == ComparisonResult.MATCH) {
@@ -116,12 +148,28 @@ public class RenderUtils {
return;
}
- // Save the rendered View.
- File failureFile = createPath(mGoldenFolder + FAILURE_FOLDER_RELATIVE, imagename);
- saveBitmap(bitmap, failureFile);
+ File failureOutputFile =
+ createPath(mOutputDirectory + FAILURE_FOLDER_RELATIVE, imagename);
+ saveBitmap(testBitmap, failureOutputFile);
+
+ if (result != ComparisonResult.GOLDEN_NOT_FOUND) {
+ File goldenOutputFile =
+ createPath(mOutputDirectory + GOLDEN_FOLDER_RELATIVE, imagename);
+ saveBitmap(goldenBitmap, goldenOutputFile);
+
+ File diffOutputFile =
+ createPath(mOutputDirectory + DIFF_FOLDER_RELATIVE, imagename);
+ saveBitmap(diffBitmap, diffOutputFile);
+ }
if (isGenerateMode()) {
- Log.i(TAG, "%s - generated image saved to %s.", id, failureFile.getAbsolutePath());
+ Log.i(TAG, "%s - generated image saved to %s.", id,
+ failureOutputFile.getAbsolutePath());
+ return;
+ }
+
+ if (REPORT_ONLY_DO_NOT_FAIL) {
+ Log.d(TAG, "Image comparison for %s: %s", id, result.name());
return;
}
@@ -137,8 +185,7 @@ public class RenderUtils {
} else if (result == ComparisonResult.MISMATCH) {
throw new ImageMismatchException(
String.format("Image comparison failed on %s. Failure image saved to %s.",
- id, failureFile.getAbsolutePath()));
-
+ id, failureOutputFile.getAbsolutePath()));
}
}
}
@@ -163,6 +210,9 @@ public class RenderUtils {
/**
* Creates an image name combining the image description with details about the device
* (eg model, current orientation).
+ *
+ * This function must be kept in sync with |RE_RENDER_IMAGE_NAME| from
+ * src/build/android/pylib/local/device/local_device_instrumentation_test_run.py.
*/
private static String imageName(Activity activity, String testClass, String desc) {
Point outSize = new Point();
@@ -185,14 +235,13 @@ public class RenderUtils {
}
/**
- * Convenience method to create a File pointing to |filename| in |folder| in the external
- * storage directory.
+ * Convenience method to create a File pointing to |filename| in |folder|.
* @throws IOException
*/
private static File createPath(String folder, String filename) throws IOException {
- File path = new File(UrlUtils.getIsolatedTestFilePath(folder));
+ File path = new File(folder);
if (!path.exists()) {
- if (!path.mkdir()) {
+ if (!path.mkdirs()) {
throw new IOException("Could not create " + path.getAbsolutePath());
}
}
@@ -202,12 +251,111 @@ public class RenderUtils {
/**
* Returns whether the given |bitmap| is equal to the one stored in |file|.
*/
- private static ComparisonResult compareBmpToGolden(Bitmap bitmap, File file) {
- BitmapFactory.Options options = new BitmapFactory.Options();
- options.inPreferredConfig = bitmap.getConfig();
- Bitmap golden = BitmapFactory.decodeFile(file.getAbsolutePath(), options);
+ private static ComparisonResult compareBitmapToGolden(Bitmap test, Bitmap golden, Bitmap diff) {
+ int maxWidth = Math.max(test.getWidth(), golden.getWidth());
+ int maxHeight = Math.max(test.getHeight(), golden.getHeight());
+ int minWidth = Math.min(test.getWidth(), golden.getWidth());
+ int minHeight = Math.min(test.getHeight(), golden.getHeight());
- if (golden == null) return ComparisonResult.GOLDEN_NOT_FOUND;
- return bitmap.sameAs(golden) ? ComparisonResult.MATCH : ComparisonResult.MISMATCH;
+ int diffPixelsCount = comparePixels(test, golden, diff, 0, 0, minWidth, 0, minHeight)
+ + compareSizes(diff, minWidth, maxWidth, minHeight, maxHeight);
+
+ if (diffPixelsCount > PIXEL_DIFF_THRESHOLD) {
+ return ComparisonResult.MISMATCH;
+ }
+ return ComparisonResult.MATCH;
+ }
+
+ /**
+ * Compares two bitmaps pixel-wise.
+ *
+ * @param testImage Bitmap of test image.
+ *
+ * @param goldenImage Bitmap of golden image.
+ *
+ * @param diffImage This is an output argument. Function will set pixels in the |diffImage| to
+ * either transparent or red depending on whether that pixel differed in the golden and test
+ * bitmaps. diffImage should have its width and height be the max width and height of the
+ * golden and test bitmaps.
+ *
+ * @param diffThreshold Threshold for when to consider two color values as different. These
+ * values are 8 bit (256) so this threshold value should be in range 0-256.
+ *
+ * @param startWidth Start x-coord to start diffing the Bitmaps.
+ *
+ * @param endWidth End x-coord to start diffing the Bitmaps.
+ *
+ * @param startHeight Start y-coord to start diffing the Bitmaps.
+ *
+ * @param endHeight End x-coord to start diffing the Bitmaps.
+ *
+ * @return Returns number of pixels that differ between |goldenImage| and |testImage|
+ */
+ private static int comparePixels(Bitmap testImage, Bitmap goldenImage, Bitmap diffImage,
+ int diffThreshold, int startWidth, int endWidth, int startHeight, int endHeight) {
+ int diffPixels = 0;
+
+ for (int x = startWidth; x < endWidth; x++) {
+ for (int y = startHeight; y < endHeight; y++) {
+ int goldenImageColor = goldenImage.getPixel(x, y);
+ int testImageColor = testImage.getPixel(x, y);
+
+ int redDiff = Math.abs(Color.red(goldenImageColor) - Color.red(testImageColor));
+ int blueDiff =
+ Math.abs(Color.green(goldenImageColor) - Color.green(testImageColor));
+ int greenDiff = Math.abs(Color.blue(goldenImageColor) - Color.blue(testImageColor));
+ int alphaDiff =
+ Math.abs(Color.alpha(goldenImageColor) - Color.alpha(testImageColor));
+
+ if (redDiff > diffThreshold || blueDiff > diffThreshold || greenDiff > diffThreshold
+ || alphaDiff > diffThreshold) {
+ diffPixels++;
+ diffImage.setPixel(x, y, Color.RED);
+ } else {
+ diffImage.setPixel(x, y, Color.TRANSPARENT);
+ }
+ }
+ }
+ return diffPixels;
+ }
+
+ /**
+ * Compares two bitmaps size.
+ *
+ * @param diffImage This is an output argument. Function will set pixels in the |diffImage| to
+ * either transparent or red depending on whether that pixel coordinate occurs in the
+ * dimensions of the golden and not the test bitmap or vice-versa.
+ *
+ * @param minWidth Min width of golden and test bitmaps.
+ *
+ * @param maxWidth Max width of golden and test bitmaps.
+ *
+ * @param minHeight Min height of golden and test bitmaps.
+ *
+ * @param maxHeight Max height of golden and test bitmaps.
+ *
+ * @return Returns number of pixels that differ between |goldenImage| and |testImage| due to
+ * their size.
+ */
+ private static int compareSizes(
+ Bitmap diffImage, int minWidth, int maxWidth, int minHeight, int maxHeight) {
+ int diffPixels = 0;
+ if (maxWidth > minWidth) {
+ for (int x = minWidth; x < maxWidth; x++) {
+ for (int y = 0; y < maxHeight; y++) {
+ diffImage.setPixel(x, y, Color.RED);
+ }
+ }
+ diffPixels += (maxWidth - minWidth) * maxHeight;
+ }
+ if (maxHeight > minHeight) {
+ for (int x = 0; x < maxWidth; x++) {
+ for (int y = minHeight; y < maxHeight; y++) {
+ diffImage.setPixel(x, y, Color.RED);
+ }
+ }
+ diffPixels += (maxHeight - minHeight) * minWidth;
+ }
+ return diffPixels;
}
}
« no previous file with comments | « build/android/test_runner.pydeps ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698