diff --git a/.github/scripts/verify-test-reports.py b/.github/scripts/verify-test-reports.py new file mode 100644 index 0000000..98aa65c --- /dev/null +++ b/.github/scripts/verify-test-reports.py @@ -0,0 +1,26 @@ +"""Reject missing, empty, failed, skipped, duplicate or incomplete test reports.""" +from pathlib import Path +import xml.etree.ElementTree as ET + +reports = list(Path('target/surefire-reports').glob('TEST-*.xml')) +assert reports, 'No Surefire XML reports found' +expected = { + 'jargs.test.gnu.CmdLineParserTestCase': 11, + 'jargs.test.gnu.CustomOptionTestCase': 2, + 'com.yahoo.platform.yui.compressor.CompressionTest': 4, +} +seen = set() +counts = {} +for report in reports: + suite = ET.parse(report).getroot() + cases = suite.findall('testcase') + assert cases, f'Empty test report: {report}' + for case in cases: + key = (case.attrib['classname'], case.attrib['name']) + assert key not in seen, f'Duplicate test: {key}' + assert not any(case.find(tag) is not None for tag in ('failure', 'error', 'skipped')), key + seen.add(key) + counts[key[0]] = counts.get(key[0], 0) + 1 +for name, minimum in expected.items(): + assert counts.get(name, 0) >= minimum, f'Missing tests in {name}: {counts.get(name, 0)} < {minimum}' +print(f'Verified {len(seen)} unique passing tests across {len(reports)} reports') diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9663666..dd001c8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,15 +1,3 @@ -# CI workflow for easy4j Spring Boot Starter -# -# Triggers: -# - push / pull_request on all version-line branches -# - manual workflow_dispatch -# -# JDK matrix by version line: -# - 2.3.x / 2.7.x : JDK 8 -# - 3.0.x ~ 3.5.x : JDK 17 -# - 4.0.x / 4.1.x : JDK 17 / 21 -# -# Runs `mvn -B clean verify` with dependency convergence checks. name: CI on: @@ -30,7 +18,7 @@ jobs: strategy: fail-fast: false matrix: - java: [8, 17, 21] + java: [17, 21] steps: - name: Checkout source uses: actions/checkout@v4 @@ -45,6 +33,9 @@ jobs: - name: Build and verify run: mvn -B --no-transfer-progress clean verify + - name: Verify test reports + run: python3 .github/scripts/verify-test-reports.py + - name: Upload surefire reports if: always() uses: actions/upload-artifact@v4 @@ -52,3 +43,4 @@ jobs: name: surefire-reports-jdk${{ matrix.java }} path: target/surefire-reports retention-days: 14 + if-no-files-found: error diff --git a/pom.xml b/pom.xml index 314f1d9..1d481b4 100644 --- a/pom.xml +++ b/pom.xml @@ -127,22 +127,21 @@ maven-surefire-plugin 2.19.1 - - true - true - - once - -Xmx1024m -XX:PermSize=256m -XX:MaxPermSize=256m -Dfile.encoding=UTF-8 + true + -Xmx1024m -Dfile.encoding=UTF-8 ${basedir}/target/test-classes + **/Test*.java **/*Test.java + **/*Tests.java + **/*TestCase.java **/TestBean.java + + **/AllTests.java diff --git a/src/test/java/com/yahoo/platform/yui/compressor/CompressionTest.java b/src/test/java/com/yahoo/platform/yui/compressor/CompressionTest.java new file mode 100644 index 0000000..8920112 --- /dev/null +++ b/src/test/java/com/yahoo/platform/yui/compressor/CompressionTest.java @@ -0,0 +1,45 @@ +package com.yahoo.platform.yui.compressor; + +import java.io.StringReader; +import java.io.StringWriter; +import junit.framework.TestCase; + +public class CompressionTest extends TestCase { + private String javascript(String source, boolean munge) throws Exception { + StringWriter output = new StringWriter(); + new JavaScriptCompressor(new StringReader(source), null) + .compress(output, null, -1, munge, false, false, false); + return output.toString(); + } + + public void testJavascriptCompressionMungesLocalNames() throws Exception { + String source = "/* remove me */ function sum(first, second) { var result = first + second; return result; } sum(19, 23);"; + String compressed = javascript(source, true); + assertTrue(compressed.length() < source.length()); + assertFalse(compressed.contains("remove me")); + assertTrue(compressed, compressed.matches( + "function sum\\(([a-z]),([a-z])\\)\\{var ([a-z])=\\1\\+\\2;return \\3\\}sum\\(19,23\\);")); + } + + public void testJavascriptPreservesRegexAndStringLiterals() throws Exception { + String source = "var url = 'https://example.com/a'; var pattern = /https?:\\/\\//; pattern.test(url) ? url : 'bad';"; + assertEquals("var url=\"https://example.com/a\";var pattern=/https?:\\/\\//;pattern.test(url)?url:\"bad\";", javascript(source, false)); + } + + private String css(String source) throws Exception { + StringWriter output = new StringWriter(); + new CssCompressor(new StringReader(source)).compress(output, -1); + return output.toString(); + } + + public void testCssCompressionRemovesCommentsAndWhitespace() throws Exception { + assertEquals("body{margin:0;padding:0;color:#fff}", + css("/* remove me */ body { margin: 0px; padding: 0px; color: #ffffff; }")); + } + + public void testCssPreservesQuotedContentAndDataUrl() throws Exception { + String compressed = css(".icon { background: url(data:image/png;base64,AAAA); } .label:after { content: \"a b\"; }"); + assertTrue(compressed.contains("url(data:image/png;base64,AAAA)")); + assertTrue(compressed.contains("\"a b\"")); + } +}