diff --git a/build-config/resources/Ballerina.toml b/build-config/resources/Ballerina.toml index 0eda7ea54..98ae521d3 100644 --- a/build-config/resources/Ballerina.toml +++ b/build-config/resources/Ballerina.toml @@ -1,8 +1,8 @@ [package] org = "ballerina" -name = "tool_persist" +name = "tool.persist" version = "@toml.version@" authors = ["Ballerina"] -keywords = ["persist", "persist tool"] +keywords = ["persist", "persist tool", "ORM"] license = ["Apache-2.0"] -distribution = "2201.12.4" +distribution = "2201.13.0" diff --git a/examples/resources/bal-tools.toml b/examples/resources/bal-tools.toml index be2da31aa..63537350b 100644 --- a/examples/resources/bal-tools.toml +++ b/examples/resources/bal-tools.toml @@ -1,6 +1,6 @@ [[tool]] id = "persist" org = "ballerina" -name = "tool_persist" +name = "tool.persist" version = "@toml.version@" active = true diff --git a/gradle.properties b/gradle.properties index 85fd017aa..2fbeffcaf 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,22 +2,22 @@ org.gradle.caching=true group=io.ballerina version=1.7.0-SNAPSHOT -#dependency versions -checkstylePluginVersion=10.12.1 +# Java Dependencies +ballerinaLangVersion=2201.13.0-20250924-081800-3dae8c03 picocliVersion=4.7.4 -githubSpotbugsVersion=6.0.18 -githubJohnrengelmanShadowVersion=8.1.1 -underCouchDownloadVersion=5.4.0 -researchgateReleaseVersion=2.8.0 testngVersion=7.6.1 -jacocoVersion=0.8.10 -ballerinaGradlePluginVersion=2.3.0 - mySqlDriverVersion=8.0.29 mssqlDriverVersion=11.2.3.jre17 postgresqlDriverVersion=42.6.0 -ballerinaLangVersion=2201.13.0-20250613-152200-ecef3657 +# Gradle Plugin Versions +checkstylePluginVersion=10.12.1 +spotbugsPluginVersion=6.0.18 +shadowJarVersion=8.1.1 +downloadPluginVersion=5.4.0 +releasePluginVersion=2.8.0 +ballerinaGradlePluginVersion=2.3.0 +jacocoVersion=0.8.10 # Level 01 stdlibIoVersion=1.8.0 diff --git a/persist-cli-tests/build.gradle b/persist-cli-tests/build.gradle index 513efad76..82fd56fb2 100644 --- a/persist-cli-tests/build.gradle +++ b/persist-cli-tests/build.gradle @@ -171,6 +171,9 @@ tasks.withType(Checkstyle) { } task copyTestResources(type: Copy) { + doFirst { + delete "${buildDir}/generated-sources" + } into buildDir into("generated-sources/") { from "src/test/resources/test-src/input" diff --git a/persist-cli-tests/resources/bal-tools.toml b/persist-cli-tests/resources/bal-tools.toml index be2da31aa..63537350b 100644 --- a/persist-cli-tests/resources/bal-tools.toml +++ b/persist-cli-tests/resources/bal-tools.toml @@ -1,6 +1,6 @@ [[tool]] id = "persist" org = "ballerina" -name = "tool_persist" +name = "tool.persist" version = "@toml.version@" active = true diff --git a/persist-cli-tests/src/test/java/io/ballerina/persist/tools/BuildCodeGeneratorTest.java b/persist-cli-tests/src/test/java/io/ballerina/persist/tools/BuildCodeGeneratorTest.java index 51c93163b..c2d5fe27f 100644 --- a/persist-cli-tests/src/test/java/io/ballerina/persist/tools/BuildCodeGeneratorTest.java +++ b/persist-cli-tests/src/test/java/io/ballerina/persist/tools/BuildCodeGeneratorTest.java @@ -26,6 +26,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.io.PrintStream; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; @@ -152,7 +153,15 @@ private String collectLogOutput(Path project) throws IOException, InterruptedExc private void assertContainLogs(String log, Path project) throws IOException, InterruptedException { String generatedLog = collectLogOutput(project); - Assert.assertTrue(generatedLog.contains(log)); + PrintStream out = System.out; + if (!generatedLog.contains(log)) { + out.println("=== Build Log Output for " + project + " ==="); + out.println(generatedLog); + out.println("=== End Build Log ==="); + } + Assert.assertTrue(generatedLog.contains(log), + "Expected log message not found.\nExpected substring: '" + log + + "'\nActual log output (" + generatedLog.length() + " chars):\n" + generatedLog); } public static Process executeBuild(String distributionName, Path sourceDirectory, diff --git a/persist-cli/src/main/java/io/ballerina/persist/cmd/PersistCmd.java b/persist-cli/src/main/java/io/ballerina/persist/cmd/PersistCmd.java index 98002b970..602481bf7 100644 --- a/persist-cli/src/main/java/io/ballerina/persist/cmd/PersistCmd.java +++ b/persist-cli/src/main/java/io/ballerina/persist/cmd/PersistCmd.java @@ -40,11 +40,43 @@ public class PersistCmd implements BLauncherCmd { private static final PrintStream errStream = System.err; + private static final int EXIT_CODE_0 = 0; + private static final int EXIT_CODE_2 = 2; + private static final ExitHandler DEFAULT_EXIT_HANDLER = code -> Runtime.getRuntime().exit(code); + + private final ExitHandler exitHandler; @CommandLine.Option(names = {"-h", "--help"}, hidden = true) private boolean helpFlag; + /** + * Functional interface for handling exit behavior. + * Public to allow test access from other packages. + */ + @FunctionalInterface + public interface ExitHandler { + void exit(int code); + } + + /** + * Default constructor for production use. + */ public PersistCmd() { + this(DEFAULT_EXIT_HANDLER); + } + + /** + * Constructor for testing with custom exit handler. + * This is public to allow tests in other packages to use it. + * + * @param exitHandler custom exit handler (for testing) + */ + public PersistCmd(ExitHandler exitHandler) { + this.exitHandler = exitHandler; + } + + private void exit(int code) { + exitHandler.exit(code); } @Override @@ -52,11 +84,13 @@ public void execute() { if (helpFlag) { String commandUsageInfo = BLauncherCmd.getCommandUsageInfo(getName(), PersistCmd.class.getClassLoader()); errStream.println(commandUsageInfo); + exit(EXIT_CODE_0); return; } String commandUsageInfo = BLauncherCmd.getCommandUsageInfo(COMPONENT_IDENTIFIER, PersistCmd.class.getClassLoader()); errStream.println(commandUsageInfo); + exit(EXIT_CODE_2); } @Override diff --git a/persist-cli/src/test/java/io/ballerina/persist/cmd/ExitCodeCaptor.java b/persist-cli/src/test/java/io/ballerina/persist/cmd/ExitCodeCaptor.java new file mode 100644 index 000000000..f7f09e525 --- /dev/null +++ b/persist-cli/src/test/java/io/ballerina/persist/cmd/ExitCodeCaptor.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2025, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.ballerina.persist.cmd; + +import io.ballerina.persist.cmd.PersistCmd.ExitHandler; + +/** + * Test helper for capturing exit codes in tests. + */ +public class ExitCodeCaptor implements ExitHandler { + private int exitCode = -1; + private boolean exitCalled = false; + + @Override + public void exit(int code) { + this.exitCode = code; + this.exitCalled = true; + } + + public int getExitCode() { + if (!exitCalled) { + throw new IllegalStateException("exit() was not called"); + } + return exitCode; + } + + public boolean wasExitCalled() { + return exitCalled; + } +} diff --git a/persist-cli/src/test/java/io/ballerina/persist/cmd/PersistCmdTest.java b/persist-cli/src/test/java/io/ballerina/persist/cmd/PersistCmdTest.java new file mode 100644 index 000000000..726725366 --- /dev/null +++ b/persist-cli/src/test/java/io/ballerina/persist/cmd/PersistCmdTest.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2025, WSO2 LLC. (http://www.wso2.org). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package io.ballerina.persist.cmd; + +import org.testng.Assert; +import org.testng.annotations.Test; +import picocli.CommandLine; + +/** + * This class is used to test the functionality of the Persist command exit codes. + */ +public class PersistCmdTest { + + @Test(description = "Test persist command execution without arguments - should return exit code 2") + public void testExecuteWithoutArguments() { + String[] args = {}; + ExitCodeCaptor exitCaptor = new ExitCodeCaptor(); + PersistCmd persistCmd = new PersistCmd(exitCaptor); + new CommandLine(persistCmd).parseArgs(args); + persistCmd.execute(); + Assert.assertEquals(exitCaptor.getExitCode(), 2, + "persist command without arguments should exit with code 2"); + } + + @Test(description = "Test persist command execution with help flag - should return exit code 0") + public void testExecuteWithHelpFlag() { + String[] args = {"-h"}; + ExitCodeCaptor exitCaptor = new ExitCodeCaptor(); + PersistCmd persistCmd = new PersistCmd(exitCaptor); + new CommandLine(persistCmd).parseArgs(args); + persistCmd.execute(); + Assert.assertEquals(exitCaptor.getExitCode(), 0, + "persist command with -h flag should exit with code 0"); + } + + @Test(description = "Test persist command execution with invalid flag - should throw exception during parsing") + public void testExecuteWithInvalidFlag() { + String[] args = {"--invalidFlag"}; + ExitCodeCaptor exitCaptor = new ExitCodeCaptor(); + PersistCmd persistCmd = new PersistCmd(exitCaptor); + try { + new CommandLine(persistCmd).parseArgs(args); + Assert.fail("Expected picocli to throw exception for invalid flag"); + } catch (CommandLine.UnmatchedArgumentException e) { + // Expected: picocli rejects invalid flags + Assert.assertTrue(e.getMessage().contains("Unknown option")); + } + } +} diff --git a/persist-tool/Ballerina.toml b/persist-tool/Ballerina.toml index 758115722..e2b7dce53 100644 --- a/persist-tool/Ballerina.toml +++ b/persist-tool/Ballerina.toml @@ -1,8 +1,8 @@ [package] org = "ballerina" -name = "tool_persist" +name = "tool.persist" version = "1.7.0" authors = ["Ballerina"] -keywords = ["persist", "persist tool"] +keywords = ["persist", "persist tool", "ORM"] license = ["Apache-2.0"] -distribution = "2201.12.4" +distribution = "2201.13.0" diff --git a/persist-tool/Dependencies.toml b/persist-tool/Dependencies.toml index c159c01f8..4149f2512 100644 --- a/persist-tool/Dependencies.toml +++ b/persist-tool/Dependencies.toml @@ -5,13 +5,13 @@ [ballerina] dependencies-toml-version = "2" -distribution-version = "2201.13.0-20250613-152200-ecef3657" +distribution-version = "2201.13.0-20250924-081800-3dae8c03" [[package]] org = "ballerina" -name = "tool_persist" +name = "tool.persist" version = "1.7.0" modules = [ - {org = "ballerina", packageName = "tool_persist", moduleName = "tool_persist"} + {org = "ballerina", packageName = "tool.persist", moduleName = "tool.persist"} ] diff --git a/persist-tool/build.gradle b/persist-tool/build.gradle index 6627b114d..1b30a19b7 100644 --- a/persist-tool/build.gradle +++ b/persist-tool/build.gradle @@ -25,7 +25,7 @@ plugins { description = 'Ballerina - Persist Tool' -def packageName = "tool_persist" +def packageName = "tool.persist" def packageOrg = "ballerina" def tomlVersion = stripBallerinaExtensionVersion("${project.version}") def ballerinaTomlFilePlaceHolder = new File("${project.rootDir}/build-config/resources/Ballerina.toml") diff --git a/settings.gradle b/settings.gradle index 38f2cc384..699ac7cb5 100644 --- a/settings.gradle +++ b/settings.gradle @@ -9,10 +9,10 @@ pluginManagement { plugins { - id "com.github.spotbugs" version "${githubSpotbugsVersion}" - id "com.github.johnrengelman.shadow" version "${githubJohnrengelmanShadowVersion}" - id "de.undercouch.download" version "${underCouchDownloadVersion}" - id "net.researchgate.release" version "${researchgateReleaseVersion}" + id "com.github.spotbugs" version "${spotbugsPluginVersion}" + id "com.github.johnrengelman.shadow" version "${shadowJarVersion}" + id "de.undercouch.download" version "${downloadPluginVersion}" + id "net.researchgate.release" version "${releasePluginVersion}" id "io.ballerina.plugin" version "${ballerinaGradlePluginVersion}" }