X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=core%2Ftest%2Fsrc%2Fcom%2Fgoogle%2Fzxing%2Fcommon%2FAbstractBlackBoxTestCase.java;h=16dc1bbdeb606b599a71abb512e0d052bcded8f8;hb=222e0acc7f38874333e21892b6e85e983ccdf15a;hp=6695c4b23bbac6d8aed77e4cf2f12435e52e53d2;hpb=72e8850d9af1243e1e79dbb54c474f4d81238b42;p=zxing.git diff --git a/core/test/src/com/google/zxing/common/AbstractBlackBoxTestCase.java b/core/test/src/com/google/zxing/common/AbstractBlackBoxTestCase.java index 6695c4b2..16dc1bbd 100644 --- a/core/test/src/com/google/zxing/common/AbstractBlackBoxTestCase.java +++ b/core/test/src/com/google/zxing/common/AbstractBlackBoxTestCase.java @@ -1,5 +1,5 @@ /* - * Copyright 2008 Google Inc. + * Copyright 2008 ZXing authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,23 +26,29 @@ import com.google.zxing.client.j2se.BufferedImageMonochromeBitmapSource; import junit.framework.TestCase; import javax.imageio.ImageIO; +import java.awt.geom.AffineTransform; +import java.awt.image.AffineTransformOp; import java.awt.image.BufferedImage; +import java.awt.image.BufferedImageOp; import java.io.File; import java.io.FileInputStream; import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStreamReader; -import java.net.URL; import java.util.Hashtable; +import java.util.List; +import java.util.ArrayList; +import java.nio.charset.Charset; /** - * @author srowen@google.com (Sean Owen) + * @author Sean Owen + * @author dswitkin@google.com (Daniel Switkin) */ public abstract class AbstractBlackBoxTestCase extends TestCase { - private static final Hashtable TRY_HARDER_HINT; + protected static final Hashtable TRY_HARDER_HINT; static { - TRY_HARDER_HINT = new Hashtable(); + TRY_HARDER_HINT = new Hashtable(); TRY_HARDER_HINT.put(DecodeHintType.TRY_HARDER, Boolean.TRUE); } @@ -50,97 +56,164 @@ public abstract class AbstractBlackBoxTestCase extends TestCase { public boolean accept(File dir, String name) { String lowerCase = name.toLowerCase(); return lowerCase.endsWith(".jpg") || lowerCase.endsWith(".jpeg") || - lowerCase.endsWith(".gif") || lowerCase.endsWith(".png") || - lowerCase.endsWith(".url"); + lowerCase.endsWith(".gif") || lowerCase.endsWith(".png"); } }; + private static class TestResult { + private final int mustPassCount; + private final int tryHarderCount; + private final float rotation; + + TestResult(int mustPassCount, int tryHarderCount, float rotation) { + this.mustPassCount = mustPassCount; + this.tryHarderCount = tryHarderCount; + this.rotation = rotation; + } + public int getMustPassCount() { + return mustPassCount; + } + public int getTryHarderCount() { + return tryHarderCount; + } + public float getRotation() { + return rotation; + } + } + private final File testBase; private final Reader barcodeReader; - private final int mustPassCount; private final BarcodeFormat expectedFormat; + private final List testResults; - protected AbstractBlackBoxTestCase(File testBase, + protected AbstractBlackBoxTestCase(String testBasePathSuffix, Reader barcodeReader, - int mustPassCount, BarcodeFormat expectedFormat) { + // A little workaround to prevent aggravation in my IDE + File testBase = new File(testBasePathSuffix); + if (!testBase.exists()) { + // try starting with 'core' since the test base is often given as the project root + testBase = new File("core/" + testBasePathSuffix); + } this.testBase = testBase; this.barcodeReader = barcodeReader; - this.mustPassCount = mustPassCount; this.expectedFormat = expectedFormat; + testResults = new ArrayList(); } - public void testBlackBox() throws IOException { + /** + * Adds a new test for the current directory of images. + * + * @param mustPassCount The number of images which must decode for the test to pass. + * @param tryHarderCount The number of images which must pass using the try harder flag. + * @param rotation The rotation in degrees clockwise to use for this test. + */ + protected void addTest(int mustPassCount, int tryHarderCount, float rotation) { + testResults.add(new TestResult(mustPassCount, tryHarderCount, rotation)); + } + protected File[] getImageFiles() { assertTrue("Please run from the 'core' directory", testBase.exists()); + return testBase.listFiles(IMAGE_NAME_FILTER); + } + + protected Reader getReader() { + return barcodeReader; + } + + protected Hashtable getHints() { + return null; + } - File[] imageFiles = testBase.listFiles(IMAGE_NAME_FILTER); - int passedCount = 0; + public void testBlackBox() throws IOException { + assertFalse(testResults.isEmpty()); + + File[] imageFiles = getImageFiles(); + int testCount = testResults.size(); + int[] passedCounts = new int[testCount]; + int[] tryHarderCounts = new int[testCount]; for (File testImage : imageFiles) { System.out.println("Starting " + testImage.getAbsolutePath()); - BufferedImage image; - if (testImage.getName().endsWith(".url")) { - String urlString = readFileAsString(testImage); - image = ImageIO.read(new URL(urlString)); - } else { - image = ImageIO.read(testImage); - } - MonochromeBitmapSource source = new BufferedImageMonochromeBitmapSource(image); - Result result; - try { - result = barcodeReader.decode(source); - } catch (ReaderException re) { - System.out.println(re); - continue; - } - - if (expectedFormat != result.getBarcodeFormat()) { - System.out.println("Format mismatch: expected '" + expectedFormat + "' but got '" + - result.getBarcodeFormat() + '\''); - continue; - } + BufferedImage image = ImageIO.read(testImage); String testImageFileName = testImage.getName(); File expectedTextFile = new File(testBase, testImageFileName.substring(0, testImageFileName.indexOf('.')) + ".txt"); String expectedText = readFileAsString(expectedTextFile); - String resultText = result.getText(); - - boolean passed = expectedText.equals(resultText); - if (passed) { - passedCount++; - } else { - System.out.println("Mismatch: expected '" + expectedText + "' but got '" + resultText + '\''); - continue; - } - // Try "try harder" mode - try { - result = barcodeReader.decode(source, TRY_HARDER_HINT); - } catch (ReaderException re) { - if (passed) { - fail("Normal mode succeeded but \"try harder\" failed"); + for (int x = 0; x < testCount; x++) { + float rotation = testResults.get(x).getRotation(); + BufferedImage rotatedImage = rotateImage(image, rotation); + MonochromeBitmapSource source = new BufferedImageMonochromeBitmapSource(rotatedImage); + if (decode(source, rotation, expectedText, false)) { + passedCounts[x]++; + } + if (decode(source, rotation, expectedText, true)) { + tryHarderCounts[x]++; } - continue; } - if (expectedFormat != result.getBarcodeFormat()) { - System.out.println("Try Harder Format mismatch: expected '" + expectedFormat + "' but got '" + - result.getBarcodeFormat() + '\''); - } else if (!expectedText.equals(resultText)) { - System.out.println("Try Harder Mismatch: expected '" + expectedText + "' but got '" + - resultText + '\''); + } + + // Print the results of all tests first + for (int x = 0; x < testCount; x++) { + System.out.println("Rotation " + testResults.get(x).getRotation() + " degrees:"); + System.out.println(" " + passedCounts[x] + " of " + imageFiles.length + " images passed (" + + testResults.get(x).getMustPassCount() + " required)"); + System.out.println(" " + tryHarderCounts[x] + " of " + imageFiles.length + + " images passed with try harder (" + testResults.get(x).getTryHarderCount() + + " required)"); + } + + // Then run through again and assert if any failed + for (int x = 0; x < testCount; x++) { + assertTrue("Rotation " + testResults.get(x).getRotation() + + " degrees: Too many images failed", + passedCounts[x] >= testResults.get(x).getMustPassCount()); + assertTrue("Try harder, Rotation " + testResults.get(x).getRotation() + + " degrees: Too many images failed", + tryHarderCounts[x] >= testResults.get(x).getTryHarderCount()); + } + } + + private boolean decode(MonochromeBitmapSource source, float rotation, String expectedText, + boolean tryHarder) { + Result result; + String suffix = " (" + (tryHarder ? "try harder, " : "") + "rotation: " + rotation + ')'; + + try { + Hashtable hints = getHints(); + if (tryHarder) { + if (hints == null) { + hints = TRY_HARDER_HINT; + } else { + hints.put(DecodeHintType.TRY_HARDER, Boolean.TRUE); + } } + result = barcodeReader.decode(source, hints); + } catch (ReaderException re) { + System.out.println(re + suffix); + return false; + } + + if (!expectedFormat.equals(result.getBarcodeFormat())) { + System.out.println("Format mismatch: expected '" + expectedFormat + "' but got '" + + result.getBarcodeFormat() + '\'' + suffix); + return false; } - System.out.println(passedCount + " of " + imageFiles.length + " images passed (" + - mustPassCount + " required)"); - assertTrue("Too many images failed", passedCount >= mustPassCount); + String resultText = result.getText(); + if (!expectedText.equals(resultText)) { + System.out.println("Mismatch: expected '" + expectedText + "' but got '" + resultText + + '\'' + suffix); + return false; + } + return true; } private static String readFileAsString(File file) throws IOException { - StringBuilder result = new StringBuilder(); - InputStreamReader reader = new InputStreamReader(new FileInputStream(file), "UTF-8"); + StringBuilder result = new StringBuilder((int) file.length()); + InputStreamReader reader = new InputStreamReader(new FileInputStream(file), Charset.forName("UTF8")); try { char[] buffer = new char[256]; int charsRead; @@ -153,4 +226,15 @@ public abstract class AbstractBlackBoxTestCase extends TestCase { return result.toString(); } + protected static BufferedImage rotateImage(BufferedImage original, float degrees) { + if (degrees == 0.0f) { + return original; + } else { + AffineTransform at = new AffineTransform(); + at.rotate(Math.toRadians(degrees), original.getWidth() / 2.0, original.getHeight() / 2.0); + BufferedImageOp op = new AffineTransformOp(at, AffineTransformOp.TYPE_BICUBIC); + return op.filter(original, null); + } + } + } \ No newline at end of file