Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions build-config/resources/Ballerina.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
[package]
org = "ballerina"
name = "tool_protoc"
name = "tool.grpc"
version = "@toml.version@"
authors = ["Ballerina"]
keywords = ["grpc", "protoc tool"]
license = ["Apache-2.0"]
distribution = "2201.12.3"
distribution = "2201.13.0"
16 changes: 9 additions & 7 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,22 @@ org.gradle.caching=true
group=io.ballerina
version=1.0.0-SNAPSHOT

#dependency versions
ballerinaLangVersion=2201.12.0
checkstylePluginVersion=10.12.1
# Java Dependencies
ballerinaLangVersion=2201.13.0-20250924-081800-3dae8c03
commonsLang3Version=3.8.1
slf4jVersion=1.7.30
protoGoogleCommonsVersion=1.17.0
protobufJavaVersion=3.23.4
picocliVersion=4.0.1
githubSpotbugsVersion=6.0.18
githubJohnrengelmanShadowVersion=8.1.1
underCouchDownloadVersion=5.4.0
researchgateReleaseVersion=2.8.0
testngVersion=7.6.1

# Gradle Plugin Versions
jacocoVersion=0.8.10
checkstylePluginVersion=10.12.1
spotbugsPluginVersion=6.0.18
shadowJarPluginVersion=8.1.1
downloadPluginVersion=5.4.0
releasePluginVersion=2.8.0
ballerinaGradlePluginVersion=2.3.0

stdlibIoVersion=1.8.0
Expand Down
1 change: 1 addition & 0 deletions protoc-cli/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ checkstyle {
}

checkstyleMain.dependsOn(":checkstyle:downloadCheckstyleRuleFiles")
checkstyleTest.dependsOn(":checkstyle:downloadCheckstyleRuleFiles")

def excludePattern = '**/module-info.java'
tasks.withType(Checkstyle) {
Expand Down
42 changes: 39 additions & 3 deletions protoc-cli/src/main/java/io/ballerina/protoc/cli/GrpcCmd.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,18 +70,47 @@
public class GrpcCmd implements BLauncherCmd {

private static final Logger LOG = LoggerFactory.getLogger(GrpcCmd.class);
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 PrintStream outStream;
private static final String PROTO_EXTENSION = "proto";

private CommandLine parentCmdParser;
private final ExitHandler exitHandler;

/**
* Functional interface for handling exit behavior.
* Public to allow test access from other packages.
*/
@FunctionalInterface
public interface ExitHandler {
void exit(int code);
}

public GrpcCmd() {
this.outStream = System.out;
this(System.out, DEFAULT_EXIT_HANDLER);
}

public GrpcCmd(PrintStream outStream) {
this(outStream, DEFAULT_EXIT_HANDLER);
}

/**
* Constructor for testing with custom exit handler.
* This is public to allow tests in other packages to use it.
*
* @param outStream output stream
* @param exitHandler custom exit handler (for testing)
*/
public GrpcCmd(PrintStream outStream, ExitHandler exitHandler) {
this.outStream = outStream;
this.exitHandler = exitHandler;
}

private void exit(int code) {
exitHandler.exit(code);
}

@CommandLine.Option(names = {"-h", "--help"}, hidden = true, usageHelp = true)
Expand Down Expand Up @@ -134,9 +163,16 @@ private static void exportResource(String resourceName, ClassLoader classLoader)

@Override
public void execute() {
// Show help text
if (helpFlag || protoPath == null || protoPath.trim().isEmpty()) {
// Show help text with exit code 0 if help flag is present
if (helpFlag) {
printLongDesc(new StringBuilder());
exit(EXIT_CODE_0);
return;
}
// Show help text with exit code 2 if no input provided
if (protoPath == null || protoPath.trim().isEmpty()) {
printLongDesc(new StringBuilder());
exit(EXIT_CODE_2);
return;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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.protoc.cli;

import io.ballerina.protoc.cli.GrpcCmd.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;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* 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.protoc.cli;

import org.testng.Assert;
import org.testng.annotations.Test;
import picocli.CommandLine;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;

/**
* This class is used to test the functionality of the gRPC command exit codes.
*/
public class GrpcCmdTest {

@Test(description = "Test grpc command execution without arguments - should return exit code 2")
public void testExecuteWithoutArguments() {
String[] args = {};
ExitCodeCaptor exitCaptor = new ExitCodeCaptor();
ByteArrayOutputStream outContent = new ByteArrayOutputStream();
PrintStream printStream = new PrintStream(outContent);
GrpcCmd grpcCmd = new GrpcCmd(printStream, exitCaptor);
new CommandLine(grpcCmd).parseArgs(args);
grpcCmd.execute();
Assert.assertEquals(exitCaptor.getExitCode(), 2,
"grpc command without arguments should exit with code 2");
}

@Test(description = "Test grpc command execution with help flag - should return exit code 0")
public void testExecuteWithHelpFlag() {
String[] args = {"-h"};
ExitCodeCaptor exitCaptor = new ExitCodeCaptor();
ByteArrayOutputStream outContent = new ByteArrayOutputStream();
PrintStream printStream = new PrintStream(outContent);
GrpcCmd grpcCmd = new GrpcCmd(printStream, exitCaptor);
new CommandLine(grpcCmd).parseArgs(args);
grpcCmd.execute();
Assert.assertEquals(exitCaptor.getExitCode(), 0,
"grpc command with -h flag should exit with code 0");
}

@Test(description = "Test grpc command execution with invalid flag - should throw exception during parsing")
public void testExecuteWithInvalidFlag() {
String[] args = {"--invalidFlag"};
ExitCodeCaptor exitCaptor = new ExitCodeCaptor();
ByteArrayOutputStream outContent = new ByteArrayOutputStream();
PrintStream printStream = new PrintStream(outContent);
GrpcCmd grpcCmd = new GrpcCmd(printStream, exitCaptor);
try {
new CommandLine(grpcCmd).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"));
}
}
}
28 changes: 28 additions & 0 deletions protoc-cli/src/test/resources/testng.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
-->

<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >

<suite name="BallerinaProtocCliTests">
<test name="protoc-cli-test-suite" preserve-order="true" parallel="false">
<packages>
<package name="io.ballerina.protoc.cli.*"/>
</packages>
</test>
</suite>
4 changes: 2 additions & 2 deletions protoc-tool/Ballerina.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
[package]
org = "ballerina"
name = "tool_protoc"
name = "tool.grpc"
version = "1.0.0"
authors = ["Ballerina"]
keywords = ["grpc", "protoc tool"]
license = ["Apache-2.0"]
distribution = "2201.12.3"
distribution = "2201.13.0"
6 changes: 3 additions & 3 deletions protoc-tool/Dependencies.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@

[ballerina]
dependencies-toml-version = "2"
distribution-version = "2201.12.0"
distribution-version = "2201.13.0-20250924-081800-3dae8c03"

[[package]]
org = "ballerina"
name = "tool_protoc"
name = "tool.grpc"
version = "1.0.0"
modules = [
{org = "ballerina", packageName = "tool_protoc", moduleName = "tool_protoc"}
{org = "ballerina", packageName = "tool.grpc", moduleName = "tool.grpc"}
]

6 changes: 5 additions & 1 deletion protoc-tool/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ plugins {

description = 'Ballerina - Protoc Tool'

def packageName = "tool_protoc"
def packageName = "tool.grpc"
def packageOrg = "ballerina"
def tomlVersion = stripBallerinaExtensionVersion("${project.version}")
def ballerinaTomlFilePlaceHolder = new File("${project.rootDir}/build-config/resources/Ballerina.toml")
Expand Down Expand Up @@ -94,6 +94,10 @@ publishing {
}
}

clean {
delete file("$projectDir/target")
}

updateTomlFiles.dependsOn copyStdlibs
build.dependsOn updateTomlFiles
build.dependsOn "generatePomFileForMavenPublication"
Expand Down
8 changes: 4 additions & 4 deletions settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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 "${shadowJarPluginVersion}"
id "de.undercouch.download" version "${downloadPluginVersion}"
id "net.researchgate.release" version "${releasePluginVersion}"
id "io.ballerina.plugin" version "${ballerinaGradlePluginVersion}"
}

Expand Down
7 changes: 7 additions & 0 deletions tooling-tests/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,11 @@ test {
dependsOn(copyStdlibs)
systemProperty "ballerina.home", ballerinaDist
systemProperty "ballerina.offline.flag", "true"
binaryResultsDirectory = file("$buildDir/test-results/binary")
useTestNG() {
suites 'src/test/resources/testng.xml'
outputDirectory = file("$buildDir/test-output")
useDefaultListeners = true
}
testLogging.showStandardStreams = true
testLogging {
Expand All @@ -168,6 +171,10 @@ test {
finalizedBy jacocoTestReport
}

clean {
delete file("$buildDir/generated-sources")
}

jacoco {
toolVersion = "${jacocoVersion}"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

package io.ballerina.protoc.tools;

import io.ballerina.protoc.cli.GrpcCmd;
import org.testng.Assert;
import org.testng.annotations.Test;

Expand Down Expand Up @@ -57,11 +58,7 @@ public void testHelloWorldWithDependency() {
public void testCommandWithoutArguments() {
// Capture output using ByteArrayOutputStream with explicit encoding
java.io.ByteArrayOutputStream outputStream = new java.io.ByteArrayOutputStream();
java.io.PrintStream printStream = new java.io.PrintStream(outputStream, true,
java.nio.charset.StandardCharsets.UTF_8);

// Create a GrpcCmd instance with the captured print stream
io.ballerina.protoc.cli.GrpcCmd grpcCmd = new io.ballerina.protoc.cli.GrpcCmd(printStream);
GrpcCmd grpcCmd = ToolingTestUtils.createGrpcCmd(outputStream);

try {
grpcCmd.execute();
Expand All @@ -78,9 +75,7 @@ public void testCommandWithoutArguments() {
@Test
public void testCommandWithHelpFlag() {
java.io.ByteArrayOutputStream outputStream = new java.io.ByteArrayOutputStream();
java.io.PrintStream printStream = new java.io.PrintStream(outputStream, true,
java.nio.charset.StandardCharsets.UTF_8);
io.ballerina.protoc.cli.GrpcCmd grpcCmd = new io.ballerina.protoc.cli.GrpcCmd(printStream);
GrpcCmd grpcCmd = ToolingTestUtils.createGrpcCmd(outputStream);

try {
java.lang.reflect.Field helpFlagField = grpcCmd.getClass().getDeclaredField("helpFlag");
Expand Down
Loading