Skip to content

Commit

Permalink
Merge pull request #1560 from ballerina-platform/1.8.x
Browse files Browse the repository at this point in the history
Sync master with 1.8.x branch
  • Loading branch information
lnash94 authored Oct 20, 2023
2 parents a175302 + 3be01ed commit 48e6cde
Show file tree
Hide file tree
Showing 48 changed files with 1,063 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -238,5 +238,8 @@ public String toString() {
public static final String YML_EXTENSION = ".yml";
public static final String PLUS = "+";
public static final String UNDERSCORE = "_";

public static final String HTTP_202 = "202";
public static final String HTTP_400 = "400";
public static final String ACCEPTED = "Accepted";
public static final String BAD_REQUEST = "BadRequest";
}
Original file line number Diff line number Diff line change
Expand Up @@ -283,8 +283,8 @@ private String getMediaTypeForSyntaxKind(TypeDescriptorNode payloadNode) {
return customMediaPrefix == null ? MediaType.APPLICATION_OCTET_STREAM :
APPLICATION_PREFIX + customMediaPrefix + OCTECT_STREAM_POSTFIX;
case SIMPLE_NAME_REFERENCE:
SimpleNameReferenceNode record = (SimpleNameReferenceNode) payloadNode;
TypeSymbol typeSymbol = getReferenceTypeSymbol(semanticModel.symbol(record));
case QUALIFIED_NAME_REFERENCE:
TypeSymbol typeSymbol = getReferenceTypeSymbol(semanticModel.symbol(payloadNode));
if (typeSymbol instanceof TypeReferenceTypeSymbol) {
typeSymbol = ((TypeReferenceTypeSymbol) typeSymbol).typeDescriptor();
}
Expand Down Expand Up @@ -346,16 +346,21 @@ private void handleArrayTypePayload(Map<String, Schema> schema, ArrayTypeDescrip
TypeDescriptorNode typeDescriptorNode = arrayNode.memberTypeDesc();
// Nested array not allowed
io.swagger.v3.oas.models.media.MediaType media = new io.swagger.v3.oas.models.media.MediaType();
if (typeDescriptorNode.kind().equals(SyntaxKind.SIMPLE_NAME_REFERENCE)) {
if (typeDescriptorNode.kind().equals(SyntaxKind.SIMPLE_NAME_REFERENCE) ||
typeDescriptorNode.kind().equals(SyntaxKind.QUALIFIED_NAME_REFERENCE)) {
//handle record for components
SimpleNameReferenceNode referenceNode = (SimpleNameReferenceNode) typeDescriptorNode;
TypeSymbol typeSymbol = getReferenceTypeSymbol(semanticModel.symbol(referenceNode));
TypeSymbol typeSymbol = getReferenceTypeSymbol(semanticModel.symbol(typeDescriptorNode));
OpenAPIComponentMapper componentMapper = new OpenAPIComponentMapper(components);
componentMapper.createComponentSchema(schema, typeSymbol);
diagnostics.addAll(componentMapper.getDiagnostics());
Schema itemSchema = new Schema();
arraySchema.setItems(itemSchema.$ref(ConverterCommonUtils.unescapeIdentifier(
referenceNode.name().text().trim())));
String referenceName;
if (typeDescriptorNode.kind().equals(SyntaxKind.SIMPLE_NAME_REFERENCE)) {
referenceName = ((SimpleNameReferenceNode) typeDescriptorNode).name().toString().trim();
} else {
referenceName = ((QualifiedNameReferenceNode) typeDescriptorNode).identifier().text();
}
arraySchema.setItems(itemSchema.$ref(ConverterCommonUtils.unescapeIdentifier(referenceName)));
media.setSchema(arraySchema);
} else if (typeDescriptorNode.kind() == SyntaxKind.BYTE_TYPE_DESC) {
StringSchema byteSchema = new StringSchema();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
import io.ballerina.openapi.converter.utils.ConverterCommonUtils;
import io.ballerina.tools.diagnostics.Location;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.headers.Header;
import io.swagger.v3.oas.models.media.ArraySchema;
import io.swagger.v3.oas.models.media.ComposedSchema;
Expand Down Expand Up @@ -92,7 +93,9 @@
import static io.ballerina.compiler.syntax.tree.SyntaxKind.RECORD_FIELD;
import static io.ballerina.compiler.syntax.tree.SyntaxKind.SIMPLE_NAME_REFERENCE;
import static io.ballerina.compiler.syntax.tree.SyntaxKind.TYPE_REFERENCE;
import static io.ballerina.openapi.converter.Constants.ACCEPTED;
import static io.ballerina.openapi.converter.Constants.APPLICATION_PREFIX;
import static io.ballerina.openapi.converter.Constants.BAD_REQUEST;
import static io.ballerina.openapi.converter.Constants.BODY;
import static io.ballerina.openapi.converter.Constants.BYTE;
import static io.ballerina.openapi.converter.Constants.BYTE_ARRAY;
Expand All @@ -105,7 +108,9 @@
import static io.ballerina.openapi.converter.Constants.HTTP_200_DESCRIPTION;
import static io.ballerina.openapi.converter.Constants.HTTP_201;
import static io.ballerina.openapi.converter.Constants.HTTP_201_DESCRIPTION;
import static io.ballerina.openapi.converter.Constants.HTTP_202;
import static io.ballerina.openapi.converter.Constants.HTTP_204;
import static io.ballerina.openapi.converter.Constants.HTTP_400;
import static io.ballerina.openapi.converter.Constants.HTTP_500;
import static io.ballerina.openapi.converter.Constants.HTTP_500_DESCRIPTION;
import static io.ballerina.openapi.converter.Constants.HTTP_CODES;
Expand Down Expand Up @@ -197,8 +202,13 @@ public void getResourceOutput(FunctionDefinitionNode resource, OperationAdaptor
} else {
// When the return type is not mention in the resource function.
ApiResponse apiResponse = new ApiResponse();
apiResponse.description("Accepted");
apiResponses.put("202", apiResponse);
apiResponse.description(ACCEPTED);
apiResponses.put(HTTP_202, apiResponse);
if (operation.getRequestBody() != null || operation.getParameters() != null) {
ApiResponse badRequestResponse = new ApiResponse();
badRequestResponse.description(BAD_REQUEST);
apiResponses.put(HTTP_400, badRequestResponse);
}
}
operation.setResponses(apiResponses);
}
Expand Down Expand Up @@ -433,7 +443,17 @@ private Optional<ApiResponses> getAPIResponses(OperationAdaptor operationAdaptor
io.swagger.v3.oas.models.media.MediaType mediaType = new io.swagger.v3.oas.models.media.MediaType();
String statusCode = httpMethod.equals(POST) ? HTTP_201 : HTTP_200;
String description = httpMethod.equals(POST) ? HTTP_201_DESCRIPTION : HTTP_200_DESCRIPTION;

if (typeNode.parent().kind() == SyntaxKind.OPTIONAL_TYPE_DESC) {
ApiResponse acceptedRequestResponse = new ApiResponse();
acceptedRequestResponse.description(ACCEPTED);
apiResponses.put(HTTP_202, acceptedRequestResponse);
Operation operation = operationAdaptor.getOperation();
if (operation.getRequestBody() != null || operation.getParameters() != null) {
ApiResponse badRequestResponse = new ApiResponse();
badRequestResponse.description(BAD_REQUEST);
apiResponses.put(HTTP_400, badRequestResponse);
}
}
String mediaTypeString;
switch (typeNode.kind()) {
case QUALIFIED_NAME_REFERENCE:
Expand Down Expand Up @@ -790,11 +810,11 @@ private static void addResponse(ApiResponses apiResponses, Optional<ApiResponses
apiResponse.ifPresent(responses -> responses.forEach((key, value) -> {
if (apiResponses.containsKey(key)) {
ApiResponse res = apiResponses.get(key);
Content content = res.getContent();
if (content == null) {
content = new Content();
}
if (value.getContent() != null) {
Content content = res.getContent();
if (content == null) {
content = new Content();
}
String mediaType = value.getContent().keySet().iterator().next();
Schema newSchema = value.getContent().values().iterator().next().getSchema();
if (content.containsKey(mediaType)) {
Expand All @@ -813,8 +833,8 @@ private static void addResponse(ApiResponses apiResponses, Optional<ApiResponses
} else {
content.put(mediaType, value.getContent().values().iterator().next());
}
res.content(content);
}
res.content(content);
apiResponses.put(key, res);
} else {
apiResponses.put(key, value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,12 @@ public void testForAllTypeDefinitions() throws IOException {
@Test(description = "When the record field has type definitions with nullable")
public void testForAllTypeDefinitionWithNullableValue() throws IOException {
Path ballerinaFilePath = RES_DIR.resolve("data_type/nullable_type_def.bal");
//Compare generated yaml file with expected yaml content
TestUtils.compareWithGeneratedFile(ballerinaFilePath, "data_type/nullable_type_def.yaml");
}

@Test(description = "test for tuple type scenarios")
public void testForTupleType() throws IOException {
Path ballerinaFilePath = RES_DIR.resolve("data_type/tuple_types.bal");
//Compare generated yaml file with expected yaml content
TestUtils.compareWithGeneratedFile(ballerinaFilePath, "data_type/tuple_type.yaml");
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Copyright (c) 2023, 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.openapi.generators.openapi;

import io.ballerina.openapi.cmd.OASContractGenerator;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

/**
* This test class is covering the negative unit tests for return type scenarios.
*/
public class NegativeResponseTests {
private static final Path RES_DIR = Paths.get("src/test/resources/ballerina-to-openapi").toAbsolutePath();
private Path tempDir;

@BeforeMethod
public void setup() throws IOException {
this.tempDir = Files.createTempDirectory("bal-to-openapi-test-out-" + System.nanoTime());
}

@Test(description = "When the resource has nil type return")
public void testNilReturnType() {
Path ballerinaFilePath = RES_DIR.resolve("response/negative/nil_return_type.bal");
OASContractGenerator openApiConverterUtils = new OASContractGenerator();
openApiConverterUtils.generateOAS3DefinitionsAllService(ballerinaFilePath, this.tempDir, null
, false);
//TODO: Uncomment after merging this PR https://github.com/ballerina-platform/openapi-tools/pull/1370.
// Assert.assertFalse(openApiConverterUtils.getErrors().isEmpty());
Assert.assertFalse(Files.exists(tempDir.resolve("payloadV_openapi.yaml")));
}


@AfterMethod
public void cleanUp() {
TestUtils.deleteDirectory(this.tempDir);
}

@AfterTest
public void clean() {
System.setErr(null);
System.setOut(null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,26 @@ public void testResponseHasServiceConfigWithCorsWithoutBasePath() throws IOExcep
Assert.assertTrue(generatedYaml.contains(expectedYamlContent));
}

@Test(description = "When the resource has nil type return")
public void testNilReturnType() throws IOException {
Path ballerinaFilePath = RES_DIR.resolve("response/nil_return_type.bal");
OASContractGenerator openApiConverterUtils = new OASContractGenerator();
openApiConverterUtils.generateOAS3DefinitionsAllService(ballerinaFilePath, this.tempDir, null
, false);
Assert.assertTrue(openApiConverterUtils.getErrors().isEmpty());
compareWithGeneratedFile(ballerinaFilePath, "response/nil_return_type.yaml");
}

@Test(description = "When the resource has nil union type return")
public void testNilUnionReturnType() throws IOException {
Path ballerinaFilePath = RES_DIR.resolve("response/nil_union_return_type.bal");
OASContractGenerator openApiConverterUtils = new OASContractGenerator();
openApiConverterUtils.generateOAS3DefinitionsAllService(ballerinaFilePath, this.tempDir, null
, false);
Assert.assertTrue(openApiConverterUtils.getErrors().isEmpty());
compareWithGeneratedFile(ballerinaFilePath, "response/nil_union_return_type.yaml");
}

@AfterMethod
public void cleanUp() {
TestUtils.deleteDirectory(this.tempDir);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@ paths:
responses:
"202":
description: Accepted
"400":
description: BadRequest
components: {}
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@ paths:
responses:
"202":
description: Accepted
"400":
description: BadRequest
components: {}
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@ paths:
responses:
"202":
description: Accepted
"400":
description: BadRequest
components: {}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,15 @@ service /payloadV on new http:Listener(9090) {
return created;
}

# Represents Snowpeak reservations resource
#
# + reservations - Array representation of Reservations
# + return - `ReservationCreated` or ReservationConflict representation
resource function post reservations(@http:Payload rep:Reservation[] reservations)
returns @http:Cache{} http:Created|rep:ReservationConflict {
return http:CREATED;
}

# Represents Snowpeak payment resource
#
# + id - Unique identification of payment
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,6 @@ paths:
responses:
"202":
description: Accepted
"400":
description: BadRequest
components: {}
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,6 @@ paths:
responses:
"202":
description: Accepted
"400":
description: BadRequest
components: {}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ paths:
responses:
"202":
description: Accepted
"400":
description: BadRequest
components:
schemas:
ReserveRoom:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ paths:
responses:
"202":
description: Accepted
"400":
description: BadRequest
components:
schemas:
ReserveRoom:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ paths:
responses:
"202":
description: Accepted
"400":
description: BadRequest
components:
schemas:
Link:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ paths:
responses:
"202":
description: Accepted
"400":
description: BadRequest
/getOrder:
post:
operationId: postGetorder
Expand All @@ -34,6 +36,8 @@ paths:
responses:
"202":
description: Accepted
"400":
description: BadRequest
components:
schemas:
Link:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ paths:
responses:
"202":
description: Accepted
"400":
description: BadRequest
components:
schemas:
Link:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ paths:
responses:
"202":
description: Accepted
"400":
description: BadRequest
components:
schemas:
Link:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ paths:
responses:
"202":
description: Accepted
"400":
description: BadRequest
components:
schemas:
Salary:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ paths:
responses:
"202":
description: Accepted
"400":
description: BadRequest
components:
schemas:
User:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ paths:
responses:
"202":
description: Accepted
"400":
description: BadRequest
/reservation/{id}:
get:
operationId: getReservationId
Expand All @@ -35,6 +37,8 @@ paths:
responses:
"202":
description: Accepted
"400":
description: BadRequest
components:
schemas:
PriceMap:
Expand Down
Loading

0 comments on commit 48e6cde

Please sign in to comment.