diff --git a/.gitignore b/.gitignore index 05d601f..866c9fd 100644 --- a/.gitignore +++ b/.gitignore @@ -39,6 +39,7 @@ target/ # Test test-output/ +scripts/codacy-coverage-reporter-assembly.jar # Local helpers local/ diff --git a/.travis.yml b/.travis.yml index db0b00b..68bb321 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,9 +14,9 @@ install: - ant package script: + - xvfb-run ant report - docker run -v=$(pwd):/app --workdir=/app coala/base coala --ci - - ant report after_success: - curl https://secure.central.sonatype.com/maven2/com/codacy/codacy-coverage-reporter/1.0.13/codacy-coverage-reporter-1.0.13-assembly.jar > codacy-coverage-reporter-assembly.jar - - java -cp codacy-coverage-reporter-assembly.jar com.codacy.CodacyCoverageReporter -l Java -r test/site/jacoco/report.xml + - java -cp codacy-coverage-reporter-assembly.jar com.codacy.CodacyCoverageReporter -l Java -r test-output/site/jacoco/report.xml diff --git a/lib/test/commons-io-2.5-javadoc.jar b/lib/test/commons-io-2.5-javadoc.jar new file mode 100644 index 0000000..b957529 Binary files /dev/null and b/lib/test/commons-io-2.5-javadoc.jar differ diff --git a/lib/test/commons-io-2.5.jar b/lib/test/commons-io-2.5.jar new file mode 100644 index 0000000..1234918 Binary files /dev/null and b/lib/test/commons-io-2.5.jar differ diff --git a/scripts/upload-coverage-report.sh b/scripts/upload-coverage-report.sh new file mode 100755 index 0000000..8fd4c30 --- /dev/null +++ b/scripts/upload-coverage-report.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +root=$(dirname "${BASH_SOURCE}")/.. + +# Download https://secure.central.sonatype.com/maven2/com/codacy/codacy-coverage-reporter/1.0.13/codacy-coverage-reporter-1.0.13-assembly.jar +# curl https://secure.central.sonatype.com/maven2/com/codacy/codacy-coverage-reporter/1.0.13/codacy-coverage-reporter-1.0.13-assembly.jar > codacy-coverage-reporter-assembly.jar +cd ${root} +# Set the token first: +# export CODACY_PROJECT_TOKEN=%Project_Token% +COMMIT=$(git log -n 1 --pretty=format:"%H") +echo ${COMMIT} +java -cp ./scripts/codacy-coverage-reporter-assembly.jar com.codacy.CodacyCoverageReporter -l Java --commitUUID ${COMMIT} -r ./test-output/site/jacoco/report.xml +cd - > /dev/null diff --git a/src/rprocessing/Runner.java b/src/rprocessing/Runner.java index 85fcf1f..d4a7a22 100644 --- a/src/rprocessing/Runner.java +++ b/src/rprocessing/Runner.java @@ -1,11 +1,11 @@ package rprocessing; import org.renjin.eval.EvalException; + import rprocessing.exception.NotFoundException; import rprocessing.exception.REvalException; import rprocessing.lancher.StandaloneSketch; import rprocessing.util.Printer; -import rprocessing.util.RScriptReader; import rprocessing.util.StreamPrinter; /** @@ -17,11 +17,11 @@ public class Runner { public static RunnableSketch sketch; - @SuppressWarnings("unused") - private static final String CORE_TEXT = - RScriptReader.readResourceAsText(Runner.class, "r/core.R"); + // private static final String CORE_TEXT = + // RScriptReader.readResourceAsText(Runner.class, "r/core.R"); - private static final boolean VERBOSE = Boolean.parseBoolean(System.getenv("VERBOSE_RLANG_MODE")); + private static final boolean VERBOSE = Boolean.parseBoolean(System + .getenv("VERBOSE_RLANG_MODE")); private static void log(final Object... objs) { if (!VERBOSE) { @@ -39,7 +39,8 @@ public static void main(final String[] args) throws Exception { } try { sketch = new StandaloneSketch(args); - runSketchBlocking(sketch, new StreamPrinter(System.out), new StreamPrinter(System.err)); + runSketchBlocking(sketch, new StreamPrinter(System.out), new StreamPrinter( + System.err)); } catch (final Throwable t) { System.err.println(t); System.exit(-1); @@ -47,14 +48,15 @@ public static void main(final String[] args) throws Exception { } public static synchronized void runSketchBlocking(final RunnableSketch sketch, - final Printer stdout, final Printer stderr) throws REvalException, NotFoundException { + final Printer stdout, final Printer stderr) throws REvalException, + NotFoundException { runSketchBlocking(sketch, stdout, stderr, null); } public static synchronized void runSketchBlocking(final RunnableSketch sketch, final Printer stdout, final Printer stderr, - final SketchPositionListener sketchPositionListener) - throws REvalException, NotFoundException { + final SketchPositionListener sketchPositionListener) throws REvalException, + NotFoundException { final String[] args = sketch.getPAppletArguments(); log("Tring to initialize RLangPApplet."); diff --git a/src/test/e2e/core/E2eTestBase.java b/src/test/e2e/core/E2eTestBase.java new file mode 100644 index 0000000..637b461 --- /dev/null +++ b/src/test/e2e/core/E2eTestBase.java @@ -0,0 +1,55 @@ +package test.e2e.core; + +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import rprocessing.Runner; +import test.e2e.util.ImageUtils; +import test.e2e.util.TempFile; + +public abstract class E2eTestBase { + + protected static float THRESHOLD = (float) 0.01; + protected static String SAVE_CODE_TEMPLATE = "processing$saveFrame(\"%s\")\nprocessing$exit()"; + + protected String code; + protected String coreCode; + protected String referenceURI; + + protected String referenceImage(String path) throws MalformedURLException { + return "https://processing.org/reference/images/" + path; + } + + protected float diffImage(File file, String fileURL) throws MalformedURLException, IOException { + return ImageUtils.DiffImage(file, new URL(fileURL)); + } + + protected float diffImageWithProcessingReference(File file, String referenceURL) + throws MalformedURLException, IOException { + return diffImage(file, referenceImage(referenceURL)); + } + + protected void runSketch(String path) throws Exception { + String[] args = new String[] {path}; + Runner.main(args); + } + + protected void defaultOperation() throws Exception { + // Create temp sketch file and image file. + File saveFile = TempFile.createTempImage(); + code = assembleCode(saveFile.getCanonicalPath()); + File sketchFile = TempFile.createSketchTempFile(code); + System.out.println("## Code to test\n"); + System.out.println(code); + + // Run the sketch and save the image to saveFile. + this.runSketch(sketchFile.getCanonicalPath()); + + assert (diffImageWithProcessingReference(saveFile, referenceURI) < THRESHOLD); + } + + protected String assembleCode(String filename) { + return coreCode + "\n" + String.format(SAVE_CODE_TEMPLATE, filename); + } +} diff --git a/src/test/e2e/core/primitives2d/TriangleTest.java b/src/test/e2e/core/primitives2d/TriangleTest.java new file mode 100644 index 0000000..6439183 --- /dev/null +++ b/src/test/e2e/core/primitives2d/TriangleTest.java @@ -0,0 +1,27 @@ +package test.e2e.core.primitives2d; + +import static org.junit.Assert.fail; +import org.junit.Test; +import test.e2e.core.E2eTestBase; + +/** + * + * @author github.com/gaocegege + */ +public class TriangleTest extends E2eTestBase { + + public TriangleTest() { + coreCode = "processing$triangle(30, 75, 58, 20, 86, 75)"; + referenceURI = "triangle_.png"; + } + + @Test + public void test() { + try { + defaultOperation(); + } catch (Exception exception) { + System.err.println(exception); + fail("Should not have thrown any exception"); + } + } +} diff --git a/src/test/e2e/util/ImageUtils.java b/src/test/e2e/util/ImageUtils.java new file mode 100644 index 0000000..6b75ebe --- /dev/null +++ b/src/test/e2e/util/ImageUtils.java @@ -0,0 +1,45 @@ +package test.e2e.util; + +import java.io.File; +import java.io.IOException; +import java.net.URL; + +import javax.imageio.ImageIO; + +import processing.core.PApplet; +import processing.core.PImage; + +/** + * + * @author github.com/gaocegege + */ +public class ImageUtils { + public static float DiffImage(File actualFile, URL testURL) throws IOException { + PImage actualImage = new PImage(ImageIO.read(actualFile)); + PImage testImage = new PImage(ImageIO.read(testURL)); + + return imgDifference(actualImage, testImage); + } + + private static float imgDifference(PImage i0, PImage i1) { + float diff = 0; + i0.loadPixels(); + int[] ip0 = i0.pixels; + i1.loadPixels(); + int[] ip1 = i1.pixels; + for (int n = 0; n < ip0.length; n++) { + int pxl0 = ip0[n], r0, g0, b0; + int pxl1 = ip1[n], r1, g1, b1; + r0 = (pxl0 >> 20) & 0xF; + g0 = (pxl0 >> 12) & 0xF; + b0 = (pxl0 >> 4) & 0xF; + r1 = (pxl1 >> 20) & 0xF; + g1 = (pxl1 >> 12) & 0xF; + b1 = (pxl1 >> 4) & 0xF; + diff += PApplet.abs(r0 - r1) + PApplet.abs(g0 - g1) + PApplet.abs(b0 - b1); + } + // Each colour channel can have a difference 0-15 + // Considering 3 colour channels (ignoring alpha) + return diff / (ip0.length * 3 * 15); + } +} diff --git a/src/test/e2e/util/TempFile.java b/src/test/e2e/util/TempFile.java new file mode 100644 index 0000000..e422021 --- /dev/null +++ b/src/test/e2e/util/TempFile.java @@ -0,0 +1,34 @@ +package test.e2e.util; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import org.apache.commons.io.FileUtils; + +/** + * TempFile creates the tempfile and delete it when exits. + * + * @author github.com/gaocegege + */ +public class TempFile { + private static String SKETCH_PREFIX = "Processing.R."; + private static String SKETCH_SUFFIX = ".tmp.rpde"; + private static String PNG_SUFFIX = ".tmp.png"; + + public static File createTempImage() throws IOException { + // this temporary file remains after the jvm exits. + File tempFile = File.createTempFile(SKETCH_PREFIX, PNG_SUFFIX); + tempFile.deleteOnExit(); + + return tempFile; + } + + public static File createSketchTempFile(String code) throws IOException { + // this temporary file remains after the jvm exits. + File tempFile = File.createTempFile(SKETCH_PREFIX, SKETCH_SUFFIX); + tempFile.deleteOnExit(); + + FileUtils.writeStringToFile(tempFile, code, Charset.defaultCharset()); + return tempFile; + } +}