Skip to content

Commit

Permalink
Fix corner case for oneOf definitions when there are multiple arrays …
Browse files Browse the repository at this point in the history
…nested
  • Loading branch information
en-milie committed Sep 14, 2023
1 parent 6bf0e07 commit e8b08e4
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 18 deletions.
14 changes: 8 additions & 6 deletions src/main/java/com/endava/cats/factory/FuzzingDataFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.endava.cats.model.generator.OpenAPIModelGenerator;
import com.endava.cats.openapi.OpenApiUtils;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import io.github.ludovicianul.prettylogger.PrettyLogger;
import io.github.ludovicianul.prettylogger.PrettyLoggerFactory;
Expand Down Expand Up @@ -437,8 +438,13 @@ private Map<String, Map<String, JsonElement>> joinCommonOneAndAnyOfs(Map<String,

private Map<String, Map<String, JsonElement>> getAnyOrOneOffElements(String jsonElementKey, JsonElement jsonElement) {
Map<String, Map<String, JsonElement>> anyOrOneOfs = new HashMap<>();

for (Map.Entry<String, JsonElement> elementEntry : jsonElement.getAsJsonObject().entrySet()) {
JsonObject jsonObject = null;
if (jsonElement.isJsonArray()) {
jsonObject = jsonElement.getAsJsonArray().get(0).getAsJsonObject();
} else {
jsonObject = jsonElement.getAsJsonObject();
}
for (Map.Entry<String, JsonElement> elementEntry : jsonObject.entrySet()) {
if (elementEntry.getValue().isJsonArray() && !elementEntry.getValue().getAsJsonArray().isEmpty() && !elementEntry.getValue().getAsJsonArray().get(0).isJsonPrimitive() && !elementEntry.getValue().getAsJsonArray().get(0).isJsonNull()) {
anyOrOneOfs.putAll(this.getAnyOrOneOffElements(this.createArrayKey(jsonElementKey, elementEntry.getKey()), elementEntry.getValue().getAsJsonArray().get(0)));
} else if (elementEntry.getKey().contains(ONE_OF) || elementEntry.getKey().contains(ANY_OF)) {
Expand Down Expand Up @@ -476,16 +482,12 @@ private BiFunction<Map<String, JsonElement>, Map<String, JsonElement>, Map<Strin

/**
* Creates a fully qualified Json path.
* If the initial path ends with an array, it won't add the elementEntry.
*
* @param jsonElementKey the initial path
* @param elementEntry the next element path
* @return a fully qualified JsonPath
*/
private String createSimpleElementPath(String jsonElementKey, String elementEntry) {
if (jsonElementKey.contains("[*]")) {
return jsonElementKey;
}
return jsonElementKey + "." + elementEntry;
}

Expand Down
26 changes: 14 additions & 12 deletions src/main/java/com/endava/cats/json/JsonUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -155,18 +155,20 @@ public static String createValidOneOfAnyOfNode(String payload, String nodeKey, S
} catch (PathNotFoundException e) {
String pathTowardsReplacement = nodeKey.substring(0, nodeKey.lastIndexOf("."));
String replacementKey = nodeKey.substring(nodeKey.lastIndexOf(".") + 1);
String interimPayload = JsonPath.parse(payload).renameKey(pathTowardsReplacement, alternativeKey, replacementKey).jsonString();

DocumentContext finalPayload = JsonPath.parse(interimPayload);
toEliminate.forEach(toEliminateKey -> {
try {
finalPayload.delete(pathTowardsReplacement + "." + toEliminateKey);
} catch (PathNotFoundException ex) {
LOGGER.debug("Path not found when removing any_of/one_of: {}", ex.getMessage());
}
});

return finalPayload.jsonString();
if (payload.contains("_OF")) {
String interimPayload = JsonPath.parse(payload).renameKey(pathTowardsReplacement, alternativeKey, replacementKey).jsonString();

DocumentContext finalPayload = JsonPath.parse(interimPayload);
toEliminate.forEach(toEliminateKey -> {
try {
finalPayload.delete(pathTowardsReplacement + "." + toEliminateKey);
} catch (PathNotFoundException ex) {
LOGGER.debug("Path not found when removing any_of/one_of: {}", ex.getMessage());
}
});
return finalPayload.jsonString();
}
return payload;
}
}

Expand Down
11 changes: 11 additions & 0 deletions src/test/java/com/endava/cats/factory/FuzzingDataFactoryTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,17 @@ void shouldGenerateMultiplePayloadsWhenContractGeneratedFromNSwagAndMultipleOneO
Assertions.assertThat(JsonParser.parseString(firstData.getPayload()).getAsJsonObject().get("Components").isJsonArray()).isTrue();
}

@Test
void shouldGenerateValidResponseForOneOfNestedCombinations() throws Exception {
List<FuzzingData> dataList = setupFuzzingData("/api/groops/{groopId}/StartGroopitPaging", "src/test/resources/nswag_gen_oneof.json");
Assertions.assertThat(dataList).hasSize(1);
FuzzingData firstData = dataList.get(0);
Assertions.assertThat(firstData.getPayload()).doesNotContain("ANY_OF", "ONE_OF", "ALL_OF");
Assertions.assertThat(firstData.getResponses().get("200")).hasSize(9);
String firstResponse = firstData.getResponses().get("200").get(0);
Assertions.assertThat(firstResponse).doesNotContain("ANY_OF", "ONE_OF", "ALL_OF");
}

@Test
void shouldThrowExceptionWhenSchemeDoesNotExist() {
Assertions.assertThatThrownBy(() -> setupFuzzingData("/pet-types", "src/test/resources/petstore-no-schema.yml")).isInstanceOf(IllegalArgumentException.class);
Expand Down

0 comments on commit e8b08e4

Please sign in to comment.