From 7166ac47c58a4a8acccebb07ae9395773ad9958e Mon Sep 17 00:00:00 2001 From: Lena Date: Sat, 1 Aug 2026 00:00:00 +0000 Subject: test-rig: exercise release paths --- test-rig/Pixhash.java | 68 +++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 58 insertions(+), 10 deletions(-) (limited to 'test-rig/Pixhash.java') diff --git a/test-rig/Pixhash.java b/test-rig/Pixhash.java index b35a560..3bd8c8a 100644 --- a/test-rig/Pixhash.java +++ b/test-rig/Pixhash.java @@ -1,9 +1,9 @@ -// Verify that a screencap PNG is non-uniform - i.e., MediaCodec -// actually painted something. Exits 0 if the image has at least -// `--min` percent of pixels that differ from pixel (0,0); 1 otherwise. +// Verify a screencap. The default checks non-uniformity. --pattern also +// requires the four large color fields drawn by the debug Pattern activity, +// so ordinary app chrome cannot make a black video surface pass. // // java test-rig/Pixhash.java # default min=5% -// java test-rig/Pixhash.java --min 1 +// java test-rig/Pixhash.java --pattern // // ImageIO/BufferedImage live in java.desktop, which the image's // openjdk-17-jdk-headless package does ship (headless only disables @@ -17,16 +17,26 @@ import java.awt.image.BufferedImage; public final class Pixhash { public static void main(String[] args) throws IOException { - if (args.length < 1) { - System.err.println("usage: java Pixhash.java [--min N]"); - System.exit(2); - } + if (args.length < 1) usage(); double minPercent = 5.0; + boolean pattern = false; for (int i = 1; i < args.length; i++) { - if ("--min".equals(args[i]) && i + 1 < args.length) { - minPercent = Double.parseDouble(args[++i]); + if ("--min".equals(args[i])) { + if (++i >= args.length) usage(); + try { + minPercent = Double.parseDouble(args[i]); + } catch (NumberFormatException e) { + usage(); + } + } else if ("--pattern".equals(args[i])) { + pattern = true; + } else { + usage(); } } + if (!Double.isFinite(minPercent) || minPercent < 0.0 || minPercent > 100.0) { + usage(); + } BufferedImage img = ImageIO.read(new File(args[0])); if (img == null) { @@ -50,5 +60,43 @@ public final class Pixhash { System.err.printf("pixhash: only %.2f%% differ, need %.2f%%%n", pct, minPercent); System.exit(1); } + if (pattern) checkPattern(img); + } + + private static void usage() { + System.err.println("usage: java Pixhash.java [--min N] [--pattern]"); + System.exit(2); + } + + private static void checkPattern(BufferedImage img) { + long red = 0, green = 0, blue = 0, yellow = 0, sampled = 0; + // Sampling every fourth pixel keeps the check cheap on 1080p images. + for (int y = 0; y < img.getHeight(); y += 4) { + for (int x = 0; x < img.getWidth(); x += 4) { + int rgb = img.getRGB(x, y); + int r = (rgb >>> 16) & 0xff; + int g = (rgb >>> 8) & 0xff; + int b = rgb & 0xff; + sampled++; + if (r >= 140 && g <= 110 && b <= 110) red++; + else if (g >= 110 && r <= 120 && b <= 120) green++; + else if (b >= 140 && r <= 110 && g <= 130) blue++; + else if (r >= 140 && g >= 120 && b <= 120) yellow++; + } + } + double rp = 100.0 * red / sampled; + double gp = 100.0 * green / sampled; + double bp = 100.0 * blue / sampled; + double yp = 100.0 * yellow / sampled; + System.out.printf("pixhash: pattern red=%.2f green=%.2f blue=%.2f yellow=%.2f%%%n", + rp, gp, bp, yp); + // A rotated 16:9 target fills only about one third of a portrait + // source after correct letterboxing. Require every field and strong + // combined coverage rather than assuming the video fills the screen. + if (rp < 5.0 || gp < 5.0 || bp < 5.0 || yp < 5.0 + || rp + gp + bp + yp < 25.0) { + System.err.println("pixhash: expected four-color target pattern was not rendered"); + System.exit(1); + } } } -- cgit v1.2.3