diff --git a/.github/workflows/nativeCompile.yml b/.github/workflows/nativeCompile.yml index 4fd9a053..8ae3d3b5 100644 --- a/.github/workflows/nativeCompile.yml +++ b/.github/workflows/nativeCompile.yml @@ -47,6 +47,10 @@ jobs: - name: Build ac/acx run: ./gradlew nativeCompile + - name: Run CLTH tests + shell: bash + run: ./scripts/run-clth-tests.sh + - name: Upload binary uses: actions/upload-artifact@v4 with: diff --git a/.gitignore b/.gitignore index f23f6feb..7c145f47 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,9 @@ build/ .vscode .idea +# Any binaries downloaded +.bin/ + # In case we run it locally, AppleCommander files we don't want to commit AppleCommander.preferences *.bas diff --git a/app/cli-tests/build.gradle b/app/cli-tests/build.gradle new file mode 100644 index 00000000..990bb522 --- /dev/null +++ b/app/cli-tests/build.gradle @@ -0,0 +1,31 @@ +plugins { + id 'java' +} + +java { + sourceCompatibility = 21 + targetCompatibility = 21 +} + +repositories { + mavenCentral() +} + +dependencies { + implementation project(':app:cli-ac') + implementation project(':app:cli-acx') + + testImplementation platform("org.junit:junit-bom:$junitVersion") + testImplementation 'org.junit.jupiter:junit-jupiter' + testRuntimeOnly 'org.junit.platform:junit-platform-launcher' + + testImplementation "io.github.a2geek:clth:$clthVersion" +} + +test { + useJUnitPlatform() + + def junit5SystemExit = configurations.testRuntimeClasspath.files + .find { it.name.contains('junit5-system-exit') } + jvmArgumentProviders.add({["-javaagent:$junit5SystemExit"]} as CommandLineArgumentProvider) +} \ No newline at end of file diff --git a/app/cli-tests/src/test/java/com/webcodepro/applecommander/ui/AcCommandLineTest.java b/app/cli-tests/src/test/java/com/webcodepro/applecommander/ui/AcCommandLineTest.java new file mode 100644 index 00000000..0a84d08c --- /dev/null +++ b/app/cli-tests/src/test/java/com/webcodepro/applecommander/ui/AcCommandLineTest.java @@ -0,0 +1,55 @@ +/* + * AppleCommander - An Apple ][ image utility. + * Copyright (C) 2025 by Robert Greene and others + * robgreene at users.sourceforge.net + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package com.webcodepro.applecommander.ui; + +import io.github.a2geek.clth.Config; +import io.github.a2geek.clth.JUnitHelper; +import io.github.a2geek.clth.TestHarness; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.io.IOException; +import java.io.InputStream; +import java.io.UncheckedIOException; +import java.util.stream.Stream; + +import io.github.a2geek.clth.TestSuite; + +public class AcCommandLineTest { + @ParameterizedTest(name = "{1}: {2}") + @MethodSource("testCases") + public void test(TestSuite testSuite, String name, String parameters) { + TestHarness.run(testSuite, JUnitHelper::execute, TestHarness.FilePreservation.DELETE); + } + + public static Stream testCases() { + try (InputStream inputStream = AcCommandLineTest.class.getResourceAsStream("/ac-config.yml")) { + assert inputStream != null; + String document = new String(inputStream.readAllBytes()); + Config config = Config.load(document); + + return TestSuite.build(config) + .map(t -> Arguments.of(t, t.testName(), String.join(" ", t.variables().values()))); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } +} diff --git a/app/cli-tests/src/test/java/io/github/applecommander/acx/AcxCommandLineTest.java b/app/cli-tests/src/test/java/io/github/applecommander/acx/AcxCommandLineTest.java new file mode 100644 index 00000000..e0b09b2f --- /dev/null +++ b/app/cli-tests/src/test/java/io/github/applecommander/acx/AcxCommandLineTest.java @@ -0,0 +1,55 @@ +/* + * AppleCommander - An Apple ][ image utility. + * Copyright (C) 2025 by Robert Greene and others + * robgreene at users.sourceforge.net + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +package io.github.applecommander.acx; + +import io.github.a2geek.clth.Config; +import io.github.a2geek.clth.JUnitHelper; +import io.github.a2geek.clth.TestHarness; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.io.IOException; +import java.io.InputStream; +import java.io.UncheckedIOException; +import java.util.stream.Stream; + +import io.github.a2geek.clth.TestSuite; + +public class AcxCommandLineTest { + @ParameterizedTest(name = "{1}: {2}") + @MethodSource("testCases") + public void test(TestSuite testSuite, String name, String parameters) { + TestHarness.run(testSuite, JUnitHelper::execute, TestHarness.FilePreservation.DELETE); + } + + public static Stream testCases() { + try (InputStream inputStream = AcxCommandLineTest.class.getResourceAsStream("/acx-config.yml")) { + assert inputStream != null; + String document = new String(inputStream.readAllBytes()); + Config config = Config.load(document); + + return TestSuite.build(config) + .map(t -> Arguments.of(t, t.testName(), String.join(" ", t.variables().values()))); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } +} diff --git a/app/cli-tests/src/test/resources/ac-config.yml b/app/cli-tests/src/test/resources/ac-config.yml new file mode 100644 index 00000000..73622345 --- /dev/null +++ b/app/cli-tests/src/test/resources/ac-config.yml @@ -0,0 +1,50 @@ +commands: + ac: + main-class: com.webcodepro.applecommander.ui.ac + system-exit: no + executable: app/cli-ac/build/native/nativeCompile/ac-* + +files: + txtfile: + type: text + # See: https://www.lipsum.com/ + content: | + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. + Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint + occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. + basfile: + type: text + content: | + 10 TEXT : HOME + 20 PRINT "HELLO, WORLD" + 30 END + binfile: + type: binary + # Address $300 + content: | + 20 2f fb 20 58 fc a0 0b b9 14 03 20 ed fd 88 d0 + f7 20 8e fd 60 c4 cc d2 cf d7 a0 cf cc cc c5 c8 + testdisk.dsk: + type: temporary + prefix: testdisk + suffix: .dsk + testdisk.po: + type: temporary + prefix: testdisk + suffix: .po + +tests: + - name: ticket192-ac + variables: + # All arrays must be same length -- only iterated over, not matrixed + flag: ["-dos140", "-pro140", "-pas140"] + volname: ["", "TEST", "TEST"] # blank will be skipped + disk: ["$testdisk.dsk", "$testdisk.po", "$testdisk.po"] + steps: + - command: ac $flag $disk $volname + - command: ac -pt $disk TESTFILE + stdin: $txtfile + - command: ac -d $disk TESTFILE + - command: ac -pt $disk TESTFILE + stdin: $txtfile diff --git a/app/cli-tests/src/test/resources/acx-config.yml b/app/cli-tests/src/test/resources/acx-config.yml new file mode 100644 index 00000000..cc103ab3 --- /dev/null +++ b/app/cli-tests/src/test/resources/acx-config.yml @@ -0,0 +1,47 @@ +commands: + acx: + main-class: io.github.applecommander.acx.Main + system-exit: yes + executable: app/cli-acx/build/native/nativeCompile/acx-* + +files: + txtfile: + type: text + # See: https://www.lipsum.com/ + content: | + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna + aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. + Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint + occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. + basfile: + type: text + content: | + 10 TEXT : HOME + 20 PRINT "HELLO, WORLD" + 30 END + binfile: + type: binary + # Address $300 + content: | + 20 2f fb 20 58 fc a0 0b b9 14 03 20 ed fd 88 d0 + f7 20 8e fd 60 c4 cc d2 cf d7 a0 cf cc cc c5 c8 + testdisk.dsk: + type: temporary + prefix: testdisk + suffix: .dsk + testdisk.po: + type: temporary + prefix: testdisk + suffix: .po + +tests: + - name: ticket192-acx + variables: + # All arrays must be same length -- only iterated over, not matrixed + flag: ["--dos", "--prodos", "--pascal"] + disk: ["$testdisk.dsk", "$testdisk.po", "$testdisk.po"] + steps: + - command: acx mkdisk -d $disk $flag + - command: acx import -d $disk $txtfile --name TESTFILE + - command: acx rm -d $disk TESTFILE + - command: acx import -d $disk $txtfile --name TESTFILE diff --git a/build.gradle b/build.gradle index e996ab81..1944f715 100644 --- a/build.gradle +++ b/build.gradle @@ -17,4 +17,5 @@ ext { springBoot = "2.7.7" acdasmVersion = "6.0" graalvmBuildVersion = "0.10.6" + clthVersion = "1.1" } diff --git a/lib/ac-api/src/main/resources/META-INF/native-image/org.applecommander/ac-api/resource-config.json b/lib/ac-api/src/main/resources/META-INF/native-image/org.applecommander/ac-api/resource-config.json index 808dc2c2..a840a3a8 100644 --- a/lib/ac-api/src/main/resources/META-INF/native-image/org.applecommander/ac-api/resource-config.json +++ b/lib/ac-api/src/main/resources/META-INF/native-image/org.applecommander/ac-api/resource-config.json @@ -5,19 +5,19 @@ "pattern": "META-INF/MANIFEST.MF" }, { - "pattern": "META-INF/services/*" + "pattern": "META-INF/services/.*" }, { - "pattern": "com/webcodepro/applecommander/storage/os/prodos/*" + "pattern": "com/webcodepro/applecommander/storage/os/prodos/.*" }, { - "pattern": "com/webcodepro/applecommander/storage/*" + "pattern": "com/webcodepro/applecommander/storage/.*" }, { - "pattern": "com/webcodepro/applecommander/ui/*" + "pattern": "com/webcodepro/applecommander/ui/.*" }, { - "pattern": "com/webcodepro/applecommander/util/*" + "pattern": "com/webcodepro/applecommander/util/.*" } ] }, diff --git a/scripts/run-clth-tests.sh b/scripts/run-clth-tests.sh new file mode 100755 index 00000000..a3a68624 --- /dev/null +++ b/scripts/run-clth-tests.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +DIR=".bin" +if [ ! -d ${DIR} ] +then + mkdir ${DIR} +fi + +CLTH="${DIR}/clth.jar" +if [ ! -f ${CLTH} ] +then + curl -o ${CLTH} -L https://github.com/a2geek/command-line-test-harness/releases/download/1.1/clth-1.1.jar +fi + +java -jar ${CLTH} app/cli-tests/src/test/resources/{ac,acx}-config.yml diff --git a/settings.gradle b/settings.gradle index b73f31fe..7b4f6f69 100644 --- a/settings.gradle +++ b/settings.gradle @@ -4,6 +4,7 @@ include 'lib:ac-api' include 'lib:ac-swt-common' include 'app:cli-ac' include 'app:cli-acx' +include 'app:cli-tests' include 'app:ant-ac' include 'app:gui-swt-macosx-aarch64' include 'app:gui-swt-macosx-x86_64'