From 4213a98bce14cca07dc7503d108a786cafd624b9 Mon Sep 17 00:00:00 2001 From: Vest Date: Fri, 22 Nov 2024 15:51:13 +0100 Subject: [PATCH 01/74] Added initial GH action support --- .github/workflows/gradle.yml | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 829c5554dba..824ad6201c1 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -1,19 +1,33 @@ -name: Java CI +# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle -on: [push] +name: Build PCGen with Gradle + +on: + push: + branches: [ "gh_build" ] # use current branch for testing purposes only + pull_request: + branches: [ "master" ] jobs: build: runs-on: ubuntu-latest + permissions: + contents: read steps: - - name: Checkout Code - uses: actions/checkout@v3 - - name: Set up JDK 17 - uses: actions/setup-java@v3 - with: - distribution: 'temurin' - java-version: '17' - - name: Build with Gradle - run: ./gradlew build + - uses: actions/checkout@v4 + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'temurin' + + # Configure Gradle for optimal use in GitHub Actions, including caching of downloaded dependencies. + # See: https://github.com/gradle/actions/blob/main/setup-gradle/README.md + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + + - name: Build with Gradle Wrapper + run: ./gradlew build From 4d6772e5651f75db0f9b9a623f9fb8e9bfaecff9 Mon Sep 17 00:00:00 2001 From: Vest Date: Fri, 22 Nov 2024 16:05:13 +0100 Subject: [PATCH 02/74] Upgraded gradle wrapper to 8.11.1. --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 79eb9d003fe..c1d5e018598 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME From 89188be92097ce9fae8aedd428e288eebb49956a Mon Sep 17 00:00:00 2001 From: Vest Date: Fri, 22 Nov 2024 16:08:37 +0100 Subject: [PATCH 03/74] Added testing to gh-action. --- .github/workflows/gradle.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 824ad6201c1..71ff2f78215 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -30,4 +30,10 @@ jobs: uses: gradle/actions/setup-gradle@v4 - name: Build with Gradle Wrapper - run: ./gradlew build + run: ./gradlew build test slowtest + +# - name: Upload build artifacts +# uses: actions/upload-artifact@v4 +# with: +# name: Package +# path: build/libs From 3d1400a51b0389201d171d0d0c5aa46b20dc757f Mon Sep 17 00:00:00 2001 From: Vest Date: Fri, 22 Nov 2024 18:17:31 +0100 Subject: [PATCH 04/74] First attempt to log data in test. It failed in GH actions. --- code/src/test/pcgen/inttest/PcgenFtlTestCase.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/code/src/test/pcgen/inttest/PcgenFtlTestCase.java b/code/src/test/pcgen/inttest/PcgenFtlTestCase.java index 38d2175fd07..9e1678089e0 100644 --- a/code/src/test/pcgen/inttest/PcgenFtlTestCase.java +++ b/code/src/test/pcgen/inttest/PcgenFtlTestCase.java @@ -21,6 +21,8 @@ import java.io.IOException; import java.nio.file.Files; import java.util.Locale; +import java.util.logging.Logger; + import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.xmlunit.builder.DiffBuilder; @@ -39,6 +41,8 @@ */ public abstract class PcgenFtlTestCase { + private static final Logger log = Logger.getLogger(PcgenFtlTestCase.class.getName()); + private static final String TEST_CONFIG_FILE = "config.ini.junit"; @BeforeEach @@ -62,8 +66,7 @@ public void tearDown() */ public static void runTest(String character, String mode) throws IOException { - System.out.println("RUNTEST with the character: " + character - + " and the game mode: " + mode); + log.info("RUNTEST with the character: " + character + " and the game mode: " + mode); // Delete the old generated output for this test File outputFolder = new File("code/testsuite/output"); outputFolder.mkdirs(); From 2cf3d441234e8cd5fd04ca5f37adecf1b6bd801f Mon Sep 17 00:00:00 2001 From: Vest Date: Fri, 22 Nov 2024 18:55:21 +0100 Subject: [PATCH 05/74] Added the logging to all tests. --- build.gradle | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/build.gradle b/build.gradle index b68caf955f9..b46c5e7e7fc 100644 --- a/build.gradle +++ b/build.gradle @@ -748,6 +748,10 @@ tasks.named("jre") { dependsOn downloadJRE, downloadJavaFXModules } +tasks.withType(Test) { + testLogging.showStandardStreams = true +} + tasks.named("test", Test) { exclude 'pcgen/testsupport/**' useJUnitPlatform() From 0f6b522dc62ab329394d6131c17c54fd1c0ba450 Mon Sep 17 00:00:00 2001 From: Vest Date: Fri, 22 Nov 2024 18:59:55 +0100 Subject: [PATCH 06/74] Added gradle cache to a github action setup-java. --- .github/workflows/gradle.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 71ff2f78215..ed266dc1ac7 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -18,11 +18,13 @@ jobs: steps: - uses: actions/checkout@v4 + - name: Set up JDK 21 uses: actions/setup-java@v4 with: java-version: '21' distribution: 'temurin' + cache: gradle # Configure Gradle for optimal use in GitHub Actions, including caching of downloaded dependencies. # See: https://github.com/gradle/actions/blob/main/setup-gradle/README.md From 3e474f9d3b3f736b3b348e304ef22404786a6713 Mon Sep 17 00:00:00 2001 From: Vest Date: Fri, 22 Nov 2024 19:17:06 +0100 Subject: [PATCH 07/74] Disabled logging, but added the test results upload. --- .github/workflows/gradle.yml | 9 +++++++++ build.gradle | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index ed266dc1ac7..b70790a52cb 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -34,6 +34,15 @@ jobs: - name: Build with Gradle Wrapper run: ./gradlew build test slowtest + - name: Publish Test Results + uses: EnricoMi/publish-unit-test-result-action@v2 + if: always() + with: + files: | + build/test-results/**/*.xml + build/test-results/**/*.trx + build/test-results/**/*.json + # - name: Upload build artifacts # uses: actions/upload-artifact@v4 # with: diff --git a/build.gradle b/build.gradle index b46c5e7e7fc..cd460a41ff5 100644 --- a/build.gradle +++ b/build.gradle @@ -749,7 +749,7 @@ tasks.named("jre") { } tasks.withType(Test) { - testLogging.showStandardStreams = true + testLogging.showStandardStreams = false } tasks.named("test", Test) { From 44a4cd76517e9dd184f5993ba158f2351ced65a0 Mon Sep 17 00:00:00 2001 From: Vest Date: Fri, 22 Nov 2024 20:30:24 +0100 Subject: [PATCH 08/74] Enabled "write" permissions for test results --- .github/workflows/gradle.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index b70790a52cb..c287a7cdce4 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -14,7 +14,8 @@ jobs: runs-on: ubuntu-latest permissions: - contents: read + checks: write + pull-requests: write steps: - uses: actions/checkout@v4 From ccf45fd058e84ee009f189a605df9cfabda2346e Mon Sep 17 00:00:00 2001 From: Vest Date: Fri, 22 Nov 2024 21:28:14 +0100 Subject: [PATCH 09/74] Refactored TestHelper.java Added some logging. --- .../test/pcgen/inttest/PcgenFtlTestCase.java | 4 +- code/src/test/pcgen/util/TestHelper.java | 42 ++++++++++--------- 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/code/src/test/pcgen/inttest/PcgenFtlTestCase.java b/code/src/test/pcgen/inttest/PcgenFtlTestCase.java index 9e1678089e0..89536073667 100644 --- a/code/src/test/pcgen/inttest/PcgenFtlTestCase.java +++ b/code/src/test/pcgen/inttest/PcgenFtlTestCase.java @@ -41,7 +41,7 @@ */ public abstract class PcgenFtlTestCase { - private static final Logger log = Logger.getLogger(PcgenFtlTestCase.class.getName()); + private static final Logger LOG = Logger.getLogger(PcgenFtlTestCase.class.getName()); private static final String TEST_CONFIG_FILE = "config.ini.junit"; @@ -66,7 +66,7 @@ public void tearDown() */ public static void runTest(String character, String mode) throws IOException { - log.info("RUNTEST with the character: " + character + " and the game mode: " + mode); + LOG.info("RUNTEST with the character: " + character + " and the game mode: " + mode); // Delete the old generated output for this test File outputFolder = new File("code/testsuite/output"); outputFolder.mkdirs(); diff --git a/code/src/test/pcgen/util/TestHelper.java b/code/src/test/pcgen/util/TestHelper.java index a75801b32ea..a79d729bf51 100644 --- a/code/src/test/pcgen/util/TestHelper.java +++ b/code/src/test/pcgen/util/TestHelper.java @@ -81,7 +81,11 @@ import java.net.URI; import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.StringTokenizer; +import java.util.logging.Logger; +import java.util.logging.Level; /** * Helps Junit tests @@ -89,6 +93,8 @@ @SuppressWarnings("nls") public final class TestHelper { + private static final Logger LOG = Logger.getLogger(TestHelper.class.getName()); + private static boolean loaded = false; private static final LstObjectFileLoader eqLoader = new GenericLoader<>(Equipment.class); private static final LstObjectFileLoader abLoader = new AbilityLoader(); @@ -208,7 +214,7 @@ public static Object findField(final Class aClass, final String fieldName) } catch (SecurityException e) { - System.out.println(e); + LOG.log(Level.SEVERE, "SecurityException is thrown in findField", e); } return null; } @@ -460,29 +466,25 @@ public static boolean hasWeaponProfKeyed(PlayerCharacter pc, } /** - * Locate the data folder which contains the primary set of LST data. This - * defaults to the data folder under the current directory, but can be - * customised in the config.ini folder. + * Locate the data folder which contains the primary set of LST data. This defaults to the data folder under the + * current directory but can be customized in the config.ini folder. * @return The path of the data folder. */ public static String findDataFolder() { // Set the pcc location to "data" String pccLoc = "data"; - // Read in options.ini and override the pcc location if it exists - try (BufferedReader br = new BufferedReader(new InputStreamReader( - new FileInputStream("config.ini"), StandardCharsets.UTF_8))) + + // Read in config.ini and override the pcc location if it exists + try (var lines = Files.lines(Path.of("config.ini"))) { - while (br.ready()) - { - String line = br.readLine(); - if (line != null - && line.startsWith("pccFilesPath=")) - { - pccLoc = line.substring(13); - break; - } - } + var pccFilesPath = lines + .filter(line -> line.startsWith("pccFilesPath=")) + .map(line -> line.substring(13)) + .findFirst() + .orElse(pccLoc); + + return pccFilesPath; } catch (IOException e) { // Ignore, see method comment @@ -508,7 +510,7 @@ public static void createDummySettingsFile(String configFileName, bw.write("settingsPath=" + configFolder + "\r\n"); if (pccLoc != null) { - System.out.println("Using PCC Location of '" + pccLoc + "'."); + LOG.info("Using PCC Location of '" + pccLoc + "'."); bw.write("pccFilesPath=" + pccLoc + "\r\n"); } bw.write("customPath=testsuite\\\\customdata\r\n"); @@ -520,7 +522,7 @@ public static void loadGameModes(String testConfigFile) { String configFolder = "testsuite"; String pccLoc = TestHelper.findDataFolder(); - System.out.println("Got data folder of " + pccLoc); + LOG.info("Got data folder of " + pccLoc); try { TestHelper.createDummySettingsFile(testConfigFile, configFolder, @@ -570,7 +572,7 @@ public static PCClass parsePCClassText(String classPCCText, String line = tok.nextToken(); if (!StringUtils.isBlank(line)) { - System.out.println("Processing line:'" + line + "'."); + LOG.info("Processing line:'" + line + "'."); reconstClass = pcClassLoader.parseLine(Globals.getContext(), reconstClass, line, source); From 78968a121d9a804a5277dbbebc988cac7a3c08e9 Mon Sep 17 00:00:00 2001 From: Vest Date: Mon, 25 Nov 2024 17:52:22 +0100 Subject: [PATCH 10/74] Updated cache-dependency-path. --- .github/workflows/gradle.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index c287a7cdce4..3100a332a8d 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -26,6 +26,12 @@ jobs: java-version: '21' distribution: 'temurin' cache: gradle + cache-dependency-path: + build.gradle + code/gradle/autobuild.gradle + code/gradle/distribution.gradle + code/gradle/release.gradle + code/gradle/reporting.gradle # Configure Gradle for optimal use in GitHub Actions, including caching of downloaded dependencies. # See: https://github.com/gradle/actions/blob/main/setup-gradle/README.md From 797b24f75ca0464651063093e6aed7a8e9f0721b Mon Sep 17 00:00:00 2001 From: Vest Date: Mon, 25 Nov 2024 17:57:43 +0100 Subject: [PATCH 11/74] First attempt to cache build/classes and build/jre --- .github/workflows/gradle.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 3100a332a8d..1bfba1a0ab3 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -38,6 +38,15 @@ jobs: - name: Setup Gradle uses: gradle/actions/setup-gradle@v4 + - uses: actions/cache@v4 + with: + path: | + build/classes + build/jre + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} + restore-keys: | + ${{ runner.os }}-gradle- + - name: Build with Gradle Wrapper run: ./gradlew build test slowtest From 4b2d6679e7007b47a4f248def1ef37e4cb2e9fb9 Mon Sep 17 00:00:00 2001 From: Vest Date: Mon, 25 Nov 2024 18:02:17 +0100 Subject: [PATCH 12/74] Corrected a typo in gradle.yml --- .github/workflows/gradle.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 1bfba1a0ab3..9f7660917b4 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -26,7 +26,7 @@ jobs: java-version: '21' distribution: 'temurin' cache: gradle - cache-dependency-path: + cache-dependency-path: | build.gradle code/gradle/autobuild.gradle code/gradle/distribution.gradle From 38eab4b308ef89443924374bb3dec2baa055bc39 Mon Sep 17 00:00:00 2001 From: Vest Date: Mon, 25 Nov 2024 18:28:49 +0100 Subject: [PATCH 13/74] Try to clear the cache and fill it with values. --- .github/workflows/gradle.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 9f7660917b4..8d38eda05be 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -37,6 +37,10 @@ jobs: # See: https://github.com/gradle/actions/blob/main/setup-gradle/README.md - name: Setup Gradle uses: gradle/actions/setup-gradle@v4 + with: + cache-disabled: false + cache-read-only: false + cache-overwrite-existing: true - uses: actions/cache@v4 with: From 5b85e178e7b779477b570ea1d2b71bac678d2c00 Mon Sep 17 00:00:00 2001 From: Vest Date: Sun, 22 Dec 2024 23:08:45 +0100 Subject: [PATCH 14/74] First step to remove NSIS from the distro; Removed explicit System.exit(0) in Main. It allows to enable "slowtest" that generates and compares XMLs. Marked SystemExitInterceptor as deprecated and removal=true. Since Java does not offer any alternative, we have to find a better solution. P.S. NSIS is planned to be removed to use jpackage only. --- build.gradle | 2 +- code/gradle/release.gradle | 5 +-- code/src/java/pcgen/cdom/base/Constants.java | 3 +- code/src/java/pcgen/system/Main.java | 5 ++- .../test/pcgen/inttest/PcgenFtlTestCase.java | 45 ++++++++++--------- code/src/test/pcgen/util/TestHelper.java | 1 - .../util/SystemExitInterceptor.java | 7 ++- 7 files changed, 37 insertions(+), 31 deletions(-) diff --git a/build.gradle b/build.gradle index 2ca68aae0d3..d1ad8bf85e1 100644 --- a/build.gradle +++ b/build.gradle @@ -955,7 +955,7 @@ apply from: 'code/gradle/reporting.gradle' apply from: 'code/gradle/release.gradle' tasks.register("allTasks") { - dependsOn build, slowtest, javadoc, buildNsis, allReports + dependsOn build, slowtest, javadoc, allReports description = "Runs tasks build, slowtest, javadoc, buildNsis and allReports" } diff --git a/code/gradle/release.gradle b/code/gradle/release.gradle index 768dc842053..ebd7f7c3668 100644 --- a/code/gradle/release.gradle +++ b/code/gradle/release.gradle @@ -420,7 +420,7 @@ tasks.register("sourcesJar", Jar) { } tasks.register("assembleArtifacts", Copy) { - dependsOn build, runtimeZip, sourcesJar, buildNsis + dependsOn build, runtimeZip, sourcesJar if (Os.isFamily(Os.FAMILY_MAC) || Os.isFamily(Os.FAMILY_UNIX)) { @@ -431,9 +431,6 @@ tasks.register("assembleArtifacts", Copy) { into releaseDir // buildNsis puts the exe into the release folder directly - from(layout.buildDirectory.dir("nsisRelease")){ - include '*.exe' - } from(layout.buildDirectory.dir("libs")){ include 'pcgen*-sources.jar' } diff --git a/code/src/java/pcgen/cdom/base/Constants.java b/code/src/java/pcgen/cdom/base/Constants.java index 6c95580490c..bd602422eca 100644 --- a/code/src/java/pcgen/cdom/base/Constants.java +++ b/code/src/java/pcgen/cdom/base/Constants.java @@ -28,7 +28,6 @@ @SuppressWarnings("PMD.ConstantsInInterface") public interface Constants { - /******************************************************************** * Static definitions of Equipment location strings ********************************************************************/ @@ -111,7 +110,7 @@ public interface Constants String INTERNAL_WEAPON_PROF = "PCGENi_WEAPON_PROFICIENCY"; //$NON-NLS-1$ /** Line Separator. */ - String LINE_SEPARATOR = System.getProperty("line.separator"); //$NON-NLS-1$ + String LINE_SEPARATOR = System.lineSeparator(); //$NON-NLS-1$ /** The constant string "None". */ String NONE = "None"; //$NON-NLS-1$ diff --git a/code/src/java/pcgen/system/Main.java b/code/src/java/pcgen/system/Main.java index 5e528ac22bb..8208d98be71 100644 --- a/code/src/java/pcgen/system/Main.java +++ b/code/src/java/pcgen/system/Main.java @@ -367,7 +367,10 @@ public static void shutdown(boolean success) CustomData.writeCustomItems(); } - System.exit(success ? 0 : 1); + if (!success) + { + System.exit(1); + } } private static void initPrintPreviewFonts() diff --git a/code/src/test/pcgen/inttest/PcgenFtlTestCase.java b/code/src/test/pcgen/inttest/PcgenFtlTestCase.java index 89536073667..39c7b283779 100644 --- a/code/src/test/pcgen/inttest/PcgenFtlTestCase.java +++ b/code/src/test/pcgen/inttest/PcgenFtlTestCase.java @@ -29,7 +29,7 @@ import org.xmlunit.builder.Input; import org.xmlunit.diff.Diff; import pcgen.LocaleDependentTestCase; -import pcgen.cdom.base.Constants; +import pcgen.system.Main; import pcgen.util.TestHelper; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -66,32 +66,32 @@ public void tearDown() */ public static void runTest(String character, String mode) throws IOException { - LOG.info("RUNTEST with the character: " + character + " and the game mode: " + mode); + LOG.info("RUNTEST with the character: " + character + " and the game mode: " + mode); // Delete the old generated output for this test - File outputFolder = new File("code/testsuite/output"); + String characterFileName = character + ".xml"; + String characterPCFileName = character + ".pcg"; + var inputFolder = new File("code/testsuite/PCGfiles"); + var outputFolder = new File("code/testsuite/output"); + var csheetsFolder = new File("code/testsuite/csheets"); outputFolder.mkdirs(); - String outputFileName = character + ".xml"; - File outputFileFile = new File(outputFolder, outputFileName); + + var inputFile = new File(inputFolder, characterPCFileName); + var outputFile = new File(outputFolder, characterFileName); + var expectedFile = new File(csheetsFolder, characterFileName); String pccLoc = TestHelper.findDataFolder(); - // The String holder for the XML of the expected result - String expected; - // The String holder for the XML of the actual result - String actual; /* * Override the pcc location, game mode and several other properties in * the options.ini file */ String configFolder = "testsuite"; - TestHelper.createDummySettingsFile(TEST_CONFIG_FILE, configFolder, - pccLoc); + TestHelper.createDummySettingsFile(TEST_CONFIG_FILE, configFolder, pccLoc); // Fire off PCGen, which will produce an XML file - String characterFile = "code/testsuite/PCGfiles/" + character - + Constants.EXTENSION_CHARACTER_FILE; + //String characterFile = "code/testsuite/PCGfiles/" + character + Constants.EXTENSION_CHARACTER_FILE; - String outputFile = outputFileFile.getCanonicalPath(); + //String outputFile = outputFile.getCanonicalPath(); // The code below had to be commented out as in Java 21+ there's no more SecurityManager // At time of writing there is no replacement, see JDK-8199704 @@ -111,14 +111,19 @@ public static void runTest(String character, String mode) throws IOException revertSystemExitInterceptor.run(); */ - // Read in the actual XML produced by PCGen - actual = Files.readString(outputFileFile.toPath()); - // Read in the expected XML - expected = Files.readString( - new File("code/testsuite/csheets/" + character + ".xml").toPath()); + Main.main("--character", inputFile.getCanonicalPath(), + "--exportsheet", "code/testsuite/base-xml.ftl", + "--outputfile", outputFile.getCanonicalPath(), + "--configfilename", TEST_CONFIG_FILE); + + // the XML of the expected result + var expected = Files.readString(expectedFile.toPath()); + // the XML of the actual result + var actual = Files.readString(outputFile.toPath()); Diff myDiff = DiffBuilder.compare(Input.fromString(expected)) - .withTest(Input.fromString(actual)).build(); + .withTest(Input.fromString(actual)) + .build(); assertFalse(myDiff.hasDifferences(), myDiff.toString()); } diff --git a/code/src/test/pcgen/util/TestHelper.java b/code/src/test/pcgen/util/TestHelper.java index a79d729bf51..222aef4fa35 100644 --- a/code/src/test/pcgen/util/TestHelper.java +++ b/code/src/test/pcgen/util/TestHelper.java @@ -515,7 +515,6 @@ public static void createDummySettingsFile(String configFileName, } bw.write("customPath=testsuite\\\\customdata\r\n"); } - } public static void loadGameModes(String testConfigFile) diff --git a/code/src/testcommon/util/SystemExitInterceptor.java b/code/src/testcommon/util/SystemExitInterceptor.java index d54a5c461b4..2f216a5dd1d 100644 --- a/code/src/testcommon/util/SystemExitInterceptor.java +++ b/code/src/testcommon/util/SystemExitInterceptor.java @@ -8,14 +8,17 @@ *

* Note: A replacement API to intercept System.exit is in discussion in JDK-8199704. * The SecurityManager is unlikely to be removed from Java before such an alternative exists. + * + * There is no alternative in Java 21. Probably this is the time to remove this class and everything that uses it. */ +@Deprecated(forRemoval = true, since = "17") public class SystemExitInterceptor { /** - * Temporarily replaces the security manager in order to intercept calls to System.exit. + * Temporarily replaces the security manager to intercept calls to System.exit. * - * @return A runnable that needs to be called in order to revert the change. + * @return A runnable that needs to be called to revert the change. */ @SuppressWarnings("removal") public static Runnable startInterceptor() From ea32a3a5d3f7c8c807531256fae3fa7bc6793069 Mon Sep 17 00:00:00 2001 From: Vest Date: Sun, 22 Dec 2024 23:34:49 +0100 Subject: [PATCH 15/74] Performance optimization: the debugPrint (when called frequently) uses StackTrace to determine the logger name. This is expensive and replaced with an explicit logger creation. --- .../pcgen/rules/context/LoadContextInst.java | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/code/src/java/pcgen/rules/context/LoadContextInst.java b/code/src/java/pcgen/rules/context/LoadContextInst.java index 2bfee8a75a8..0394b798f64 100644 --- a/code/src/java/pcgen/rules/context/LoadContextInst.java +++ b/code/src/java/pcgen/rules/context/LoadContextInst.java @@ -1,16 +1,16 @@ /* * Copyright 2007 (C) Tom Parker - * + * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. - * + * * This library 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 Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA @@ -24,6 +24,8 @@ import java.util.List; import java.util.Objects; import java.util.Optional; +import java.util.logging.Logger; +import java.util.logging.Level; import pcgen.base.formula.inst.NEPFormula; import pcgen.base.proxy.DeferredMethodController; @@ -63,6 +65,7 @@ abstract class LoadContextInst implements LoadContext { + Logger LOG = Logger.getLogger(LoadContextInst.class.getName()); private static final PrerequisiteWriter PREREQ_WRITER = new PrerequisiteWriter(); @@ -135,7 +138,7 @@ public int getWriteMessageCount() /** * Sets the extract URI. This is a shortcut for setting the URI on both the * graph and obj members. - * + * * @param extractURI */ @Override @@ -149,7 +152,7 @@ public void setExtractURI(URI extractURI) /** * Sets the source URI. This is a shortcut for setting the URI on both the * graph and obj members. - * + * * @param sourceURI */ @Override @@ -160,7 +163,7 @@ public void setSourceURI(URI sourceURI) getReferenceContext().setSourceURI(sourceURI); getListContext().setSourceURI(sourceURI); clearStatefulInformation(); - Logging.debugPrint("Starting Load of " + sourceURI); + LOG.log(Level.FINER, "Starting Load of " + sourceURI); } @Override @@ -346,7 +349,7 @@ public void unconditionallyProcess(T cdo, String key, Strin /** * Produce the LST code for any occurrences of subtokens of the parent token. - * + * * @param The type of object to be processed, generally a CDOMObject. * @param cdo The object to be partially unparsed * @param tokenName The name of the parent token @@ -373,12 +376,12 @@ public T cloneConstructedCDOMObject(T cdo, String newName } /** - * Create a copy of a CDOMObject duplicating any references to the old + * Create a copy of a CDOMObject duplicating any references to the old * object. (e.g. Spell, Domain etc) - * + * * Package protected rather than private for testing only - * - * @param cdo The original object being copied. + * + * @param cdo The original object being copied. * @param newName The name that should be given to the new object. * @return The newly created CDOMObject. */ From 4effb4f4a7e841617bca73d2f84c5ae04fc67376 Mon Sep 17 00:00:00 2001 From: Vest Date: Sun, 22 Dec 2024 23:44:05 +0100 Subject: [PATCH 16/74] Refactored Logging.java. --- code/src/java/pcgen/util/Logging.java | 29 ++++++++------------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/code/src/java/pcgen/util/Logging.java b/code/src/java/pcgen/util/Logging.java index d3c390434a1..a7f0edf9ba9 100644 --- a/code/src/java/pcgen/util/Logging.java +++ b/code/src/java/pcgen/util/Logging.java @@ -69,8 +69,8 @@ public final class Logging /** Log level for application debug output. */ public static final Level DEBUG = Level.FINER; - private static Logger pcgenLogger; - private static Logger pluginLogger; + private static Logger pcgenLogger = Logger.getLogger("pcgen"); + private static Logger pluginLogger = Logger.getLogger("plugin"); /** * Do any required initialization of the Logger. @@ -113,31 +113,19 @@ private Logging() */ public static void setDebugMode(final boolean argDebugMode) { - retainRootLoggers(); - debugMode = argDebugMode; if (debugMode) { - Logger.getLogger("pcgen").setLevel(DEBUG); - Logger.getLogger("plugin").setLevel(DEBUG); + pcgenLogger.setLevel(DEBUG); + pluginLogger.setLevel(DEBUG); } else { - Logger.getLogger("pcgen").setLevel(LST_WARNING); - Logger.getLogger("plugin").setLevel(LST_WARNING); + pcgenLogger.setLevel(LST_WARNING); + pluginLogger.setLevel(LST_WARNING); } } - /** - * Ensure that our root loggers (pcgen and plugin) do not get garbage - * collected, otherwise we lose the logging level! - */ - private static void retainRootLoggers() - { - pcgenLogger = Logger.getLogger("pcgen"); - pluginLogger = Logger.getLogger("plugin"); - } - /** * Is someone debugging PCGen? * @@ -613,10 +601,9 @@ public static Level getCurrentLoggingLevel() */ public static void setCurrentLoggingLevel(Level level) { - retainRootLoggers(); debugMode = (level == Logging.DEBUG); - Logger.getLogger("pcgen").setLevel(level); - Logger.getLogger("plugin").setLevel(level); + pcgenLogger.setLevel(level); + pluginLogger.setLevel(level); } private static final LinkedList queuedMessages = new LinkedList<>(); From c8495ca040a3124fccdd6a2349d7bfcd6d67b851 Mon Sep 17 00:00:00 2001 From: Vest Date: Tue, 24 Dec 2024 13:04:19 +0100 Subject: [PATCH 17/74] Upgraded gradle-wrapper from 8.11.1 to 8.12 --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index c1d5e018598..e0fd02028bc 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME From 505d668797826d8116754b84f9e9cf86194b79e9 Mon Sep 17 00:00:00 2001 From: Vest Date: Tue, 24 Dec 2024 13:24:42 +0100 Subject: [PATCH 18/74] Remove .run/ from git repository, because it tracked by mistake in #7056 --- .gitignore | 1 + .run/Main.run.xml | 11 ----------- 2 files changed, 1 insertion(+), 11 deletions(-) delete mode 100644 .run/Main.run.xml diff --git a/.gitignore b/.gitignore index d55f55791dd..9513db7ac5a 100644 --- a/.gitignore +++ b/.gitignore @@ -94,6 +94,7 @@ code/build.eclipse/ # IntelliJ IDE .idea/ +.run/ out/ pcgendev.iml pcgen.iml diff --git a/.run/Main.run.xml b/.run/Main.run.xml deleted file mode 100644 index 38778279d24..00000000000 --- a/.run/Main.run.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - \ No newline at end of file From 5dfc7e01853e1e28eaeacb8ee404f3d51b9f8826 Mon Sep 17 00:00:00 2001 From: Vest Date: Tue, 24 Dec 2024 23:55:08 +0100 Subject: [PATCH 19/74] Refactored several classes. The main goal was adding the Optional to methods that return null. In some cases, the null reference/result was not checked, but the code never failed, because it was not executed. There were no tests, that is why it was difficult to check, whether the refactoring was right :( --- code/src/java/pcgen/core/Globals.java | 12 +- code/src/java/pcgen/gui2/PCGenFrame.java | 8 +- .../pcgen/gui2/converter/LSTConverter.java | 112 +++++---- .../src/java/pcgen/gui2/converter/Loader.java | 11 +- .../gui2/converter/panel/GameModePanel.java | 9 +- .../pcgen/persistence/GameModeFileLoader.java | 233 +++++++++--------- .../pcgen/persistence/SourceFileLoader.java | 31 +-- .../pcgen/persistence/lst/LstFileLoader.java | 47 ++-- .../persistence/lst/LstLineFileLoader.java | 7 +- .../persistence/lst/LstObjectFileLoader.java | 29 ++- .../pcgen/persistence/lst/VariableLoader.java | 14 +- 11 files changed, 257 insertions(+), 256 deletions(-) diff --git a/code/src/java/pcgen/core/Globals.java b/code/src/java/pcgen/core/Globals.java index 15b8e1caeaf..c6ef2a83378 100644 --- a/code/src/java/pcgen/core/Globals.java +++ b/code/src/java/pcgen/core/Globals.java @@ -540,8 +540,8 @@ public static void clearCampaignsForRefresh() /** * Check if enough data has been loaded to support character creation. - * Will also report to the log the number of items of each of the - * necessary types that are currently loaded. + * Will also report to the log the number of items of each of the + * necessary types that are currently loaded. * @return true or false */ public static boolean displayListsHappy() @@ -722,7 +722,7 @@ public static boolean selectPaper(final String paperName) } /** - * Apply the user's preferences to the initial state of the Globals. + * Apply the user's preferences to the initial state of the Globals. */ public static void initPreferences() { @@ -789,8 +789,8 @@ static List sortPObjectList(final List - * + * @param + * * @param aList * @return Sorted list of Pcgen Objects */ @@ -1033,7 +1033,7 @@ else if (fType.equals("mac_user")) private static int bonusParsing(final String l, final int level, int num, final PlayerCharacter aPC) { - // should be in format levelnum,rangenum[,numchoices] + // should be in format levelnum,rangenum[,numchoices] final StringTokenizer aTok = new StringTokenizer(l, "|", false); final int startLevel = Integer.parseInt(aTok.nextToken()); final String rangeLevelFormula = aTok.nextToken(); diff --git a/code/src/java/pcgen/gui2/PCGenFrame.java b/code/src/java/pcgen/gui2/PCGenFrame.java index 2160dee417e..8857579353c 100644 --- a/code/src/java/pcgen/gui2/PCGenFrame.java +++ b/code/src/java/pcgen/gui2/PCGenFrame.java @@ -1560,6 +1560,7 @@ public void run() updateTitle(); } + // TODO there are no examples with licenses. Either remove this or add a test. private void showLicenses() { PropertyContext context = PCGenSettings.OPTIONS_CONTEXT; @@ -1576,11 +1577,8 @@ private void showLicenses() { showLicenseDialog(LanguageBundle.getString("in_specialLicenses"), licenses); //$NON-NLS-1$ } - for (String license : loader.getOtherLicenses()) - { - showLicenseDialog(LanguageBundle.getString("in_specialLicenses"), license); //$NON-NLS-1$ - } - + loader.getOtherLicenses() + .forEach(license -> showLicenseDialog(LanguageBundle.getString("in_specialLicenses"), license)); //$NON-NLS-1$ } } if (loader.hasMatureCampaign() && context.initBoolean(PCGenSettings.OPTION_SHOW_MATURE_ON_LOAD, true)) diff --git a/code/src/java/pcgen/gui2/converter/LSTConverter.java b/code/src/java/pcgen/gui2/converter/LSTConverter.java index 01d11fa9a5b..c3acc78295b 100644 --- a/code/src/java/pcgen/gui2/converter/LSTConverter.java +++ b/code/src/java/pcgen/gui2/converter/LSTConverter.java @@ -1,16 +1,16 @@ /* * Copyright (c) 2009 Tom Parker - * + * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 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 Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA @@ -30,6 +30,7 @@ import java.util.HashSet; import java.util.List; import java.util.Observable; +import java.util.Optional; import java.util.Set; import pcgen.base.util.DoubleKeyMapToList; @@ -117,7 +118,7 @@ public int getNumFilesInCampaign(Campaign campaign) } /** - * Initialise the list of campaigns. This will load the ability + * Initialise the list of campaigns. This will load the ability * categories in advance of the conversion. * @param campaigns The campaigns or sources to be converted. */ @@ -182,7 +183,7 @@ private void startItem(final Campaign campaign) continue; } File in = new File(uri); - // Use canonical name to stop reruns for the same file referred to using .. + // Use canonical name to stop reruns for the same file referred to using .. URI canonicalUri; try { @@ -223,19 +224,20 @@ private void startItem(final Campaign campaign) try { changeLogWriter.append("\nProcessing ").append(String.valueOf(in)).append("\n"); - String result = load(uri, loader); - if (result != null) - { - try (Writer out = new BufferedWriter(new OutputStreamWriter( - new FileOutputStream(outFile), - StandardCharsets.UTF_8 - ))) - { - out.write(result); - } - } + load(uri, loader) + .ifPresent((String result) -> { + try (Writer out = new BufferedWriter(new OutputStreamWriter( + new FileOutputStream(outFile), + StandardCharsets.UTF_8))) + { + out.write(result); + } catch (IOException e) + { + Logging.errorPrint(e.getLocalizedMessage(), e); + } + }); } - catch (PersistenceLayerException | IOException | InterruptedException e) + catch (PersistenceLayerException | IOException e) { Logging.errorPrint(e.getLocalizedMessage(), e); } @@ -299,49 +301,57 @@ private File findSubRoot(File root, File in) return findSubRoot(root, parent); } - private String load(URI uri, Loader loader) throws InterruptedException, PersistenceLayerException + private Optional load(URI uri, Loader loader) throws PersistenceLayerException { - String dataBuffer; context.setSourceURI(uri); context.setExtractURI(uri); try { - dataBuffer = LstFileLoader.readFromURI(uri); - } - catch (PersistenceLayerException ple) - { - String message = LanguageBundle.getFormattedString("Errors.LstFileLoader.LoadError", //$NON-NLS-1$ - uri, ple.getMessage()); - Logging.errorPrint(message); - return null; - } + return LstFileLoader.readFromURI(uri) + .map((String dataBuffer) -> { + StringBuilder resultBuffer = new StringBuilder(dataBuffer.length()); - StringBuilder resultBuffer = new StringBuilder(dataBuffer.length()); - final String aString = dataBuffer; - - String[] fileLines = aString.split(LstFileLoader.LINE_SEPARATOR_REGEXP); - for (int line = 0; line < fileLines.length; line++) - { - String lineString = fileLines[line]; - if ((lineString.isEmpty()) || (lineString.charAt(0) == LstFileLoader.LINE_COMMENT_CHAR) - || lineString.startsWith("SOURCE")) - { - resultBuffer.append(lineString); - } - else - { - List newObj = loader.process(resultBuffer, line, lineString, decider); - if (newObj != null) - { - for (CDOMObject cdo : newObj) + String[] fileLines = dataBuffer.split(LstFileLoader.LINE_SEPARATOR_REGEXP); + for (int line = 0; line < fileLines.length; line++) { - injected.addToListFor(loader, uri, cdo); + String lineString = fileLines[line]; + if ((lineString.isEmpty()) || (lineString.charAt(0) == LstFileLoader.LINE_COMMENT_CHAR) + || lineString.startsWith("SOURCE")) + { + resultBuffer.append(lineString); + } + else + { + try + { + List newObj = loader.process(resultBuffer, line, lineString, decider); + if (newObj != null) + { + for (CDOMObject cdo : newObj) + { + injected.addToListFor(loader, uri, cdo); + } + } + } + catch (PersistenceLayerException | InterruptedException e) + { + String message = LanguageBundle.getFormattedString("Errors.LstFileLoader.LoadError", //$NON-NLS-1$ + uri, e.getMessage()); + Logging.errorPrint(message, e); + return null; + } + } + resultBuffer.append("\n"); } - } - } - resultBuffer.append("\n"); + return resultBuffer.toString(); + }); + } + catch (PersistenceLayerException ple) + { + Logging.errorPrint(LanguageBundle.getFormattedString("Errors.LstFileLoader.LoadError", //$NON-NLS-1$ + uri, ple.getMessage())); + return Optional.empty(); } - return resultBuffer.toString(); } public Collection getInjectedLoaders() diff --git a/code/src/java/pcgen/gui2/converter/Loader.java b/code/src/java/pcgen/gui2/converter/Loader.java index 694ecd0a2fe..8608d5685de 100644 --- a/code/src/java/pcgen/gui2/converter/Loader.java +++ b/code/src/java/pcgen/gui2/converter/Loader.java @@ -1,16 +1,16 @@ /* * Copyright (c) 2009 Tom Parker - * + * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 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 Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA @@ -26,9 +26,8 @@ public interface Loader { - public List process(StringBuilder sb, int line, String lineString, ConversionDecider decider) + List process(StringBuilder sb, int line, String lineString, ConversionDecider decider) throws PersistenceLayerException, InterruptedException; - public List getFiles(Campaign campaign); - + List getFiles(Campaign campaign); } diff --git a/code/src/java/pcgen/gui2/converter/panel/GameModePanel.java b/code/src/java/pcgen/gui2/converter/panel/GameModePanel.java index 3188e56eb6f..664acfe0e87 100644 --- a/code/src/java/pcgen/gui2/converter/panel/GameModePanel.java +++ b/code/src/java/pcgen/gui2/converter/panel/GameModePanel.java @@ -1,16 +1,16 @@ /* * Copyright (c) 2009 Tom Parker - * + * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 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 Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA @@ -88,7 +88,8 @@ public boolean performAnalysis(CDOMObject pc) SettingsHandler.setGame(gameMode.getName()); } // Globals.emptyLists(); - Globals.sortPObjectListByName(Globals.getCampaignList()); + // TODO the campaign list is an unmodifiable list, so it is not possible to sort it. + // Globals.sortPObjectListByName(Globals.getCampaignList()); return saveGameMode(pc); } diff --git a/code/src/java/pcgen/persistence/GameModeFileLoader.java b/code/src/java/pcgen/persistence/GameModeFileLoader.java index 9bd9cb3c14d..fc9ef48ee97 100644 --- a/code/src/java/pcgen/persistence/GameModeFileLoader.java +++ b/code/src/java/pcgen/persistence/GameModeFileLoader.java @@ -20,6 +20,8 @@ import java.io.File; import java.io.FilenameFilter; import java.net.URI; +import java.util.Optional; +import java.util.logging.Level; import pcgen.cdom.base.Constants; import pcgen.cdom.content.TabInfo; @@ -57,7 +59,6 @@ public class GameModeFileLoader extends PCGenTask { - private static final FilenameFilter GAME_MODE_FILE_FILTER = (aFile, aString) -> { try { @@ -132,57 +133,58 @@ private void loadGameModes(String[] gameFiles) { File specGameModeDir = new File(gameModeDir, gameFile); File miscInfoFile = new File(specGameModeDir, "miscinfo.lst"); - final GameMode gm = GameModeFileLoader.loadGameModeMiscInfo(gameFile, miscInfoFile.toURI()); - if (gm != null) - { - String gmName = gm.getName(); - //SettingsHandler.setGame(gmName); - LoadContext context = gm.getModeContext(); - loadGameModeInfoFile(gm, new File(specGameModeDir, "level.lst").toURI(), "level"); - loadGameModeInfoFile(gm, new File(specGameModeDir, "rules.lst").toURI(), "rules"); - // Load equipmentslot.lst - GameModeFileLoader.loadGameModeLstFile(context, eqSlotLoader, gmName, gameFile, "equipmentslots.lst"); + GameModeFileLoader.loadGameModeMiscInfo(gameFile, miscInfoFile.toURI()) + .ifPresentOrElse((GameMode gameMode) -> { + String gmName = gameMode.getName(); + //SettingsHandler.setGame(gmName); + LoadContext context = gameMode.getModeContext(); + loadGameModeInfoFile(gameMode, new File(specGameModeDir, "level.lst").toURI(), "level"); + loadGameModeInfoFile(gameMode, new File(specGameModeDir, "rules.lst").toURI(), "rules"); - // Load paperInfo.lst - GameModeFileLoader.loadGameModeLstFile(context, paperLoader, gmName, gameFile, "paperInfo.lst"); + // Load equipmentslot.lst + GameModeFileLoader.loadGameModeLstFile(context, eqSlotLoader, gmName, gameFile, "equipmentslots.lst"); - // Load bio files - GameModeFileLoader.loadGameModeLstFile(context, traitLoader, gmName, gameFile, - "bio" + File.separator + "traits.lst"); - GameModeFileLoader.loadGameModeLstFile(context, locationLoader, gmName, gameFile, - "bio" + File.separator + "locations.lst"); + // Load paperInfo.lst + GameModeFileLoader.loadGameModeLstFile(context, paperLoader, gmName, gameFile, "paperInfo.lst"); - // Load load.lst and check for completeness - GameModeFileLoader.loadGameModeLstFile(context, loadInfoLoader, gmName, gameFile, "load.lst"); + // Load bio files + GameModeFileLoader.loadGameModeLstFile(context, traitLoader, gmName, gameFile, + "bio" + File.separator + "traits.lst"); + GameModeFileLoader.loadGameModeLstFile(context, locationLoader, gmName, gameFile, + "bio" + File.separator + "locations.lst"); - // Load sizeAdjustment.lst - GameModeFileLoader.loadGameModeLstFile(context, sizeLoader, gmName, gameFile, "sizeAdjustment.lst", - false); + // Load load.lst and check for completeness + GameModeFileLoader.loadGameModeLstFile(context, loadInfoLoader, gmName, gameFile, "load.lst"); - // Load statsandchecks.lst - GameModeFileLoader.loadGameModeLstFile(context, statCheckLoader, gmName, gameFile, "statsandchecks.lst", - false); + // Load sizeAdjustment.lst + GameModeFileLoader.loadGameModeLstFile(context, sizeLoader, gmName, gameFile, "sizeAdjustment.lst", + false); - // Load equipIcons.lst - GameModeFileLoader.loadGameModeLstFile(context, equipIconLoader, gmName, gameFile, "equipIcons.lst"); + // Load statsandchecks.lst + GameModeFileLoader.loadGameModeLstFile(context, statCheckLoader, gmName, gameFile, "statsandchecks.lst", + false); - GameModeFileLoader.loadGameModeLstFile(context, codeControlLoader, gmName, gameFile, "codeControl.lst"); + // Load equipIcons.lst + GameModeFileLoader.loadGameModeLstFile(context, equipIconLoader, gmName, gameFile, "equipIcons.lst"); - // Load pointbuymethods.lst - loadPointBuyFile(context, gameFile, gmName); - for (final PointBuyCost pbc : context.getReferenceContext() - .getConstructedCDOMObjects(PointBuyCost.class)) - { - gm.addPointBuyStatCost(pbc); - } + GameModeFileLoader.loadGameModeLstFile(context, codeControlLoader, gmName, gameFile, "codeControl.lst"); - // Load migration.lst - GameModeFileLoader.loadGameModeLstFile(context, migrationLoader, gmName, gameFile, "migration.lst"); + // Load pointbuymethods.lst + loadPointBuyFile(context, gameFile, gmName); + for (final PointBuyCost pbc : context.getReferenceContext() + .getConstructedCDOMObjects(PointBuyCost.class)) + { + gameMode.addPointBuyStatCost(pbc); + } - GameModeFileLoader.loadGameModeLstFile(context, bioLoader, gmName, gameFile, - "bio" + File.separator + "biosettings.lst"); - } + // Load migration.lst + GameModeFileLoader.loadGameModeLstFile(context, migrationLoader, gmName, gameFile, "migration.lst"); + + GameModeFileLoader.loadGameModeLstFile(context, bioLoader, gmName, gameFile, + "bio" + File.separator + "biosettings.lst"); + }, () -> Logging.log(Level.WARNING, "There is no data for game mode: " + gameFile + + ", and the URI: " + miscInfoFile.toURI())); progress++; setProgress(progress); @@ -259,10 +261,40 @@ private static boolean loadGameModeLstFile(LoadContext context, LstLineFileLoade private void loadGameModeInfoFile(GameMode gameMode, URI uri, String aType) { - String data; try { - data = LstFileLoader.readFromURI(uri); + LstFileLoader.readFromURI(uri) + .ifPresentOrElse((String data) -> { + String[] fileLines = data.split(LstFileLoader.LINE_SEPARATOR_REGEXP); + String xpTable = ""; + for (int i = 0; i < fileLines.length; i++) + { + String aLine = fileLines[i]; + + // Ignore commented-out and empty lines + if (aLine.isEmpty() || (aLine.charAt(0) == '#')) + { + continue; + } + + if (aType.equals("level")) + { + xpTable = LevelLoader.parseLine(gameMode, aLine, i + 1, uri, xpTable); + } else if (aType.equals("rules")) + { + try + { + ruleCheckLoader.parseLine(gameMode.getModeContext(), aLine, uri); + } catch (final PersistenceLayerException e) + { + Logging.errorPrint( + LanguageBundle.getFormattedString( + "Errors.LstSystemLoader.loadGameModeInfoFile", //$NON-NLS-1$ + uri, e.getMessage())); + } + } + } + }, () -> Logging.log(Level.WARNING, "There was no data in the URI: " + uri)); } catch (final PersistenceLayerException ple) { @@ -270,48 +302,52 @@ private void loadGameModeInfoFile(GameMode gameMode, URI uri, String aType) LanguageBundle.getFormattedString( "Errors.LstSystemLoader.loadGameModeInfoFile", //$NON-NLS-1$ uri, ple.getMessage())); - return; - } - - String[] fileLines = data.split(LstFileLoader.LINE_SEPARATOR_REGEXP); - String xpTable = ""; - for (int i = 0; i < fileLines.length; i++) - { - String aLine = fileLines[i]; - - // Ignore commented-out and empty lines - if (aLine.isEmpty() || (aLine.charAt(0) == '#')) - { - continue; - } - - if (aType.equals("level")) - { - xpTable = LevelLoader.parseLine(gameMode, aLine, i + 1, uri, xpTable); - } - else if (aType.equals("rules")) - { - try - { - ruleCheckLoader.parseLine(gameMode.getModeContext(), aLine, uri); - } - catch (final PersistenceLayerException e) - { - Logging.errorPrint( - LanguageBundle.getFormattedString( - "Errors.LstSystemLoader.loadGameModeInfoFile", //$NON-NLS-1$ - uri, e.getMessage())); - } - } } } - private static GameMode loadGameModeMiscInfo(String aName, URI uri) + private static Optional loadGameModeMiscInfo(String aName, URI uri) { - String data; try { - data = LstFileLoader.readFromURI(uri); + return LstFileLoader.readFromURI(uri) + .map((String data) -> { + String[] fileLines = data.split(LstFileLoader.LINE_SEPARATOR_REGEXP); + + GameMode gameMode = new GameMode(aName); + SystemCollections.addToGameModeList(gameMode); + gameMode.getModeContext().getReferenceContext().importObject(AbilityCategory.FEAT); + + for (int i = 0; i < fileLines.length; i++) + { + String aLine = fileLines[i]; + + // Ignore commented-out and empty lines + if (aLine.isEmpty() || (aLine.charAt(0) == '#')) + { + continue; + } + + GameModeLoader.parseMiscGameInfoLine(gameMode, aLine, uri, i + 1); + } + + // Record how the FEAT category was configured + AbilityCategory feat = new AbilityCategory(); + feat.copyFields(AbilityCategory.FEAT); + gameMode.setFeatTemplate(feat); + + int[] dieSizes = gameMode.getDieSizes(); + if (dieSizes == null || dieSizes.length == 0) + { + final int[] defaultDieSizes = {1, 2, 3, 4, 6, 8, 10, 12, 20, 100, 1000}; + gameMode.setDieSizes(defaultDieSizes); + Logging.log(Logging.LST_ERROR, "GameMode (" + gameMode.getName() + + ") : MiscInfo.lst did not contain any valid DIESIZES. " + "Using the system default DIESIZES."); + } + addDefaultUnitSet(gameMode); + addDefaultTabInfo(gameMode); + gameMode.applyPreferences(); + return gameMode; + }); } catch (final PersistenceLayerException ple) { @@ -319,45 +355,8 @@ private static GameMode loadGameModeMiscInfo(String aName, URI uri) LanguageBundle.getFormattedString( "Errors.LstSystemLoader.loadGameModeInfoFile", //$NON-NLS-1$ uri, ple.getMessage())); - return null; - } - - String[] fileLines = data.split(LstFileLoader.LINE_SEPARATOR_REGEXP); - - GameMode gameMode = new GameMode(aName); - SystemCollections.addToGameModeList(gameMode); - gameMode.getModeContext().getReferenceContext().importObject(AbilityCategory.FEAT); - - for (int i = 0; i < fileLines.length; i++) - { - String aLine = fileLines[i]; - - // Ignore commented-out and empty lines - if (aLine.isEmpty() || (aLine.charAt(0) == '#')) - { - continue; - } - - GameModeLoader.parseMiscGameInfoLine(gameMode, aLine, uri, i + 1); - } - - // Record how the FEAT category was configured - AbilityCategory feat = new AbilityCategory(); - feat.copyFields(AbilityCategory.FEAT); - gameMode.setFeatTemplate(feat); - - int[] dieSizes = gameMode.getDieSizes(); - if (dieSizes == null || dieSizes.length == 0) - { - final int[] defaultDieSizes = {1, 2, 3, 4, 6, 8, 10, 12, 20, 100, 1000}; - gameMode.setDieSizes(defaultDieSizes); - Logging.log(Logging.LST_ERROR, "GameMode (" + gameMode.getName() - + ") : MiscInfo.lst did not contain any valid DIESIZES. " + "Using the system default DIESIZES."); + return Optional.empty(); } - addDefaultUnitSet(gameMode); - addDefaultTabInfo(gameMode); - gameMode.applyPreferences(); - return gameMode; } /** diff --git a/code/src/java/pcgen/persistence/SourceFileLoader.java b/code/src/java/pcgen/persistence/SourceFileLoader.java index 5e9ac82e483..5068a3f7428 100644 --- a/code/src/java/pcgen/persistence/SourceFileLoader.java +++ b/code/src/java/pcgen/persistence/SourceFileLoader.java @@ -28,9 +28,11 @@ import java.util.List; import java.util.Observable; import java.util.Observer; +import java.util.Optional; import java.util.Set; import java.util.logging.Handler; import java.util.logging.LogRecord; +import java.util.stream.Stream; import pcgen.base.formatmanager.FormatUtilities; import pcgen.base.formula.base.LegalScope; @@ -250,21 +252,22 @@ public String getLicenses() /** * @return a list of licenses read from the campaign license files */ - public Iterable getOtherLicenses() + public Stream getOtherLicenses() { - Collection licenses = new ArrayList<>(); - for (CampaignSourceEntry licenseFile : licenseFiles) - { - try - { - String dataBuffer = LstFileLoader.readFromURI(licenseFile.getURI()); - licenses.add(dataBuffer); - } catch (PersistenceLayerException e) - { - Logging.errorPrint("Could not read license at " + licenseFile, e); - } - } - return licenses; + return licenseFiles.stream() + .map(CampaignSourceEntry::getURI) + .map((URI uri) -> { + try + { + return LstFileLoader.readFromURI(uri); + } catch (PersistenceLayerException e) + { + Logging.errorPrint("Could not read license at " + uri, e); + return Optional.empty(); + } + }) + .filter(Optional::isPresent) + .map(Optional::get); } public String getMatureInfo() diff --git a/code/src/java/pcgen/persistence/lst/LstFileLoader.java b/code/src/java/pcgen/persistence/lst/LstFileLoader.java index 0396d470f96..c4d8d5955e7 100644 --- a/code/src/java/pcgen/persistence/lst/LstFileLoader.java +++ b/code/src/java/pcgen/persistence/lst/LstFileLoader.java @@ -27,7 +27,8 @@ import java.nio.charset.MalformedInputException; import java.nio.file.Files; import java.nio.file.Path; -import org.jetbrains.annotations.Nullable; +import java.util.Optional; + import pcgen.cdom.base.Constants; import pcgen.core.SettingsHandler; import pcgen.core.utils.CoreUtility; @@ -70,21 +71,18 @@ private LstFileLoader() /** * This method reads the given URI and returns its content as a string. If an error occurs, we don't throw an - * exception, but log the error in the logger. It is possible to read file content from the remote link, but + * exception but log the error in the logger. It is possible to read file content from the remote link, but * a corresponding option must be enabled in settings. * - * @param uri URI of the remote content - * @return String file content - * @throws PersistenceLayerException is thrown when a null URI is provided + * @param uri URI of the remote content + * @return String file content + * @throws PersistenceLayerException is thrown when a null URI is provided */ - @Nullable - public static String readFromURI(URI uri) throws PersistenceLayerException + public static Optional readFromURI(URI uri) throws PersistenceLayerException { - if (uri == null) - { - // We have a problem! - throw new PersistenceLayerException("LstFileLoader.readFromURI() received a null URI parameter!"); - } + uri = Optional.ofNullable(uri) + .orElseThrow(() -> new PersistenceLayerException( + "LstFileLoader.readFromURI() received a null URI parameter!")); try { @@ -98,9 +96,8 @@ public static String readFromURI(URI uri) throws PersistenceLayerException "The file %s uses UTF-8-BOM encoding. LST files must be UTF-8".formatted(uri)); result = result.substring(1); } - return result; - } - else if (SettingsHandler.isLoadURLs()) // load from remote URIs + return Optional.of(result); + } else if (SettingsHandler.isLoadURLs()) // load from remote URIs { try (HttpClient client = HttpClient.newHttpClient()) { @@ -108,30 +105,26 @@ else if (SettingsHandler.isLoadURLs()) // load from remote URIs .uri(uri) .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); - return response.body(); + return Optional.of(response.body()); } - } - else + } else { - // Just to protect people from using web - // sources without their knowledge, - // we added a preference. + // Just to protect people from using web sources without their knowledge, we added a preference. ShowMessageDelegate.showMessageDialog("Preferences are currently set to NOT allow\nloading of " - + "sources from web links.\n" + uri + " is a web link", Constants.APPLICATION_NAME, - MessageType.ERROR); + + "sources from web links.\n" + uri + " is a web link", Constants.APPLICATION_NAME, + MessageType.ERROR); } } catch (MalformedInputException ie) { Logging.errorPrint("ERROR: " + uri + "\nThe file doesn't use UTF-8 encoding. LST files must be UTF-8", ie); - } - catch (IOException | InterruptedException e) + } catch (IOException | InterruptedException e) { // Don't throw an exception here because a simple // file not found will prevent ANY other files from // being loaded/processed -- NOT what we want Logging.errorPrint("ERROR: " + uri + '\n' + "Exception type: " + e.getClass().getName() + "\n" + "Message: " - + e.getMessage(), e); + + e.getMessage(), e); } - return null; + return Optional.empty(); } } diff --git a/code/src/java/pcgen/persistence/lst/LstLineFileLoader.java b/code/src/java/pcgen/persistence/lst/LstLineFileLoader.java index 94565c1e4b5..80e2c5efeb1 100644 --- a/code/src/java/pcgen/persistence/lst/LstLineFileLoader.java +++ b/code/src/java/pcgen/persistence/lst/LstLineFileLoader.java @@ -42,8 +42,8 @@ */ public abstract class LstLineFileLoader extends Observable { - /** - * Stores what game mode the objects loaded by this loader should be + /** + * Stores what game mode the objects loaded by this loader should be * associated with. */ // TODO - Should be a constant. @@ -59,7 +59,8 @@ public abstract class LstLineFileLoader extends Observable */ public void loadLstFile(LoadContext context, URI uri) throws PersistenceLayerException { - String dataBuffer = LstFileLoader.readFromURI(uri); + String dataBuffer = LstFileLoader.readFromURI(uri) + .orElseThrow(() -> new PersistenceLayerException("Failed to read from URI: " + uri)); if (context != null) { context.setSourceURI(uri); diff --git a/code/src/java/pcgen/persistence/lst/LstObjectFileLoader.java b/code/src/java/pcgen/persistence/lst/LstObjectFileLoader.java index 0d7e6eaffea..9d566760dbf 100644 --- a/code/src/java/pcgen/persistence/lst/LstObjectFileLoader.java +++ b/code/src/java/pcgen/persistence/lst/LstObjectFileLoader.java @@ -68,7 +68,7 @@ public abstract class LstObjectFileLoader extends Observab /** * This method loads the given list of LST files. * @param fileList containing the list of files to read - * @throws PersistenceLayerException + * @throws PersistenceLayerException */ public void loadLstFiles(LoadContext context, List fileList) throws PersistenceLayerException { @@ -129,22 +129,22 @@ public abstract T parseLine(LoadContext context, T target, String lstLine, Sourc * This method is called by the loading framework to signify that the * loading of this object is complete and the object should be added to the * system. - * + * *

This method will check that the loaded object should be included via * a call to {@code includeObject} and if not add it to the list of * excluded objects. - * + * *

Once the object has been verified the method will call * {@code finishObject} to give each object a chance to complete * processing. - * + * *

The object is then added to the system if it doesn't already exist. * If the object exists, the object sources are compared by date and if the * System setting allowing over-rides is set it will use the object from the * newer source. * @param context TODO * @param pObj The object that has just completed loading. - * + * * @see pcgen.persistence.lst.LstObjectFileLoader#includeObject(SourceEntry, CDOMObject) */ public void completeObject(LoadContext context, SourceEntry source, final T pObj) @@ -260,7 +260,7 @@ protected boolean includeObject(SourceEntry source, CDOMObject cdo) * duplicate loads * @param context TODO * @param key The CDOMObject containing the key to retrieve (for which there may be a duplicate) - * + * * @return CDOMObject from Globals */ protected T getMatchingObject(LoadContext context, CDOMObject key) @@ -278,10 +278,10 @@ protected void loadLstFile(LoadContext context, CampaignSourceEntry sourceEntry) setChanged(); URI uri = sourceEntry.getURI(); notifyObservers(uri); - String dataBuffer; + String aString; try { - dataBuffer = LstFileLoader.readFromURI(uri); + aString = LstFileLoader.readFromURI(uri).get(); } catch (PersistenceLayerException ple) { @@ -291,7 +291,6 @@ protected void loadLstFile(LoadContext context, CampaignSourceEntry sourceEntry) setChanged(); return; } - String aString = Objects.requireNonNull(dataBuffer); if (context != null) { context.setSourceURI(uri); @@ -426,8 +425,8 @@ private void performForget(LoadContext context, T objToForget) * This method will perform a single .COPY operation based on the LST * file content. * @param context - * @param me - * @throws PersistenceLayerException + * @param me + * @throws PersistenceLayerException */ private void performCopy(LoadContext context, ModEntry me) throws PersistenceLayerException { @@ -461,7 +460,7 @@ private void performCopy(LoadContext context, ModEntry me) throws PersistenceLay /** * Create a copy of an object with a new name. If the base object cannot be found, an error will be reported unless * the copy has been excluded by include/exclude rules for the source. - * + * * @param context The current load context in whihc the new object is to be created. * @param baseName The name of the object to be copied. * @param copyName The name of the new object. @@ -588,7 +587,7 @@ private void performMod(LoadContext context, List entryList) /** * This method will process the lines containing a .COPY directive - * @throws PersistenceLayerException + * @throws PersistenceLayerException */ private void processCopies(LoadContext context) throws PersistenceLayerException { @@ -656,14 +655,14 @@ public static final class ModEntry * @param aLstLine LST syntax modification * [must not be null] * @param aLineNumber - * + * * @throws IllegalArgumentException if aSource or aLstLine is null. */ private ModEntry(final CampaignSourceEntry aSource, final String aLstLine, final int aLineNumber) { super(); - // These are programming errors so the msgs don't need to be + // These are programming errors so the msgs don't need to be // internationalized. Objects.requireNonNull(aSource, "source must not be null"); diff --git a/code/src/java/pcgen/persistence/lst/VariableLoader.java b/code/src/java/pcgen/persistence/lst/VariableLoader.java index a8f0b15ec2d..836280641a6 100644 --- a/code/src/java/pcgen/persistence/lst/VariableLoader.java +++ b/code/src/java/pcgen/persistence/lst/VariableLoader.java @@ -3,17 +3,17 @@ * Copyright 2008-10 (C) Tom Parker * Copyright 2003 (C) David Hibbs * Copyright 2001 (C) Bryan McRoberts - * + * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. - * + * * This library 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 Lesser General Public License for more * details. - * + * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA @@ -89,7 +89,7 @@ public void loadLstFiles(LoadContext context, List fileList /** * This method loads a single LST formatted file. - * + * * @param sourceEntry * CampaignSourceEntry containing the absolute file path or the * URL from which to read LST formatted data. @@ -100,11 +100,10 @@ protected void loadLstFile(LoadContext context, CampaignSourceEntry sourceEntry) URI uri = sourceEntry.getURI(); notifyObservers(uri); - String dataBuffer; - + String aString; try { - dataBuffer = LstFileLoader.readFromURI(uri); + aString = LstFileLoader.readFromURI(uri).get(); } catch (PersistenceLayerException ple) { @@ -115,7 +114,6 @@ protected void loadLstFile(LoadContext context, CampaignSourceEntry sourceEntry) return; } - String aString = dataBuffer; if (context != null) { context.setSourceURI(uri); From e049370a9dc0107daa380aed8efb21b6f455d9d7 Mon Sep 17 00:00:00 2001 From: Vest Date: Fri, 27 Dec 2024 14:43:49 +0100 Subject: [PATCH 20/74] Corrected pf_Cleric test; 1. Corrected the typo in special properties (light crossbow); 2. Corrected maxdex for MAXDEX bonus; --- code/src/java/pcgen/core/PlayerCharacter.java | 8 +++++- .../src/java/pcgen/util/enumeration/Load.java | 1 - .../test/pcgen/inttest/PcgenFtlTestCase.java | 5 +++- code/testsuite/PCGfiles/pf_Cleric.pcg | 1 - code/testsuite/csheets/pf_Cleric.xml | 26 +++++++++---------- .../core_rulebook/cr_equip_arms_armor.lst | 3 +-- 6 files changed, 25 insertions(+), 19 deletions(-) diff --git a/code/src/java/pcgen/core/PlayerCharacter.java b/code/src/java/pcgen/core/PlayerCharacter.java index 9f3e3a7c749..131aad2d8f4 100644 --- a/code/src/java/pcgen/core/PlayerCharacter.java +++ b/code/src/java/pcgen/core/PlayerCharacter.java @@ -5477,7 +5477,13 @@ public int processOldMaxDex() { final int statBonus = (int) getStatBonusTo("MISC", "MAXDEX"); final Load load = getHouseRuledLoadType(); - int bonus = (load == Load.MEDIUM) ? 2 : (load == Load.HEAVY) ? 1 : (load == Load.OVERLOAD) ? 0 : statBonus; + int bonus = switch (load) + { + case MEDIUM -> 3; + case HEAVY -> 1; + case OVERLOAD -> 0; + default -> statBonus; + }; // If this is still true after all the equipment has been // examined, then we should use the Maximum - Maximum Dex modifier. diff --git a/code/src/java/pcgen/util/enumeration/Load.java b/code/src/java/pcgen/util/enumeration/Load.java index c71b7751bd6..cc73bf74875 100644 --- a/code/src/java/pcgen/util/enumeration/Load.java +++ b/code/src/java/pcgen/util/enumeration/Load.java @@ -33,7 +33,6 @@ public enum Load HEAVY(FontManipulation::bold_italic, UIPropertyContext::getVirtualColor), OVERLOAD(FontManipulation::bold_italic, UIPropertyContext::getNotQualifiedColor); - private static final DoubleFunction LIGHT_ENCUMBERED_MOVE = unencumberedMove -> unencumberedMove; private static final DoubleFunction MEDIUM_HEAVY_ENCUMBERED_MOVE = unencumberedMove -> { if (CoreUtility.doublesEqual(unencumberedMove, 5) || CoreUtility.doublesEqual(unencumberedMove, 10)) diff --git a/code/src/test/pcgen/inttest/PcgenFtlTestCase.java b/code/src/test/pcgen/inttest/PcgenFtlTestCase.java index 39c7b283779..8a020f71222 100644 --- a/code/src/test/pcgen/inttest/PcgenFtlTestCase.java +++ b/code/src/test/pcgen/inttest/PcgenFtlTestCase.java @@ -20,6 +20,7 @@ import java.io.File; import java.io.IOException; import java.nio.file.Files; +import java.text.MessageFormat; import java.util.Locale; import java.util.logging.Logger; @@ -89,7 +90,7 @@ public static void runTest(String character, String mode) throws IOException TestHelper.createDummySettingsFile(TEST_CONFIG_FILE, configFolder, pccLoc); // Fire off PCGen, which will produce an XML file - //String characterFile = "code/testsuite/PCGfiles/" + character + Constants.EXTENSION_CHARACTER_FILE; + // String characterFile = "code/testsuite/PCGfiles/" + character + Constants.EXTENSION_CHARACTER_FILE; //String outputFile = outputFile.getCanonicalPath(); @@ -121,6 +122,8 @@ public static void runTest(String character, String mode) throws IOException // the XML of the actual result var actual = Files.readString(outputFile.toPath()); + LOG.info( + MessageFormat.format("Comparing the expected ({0}) and actual ({1}) results", expectedFile, outputFile)); Diff myDiff = DiffBuilder.compare(Input.fromString(expected)) .withTest(Input.fromString(actual)) .build(); diff --git a/code/testsuite/PCGfiles/pf_Cleric.pcg b/code/testsuite/PCGfiles/pf_Cleric.pcg index 7e2b2f29ee1..deec9285db3 100644 --- a/code/testsuite/PCGfiles/pf_Cleric.pcg +++ b/code/testsuite/PCGfiles/pf_Cleric.pcg @@ -263,7 +263,6 @@ CHARACTERMAGIC: CHARACTERDMNOTES: # Kits -KIT:Character Traits # Character Master/Follower diff --git a/code/testsuite/csheets/pf_Cleric.xml b/code/testsuite/csheets/pf_Cleric.xml index e8750108a25..73bd1693f97 100644 --- a/code/testsuite/csheets/pf_Cleric.xml +++ b/code/testsuite/csheets/pf_Cleric.xml @@ -876,9 +876,9 @@ BIO 2 - +2 - +0 - +2 + +0 + -2 + +0 +0 @@ -888,7 +888,7 @@ BIO 1 5 M - + You draw a light crossbow back by pulling a lever. Loading a light crossbow is a move action that provokes attacks of opportunity.&nl;Normally, operating a light crossbow requires two hands. However, you can shoot, but not load, a light crossbow with one hand at a -2 penalty on attack rolls. You can shoot a light crossbow with each hand, but you take a penalty on attack rolls as if attacking with two light weapons. This penalty is cumulative with the penalty for one-handed firing.