package qz.printer.action; import javafx.print.*; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import qz.common.Constants; import qz.printer.action.html.WebApp; import qz.printer.action.html.WebAppModel; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; public class WebAppTest { private static final Logger log = LogManager.getLogger(WebAppTest.class); private static final int SPOOLER_WAIT = 2000; // millis private static final Path RASTER_OUTPUT_DIR = Paths.get("./out"); // see ant ${out.dir} private static final String RASTER_OUTPUT_FORMAT = "png"; public static void main(String[] args) { try { WebApp.initialize(); cleanup(); // RASTER// int rasterKnownHeightTests = 1000; if (args.length > 1) { rasterKnownHeightTests = Integer.parseInt(args[1]); } int rasterFittedHeightTests = 1000; if (args.length > 2) { rasterFittedHeightTests = Integer.parseInt(args[2]); } if (!testRasterKnownSize(rasterKnownHeightTests)) { log.error("Testing well defined sizes failed"); } else if (!testRasterFittedSize(rasterFittedHeightTests)) { log.error("Testing fit to height sizing failed"); } else { log.info("All raster tests passed"); } // VECTOR // int vectorKnownHeightPrints = 100; if (args.length > 3) { vectorKnownHeightPrints = Integer.parseInt(args[3]); } int vectorFittedHeightPrints = 100; if (args.length > 4) { vectorFittedHeightPrints = Integer.parseInt(args[4]); } if (!testVectorKnownPrints(vectorKnownHeightPrints)) { log.error("Failed vector prints with defined heights"); } else if (!testVectorFittedPrints(vectorFittedHeightPrints)) { log.error("Failed vector prints with fit to height sizing"); } else { log.info("All vector prints completed"); } } catch(Throwable t) { log.error("Tests failed due to an exception", t); } System.exit(0); //explicit exit since jfx is running in background } public static boolean testRasterKnownSize(int trials) throws Throwable { for(int i = 0; i < trials; i++) { //new size every run double printW = Math.max(2, (int)(Math.random() * 110) / 10d) * 72d; double printH = Math.max(3, (int)(Math.random() * 110) / 10d) * 72d; double zoom = Math.max(0.5d, (int)(Math.random() * 30) / 10d); String id = "known-" + i; WebAppModel model = buildModel(id, printW, printH, zoom, true, (int)(Math.random() * 360)); BufferedImage sample = WebApp.raster(model); if (sample == null) { log.error("Failed to create capture"); return false; } //TODO - check bottom right matches expected color //check capture for dimensional accuracy within 1 pixel of expected (due to int rounding) int expectedWidth = (int)Math.round(printW * (96d / 72d) * zoom); int expectedHeight = (int)Math.round(printH * (96d / 72d) * zoom); boolean passed = true; if (!Arrays.asList(expectedWidth, expectedWidth + 1, expectedWidth - 1).contains(sample.getWidth())) { log.error("Expected width to be {} but got {}", expectedWidth, sample.getWidth()); passed = false; } if (!Arrays.asList(expectedHeight, expectedHeight + 1, expectedHeight - 1).contains(sample.getHeight())) { log.error("Expected height to be {} but got {}", expectedHeight, sample.getHeight()); passed = false; } saveAudit(passed? id:"invalid", sample); if (!passed) { return false; } } return true; } public static boolean testRasterFittedSize(int trials) throws Throwable { for(int i = 0; i < trials; i++) { //new size every run (height always starts at 0) double printW = Math.max(2, (int)(Math.random() * 110) / 10d) * 72d; double zoom = Math.max(0.5d, (int)(Math.random() * 30) / 10d); String id = "fitted-" + i; WebAppModel model = buildModel(id, printW, 0, zoom, true, (int)(Math.random() * 360)); BufferedImage sample = WebApp.raster(model); if (sample == null) { log.error("Failed to create capture"); return false; } //TODO - check bottom right matches expected color //check capture for dimensional accuracy within 1 pixel of expected (due to int rounding) //expected height is not known for these tests int expectedWidth = (int)Math.round(printW * (96d / 72d) * zoom); boolean passed = true; if (!Arrays.asList(expectedWidth, expectedWidth + 1, expectedWidth - 1).contains(sample.getWidth())) { log.error("Expected width to be {} but got {}", expectedWidth, sample.getWidth()); passed = false; } saveAudit(passed? id:"invalid", sample); if (!passed) { return false; } } return true; } public static boolean testVectorKnownPrints(int trials) throws Throwable { PrinterJob job = buildVectorJob("vector-test-known"); for(int i = 0; i < trials; i++) { //new size every run double printW = Math.max(2, (int)(Math.random() * 85) / 10d) * 72d; double printH = Math.max(3, (int)(Math.random() * 110) / 10d) * 72d; String id = "known-" + i; WebAppModel model = buildModel(id, printW, printH, 1, false, (int)(Math.random() * 360)); WebApp.print(job, model); } job.endJob(); try { log.info("Waiting {} seconds for the spooler to catch up.", SPOOLER_WAIT / 1000); Thread.sleep(SPOOLER_WAIT); } catch(InterruptedException ignore) {} return job.getJobStatus() != PrinterJob.JobStatus.ERROR; } public static boolean testVectorFittedPrints(int trials) throws Throwable { PrinterJob job = buildVectorJob("vector-test-fitted"); for(int i = 0; i < trials; i++) { //new size every run double printW = Math.max(2, (int)(Math.random() * 85) / 10d) * 72d; String id = "fitted-" + i; WebAppModel model = buildModel(id, printW, 0, 1, false, (int)(Math.random() * 360)); WebApp.print(job, model); } job.endJob(); try { log.info("Waiting {} seconds for the spooler to catch up.", SPOOLER_WAIT / 1000); Thread.sleep(SPOOLER_WAIT); } catch(InterruptedException ignore) {} return job.getJobStatus() != PrinterJob.JobStatus.ERROR; } private static WebAppModel buildModel(String index, double width, double height, double zoom, boolean scale, int hue) { int level = (int)(Math.random() * 50) + 25; WebAppModel model = new WebAppModel("" + "
" + "| Generated content: | " + "" + index + " | " + "
| Content size: | " + "" + width + "x" + height + " | " + "
| Physical size: | " + "" + (width / 72d) + "x" + (height / 72d) + " | " + "
| Zoomed to | " + "x " + zoom + " | " + "