Skip to content

Commit

Permalink
Merge pull request #1705 from ballerina-platform/fix-client-method-si…
Browse files Browse the repository at this point in the history
…gnature

Fix integration and native tests with client method changes
  • Loading branch information
TharmiganK authored May 3, 2024
2 parents a891703 + 1057b00 commit 388a2b4
Show file tree
Hide file tree
Showing 14 changed files with 741 additions and 172 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
org.gradle.caching=true
group=io.ballerina
version=1.9.0-SNAPSHOT
version=2.0.0-SNAPSHOT

# Client Native Version
clientNativeVersion=1.0.0-SNAPSHOT
Expand Down
75 changes: 37 additions & 38 deletions openapi-client-native/ballerina-tests/client.bal

Large diffs are not rendered by default.

38 changes: 19 additions & 19 deletions openapi-client-native/ballerina-tests/tests/test.bal
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ function testResourceMethod3() returns error? {

@test:Config {}
function testResourceMethod4() returns error? {
OkAlbumArray res = check albumClient->/albums.get("Hard Rock");
OkAlbumArray res = check albumClient->/albums.get(genre = "Hard Rock");
Album[] expected = [
{id: "2", name: "Back in Black", artist: "AC/DC", genre: "Hard Rock"}
];
Expand All @@ -62,7 +62,7 @@ function testResourceMethod4() returns error? {

@test:Config {}
function testResourceMethod5() {
OkAlbumArray|NotFoundErrorMessage|error res = albumClient->/albums.get("Hard Rock");
OkAlbumArray|NotFoundErrorMessage|error res = albumClient->/albums.get(genre = "Hard Rock");
OkAlbumArray expected = {
mediaType: "application/json",
headers: {user\-id: "user-1", req\-id: 1},
Expand All @@ -79,7 +79,7 @@ function testResourceMethod5() {

@test:Config {}
function testResourceMethod6() {
OkAlbumArray|NotFoundErrorMessage|error res = albumClient->/albums.get("Rock");
OkAlbumArray|NotFoundErrorMessage|error res = albumClient->/albums.get(genre = "Rock");
NotFoundErrorMessage expected = {
mediaType: "application/json",
headers: {user\-id: "user-1", req\-id: 1},
Expand All @@ -96,7 +96,7 @@ function testResourceMethod6() {

@test:Config {}
function testResourceMethod7() {
OkAlbumArray|NotFoundErrorMessage|error res = albumClient->/albums\-all;
OkAlbumArray|NotFoundErrorMessage|error res = albumClient->/albumsAll;
OkAlbumArray expected = {
mediaType: "application/json",
headers: {user\-id: "user-1", req\-id: 1},
Expand Down Expand Up @@ -198,7 +198,7 @@ function testResourceMethod11() {
http:Request req = new;
Album newAlbum = {id: "5", name: "The Wall", artist: "Pink Floyd", genre: "Progressive Rock"};
req.setJsonPayload(newAlbum);
CreatedAlbum|error res = albumClient->/albums\-1/a/[3].post(req);
CreatedAlbum|error res = albumClient->/albums1/a/[3].post(req);
CreatedAlbum expected = {
mediaType: "application/json",
headers: {user\-id: "user-1", req\-id: 1},
Expand Down Expand Up @@ -230,7 +230,7 @@ function testResourceMethod12() {
http:Request req = new;
Album existingAlbum = {id: "1", name: "The Dark Side of the Moon", artist: "Pink Floyd", genre: "Progressive Rock"};
req.setJsonPayload(existingAlbum);
CreatedAlbum|ConflictAlbum|error res = albumClient->/albums\-1/a/[3].post(req);
CreatedAlbum|ConflictAlbum|error res = albumClient->/albums1/a/[3].post(req);
ConflictAlbum expected = {
mediaType: "application/json",
headers: {user\-id: "user-1", req\-id: 1},
Expand Down Expand Up @@ -259,7 +259,7 @@ function testResourceMethod13() {
http:Request req = new;
json notAnAlbum = {id: "4", name: "The Wall", artist: "Pink Floyd"};
req.setJsonPayload(notAnAlbum);
CreatedAlbum|ConflictAlbum|BadRequestErrorPayload|error res = albumClient->/albums\-1/a/[3].post(req);
CreatedAlbum|ConflictAlbum|BadRequestErrorPayload|error res = albumClient->/albums1/a/[3].post(req);
test:assertTrue(res is BadRequestErrorPayload);

res = albumClient->postAlbums1("a", 3, req);
Expand All @@ -269,7 +269,7 @@ function testResourceMethod13() {
@test:Config {}
function testResourceMethod14() {
Album[] newAlbums = [{id: "6", name: "The Wall", artist: "Pink Floyd", genre: "Progressive Rock"}];
CreatedAlbumArray|error res = albumClient->/albums\-all/a.post(newAlbums, query = "q");
CreatedAlbumArray|error res = albumClient->/albumsAll/a.post(newAlbums, query = "q");
CreatedAlbumArray expected = {
mediaType: "application/json",
headers: {user\-id: "user-1", req\-id: 1},
Expand Down Expand Up @@ -297,7 +297,7 @@ function testResourceMethod14() {

function testResourceMethod15() {
Album[] existingAlbums = [{id: "1", name: "The Dark Side of the Moon", artist: "Pink Floyd", genre: "Progressive Rock"}];
CreatedAlbumArray|ConflictAlbum|error res = albumClient->/albums\-all/a.post(existingAlbums);
CreatedAlbumArray|ConflictAlbum|error res = albumClient->/albumsAll/a.post(existingAlbums);
ConflictAlbum expected = {
mediaType: "application/json",
headers: {user\-id: "user-1", req\-id: 1},
Expand Down Expand Up @@ -326,7 +326,7 @@ function testResourceMethod16() {
http:Request req = new;
Album[] newAlbums = [{id: "7", name: "The Wall", artist: "Pink Floyd", genre: "Progressive Rock"}];
req.setJsonPayload(newAlbums);
CreatedAlbumArray|error res = albumClient->/albums\-all\-1.post(req, query = "q");
CreatedAlbumArray|error res = albumClient->/albumsAll1.post(req, query = "q");
CreatedAlbumArray expected = {
mediaType: "application/json",
headers: {user\-id: "user-1", req\-id: 1},
Expand Down Expand Up @@ -358,7 +358,7 @@ function testResourceMethod17() {
http:Request req = new;
Album[] existingAlbums = [{id: "1", name: "The Dark Side of the Moon", artist: "Pink Floyd", genre: "Progressive Rock"}];
req.setJsonPayload(existingAlbums);
CreatedAlbumArray|ConflictAlbum|error res = albumClient->/albums\-all\-1.post(req, query = "q");
CreatedAlbumArray|ConflictAlbum|error res = albumClient->/albumsAll1.post(req, query = "q");
ConflictAlbum expected = {
mediaType: "application/json",
headers: {user\-id: "user-1", req\-id: 1},
Expand Down Expand Up @@ -387,7 +387,7 @@ function testResourceMethod18() {
http:Request req = new;
json notAnAlbum = [{id: "4", name: "The Wall", artist: "Pink Floyd"}];
req.setJsonPayload(notAnAlbum);
CreatedAlbumArray|ConflictAlbum|BadRequestErrorPayload|error res = albumClient->/albums\-all\-1.post(req, query = "q");
CreatedAlbumArray|ConflictAlbum|BadRequestErrorPayload|error res = albumClient->/albumsAll1.post(req, query = "q");
test:assertTrue(res is BadRequestErrorPayload);

res = albumClient->postAlbumsAll1(req, query = "q");
Expand Down Expand Up @@ -443,7 +443,7 @@ function testRemoteMethod3() returns error? {

@test:Config {}
function testRemoteMethod4() returns error? {
OkAlbumArray res = check albumClient->getAlbums("Hard Rock");
OkAlbumArray res = check albumClient->getAlbums(genre = "Hard Rock");
Album[] expected = [
{id: "2", name: "Back in Black", artist: "AC/DC", genre: "Hard Rock"}
];
Expand All @@ -453,7 +453,7 @@ function testRemoteMethod4() returns error? {

@test:Config {}
function testRemoteMethod5() {
OkAlbumArray|NotFoundErrorMessage|error res = albumClient->getAlbums("Hard Rock");
OkAlbumArray|NotFoundErrorMessage|error res = albumClient->getAlbums(genre = "Hard Rock");
OkAlbumArray expected = {
mediaType: "application/json",
headers: {user\-id: "user-1", req\-id: 1},
Expand All @@ -470,7 +470,7 @@ function testRemoteMethod5() {

@test:Config {}
function testRemoteMethod6() {
OkAlbumArray|NotFoundErrorMessage|error res = albumClient->getAlbums("Rock");
OkAlbumArray|NotFoundErrorMessage|error res = albumClient->getAlbums(genre = "Rock");
NotFoundErrorMessage expected = {
mediaType: "application/json",
headers: {user\-id: "user-1", req\-id: 1},
Expand All @@ -487,7 +487,7 @@ function testRemoteMethod6() {

@test:Config {}
function testInvalidMethodInvocation() {
OkAlbumArray|NotFoundErrorMessage|error res = albumClient->getAlbums1("Hard Rock");
OkAlbumArray|NotFoundErrorMessage|error res = albumClient->getAlbums1(genre = "Hard Rock");
if res is error {
test:assertTrue(res is ClientMethodInvocationError);
test:assertEquals(res.message(), "client method invocation failed: No such method: getAlbumsImpl1");
Expand All @@ -498,7 +498,7 @@ function testInvalidMethodInvocation() {

@test:Config {}
function testAnnotationNotFound() {
OkAlbumArray|NotFoundErrorMessage|error res = albumClient->getAlbums2("Hard Rock");
OkAlbumArray|NotFoundErrorMessage|error res = albumClient->getAlbums2(genre = "Hard Rock");
if res is error {
test:assertTrue(res is ClientMethodInvocationError);
test:assertEquals(res.message(), "error in invoking client remote method: Method implementation annotation not found");
Expand All @@ -509,11 +509,11 @@ function testAnnotationNotFound() {

@test:Config {}
function testInvalidImplFunctionSignature() {
OkAlbumArray|NotFoundErrorMessage|error res = albumClient->getAlbums3("Hard Rock");
OkAlbumArray|NotFoundErrorMessage|error res = albumClient->getAlbums3(genre = "Hard Rock");
if res is error {
test:assertTrue(res is ClientMethodInvocationError);
test:assertTrue(res.message().includes("client method invocation failed: java.lang.ClassCastException: " +
"class io.ballerina.runtime.internal.values.TypedescValueImpl cannot be cast to class io.ballerina.runtime.api.values.BString"));
"class io.ballerina.runtime.internal.values.TypedescValueImpl cannot be cast to class io.ballerina.runtime.internal.values.MapValueImpl"));
} else {
test:assertFail("invalid response type");
}
Expand Down
13 changes: 13 additions & 0 deletions openapi-client-native/ballerina-tests/types.bal
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,16 @@ public type NotFoundErrorMessage record {|
ErrorMessage body;
record {|int req\-id; string user\-id;|} headers;
|};

public type GetAlbumsQueries record {
string genre = "Rock";
};

public type GetAlbumsQueriesClosed record {|
string genre;
string 'type;
|};

public type PostAlbumsAllQueries record {
string query?;
};
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@

import io.ballerina.openapi.OpenAPITest;
import io.ballerina.openapi.TestUtil;
import org.apache.commons.io.FileUtils;
import org.testng.Assert;
import org.testng.annotations.Test;

Expand All @@ -29,6 +28,8 @@
import java.nio.file.Paths;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static io.ballerina.openapi.TestUtil.DISTRIBUTIONS_DIR;
import static io.ballerina.openapi.TestUtil.RESOURCES_PATH;
Expand All @@ -40,6 +41,7 @@ public class ClientGenerationTests extends OpenAPITest {
public static final String DISTRIBUTION_FILE_NAME = DISTRIBUTIONS_DIR.toString();
public static final Path TEST_RESOURCE = Paths.get(RESOURCES_PATH.toString() + "/client");
public static final Path EXPECTED_RESOURCE = Paths.get("src/test/resources/client");
private static final String LINE_SEPARATOR = System.lineSeparator();

@Test(description = "Client generation with resource functions")
public void clientWithResourceFunction() throws IOException, InterruptedException {
Expand Down Expand Up @@ -101,14 +103,11 @@ public void resourceClientWithStatusCodeBinding() throws IOException, Interrupte
boolean successful = TestUtil.executeOpenAPI(DISTRIBUTION_FILE_NAME, projectGenPath, buildArgs);
Assert.assertTrue(Files.exists(projectGenPath.resolve("Ballerina.toml")));
Assert.assertTrue(Files.exists(projectGenPath.resolve("client.bal")));
FileUtils.contentEqualsIgnoreEOL(projectGenPath.resolve("client.bal").toFile(),
projectExpectedPath.resolve("client_resource.bal").toFile(), "UTF-8");
compareFiles(projectGenPath, "client.bal", projectExpectedPath, "client_resource.bal");
Assert.assertTrue(Files.exists(projectGenPath.resolve("types.bal")));
FileUtils.contentEqualsIgnoreEOL(projectGenPath.resolve("types.bal").toFile(),
projectExpectedPath.resolve("types.bal").toFile(), "UTF-8");
compareFiles(projectGenPath, "types.bal", projectExpectedPath, "types.bal");
Assert.assertTrue(Files.exists(projectGenPath.resolve("utils.bal")));
FileUtils.contentEqualsIgnoreEOL(projectGenPath.resolve("utils.bal").toFile(),
projectExpectedPath.resolve("utils.bal").toFile(), "UTF-8");
compareFiles(projectGenPath, "utils.bal", projectExpectedPath, "utils.bal");
}

@Test(description = "`--status-code-binding` and `--client-methods remote` options with client")
Expand All @@ -127,14 +126,11 @@ public void remoteClientWithStatusCodeBinding() throws IOException, InterruptedE
boolean successful = TestUtil.executeOpenAPI(DISTRIBUTION_FILE_NAME, projectGenPath, buildArgs);
Assert.assertTrue(Files.exists(projectGenPath.resolve("Ballerina.toml")));
Assert.assertTrue(Files.exists(projectGenPath.resolve("client.bal")));
FileUtils.contentEqualsIgnoreEOL(projectGenPath.resolve("client.bal").toFile(),
projectExpectedPath.resolve("client_resource.bal").toFile(), "UTF-8");
compareFiles(projectGenPath, "client.bal", projectExpectedPath, "client_remote.bal");
Assert.assertTrue(Files.exists(projectGenPath.resolve("types.bal")));
FileUtils.contentEqualsIgnoreEOL(projectGenPath.resolve("types.bal").toFile(),
projectExpectedPath.resolve("types.bal").toFile(), "UTF-8");
compareFiles(projectGenPath, "types.bal", projectExpectedPath, "types.bal");
Assert.assertTrue(Files.exists(projectGenPath.resolve("utils.bal")));
FileUtils.contentEqualsIgnoreEOL(projectGenPath.resolve("utils.bal").toFile(),
projectExpectedPath.resolve("utils.bal").toFile(), "UTF-8");
compareFiles(projectGenPath, "utils.bal", projectExpectedPath, "utils.bal");
}

@Test(description = "`--status-code-binding` option with service")
Expand All @@ -146,13 +142,12 @@ public void serviceWithStatusCodeBinding() throws IOException, InterruptedExcept
buildArgs.add("--mode");
buildArgs.add("service");
buildArgs.add("--status-code-binding");
Path projectGenPath = Paths.get(TEST_RESOURCE + "/project-01");
Path projectExpectedPath = Paths.get(EXPECTED_RESOURCE + "/project-01");
Path projectGenPath = Paths.get(TEST_RESOURCE + "/project-05");
Path projectExpectedPath = Paths.get(EXPECTED_RESOURCE + "/project-05");
boolean successful = TestUtil.executeOpenAPI(DISTRIBUTION_FILE_NAME, projectGenPath, buildArgs);
Assert.assertFalse(Files.exists(projectGenPath.resolve("service.bal")));
Assert.assertTrue(Files.exists(projectGenPath.resolve("Ballerina.toml")));
FileUtils.contentEqualsIgnoreEOL(projectGenPath.resolve("Ballerina.toml").toFile(),
projectExpectedPath.resolve("Ballerina.toml").toFile(), "UTF-8");
compareFiles(projectGenPath, "Ballerina.toml", projectExpectedPath, "Ballerina.toml");
}

@Test(description = "`--status-code-binding` option without any mode")
Expand All @@ -167,17 +162,13 @@ public void commonWithStatusCodeBinding() throws IOException, InterruptedExcepti
boolean successful = TestUtil.executeOpenAPI(DISTRIBUTION_FILE_NAME, projectGenPath, buildArgs);
Assert.assertTrue(Files.exists(projectGenPath.resolve("Ballerina.toml")));
Assert.assertTrue(Files.exists(projectGenPath.resolve("client.bal")));
FileUtils.contentEqualsIgnoreEOL(projectGenPath.resolve("client.bal").toFile(),
projectExpectedPath.resolve("client_resource.bal").toFile(), "UTF-8");
compareFiles(projectGenPath, "client.bal", projectExpectedPath, "client_resource.bal");
Assert.assertTrue(Files.exists(projectGenPath.resolve("types.bal")));
FileUtils.contentEqualsIgnoreEOL(projectGenPath.resolve("types.bal").toFile(),
projectExpectedPath.resolve("types.bal").toFile(), "UTF-8");
compareFiles(projectGenPath, "types.bal", projectExpectedPath, "types_all.bal");
Assert.assertTrue(Files.exists(projectGenPath.resolve("utils.bal")));
FileUtils.contentEqualsIgnoreEOL(projectGenPath.resolve("utils.bal").toFile(),
projectExpectedPath.resolve("utils.bal").toFile(), "UTF-8");
compareFiles(projectGenPath, "utils.bal", projectExpectedPath, "utils_all.bal");
Assert.assertTrue(Files.exists(projectGenPath.resolve("openapi_service.bal")));
FileUtils.contentEqualsIgnoreEOL(projectGenPath.resolve("openapi_service.bal").toFile(),
projectExpectedPath.resolve("openapi_service.bal").toFile(), "UTF-8");
compareFiles(projectGenPath, "openapi_service.bal", projectExpectedPath, "openapi_service.bal");
}

@Test(description = "`--status-code-binding` without `Ballerina.toml`")
Expand All @@ -191,7 +182,20 @@ public void nonBallerinaPackageWithStatusCodeBinding() throws IOException, Inter
Path projectExpectedPath = Paths.get(EXPECTED_RESOURCE + "/project-expected");
boolean successful = TestUtil.executeOpenAPI(DISTRIBUTION_FILE_NAME, projectGenPath, buildArgs);
Assert.assertTrue(Files.exists(projectGenPath.resolve("client.bal")));
FileUtils.contentEqualsIgnoreEOL(projectGenPath.resolve("client.bal").toFile(),
projectExpectedPath.resolve("client_normal.bal").toFile(), "UTF-8");
compareFiles(projectGenPath, "client.bal", projectExpectedPath, "client_normal.bal");
}

/**
* Compare two files.
*/
private void compareFiles(Path genPath, String generatedFileName, Path expectedPath, String expectedFileName)
throws IOException {
Stream<String> expectedFile = Files.lines(expectedPath.resolve(expectedFileName));
String expectedContent = expectedFile.collect(Collectors.joining(LINE_SEPARATOR));
Stream<String> generatedFile = Files.lines(genPath.resolve(generatedFileName));
String generatedContent = generatedFile.collect(Collectors.joining(LINE_SEPARATOR));
generatedContent = generatedContent.trim().replaceAll("\\s+", "");
expectedContent = expectedContent.trim().replaceAll("\\s+", "");
Assert.assertEquals(generatedContent, expectedContent);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[package]
org = "openapi_client_test"
name = "project"
version = "0.1.0"

[build-options]
observabilityIncluded = true

Loading

0 comments on commit 388a2b4

Please sign in to comment.