Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(cts): use custom package to fix openapi-generator-cli #254

Merged
merged 7 commits into from
Mar 17, 2022
Merged
Show file tree
Hide file tree
Changes from 5 commits
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
5 changes: 0 additions & 5 deletions .github/actions/cache/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,6 @@ runs:
shell: bash
run: curl -L "https://github.com/google/google-java-format/releases/download/v1.13.0/google-java-format-1.13.0-all-deps.jar" > /tmp/java-formatter.jar

- name: Download openapi generator jar for java (TODO REMOVE)
if: ${{ inputs.language == 'java' || inputs.job == 'cts' }}
shell: bash
run: curl -L "https://repo1.maven.org/maven2/org/openapitools/openapi-generator-cli/5.4.0/openapi-generator-cli-5.4.0.jar" > /tmp/openapi-generator-cli.jar

# Restore bundled specs: used during 'client' generation or pushing the 'codegen'
- name: Restore built abtesting spec
if: ${{ inputs.job == 'client' || inputs.job == 'codegen' }}
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@ build
dist

.openapi-generator

tests/output/*/.openapi-generator-ignore
3 changes: 0 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@ ENV JAVA_HOME=/usr/lib/jvm/default-jvm
# Java formatter
ADD https://github.com/google/google-java-format/releases/download/v1.13.0/google-java-format-1.13.0-all-deps.jar /tmp/java-formatter.jar

# openapi generator jar (TODO: REMOVE)
ADD https://repo1.maven.org/maven2/org/openapitools/openapi-generator-cli/5.4.0/openapi-generator-cli-5.4.0.jar /tmp/openapi-generator-cli.jar

# PHP dependencies
RUN apk add -U composer php8 php8-tokenizer php8-dom php8-xml php8-xmlwriter

Expand Down
1 change: 1 addition & 0 deletions config/clients.config.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"java": {
"folder": "clients/algoliasearch-client-java-2",
"customGenerator": "algolia-java",
"tests": {
"extension": ".test.java",
"outputFolder": "src/test/java/com/algolia"
Expand Down
9 changes: 0 additions & 9 deletions config/openapitools-java-cts.json

This file was deleted.

21 changes: 0 additions & 21 deletions config/openapitools-java.json

This file was deleted.

7 changes: 7 additions & 0 deletions generators/src/main/java/com/algolia/codegen/Utils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.algolia.codegen;

public class Utils {
public static String capitalize(String str) {
return str.substring(0, 1).toUpperCase() + str.substring(1);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
import java.util.*;
import java.util.Map.Entry;

import com.algolia.codegen.Utils;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.collect.ImmutableMap.Builder;
import com.samskivert.mustache.Mustache.Lambda;

Expand All @@ -19,6 +21,10 @@
public class AlgoliaCtsGenerator extends DefaultCodegen {
// cache the models
private final Map<String, CodegenModel> models = new HashMap<>();
private String language;
private String client;
private String packageName;
private boolean hasRegionalHost;

/**
* Configures the type of generator.
Expand Down Expand Up @@ -49,10 +55,35 @@ public String getName() {
*
* @return A string value for the help message
*/
@Override
public String getHelp() {
return "Generates the CTS";
}

@Override
public void processOpts() {
super.processOpts();

language = (String) additionalProperties.get("language");
client = (String) additionalProperties.get("client");
packageName = (String) additionalProperties.get("packageName");
hasRegionalHost = additionalProperties.get("hasRegionalHost").equals("true");

try {
JsonNode config = Json.mapper().readTree(new File("config/clients.config.json"));
TestConfig testConfig = Json.mapper().treeToValue(config.get(language).get("tests"), TestConfig.class);

setTemplateDir("tests/CTS/methods/requests/templates/" + language);
setOutputDir("tests/output/" + language);
supportingFiles
.add(new SupportingFile("requests.mustache", testConfig.outputFolder + "/methods/requests",
client + testConfig.extension));
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
}

@Override
public Map<String, Object> postProcessAllModels(Map<String, Object> objs) {
Map<String, Object> mod = super.postProcessAllModels(objs);
Expand All @@ -65,12 +96,6 @@ public Map<String, Object> postProcessAllModels(Map<String, Object> objs) {
return mod;
}

public AlgoliaCtsGenerator() {
super();
supportingFiles
.add(new SupportingFile("requests.mustache", "src/test/java/com/algolia/methods/requests", "search.test.java"));
}

@Override
protected Builder<String, Lambda> addMustacheLambdas() {
Builder<String, Lambda> lambdas = super.addMustacheLambdas();
Expand All @@ -85,22 +110,30 @@ public Map<String, Object> postProcessSupportingFileData(Map<String, Object> obj
try {
cts = loadCTS();

Map<String, CodegenOperation> operations = buildOperations(objs).get("Search");
Map<String, CodegenOperation> operations = buildOperations(objs);

Map<String, Object> bundle = super.postProcessSupportingFileData(objs);
// The return value of this function is not used, we need to modify the param
// itself.
Object lambda = objs.get("lambda");
Map<String, Object> bundle = objs;
bundle.clear();

// We can put whatever we want in the bundle, and it will be accessible in the
// template
bundle.put("client", "SearchApi");
bundle.put("client", createClientName());
bundle.put("import", packageName);
bundle.put("hasRegionalHost", hasRegionalHost);
bundle.put("lambda", lambda);

List<Object> blocks = new ArrayList<>();
ParametersWithDataType paramsType = new ParametersWithDataType(models);

for (Entry<String, Request[]> entry : cts.entrySet()) {
if (!operations.containsKey(entry.getKey())) {
throw new CTSException("operationId " + entry.getKey() + " does not exist in the spec");
String operationId = entry.getKey();
if (!operations.containsKey(operationId)) {
throw new CTSException("operationId " + operationId + " does not exist in the spec");
}
CodegenOperation op = operations.get(entry.getKey());
CodegenOperation op = operations.get(operationId);

List<Object> tests = new ArrayList<>();
for (int i = 0; i < entry.getValue().length; i++) {
Expand All @@ -109,45 +142,72 @@ public Map<String, Object> postProcessSupportingFileData(Map<String, Object> obj
}
Map<String, Object> testObj = new HashMap<>();
testObj.put("tests", tests);
testObj.put("operationId", operationId);
blocks.add(testObj);
}
bundle.put("blocks", blocks);

return bundle;
} catch (CTSException e) {
if (e.isSkipable()) {
System.out.println(e.getMessage());
System.exit(0);
}
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
return null;
}

private Map<String, Request[]> loadCTS() throws JsonParseException, JsonMappingException, IOException {
private Map<String, Request[]> loadCTS() throws JsonParseException, JsonMappingException, IOException, CTSException {
TreeMap<String, Request[]> cts = new TreeMap<>();
File dir = new File("tests/CTS/methods/requests/search");
File dir = new File("tests/CTS/methods/requests/" + client);
if (!dir.exists()) {
throw new CTSException("CTS not found at " + dir.getAbsolutePath(), true);
}
for (File f : dir.listFiles()) {
cts.put(f.getName().replace(".json", ""), Json.mapper().readValue(f, Request[].class));
}
return cts;
}

// Client -> operationId -> CodegenOperation
private HashMap<String, HashMap<String, CodegenOperation>> buildOperations(Map<String, Object> objs) {
HashMap<String, HashMap<String, CodegenOperation>> result = new HashMap<>();
// operationId -> CodegenOperation
private HashMap<String, CodegenOperation> buildOperations(Map<String, Object> objs) {
HashMap<String, CodegenOperation> result = new HashMap<>();
List<Map<String, Object>> apis = ((Map<String, List<Map<String, Object>>>) objs.get("apiInfo")).get("apis");
for (Map<String, Object> api : apis) {
String apiName = (String) api.get("baseName");
String apiName = ((String) api.get("baseName")).toLowerCase();
if (!apiName.equals(client.replace("-", ""))) {
continue;
}
List<CodegenOperation> operations = ((Map<String, List<CodegenOperation>>) api.get("operations"))
.get("operation");

HashMap<String, CodegenOperation> allOp = new HashMap<>();
for (CodegenOperation ope : operations) {
allOp.put(ope.operationId, ope);
result.put(ope.operationId, ope);
}
result.put(apiName, allOp);
}
return result;
}

private String createClientName() {
String[] clientParts = client.split("-");
String clientName = "";
if (language.equals("javascript")) {
// do not capitalize the first part
clientName = clientParts[0];
for (int i = 1; i < clientParts.length; i++) {
clientName += Utils.capitalize(clientParts[i]);
}
} else {
for (int i = 0; i < clientParts.length; i++) {
clientName += Utils.capitalize(clientParts[i]);
}
}

return clientName + "Api";
}

/**
* override with any special text escaping logic to handle unsafe
* characters so as to avoid code injection
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
package com.algolia.codegen.cts;

public class CTSException extends Exception {
public CTSException(String message) {
super(message);
}
private boolean skipable;

public CTSException(String message) {
super(message);
}

public CTSException(String message, boolean skipable) {
this(message);
this.skipable = skipable;
}

public boolean isSkipable() {
return skipable;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
import com.samskivert.mustache.Template;

public class EscapeQuotesLambda implements Mustache.Lambda {
@Override
public void execute(Template.Fragment fragment, Writer writer) throws IOException {
String text = fragment.execute();
writer.write(text.replace("\"", "\\\""));
}
@Override
public void execute(Template.Fragment fragment, Writer writer) throws IOException {
String text = fragment.execute();
writer.write(text.replace("\"", "\\\""));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,18 @@
import java.util.*;
import java.util.Map.Entry;

import com.algolia.codegen.Utils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;

import org.openapitools.codegen.CodegenModel;
import org.openapitools.codegen.CodegenOperation;
import org.openapitools.codegen.CodegenParameter;
import org.openapitools.codegen.CodegenProperty;
import org.openapitools.codegen.CodegenResponse;
import org.openapitools.codegen.IJsonSchemaValidationProperties;

import io.swagger.v3.core.util.Json;
import io.swagger.util.Json;

@SuppressWarnings("unchecked")
public class ParametersWithDataType {
Expand All @@ -21,13 +25,21 @@ public ParametersWithDataType(Map<String, CodegenModel> models) {
}

public Map<String, Object> buildJSONForRequest(Request req, CodegenOperation ope, int testIndex)
throws CTSException {
throws CTSException, JsonMappingException, JsonProcessingException {
Map<String, Object> test = new HashMap<>();
test.put("method", req.method);
test.put("testName", req.testName == null ? req.method : req.testName);
test.put("testIndex", testIndex);
test.put("request", req.request);

test.put("hasParameters", req.parameters.size() != 0);

if (req.parameters.size() == 0) {
return test;
}
// Give the stringified version to mustache
test.put("parameters", Json.mapper().writeValueAsString(req.parameters));

List<Object> parametersWithDataType = new ArrayList<>();

// special case if there is only bodyParam which is not an array
Expand Down Expand Up @@ -86,7 +98,7 @@ private Map<String, Object> traverseParams(String paramName, Object param, IJson
testOutput.put("parentSuffix", suffix - 1);
testOutput.put("suffix", suffix);
testOutput.put("parent", parent);
testOutput.put("objectName", baseType.substring(0, 1).toUpperCase() + baseType.substring(1));
testOutput.put("objectName", Utils.capitalize(baseType));

if (spec.getIsArray()) {
handleArray(paramName, param, testOutput, spec, suffix);
Expand Down Expand Up @@ -260,6 +272,12 @@ private String inferDataType(Object param, CodegenParameter spec, Map<String, Ob
if (output != null)
output.put("isInteger", true);
return "Integer";
case "Long":
if (spec != null)
spec.setIsNumber(true);
if (output != null)
output.put("isInteger", true);
return "Long";
case "Double":
if (spec != null)
spec.setIsNumber(true);
Expand Down
Loading