diff --git a/cli/ballerina-cli/src/test/java/io/ballerina/cli/cmd/RunBuildToolsTaskTest.java b/cli/ballerina-cli/src/test/java/io/ballerina/cli/cmd/RunBuildToolsTaskTest.java index 99d0f986f429..2c12bdcc081c 100644 --- a/cli/ballerina-cli/src/test/java/io/ballerina/cli/cmd/RunBuildToolsTaskTest.java +++ b/cli/ballerina-cli/src/test/java/io/ballerina/cli/cmd/RunBuildToolsTaskTest.java @@ -30,6 +30,7 @@ import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; +import org.wso2.ballerinalang.util.RepoUtils; import java.io.IOException; import java.nio.file.Files; @@ -52,9 +53,13 @@ public class RunBuildToolsTaskTest extends BaseCommandTest { private static final Path testDistCacheDirectory = testBuildDirectory.resolve(DIST_CACHE_DIRECTORY); Path mockCentralBalaDirPath = testDistCacheDirectory.resolve("bala"); + private static final long TWO_DAYS = 2 * 24 * 60 * 60 * 1000; + private static final long HALF_DAY = 12 * 60 * 60 * 1000; + @BeforeClass public void setup() throws IOException { super.setup(); + // copy all test resources try { Path testResources = super.tmpDir.resolve("build-tool-test-resources"); this.buildToolResources = testResources.resolve("buildToolResources"); @@ -64,6 +69,7 @@ public void setup() throws IOException { } catch (Exception e) { Assert.fail("error loading resources"); } + // compile and cache tools BCompileUtil.compileAndCacheBala(buildToolResources.resolve("tools") .resolve("dummy-tool-pkg").toString(), testDistCacheDirectory); BCompileUtil.compileAndCacheBala(buildToolResources.resolve("tools") @@ -72,12 +78,21 @@ public void setup() throws IOException { .resolve("ballerina-generate-file").toString(), testDistCacheDirectory); BCompileUtil.compileAndCacheBala(buildToolResources.resolve("tools") .resolve("hidden-cmd-tool-pkg").toString(), testDistCacheDirectory); + BCompileUtil.compileAndCacheBala(buildToolResources.resolve("tools") + .resolve("missing-interface-tool-pkg").toString(), testDistCacheDirectory); + BCompileUtil.compileAndCacheBala(buildToolResources.resolve("tools") + .resolve("no-options-tool-pkg").toString(), testDistCacheDirectory); + // add build.json files + addBuildJsonToProjects("project-lt-24h-with-build-tool", System.currentTimeMillis() - HALF_DAY); + addBuildJsonToProjects("project-gt-24h-with-build-tool", System.currentTimeMillis() - TWO_DAYS); } - @Test(description = "Resolve a tool offline", dataProvider = "buildToolProvider") - public void testOfflineToolResolution(String projectName, String outputFileName) throws IOException { + @Test(description = "Resolve a tool offline", dataProvider = "buildToolOfflineProvider") + public void testOfflineToolResolution(String projectName, String outputFileName, boolean sticky) + throws IOException { Path projectPath = buildToolResources.resolve(projectName); - Project project = BuildProject.load(projectPath, BuildOptions.builder().setOffline(true).build()); + Project project = BuildProject.load(projectPath, + BuildOptions.builder().setOffline(true).setSticky(sticky).build()); RunBuildToolsTask runBuildToolsTask = new RunBuildToolsTask(printStream); try (MockedStatic repoUtils = Mockito.mockStatic( BuildToolUtils.class, Mockito.CALLS_REAL_METHODS)) { @@ -114,45 +129,102 @@ public void testProjectForAddedGeneratedCode() throws IOException { "Generated file not found. Project instance hasn't been updated after build tools task"); } - @DataProvider(name = "buildToolProvider") - public Object[][] buildToolProvider() { + @DataProvider(name = "buildToolOfflineProvider") + public Object[][] buildToolOfflineProvider() { return new Object[][]{ { "project-with-central-build-tool", - "build-tool-offline.txt" + "build-tool-offline.txt", + false }, { "project-with-non-existent-build-tool", - "build-tool-offline-resolve-failed.txt" + "build-tool-offline-resolve-failed.txt", + false }, { "fresh-project-with-central-build-tool", - "build-tool-offline-resolve-failed-wo-version.txt" + "build-tool-offline-resolve-failed-wo-version.txt", + false }, { "project-with-2.x-central-build-tool", - "build-tool-offline-with-new-major-version-locked.txt" + "build-tool-offline-with-new-major-version-locked.txt", + false }, { "project-with-non-existent-subcommand", - "build-tool-non-existent-subcommand.txt" + "build-tool-non-existent-subcommand.txt", + false }, { "project-with-invalid-name-build-tool", - "build-tool-invalid-name.txt" + "build-tool-invalid-name.txt", + false }, { "project-with-multilevel-subcommands", - "build-tool-multilevel-subcommands.txt" + "build-tool-multilevel-subcommands.txt", + false }, { "project-with-only-subcommands", - "build-tool-only-subcommands.txt" + "build-tool-only-subcommands.txt", + false }, { "project-with-hidden-commands", - "build-tool-hidden-commands.txt" + "build-tool-hidden-commands.txt", + false + }, + { + "project-with-missing-interface-build-tool", + "build-tool-missing-interface.txt", + false + }, + { + "project-with-no-options-build-tool", + "build-tool-no-options.txt", + false + }, + { + "project-with-old-build-tool", + "build-tool-without-sticky.txt", + false + }, + { + "project-with-old-build-tool", + "build-tool-with-sticky.txt", + true + }, + { + "project-lt-24h-with-build-tool", + "build-tool-lt-24-build-file.txt", + false + }, + { + "project-gt-24h-with-build-tool", + "build-tool-gt-24-build-file.txt", + false }, }; } + + private void addBuildJsonToProjects(String projectName, long time) { + Path buildJsonPath = buildToolResources.resolve(projectName).resolve("target").resolve("build"); + String buildJsonContent = "{\n" + + " \"last_build_time\": 1710907945705,\n" + + " \"last_update_time\": " + time + ",\n" + + " \"distribution_version\": \"" + RepoUtils.getBallerinaShortVersion() + "\",\n" + + " \"last_modified_time\": {\n" + + " \"sample_build_tool_ballerina\": 1710907943604\n" + + " }\n" + + "}"; + try { + Files.createDirectories(buildJsonPath.getParent()); + Files.write(buildJsonPath, buildJsonContent.getBytes()); + } catch (IOException e) { + Assert.fail("Error writing build.json file"); + } + } } diff --git a/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-gt-24h-with-build-tool/Ballerina.toml b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-gt-24h-with-build-tool/Ballerina.toml new file mode 100644 index 000000000000..77d666333090 --- /dev/null +++ b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-gt-24h-with-build-tool/Ballerina.toml @@ -0,0 +1,10 @@ +[package] +org = "foo" +name = "winery" +version = "0.1.0" + +[[tool.dummy_tool]] +id = "main_dummy" +filePath = "delivery.json" +targetModule = "mod_main" +options.mode = "client" diff --git a/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-gt-24h-with-build-tool/Dependencies.toml b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-gt-24h-with-build-tool/Dependencies.toml new file mode 100644 index 000000000000..9dc35e4c5d2d --- /dev/null +++ b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-gt-24h-with-build-tool/Dependencies.toml @@ -0,0 +1,23 @@ + # AUTO-GENERATED FILE. DO NOT MODIFY. + +# This file is auto-generated by Ballerina for managing dependency versions. +# It should not be modified by hand. + +[ballerina] +dependencies-toml-version = "2" +distribution-version = "2201.8.5" + +[[package]] +org = "foo" +name = "winery" +version = "0.1.0" +modules = [ + {org = "foo", packageName = "winery", moduleName = "winery"} +] + +[[tool]] +id = "dummy_tool" +org = "foo" +name = "dummypkg" +version = "1.3.0" + diff --git a/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-gt-24h-with-build-tool/delivery.json b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-gt-24h-with-build-tool/delivery.json new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-gt-24h-with-build-tool/main.bal b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-gt-24h-with-build-tool/main.bal new file mode 100644 index 000000000000..62e86cafda3b --- /dev/null +++ b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-gt-24h-with-build-tool/main.bal @@ -0,0 +1,19 @@ +// Copyright (c) 2024, WSO2 LLC. (https://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. + +public function main() { + return; +} diff --git a/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-lt-24h-with-build-tool/Ballerina.toml b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-lt-24h-with-build-tool/Ballerina.toml new file mode 100644 index 000000000000..77d666333090 --- /dev/null +++ b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-lt-24h-with-build-tool/Ballerina.toml @@ -0,0 +1,10 @@ +[package] +org = "foo" +name = "winery" +version = "0.1.0" + +[[tool.dummy_tool]] +id = "main_dummy" +filePath = "delivery.json" +targetModule = "mod_main" +options.mode = "client" diff --git a/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-lt-24h-with-build-tool/Dependencies.toml b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-lt-24h-with-build-tool/Dependencies.toml new file mode 100644 index 000000000000..9dc35e4c5d2d --- /dev/null +++ b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-lt-24h-with-build-tool/Dependencies.toml @@ -0,0 +1,23 @@ + # AUTO-GENERATED FILE. DO NOT MODIFY. + +# This file is auto-generated by Ballerina for managing dependency versions. +# It should not be modified by hand. + +[ballerina] +dependencies-toml-version = "2" +distribution-version = "2201.8.5" + +[[package]] +org = "foo" +name = "winery" +version = "0.1.0" +modules = [ + {org = "foo", packageName = "winery", moduleName = "winery"} +] + +[[tool]] +id = "dummy_tool" +org = "foo" +name = "dummypkg" +version = "1.3.0" + diff --git a/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-lt-24h-with-build-tool/delivery.json b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-lt-24h-with-build-tool/delivery.json new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-lt-24h-with-build-tool/main.bal b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-lt-24h-with-build-tool/main.bal new file mode 100644 index 000000000000..62e86cafda3b --- /dev/null +++ b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-lt-24h-with-build-tool/main.bal @@ -0,0 +1,19 @@ +// Copyright (c) 2024, WSO2 LLC. (https://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. + +public function main() { + return; +} diff --git a/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-with-missing-interface-build-tool/Ballerina.toml b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-with-missing-interface-build-tool/Ballerina.toml new file mode 100644 index 000000000000..0dbfe6f0fdd2 --- /dev/null +++ b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-with-missing-interface-build-tool/Ballerina.toml @@ -0,0 +1,10 @@ +[package] +org = "foo" +name = "winery" +version = "0.1.0" + +[[tool.missing_interface_dummy_tool]] +id = "main_dummy" +filePath = "delivery.json" +targetModule = "mod_main" +options.mode = "client" diff --git a/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-with-missing-interface-build-tool/Dependencies.toml b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-with-missing-interface-build-tool/Dependencies.toml new file mode 100644 index 000000000000..8f8f288cf280 --- /dev/null +++ b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-with-missing-interface-build-tool/Dependencies.toml @@ -0,0 +1,23 @@ +# AUTO-GENERATED FILE. DO NOT MODIFY. + +# This file is auto-generated by Ballerina for managing dependency versions. +# It should not be modified by hand. + +[ballerina] +dependencies-toml-version = "2" +distribution-version = "2201.8.5" + +[[package]] +org = "foo" +name = "winery" +version = "0.1.0" +modules = [ + {org = "foo", packageName = "winery", moduleName = "winery"} +] + +[[tool]] +id = "missing_interface_dummy_tool" +org = "foo" +name = "missing_interface_pkg" +version = "1.4.0" + diff --git a/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-with-missing-interface-build-tool/delivery.json b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-with-missing-interface-build-tool/delivery.json new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-with-missing-interface-build-tool/main.bal b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-with-missing-interface-build-tool/main.bal new file mode 100644 index 000000000000..62e86cafda3b --- /dev/null +++ b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-with-missing-interface-build-tool/main.bal @@ -0,0 +1,19 @@ +// Copyright (c) 2024, WSO2 LLC. (https://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. + +public function main() { + return; +} diff --git a/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-with-no-options-build-tool/Ballerina.toml b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-with-no-options-build-tool/Ballerina.toml new file mode 100644 index 000000000000..41e8abf1ec1a --- /dev/null +++ b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-with-no-options-build-tool/Ballerina.toml @@ -0,0 +1,10 @@ +[package] +org = "foo" +name = "winery" +version = "0.1.0" + +[[tool.no_options_tool]] +id = "main_dummy" +filePath = "delivery.json" +targetModule = "mod_main" +options.mode = "client" diff --git a/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-with-no-options-build-tool/Dependencies.toml b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-with-no-options-build-tool/Dependencies.toml new file mode 100644 index 000000000000..1e414cdfad7d --- /dev/null +++ b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-with-no-options-build-tool/Dependencies.toml @@ -0,0 +1,23 @@ +# AUTO-GENERATED FILE. DO NOT MODIFY. + +# This file is auto-generated by Ballerina for managing dependency versions. +# It should not be modified by hand. + +[ballerina] +dependencies-toml-version = "2" +distribution-version = "2201.8.5" + +[[package]] +org = "foo" +name = "winery" +version = "0.1.0" +modules = [ + {org = "foo", packageName = "winery", moduleName = "winery"} +] + +[[tool]] +id = "no_options_tool" +org = "foo" +name = "no_options_pkg" +version = "1.4.0" + diff --git a/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-with-no-options-build-tool/delivery.json b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-with-no-options-build-tool/delivery.json new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-with-no-options-build-tool/main.bal b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-with-no-options-build-tool/main.bal new file mode 100644 index 000000000000..62e86cafda3b --- /dev/null +++ b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-with-no-options-build-tool/main.bal @@ -0,0 +1,19 @@ +// Copyright (c) 2024, WSO2 LLC. (https://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. + +public function main() { + return; +} diff --git a/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-with-old-build-tool/Ballerina.toml b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-with-old-build-tool/Ballerina.toml new file mode 100644 index 000000000000..77d666333090 --- /dev/null +++ b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-with-old-build-tool/Ballerina.toml @@ -0,0 +1,10 @@ +[package] +org = "foo" +name = "winery" +version = "0.1.0" + +[[tool.dummy_tool]] +id = "main_dummy" +filePath = "delivery.json" +targetModule = "mod_main" +options.mode = "client" diff --git a/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-with-old-build-tool/Dependencies.toml b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-with-old-build-tool/Dependencies.toml new file mode 100644 index 000000000000..a298dbe7285e --- /dev/null +++ b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-with-old-build-tool/Dependencies.toml @@ -0,0 +1,23 @@ + # AUTO-GENERATED FILE. DO NOT MODIFY. + +# This file is auto-generated by Ballerina for managing dependency versions. +# It should not be modified by hand. + +[ballerina] +dependencies-toml-version = "2" +distribution-version = "2201.8.5" + +[[package]] +org = "foo" +name = "winery" +version = "0.1.0" +modules = [ + {org = "foo", packageName = "winery", moduleName = "winery"} +] + +[[tool]] +id = "dummy_tool" +org = "foo" +name = "dummypkg" +version = "1.3.5" + diff --git a/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-with-old-build-tool/delivery.json b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-with-old-build-tool/delivery.json new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-with-old-build-tool/main.bal b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-with-old-build-tool/main.bal new file mode 100644 index 000000000000..62e86cafda3b --- /dev/null +++ b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/project-with-old-build-tool/main.bal @@ -0,0 +1,19 @@ +// Copyright (c) 2024, WSO2 LLC. (https://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. + +public function main() { + return; +} diff --git a/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/tools/hidden-cmd-tool-pkg/resources/sample-dummy-build-tool-1.4.0.jar b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/tools/hidden-cmd-tool-pkg/resources/sample-dummy-build-tool-1.4.0.jar new file mode 100644 index 000000000000..db8aff7694fb Binary files /dev/null and b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/tools/hidden-cmd-tool-pkg/resources/sample-dummy-build-tool-1.4.0.jar differ diff --git a/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/tools/missing-interface-tool-pkg/BalTool.toml b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/tools/missing-interface-tool-pkg/BalTool.toml new file mode 100644 index 000000000000..2d2f129f3322 --- /dev/null +++ b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/tools/missing-interface-tool-pkg/BalTool.toml @@ -0,0 +1,5 @@ +[tool] +id="missing_interface_dummy_tool" + +[[dependency]] +path="./resources/sample-dummy-build-tool-1.4.0.jar" \ No newline at end of file diff --git a/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/tools/missing-interface-tool-pkg/Ballerina.toml b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/tools/missing-interface-tool-pkg/Ballerina.toml new file mode 100644 index 000000000000..8c1ff2e38c88 --- /dev/null +++ b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/tools/missing-interface-tool-pkg/Ballerina.toml @@ -0,0 +1,8 @@ +[package] +org = "foo" +name = "missing_interface_pkg" +version = "1.4.0" +distribution = "2201.8.4" + +[build-options] +observabilityIncluded = true diff --git a/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/tools/missing-interface-tool-pkg/main.bal b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/tools/missing-interface-tool-pkg/main.bal new file mode 100644 index 000000000000..d97c13f29ea2 --- /dev/null +++ b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/tools/missing-interface-tool-pkg/main.bal @@ -0,0 +1,18 @@ +// Copyright (c) 2024, WSO2 LLC. (https://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. + +public function main() { +} diff --git a/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/tools/missing-interface-tool-pkg/resources/sample-dummy-build-tool-1.4.0.jar b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/tools/missing-interface-tool-pkg/resources/sample-dummy-build-tool-1.4.0.jar new file mode 100644 index 000000000000..edfc9002bab2 Binary files /dev/null and b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/tools/missing-interface-tool-pkg/resources/sample-dummy-build-tool-1.4.0.jar differ diff --git a/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/tools/no-options-tool-pkg/BalTool.toml b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/tools/no-options-tool-pkg/BalTool.toml new file mode 100644 index 000000000000..50fc898e527d --- /dev/null +++ b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/tools/no-options-tool-pkg/BalTool.toml @@ -0,0 +1,5 @@ +[tool] +id="no_options_tool" + +[[dependency]] +path="./resources/sample-dummy-build-tool-1.4.0.jar" \ No newline at end of file diff --git a/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/tools/no-options-tool-pkg/Ballerina.toml b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/tools/no-options-tool-pkg/Ballerina.toml new file mode 100644 index 000000000000..3e57539748c8 --- /dev/null +++ b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/tools/no-options-tool-pkg/Ballerina.toml @@ -0,0 +1,8 @@ +[package] +org = "foo" +name = "no_options_pkg" +version = "1.4.0" +distribution = "2201.8.4" + +[build-options] +observabilityIncluded = true diff --git a/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/tools/no-options-tool-pkg/main.bal b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/tools/no-options-tool-pkg/main.bal new file mode 100644 index 000000000000..d97c13f29ea2 --- /dev/null +++ b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/tools/no-options-tool-pkg/main.bal @@ -0,0 +1,18 @@ +// Copyright (c) 2024, WSO2 LLC. (https://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. + +public function main() { +} diff --git a/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/tools/no-options-tool-pkg/resources/sample-dummy-build-tool-1.4.0.jar b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/tools/no-options-tool-pkg/resources/sample-dummy-build-tool-1.4.0.jar new file mode 100644 index 000000000000..8e557d13a7dc Binary files /dev/null and b/cli/ballerina-cli/src/test/resources/test-resources/buildToolResources/tools/no-options-tool-pkg/resources/sample-dummy-build-tool-1.4.0.jar differ diff --git a/cli/ballerina-cli/src/test/resources/test-resources/command-outputs/unix/build-tool-gt-24-build-file.txt b/cli/ballerina-cli/src/test/resources/test-resources/command-outputs/unix/build-tool-gt-24-build-file.txt new file mode 100644 index 000000000000..6671dc5a756a --- /dev/null +++ b/cli/ballerina-cli/src/test/resources/test-resources/command-outputs/unix/build-tool-gt-24-build-file.txt @@ -0,0 +1,5 @@ + +Executing Build Tools + dummy_tool(main_dummy) + Running sample build tool: main_dummy + diff --git a/cli/ballerina-cli/src/test/resources/test-resources/command-outputs/unix/build-tool-lt-24-build-file.txt b/cli/ballerina-cli/src/test/resources/test-resources/command-outputs/unix/build-tool-lt-24-build-file.txt new file mode 100644 index 000000000000..050932cbd5fd --- /dev/null +++ b/cli/ballerina-cli/src/test/resources/test-resources/command-outputs/unix/build-tool-lt-24-build-file.txt @@ -0,0 +1,4 @@ + +Executing Build Tools +ERROR [Ballerina.toml:(6:1,10:24)] Build tool 'dummy_tool:1.3.0' cannot be resolved + diff --git a/cli/ballerina-cli/src/test/resources/test-resources/command-outputs/unix/build-tool-missing-interface.txt b/cli/ballerina-cli/src/test/resources/test-resources/command-outputs/unix/build-tool-missing-interface.txt new file mode 100644 index 000000000000..3e68ff7fed16 --- /dev/null +++ b/cli/ballerina-cli/src/test/resources/test-resources/command-outputs/unix/build-tool-missing-interface.txt @@ -0,0 +1,5 @@ + +Executing Build Tools +ERROR [Ballerina.toml:(6:1,10:24)] Build tool command 'missing_interface_dummy_tool' not found +WARNING: Execution of 'missing_interface_dummy_tool:main_dummy' is skipped due to errors + diff --git a/cli/ballerina-cli/src/test/resources/test-resources/command-outputs/unix/build-tool-no-options.txt b/cli/ballerina-cli/src/test/resources/test-resources/command-outputs/unix/build-tool-no-options.txt new file mode 100644 index 000000000000..363f89ef73a1 --- /dev/null +++ b/cli/ballerina-cli/src/test/resources/test-resources/command-outputs/unix/build-tool-no-options.txt @@ -0,0 +1,6 @@ + +Executing Build Tools +WARNING: Validation of tool options of 'no_options_tool' for 'main_dummy' is skipped due to: Schema file for tool options inputStream not found: no_options_tool-options-schema.json + no_options_tool(main_dummy) + Running sample build tool: main_dummy + diff --git a/cli/ballerina-cli/src/test/resources/test-resources/command-outputs/unix/build-tool-with-sticky.txt b/cli/ballerina-cli/src/test/resources/test-resources/command-outputs/unix/build-tool-with-sticky.txt new file mode 100644 index 000000000000..73ffb5c42957 --- /dev/null +++ b/cli/ballerina-cli/src/test/resources/test-resources/command-outputs/unix/build-tool-with-sticky.txt @@ -0,0 +1,4 @@ + +Executing Build Tools +ERROR [Ballerina.toml:(6:1,10:24)] Build tool 'dummy_tool:1.3.5' cannot be resolved + diff --git a/cli/ballerina-cli/src/test/resources/test-resources/command-outputs/unix/build-tool-without-sticky.txt b/cli/ballerina-cli/src/test/resources/test-resources/command-outputs/unix/build-tool-without-sticky.txt new file mode 100644 index 000000000000..6671dc5a756a --- /dev/null +++ b/cli/ballerina-cli/src/test/resources/test-resources/command-outputs/unix/build-tool-without-sticky.txt @@ -0,0 +1,5 @@ + +Executing Build Tools + dummy_tool(main_dummy) + Running sample build tool: main_dummy + diff --git a/cli/ballerina-cli/src/test/resources/test-resources/command-outputs/windows/build-tool-gt-24-build-file.txt b/cli/ballerina-cli/src/test/resources/test-resources/command-outputs/windows/build-tool-gt-24-build-file.txt new file mode 100644 index 000000000000..6671dc5a756a --- /dev/null +++ b/cli/ballerina-cli/src/test/resources/test-resources/command-outputs/windows/build-tool-gt-24-build-file.txt @@ -0,0 +1,5 @@ + +Executing Build Tools + dummy_tool(main_dummy) + Running sample build tool: main_dummy + diff --git a/cli/ballerina-cli/src/test/resources/test-resources/command-outputs/windows/build-tool-lt-24-build-file.txt b/cli/ballerina-cli/src/test/resources/test-resources/command-outputs/windows/build-tool-lt-24-build-file.txt new file mode 100644 index 000000000000..050932cbd5fd --- /dev/null +++ b/cli/ballerina-cli/src/test/resources/test-resources/command-outputs/windows/build-tool-lt-24-build-file.txt @@ -0,0 +1,4 @@ + +Executing Build Tools +ERROR [Ballerina.toml:(6:1,10:24)] Build tool 'dummy_tool:1.3.0' cannot be resolved + diff --git a/cli/ballerina-cli/src/test/resources/test-resources/command-outputs/windows/build-tool-missing-interface.txt b/cli/ballerina-cli/src/test/resources/test-resources/command-outputs/windows/build-tool-missing-interface.txt new file mode 100644 index 000000000000..3e68ff7fed16 --- /dev/null +++ b/cli/ballerina-cli/src/test/resources/test-resources/command-outputs/windows/build-tool-missing-interface.txt @@ -0,0 +1,5 @@ + +Executing Build Tools +ERROR [Ballerina.toml:(6:1,10:24)] Build tool command 'missing_interface_dummy_tool' not found +WARNING: Execution of 'missing_interface_dummy_tool:main_dummy' is skipped due to errors + diff --git a/cli/ballerina-cli/src/test/resources/test-resources/command-outputs/windows/build-tool-no-options.txt b/cli/ballerina-cli/src/test/resources/test-resources/command-outputs/windows/build-tool-no-options.txt new file mode 100644 index 000000000000..363f89ef73a1 --- /dev/null +++ b/cli/ballerina-cli/src/test/resources/test-resources/command-outputs/windows/build-tool-no-options.txt @@ -0,0 +1,6 @@ + +Executing Build Tools +WARNING: Validation of tool options of 'no_options_tool' for 'main_dummy' is skipped due to: Schema file for tool options inputStream not found: no_options_tool-options-schema.json + no_options_tool(main_dummy) + Running sample build tool: main_dummy + diff --git a/cli/ballerina-cli/src/test/resources/test-resources/command-outputs/windows/build-tool-with-sticky.txt b/cli/ballerina-cli/src/test/resources/test-resources/command-outputs/windows/build-tool-with-sticky.txt new file mode 100644 index 000000000000..73ffb5c42957 --- /dev/null +++ b/cli/ballerina-cli/src/test/resources/test-resources/command-outputs/windows/build-tool-with-sticky.txt @@ -0,0 +1,4 @@ + +Executing Build Tools +ERROR [Ballerina.toml:(6:1,10:24)] Build tool 'dummy_tool:1.3.5' cannot be resolved + diff --git a/cli/ballerina-cli/src/test/resources/test-resources/command-outputs/windows/build-tool-without-sticky.txt b/cli/ballerina-cli/src/test/resources/test-resources/command-outputs/windows/build-tool-without-sticky.txt new file mode 100644 index 000000000000..6671dc5a756a --- /dev/null +++ b/cli/ballerina-cli/src/test/resources/test-resources/command-outputs/windows/build-tool-without-sticky.txt @@ -0,0 +1,5 @@ + +Executing Build Tools + dummy_tool(main_dummy) + Running sample build tool: main_dummy + diff --git a/cli/central-client/src/main/java/org/ballerinalang/central/client/CentralAPIClient.java b/cli/central-client/src/main/java/org/ballerinalang/central/client/CentralAPIClient.java index c3590a95ed7d..0b55427c1426 100644 --- a/cli/central-client/src/main/java/org/ballerinalang/central/client/CentralAPIClient.java +++ b/cli/central-client/src/main/java/org/ballerinalang/central/client/CentralAPIClient.java @@ -682,7 +682,7 @@ public String[] pullTool(String toolId, String version, Path balaCacheDirPath, S } logResponseVerbose(packagePullResponse, pkgPullResBodyContent); - // 302 - Package is found + // 200 - Package is found if (packagePullResponse.code() == HTTP_OK) { Optional org = Optional.empty(); Optional pkgName = Optional.empty(); diff --git a/cli/central-client/src/test/java/org/ballerinalang/central/client/TestCentralApiClient.java b/cli/central-client/src/test/java/org/ballerinalang/central/client/TestCentralApiClient.java index 86917090ea7f..48533f4ee53c 100644 --- a/cli/central-client/src/test/java/org/ballerinalang/central/client/TestCentralApiClient.java +++ b/cli/central-client/src/test/java/org/ballerinalang/central/client/TestCentralApiClient.java @@ -36,6 +36,9 @@ import org.ballerinalang.central.client.model.PackageResolutionRequest; import org.ballerinalang.central.client.model.PackageResolutionResponse; import org.ballerinalang.central.client.model.PackageSearchResult; +import org.ballerinalang.central.client.model.ToolResolutionCentralRequest; +import org.ballerinalang.central.client.model.ToolResolutionCentralResponse; +import org.ballerinalang.central.client.model.ToolSearchResult; import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; @@ -83,6 +86,7 @@ public class TestCentralApiClient extends CentralAPIClient { private static final String TEST_BAL_VERSION = "slp5"; private static final String ANY_PLATFORM = "any"; private static final String TEST_BALA_NAME = "sf-any.bala"; + private static final String TEST_TOOL_BALA_NAME = "baz-toolbox-java17-0.1.0.bala"; private static final String OUTPUT_BALA = "output.bala"; private static final String WINERY = "winery"; private static final String ACCESS_TOKEN = "273cc9f6-c333-36ab-aa2q-f08e9513ff5y"; @@ -719,24 +723,25 @@ public void testPackageResolution() throws IOException, CentralClientException { @Test(description = "Test search package name resolution") public void testPackageNameResolution() throws IOException, CentralClientException { - String resString = "{\n" + - " \"resolvedModules\":[\n" + - " {\n" + - " \"organization\":\"shehanpa\",\n" + - " \"moduleName\":\"fb\",\n" + - " \"version\":\"0.7.0\",\n" + - " \"packageName\":\"fb\"\n" + - " }\n" + - " ],\n" + - " \"unresolvedModules\":[\n" + - " {\n" + - " \"organization\":\"hevayo\",\n" + - " \"moduleName\":\"fb\",\n" + - " \"version\":null,\n" + - " \"reason\":\"package not found\"\n" + - " }\n" + - " ]\n" + - "}"; + String resString = """ + { + "resolvedModules":[ + { + "organization":"shehanpa", + "moduleName":"fb", + "version":"0.7.0", + "packageName":"fb" + } + ], + "unresolvedModules":[ + { + "organization":"hevayo", + "moduleName":"fb", + "version":null, + "reason":"package not found" + } + ] + }"""; Request mockRequest = new Request.Builder() .get() .url("https://localhost:9090/registry/packages/resolve-modules") @@ -765,4 +770,152 @@ public void testPackageNameResolution() throws IOException, CentralClientExcepti PackageNameResolutionResponse.Module unresolvedModule = packageResolutionResponse.unresolvedModules().get(0); Assert.assertNull(unresolvedModule.getPackageName()); } + + @Test(description = "Test tool version resolution") + public void testToolResolution() throws IOException, CentralClientException { + String resString = "{\"resolved\":" + + "[{\"id\":\"health\", \"orgName\":\"ballerinax\", \"name\":\"health\", \"version\":\"2.1.1\"}, " + + "{\"id\":\"edi\", \"orgName\":\"ballerina\", \"name\":\"editoolspackage\", \"version\":\"1.0.0\"}], " + + "\"unresolved\":" + + "[{\"id\":\"blah\", \"version\":\"1.0.0\", " + + "\"reason\":\"unexpected error occured while searching for org name of tool id: blah\"}]}"; + Request mockRequest = new Request.Builder() + .get() + .url("https://localhost:9090/registry/tools/resolve-dependencies") + .build(); + Response mockResponse = new Response.Builder() + .request(mockRequest) + .protocol(Protocol.HTTP_1_1) + .code(HttpURLConnection.HTTP_OK) + .message("") + .body(ResponseBody.create( + MediaType.get(APPLICATION_JSON), + resString + )) + .build(); + + when(this.remoteCall.execute()).thenReturn(mockResponse); + when(this.client.newCall(any())).thenReturn(this.remoteCall); + + ToolResolutionCentralRequest toolResolutionRequest = new ToolResolutionCentralRequest(); + toolResolutionRequest.addTool("health", "2.1.0", ToolResolutionCentralRequest.Mode.MEDIUM); + toolResolutionRequest.addTool("edi", "1.0.0", ToolResolutionCentralRequest.Mode.SOFT); + toolResolutionRequest.addTool("blah", "1.0.0", ToolResolutionCentralRequest.Mode.HARD); + ToolResolutionCentralResponse toolResolutionResponse = this.resolveToolDependencies( + toolResolutionRequest, ANY_PLATFORM, TEST_BAL_VERSION); + + ToolResolutionCentralResponse.ResolvedTool resolvedTool = toolResolutionResponse.resolved().get(0); + Assert.assertEquals(resolvedTool.id(), "health"); + Assert.assertEquals(resolvedTool.org(), "ballerinax"); + Assert.assertEquals(resolvedTool.name(), "health"); + Assert.assertEquals(resolvedTool.version(), "2.1.1"); + + resolvedTool = toolResolutionResponse.resolved().get(1); + Assert.assertEquals(resolvedTool.id(), "edi"); + Assert.assertEquals(resolvedTool.org(), "ballerina"); + Assert.assertEquals(resolvedTool.name(), "editoolspackage"); + Assert.assertEquals(resolvedTool.version(), "1.0.0"); + + ToolResolutionCentralResponse.UnresolvedTool unresolvedTool = toolResolutionResponse.unresolved().get(0); + Assert.assertEquals(unresolvedTool.id(), "blah"); + Assert.assertEquals(unresolvedTool.version(), "1.0.0"); + } + + @Test(description = "Test search tool") + public void testSearchTool() throws IOException, CentralClientException { + Path toolSearchJsonPath = UTILS_TEST_RESOURCES.resolve("toolSearch.json"); + + Request mockRequest = new Request.Builder() + .get() + .url("https://localhost:9090/registry/tools/?q=foo") + .build(); + Response mockResponse = new Response.Builder() + .request(mockRequest) + .protocol(Protocol.HTTP_1_1) + .code(HttpURLConnection.HTTP_OK) + .message("") + .body(ResponseBody.create( + MediaType.get(APPLICATION_JSON), + Files.readString(toolSearchJsonPath) + )) + .build(); + + when(this.remoteCall.execute()).thenReturn(mockResponse); + when(this.client.newCall(any())).thenReturn(this.remoteCall); + + ToolSearchResult toolSearchResult = this.searchTool("health", ANY_PLATFORM, TEST_BAL_VERSION); + Assert.assertNotNull(toolSearchResult); + Assert.assertEquals(toolSearchResult.getTools().size(), 1); + Assert.assertEquals(toolSearchResult.getTools().get(0).getBalToolId(), "health"); + Assert.assertEquals(toolSearchResult.getTools().get(0).getOrganization(), "ballerinax"); + } + + @Test(description = "Test pull tool") + public void testPullTool() throws IOException, CentralClientException { + Path balaPath = UTILS_TEST_RESOURCES.resolve(TEST_TOOL_BALA_NAME); + File balaFile = new File(String.valueOf(balaPath)); + String balaFileName = "attachment; filename=baz-toolbox-java17-0.1.0.bala"; + + try (InputStream ignored = new FileInputStream(balaFile)) { + Request mockRequest = new Request.Builder() + .get() + .url("https://localhost:9090/registry/tools/sample_tool/0.1.0") + .addHeader(ACCEPT_ENCODING, IDENTITY) + .addHeader(ACCEPT, APPLICATION_OCTET_STREAM) + .build(); + String toolBalaUrl = "https://fileserver.dev-central.ballerina.io/2.0/wso2/toolbox/0.1.0/" + + "baz-toolbox-java17-0.1.0.bala"; + ResponseBody mockResponseBody = ResponseBody.create(MediaType.parse("application/json"), "{\n" + + " \"organization\": \"baz\",\n" + + " \"name\": \"toolbox\",\n" + + " \"version\": \"0.1.0\",\n" + + " \"balaURL\": \"" + toolBalaUrl + "\",\n" + + " \"platform\": \"java17\"\n}"); + Response mockResponse = new Response.Builder() + .request(mockRequest) + .protocol(Protocol.HTTP_1_1) + .code(HttpURLConnection.HTTP_OK) + .addHeader(LOCATION, this.balaUrl) + .addHeader(CONTENT_DISPOSITION, balaFileName) + .addHeader(DIGEST, "sha-256=47e043c80d516234b1e6bd93140f126c9d9e79b5c7c0600cc6316d12504c2cf4") + .message("") + .body(mockResponseBody) + .build(); + Request mockDownloadBalaRequest = new Request.Builder() + .get() + .url(toolBalaUrl) + .header(ACCEPT_ENCODING, IDENTITY) + .addHeader(CONTENT_DISPOSITION, balaFileName) + .build(); + Response mockDownloadBalaResponse = new Response.Builder() + .request(mockDownloadBalaRequest) + .protocol(Protocol.HTTP_1_1) + .code(HttpURLConnection.HTTP_OK) + .message("") + .body(ResponseBody.create( + MediaType.get(APPLICATION_OCTET_STREAM), + Files.readAllBytes(balaPath) + )) + .build(); + + when(this.remoteCall.execute()).thenReturn(mockResponse, mockDownloadBalaResponse); + when(this.client.newCall(any())).thenReturn(this.remoteCall); + + System.setProperty(CentralClientConstants.ENABLE_OUTPUT_STREAM, "true"); + this.pullTool("sample_tool", "0.1.0", TMP_DIR, ANY_PLATFORM, TEST_BAL_VERSION, false); + + Path balaDir = TMP_DIR.resolve("baz").resolve("toolbox").resolve("0.1.0").resolve("java17"); + Assert.assertTrue(balaDir.toFile().exists()); + Assert.assertTrue(balaDir.resolve("bala.json").toFile().exists()); + Assert.assertTrue(balaDir.resolve("modules").toFile().exists()); + Assert.assertTrue(balaDir.resolve("dependency-graph.json").toFile().exists()); + Assert.assertTrue(balaDir.resolve("package.json").toFile().exists()); + Assert.assertTrue(balaDir.resolve("package.json").toFile().exists()); + Assert.assertTrue(balaDir.resolve("tool").resolve("bal-tool.json").toFile().exists()); + Assert.assertTrue(balaDir.resolve("tool").resolve("libs").resolve("CompPluginRunnerCommand-1.0.0.jar") + .toFile().exists()); + } finally { + cleanTmpDir(); + } + } } diff --git a/cli/central-client/src/test/resources/test-resources/utils/baz-toolbox-java17-0.1.0.bala b/cli/central-client/src/test/resources/test-resources/utils/baz-toolbox-java17-0.1.0.bala new file mode 100644 index 000000000000..f9385d5b74c2 Binary files /dev/null and b/cli/central-client/src/test/resources/test-resources/utils/baz-toolbox-java17-0.1.0.bala differ diff --git a/cli/central-client/src/test/resources/test-resources/utils/toolSearch.json b/cli/central-client/src/test/resources/test-resources/utils/toolSearch.json new file mode 100644 index 000000000000..8b106dbfe7bb --- /dev/null +++ b/cli/central-client/src/test/resources/test-resources/utils/toolSearch.json @@ -0,0 +1,45 @@ +{ + "tools": [ + { + "id": 112418, + "organization": "ballerinax", + "name": "health", + "version": "2.1.1", + "platform": "java17", + "languageSpecificationVersion": "2023R1", + "isDeprecated": false, + "deprecateMessage": "", + "URL": "/ballerinax/health/2.1.1", + "balaVersion": "2.0.0", + "balaURL": "https://fileserver.dev-central.ballerina.io/2.0/ballerinax/health/2.1.1/ballerinax-health-java17-2.1.1.bala?Expires=1711434534&Signature=KDIhOMa3atru1UcXlF0ZGoGolYESt83vipe5guAA9ZXoTqTUnD10daOUcJhG-zyW9VaYVQHWh-XZ8QOJqKmCIrQ30JN8D7M2NFk-0DWN7H173UoVVs0IVmEjAfYrOWRmowoOCUMDOs7y6AOLo57W~oapeNrvGpAb~EQUiuIepK5PdF9JzO6gDXPWpyfSHUEhRENqcRdUv-DBSsYo~aWjG8E-DBxsKwa68SRznO~ebUhSaGZPS8wAfuXspsaps7nh0XyM22EAqEpxaE302L5FM7ufmnh3norDDw5Xqi8b3COHk4X64SWmYyHDuRAAcc39Y4bZ0d0nzVxn6P2hba3hyQ__&Key-Pair-Id=K1LACXT8B3Y0DU", + "digest": "sha-256=39f2ca85b12f291044301ac3cc7b9b3f73bbf4dff1b1b4172e9c340233bd3aca", + "summary": "This project contains an extension implementation for Ballerina CLI that generates", + "readme": "", + "template": false, + "licenses": [], + "authors": [], + "sourceCodeLocation": "", + "keywords": [], + "ballerinaVersion": "2201.8.1", + "icon": "", + "ownerUUID": "29285ffc-95b1-4397-8e7a-f45f71bc8379", + "createdDate": 1706673880000, + "pullCount": 0, + "visibility": "public", + "modules": [ + { + "packageURL": "/ballerinax/health/2.1.1", + "apiDocURL": "https://dev-lib.ballerina.io/ballerinax/health/2.1.1", + "name": "health", + "summary": "This project contains an extension implementation for Ballerina CLI that generates ", + "readme": "" + } + ], + "balToolId": "health", + "graalvmCompatible": "Unknown" + } + ], + "count": 2, + "offset": 0, + "limit": 15 +} diff --git a/compiler/ballerina-lang/src/test/java/io/ballerina/projects/DependenciesTomlTests.java b/compiler/ballerina-lang/src/test/java/io/ballerina/projects/DependenciesTomlTests.java index cc40d4c52742..9ecdb566ae86 100644 --- a/compiler/ballerina-lang/src/test/java/io/ballerina/projects/DependenciesTomlTests.java +++ b/compiler/ballerina-lang/src/test/java/io/ballerina/projects/DependenciesTomlTests.java @@ -93,6 +93,21 @@ public void testValidDependenciesToml() throws IOException { Assert.assertTrue(github.isTransitive()); Assert.assertEquals(github.dependencies().size(), 1); Assert.assertEquals(github.modules().size(), 0); + + List tools = new ArrayList<>(depsManifest.tools()); + Assert.assertEquals(tools.size(), 2); + + DependencyManifest.Tool openapiTool = tools.get(0); + Assert.assertEquals(openapiTool.id().value(), "openapi"); + Assert.assertEquals(openapiTool.org().value(), "ballerina"); + Assert.assertEquals(openapiTool.name().value(), "openapi_tool"); + Assert.assertEquals(openapiTool.version().toString(), "0.2.0"); + + DependencyManifest.Tool persistTool = tools.get(1); + Assert.assertEquals(persistTool.id().value(), "persist"); + Assert.assertEquals(persistTool.org().value(), "ballerinax"); + Assert.assertEquals(persistTool.name().value(), "persist_tool"); + Assert.assertEquals(persistTool.version().toString(), "1.2.0"); } @Test(description = "Test dependencies.toml without distribution version") @@ -339,6 +354,92 @@ public void testDependenciesTomlWithAdditionalAttributeInDependenciesArray() thr Assert.assertEquals(firstDiagnostic.location().lineRange().toString(), "(13:37,13:54)"); } + @Test(description = "Invalid Dependencies.toml file with invalid tool ids") + public void testDependenciesTomlWithInvalidToolId() throws IOException { + DependencyManifest depsManifest = getDependencyManifest( + DEPENDENCIES_TOML_REPO.resolve("tool-with-invalid-id-value.toml")); + DiagnosticResult diagnostics = depsManifest.diagnostics(); + diagnostics.errors().forEach(OUT::println); + + Assert.assertTrue(diagnostics.hasErrors()); + Assert.assertEquals(diagnostics.errors().size(), 5); + + Iterator iterator = diagnostics.errors().iterator(); + Diagnostic firstDiagnostic = iterator.next(); + Assert.assertEquals(firstDiagnostic.message(), "invalid 'id' under [[tool]]: " + + "'id' cannot have initial underscore characters"); + Assert.assertEquals(firstDiagnostic.location().lineRange().toString(), "(26:5,26:11)"); + Diagnostic secondDiagnostic = iterator.next(); + Assert.assertEquals(secondDiagnostic.message(), "invalid 'id' under [[tool]]: " + + "'id' cannot have trailing underscore characters"); + Assert.assertEquals(secondDiagnostic.location().lineRange().toString(), "(32:5,32:11)"); + Diagnostic thirdDiagnostic = iterator.next(); + Assert.assertEquals(thirdDiagnostic.message(), "invalid 'id' under [[tool]]: " + + "'id' cannot have consecutive underscore characters"); + Assert.assertEquals(thirdDiagnostic.location().lineRange().toString(), "(38:5,38:12)"); + Diagnostic fourthDiagnostic = iterator.next(); + Assert.assertEquals(fourthDiagnostic.message(), "invalid 'id' under [[tool]]: " + + "'id' can only contain alphanumerics and underscores"); + Assert.assertEquals(fourthDiagnostic.location().lineRange().toString(), "(44:5,44:11)"); + Diagnostic fifthDiagnostic = iterator.next(); + Assert.assertEquals(fifthDiagnostic.message(), "invalid 'id' under [[tool]]: " + + "'id' cannot have initial numeric characters"); + Assert.assertEquals(fifthDiagnostic.location().lineRange().toString(), "(50:5,50:11)"); + } + + @Test(description = "Invalid Dependencies.toml file with invalid org, name in tool array") + public void testDependenciesTomlWithInvalidToolOrgNameVersion() throws IOException { + DependencyManifest depsManifest = getDependencyManifest( + DEPENDENCIES_TOML_REPO.resolve("tool-with-invalid-org-name-version-value.toml")); + DiagnosticResult diagnostics = depsManifest.diagnostics(); + diagnostics.errors().forEach(OUT::println); + + Assert.assertTrue(diagnostics.hasErrors()); + Assert.assertEquals(diagnostics.errors().size(), 3); + + Iterator iterator = diagnostics.errors().iterator(); + Diagnostic firstDiagnostic = iterator.next(); + Assert.assertEquals(firstDiagnostic.message(), "invalid 'org' under [[tool]]: " + + "maximum length of 'org' is 256 characters"); + Assert.assertEquals(firstDiagnostic.location().lineRange().toString(), "(26:6,26:337)"); + Diagnostic secondDiagnostic = iterator.next(); + Assert.assertEquals(secondDiagnostic.message(), "invalid 'name' under [[tool]]: " + + "maximum length of 'name' is 256 characters"); + Assert.assertEquals(secondDiagnostic.location().lineRange().toString(), "(27:7,27:303)"); + Diagnostic thirdDiagnostic = iterator.next(); + Assert.assertEquals(thirdDiagnostic.message(), "invalid 'version' under [[tool]]: " + + "'version' should be compatible with semver"); + Assert.assertEquals(thirdDiagnostic.location().lineRange().toString(), "(28:10,28:16)"); + } + + @Test(description = "Invalid Dependencies.toml file with missing org field in tool array") + public void testInvalidDependenciesTomlToolWithoutOrg() throws IOException { + DependencyManifest depsManifest = getDependencyManifest( + DEPENDENCIES_TOML_REPO.resolve("tool-wo-org.toml")); + DiagnosticResult diagnostics = depsManifest.diagnostics(); + diagnostics.errors().forEach(OUT::println); + Assert.assertTrue(diagnostics.hasErrors()); + Assert.assertEquals(diagnostics.errors().size(), 1); + Iterator iterator = diagnostics.errors().iterator(); + Diagnostic firstDiagnostic = iterator.next(); + Assert.assertEquals(firstDiagnostic.message(), "'org' under [[tool]] is missing"); + Assert.assertEquals(firstDiagnostic.location().lineRange().toString(), "(25:0,28:17)"); + } + + @Test(description = "Invalid Dependencies.toml file with missing org value in tool array") + public void testInvalidDependenciesTomlWithoutToolOrgValue() throws IOException { + DependencyManifest depsManifest = getDependencyManifest( + DEPENDENCIES_TOML_REPO.resolve("tool-wo-org-value.toml")); + DiagnosticResult diagnostics = depsManifest.diagnostics(); + diagnostics.errors().forEach(OUT::println); + Assert.assertTrue(diagnostics.hasErrors()); + Assert.assertEquals(diagnostics.errors().size(), 1); + Iterator iterator = diagnostics.errors().iterator(); + Diagnostic firstDiagnostic = iterator.next(); + Assert.assertEquals(firstDiagnostic.location().lineRange().toString(), "(28:0,28:0)"); + Assert.assertEquals(firstDiagnostic.message(), "missing value"); + } + private DependencyManifest getDependencyManifest(Path dependenciesTomlPath) throws IOException { String dependenciesTomlContent = Files.readString(dependenciesTomlPath); TomlDocument dependenciesToml = TomlDocument.from(ProjectConstants.DEPENDENCIES_TOML, dependenciesTomlContent); diff --git a/compiler/ballerina-lang/src/test/resources/dependencies-toml/dependencies-valid.toml b/compiler/ballerina-lang/src/test/resources/dependencies-toml/dependencies-valid.toml index 487d001b66af..aca7dbd444ca 100644 --- a/compiler/ballerina-lang/src/test/resources/dependencies-toml/dependencies-valid.toml +++ b/compiler/ballerina-lang/src/test/resources/dependencies-toml/dependencies-valid.toml @@ -41,3 +41,15 @@ scope = "testOnly" dependencies = [ {org = "ballerina", name = "jballerina.java"} ] + +[[tool]] +id = "openapi" +org = "ballerina" +name = "openapi_tool" +version = "0.2.0" + +[[tool]] +id = "persist" +org = "ballerinax" +name = "persist_tool" +version = "1.2.0" diff --git a/compiler/ballerina-lang/src/test/resources/dependencies-toml/tool-with-invalid-id-value.toml b/compiler/ballerina-lang/src/test/resources/dependencies-toml/tool-with-invalid-id-value.toml new file mode 100644 index 000000000000..ac7fe7f21d7d --- /dev/null +++ b/compiler/ballerina-lang/src/test/resources/dependencies-toml/tool-with-invalid-id-value.toml @@ -0,0 +1,54 @@ +# AUTO-GENERATED FILE. DO NOT MODIFY. + +# This file is auto-generated by Ballerina for managing dependency versions. +# It should not be modified by hand. + +[ballerina] +dependencies-toml-version = "2" + +[[package]] +org = "winery" +name = "foo" +version = "1.0.0" +dependencies = [ + {name = "foo1"}, + {name = "foo2"} +] +modules = [ + {org = "winery", packageName = "foo", moduleName = "foo"} +] + +[[package]] +org = "winery" +name = "foo2" +version = "0.2.0" + +[[tool]] +id = "_edi" +org = "winery" +name = "foo2" +version = "0.2.0" + +[[tool]] +id = "edi_" +org = "winery" +name = "foo2" +version = "0.2.0" + +[[tool]] +id = "ed__i" +org = "winery" +name = "foo2" +version = "0.2.0" + +[[tool]] +id = "ed.i" +org = "winery" +name = "foo2" +version = "0.2.0" + +[[tool]] +id = "2edi" +org = "winery" +name = "foo2" +version = "0.2.0" diff --git a/compiler/ballerina-lang/src/test/resources/dependencies-toml/tool-with-invalid-org-name-version-value.toml b/compiler/ballerina-lang/src/test/resources/dependencies-toml/tool-with-invalid-org-name-version-value.toml new file mode 100644 index 000000000000..8d6e9c797549 --- /dev/null +++ b/compiler/ballerina-lang/src/test/resources/dependencies-toml/tool-with-invalid-org-name-version-value.toml @@ -0,0 +1,29 @@ +# AUTO-GENERATED FILE. DO NOT MODIFY. + +# This file is auto-generated by Ballerina for managing dependency versions. +# It should not be modified by hand. + +[ballerina] +dependencies-toml-version = "2" + +[[package]] +org = "winery" +name = "foo" +version = "1.0.0" +dependencies = [ + {org = "winery", name = "foo2"} +] +modules = [ + {org = "winery", packageName = "foo", moduleName = "foo"} +] + +[[package]] +org = "winery" +name = "foo2" +version = "0.2.0" + +[[tool]] +id = "edi" +org = "thisIsVeryLongOrganozayionJustUsingItForTestingthisIsVeryLongOrganozayionJustUsingItForTestingthisIsVeryLongOrganozayionJustUsingItForTestingthisIsVeryLongOrganozayionJustUsingItForTestingthisIsVeryLongOrganozayionJustUsingItForTestingthisIsVeryLongOrganozayionJustUsingItForTestingthisIsVeryLongOrganozayionJustUsingItForTesting" +name = "thisIsVeryLongPackageJustUsingItForTestingthisIsVeryLongPackageJustUsingItForTestingthisIsVeryLongPackageJustUsingItForTestingthisIsVeryLongPackageJustUsingItForTestingthisIsVeryLongPackageJustUsingItForTestingthisIsVeryLongPackageJustUsingItForTestingthisIsVeryLongPackageJustUsingItForTesting" +version = "22.0" diff --git a/compiler/ballerina-lang/src/test/resources/dependencies-toml/tool-wo-org-value.toml b/compiler/ballerina-lang/src/test/resources/dependencies-toml/tool-wo-org-value.toml new file mode 100644 index 000000000000..acd6857755a1 --- /dev/null +++ b/compiler/ballerina-lang/src/test/resources/dependencies-toml/tool-wo-org-value.toml @@ -0,0 +1,30 @@ +# AUTO-GENERATED FILE. DO NOT MODIFY. + +# This file is auto-generated by Ballerina for managing dependency versions. +# It should not be modified by hand. + +[ballerina] +dependencies-toml-version = "2" + +[[package]] +org = "winery" +name = "foo" +version = "1.0.0" +dependencies = [ + {name = "foo1"}, + {name = "foo2"} +] +modules = [ + {org = "winery", packageName = "foo", moduleName = "foo"} +] + +[[package]] +org = "winery" +name = "foo2" +version = "0.2.0" + +[[tool]] +id = "edi" +org = +name = "foo2" +version = "0.2.0" diff --git a/compiler/ballerina-lang/src/test/resources/dependencies-toml/tool-wo-org.toml b/compiler/ballerina-lang/src/test/resources/dependencies-toml/tool-wo-org.toml new file mode 100644 index 000000000000..be80b4680c3e --- /dev/null +++ b/compiler/ballerina-lang/src/test/resources/dependencies-toml/tool-wo-org.toml @@ -0,0 +1,29 @@ +# AUTO-GENERATED FILE. DO NOT MODIFY. + +# This file is auto-generated by Ballerina for managing dependency versions. +# It should not be modified by hand. + +[ballerina] +dependencies-toml-version = "2" + +[[package]] +org = "winery" +name = "foo" +version = "1.0.0" +dependencies = [ + {name = "foo1"}, + {name = "foo2"} +] +modules = [ + {org = "winery", packageName = "foo", moduleName = "foo"} +] + +[[package]] +org = "winery" +name = "foo1" +version = "0.1.0" + +[[tool]] +id = "edi" +name = "foo2" +version = "0.2.0"