X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=restconf%2Frestconf-openapi%2Fsrc%2Ftest%2Fjava%2Forg%2Fopendaylight%2Frestconf%2Fopenapi%2Fimpl%2FOpenApiGeneratorRFC8040Test.java;h=4d2da507e474a1d1c2288f84b529c3eee8f077a7;hb=1f6754a83ab28b43e4636c87441315614a350de2;hp=1cc730e56a8727f3505e1c4ca552e90ddad2e18d;hpb=16e0aa3828964a9e7870754d8797d68e05208328;p=netconf.git diff --git a/restconf/restconf-openapi/src/test/java/org/opendaylight/restconf/openapi/impl/OpenApiGeneratorRFC8040Test.java b/restconf/restconf-openapi/src/test/java/org/opendaylight/restconf/openapi/impl/OpenApiGeneratorRFC8040Test.java index 1cc730e56a..4d2da507e4 100644 --- a/restconf/restconf-openapi/src/test/java/org/opendaylight/restconf/openapi/impl/OpenApiGeneratorRFC8040Test.java +++ b/restconf/restconf-openapi/src/test/java/org/opendaylight/restconf/openapi/impl/OpenApiGeneratorRFC8040Test.java @@ -14,23 +14,26 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import static org.opendaylight.restconf.openapi.OpenApiTestUtils.getPathParameters; +import static org.opendaylight.restconf.openapi.OpenApiTestUtils.getPathGetParameters; +import static org.opendaylight.restconf.openapi.OpenApiTestUtils.getPathPostParameters; +import static org.opendaylight.restconf.openapi.impl.BaseYangOpenApiGenerator.BASIC_AUTH_NAME; +import static org.opendaylight.restconf.openapi.model.builder.OperationBuilder.COMPONENTS_PREFIX; -import com.fasterxml.jackson.databind.JsonNode; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.StreamSupport; import javax.ws.rs.core.UriInfo; import org.junit.BeforeClass; import org.junit.Test; import org.opendaylight.mdsal.dom.api.DOMSchemaService; import org.opendaylight.restconf.openapi.DocGenTestHelper; +import org.opendaylight.restconf.openapi.model.MediaTypeObject; import org.opendaylight.restconf.openapi.model.OpenApiObject; import org.opendaylight.restconf.openapi.model.Operation; import org.opendaylight.restconf.openapi.model.Path; +import org.opendaylight.restconf.openapi.model.Property; import org.opendaylight.restconf.openapi.model.Schema; import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext; import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils; @@ -42,7 +45,6 @@ public final class OpenApiGeneratorRFC8040Test { private static final String CONFIG_ROOT_CONTAINER = "mandatory-test_root-container"; private static final String CONFIG_MANDATORY_CONTAINER = "mandatory-test_root-container_mandatory-container"; private static final String CONFIG_MANDATORY_LIST = "mandatory-test_root-container_mandatory-list"; - private static final String MANDATORY_TEST_MODULE = "mandatory-test_module"; private static final String CONTAINER = "container"; private static final String LIST = "list"; @@ -91,6 +93,8 @@ public final class OpenApiGeneratorRFC8040Test { "/rests/data/toaster2:lst={lf1}/cont1/cont11", "/rests/data/toaster2:lst={lf1}/cont1/lst11={lf111}", "/rests/data/toaster2:lst={lf1}/lst1={key1},{key2}"); + final String configPathForPostCont = "/rests/data/toaster2:lst={lf1}/cont1"; + final String configPathForPostLeaf = "/rests/data/toaster2:lst={lf1}/cont1/cont11"; final OpenApiObject doc = generator.getApiDeclaration(TOASTER_2, REVISION_DATE, uriInfo); @@ -99,9 +103,15 @@ public final class OpenApiGeneratorRFC8040Test { assertNotNull(node.get()); assertNotNull(node.put()); assertNotNull(node.delete()); - assertNotNull(node.post()); assertNotNull(node.patch()); } + + final Path node = doc.paths().get(configPathForPostCont); + assertNotNull(node.post()); + + // Assert we do not generate post for container which contains only leafs. + final Path nodeLeaf = doc.paths().get(configPathForPostLeaf); + assertNull(nodeLeaf.post()); } /** @@ -114,51 +124,43 @@ public final class OpenApiGeneratorRFC8040Test { final Map schemas = doc.components().schemas(); assertNotNull(schemas); - final Schema configLstTop = schemas.get("toaster2_lst_TOP"); - assertNotNull(configLstTop); - DocGenTestHelper.containsReferences(configLstTop, "toaster2:lst", "#/components/schemas/toaster2_lst"); - final Schema configLst = schemas.get("toaster2_lst"); assertNotNull(configLst); DocGenTestHelper.containsReferences(configLst, "lst1", "#/components/schemas/toaster2_lst_lst1"); DocGenTestHelper.containsReferences(configLst, "cont1", "#/components/schemas/toaster2_lst_cont1"); - final Schema configLst1Top = schemas.get("toaster2_lst_lst1_TOP"); - assertNotNull(configLst1Top); - DocGenTestHelper.containsReferences(configLst1Top, "toaster2:lst1", "#/components/schemas/toaster2_lst_lst1"); - final Schema configLst1 = schemas.get("toaster2_lst_lst1"); assertNotNull(configLst1); - final Schema configCont1Top = schemas.get("toaster2_lst_cont1_TOP"); - assertNotNull(configCont1Top); - DocGenTestHelper.containsReferences(configCont1Top, "toaster2:cont1", - "#/components/schemas/toaster2_lst_cont1"); - final Schema configCont1 = schemas.get("toaster2_lst_cont1"); assertNotNull(configCont1); - DocGenTestHelper.containsReferences(configCont1, "cont11", - "#/components/schemas/toaster2_lst_cont1_cont11"); - DocGenTestHelper.containsReferences(configCont1, "lst11", - "#/components/schemas/toaster2_lst_cont1_lst11"); - - final Schema configCont11Top = schemas.get("toaster2_lst_cont1_cont11_TOP"); - assertNotNull(configCont11Top); - DocGenTestHelper.containsReferences(configCont11Top, "toaster2:cont11", - "#/components/schemas/toaster2_lst_cont1_cont11"); + DocGenTestHelper.containsReferences(configCont1, "cont11", "#/components/schemas/toaster2_lst_cont1_cont11"); + DocGenTestHelper.containsReferences(configCont1, "lst11", "#/components/schemas/toaster2_lst_cont1_lst11"); final Schema configCont11 = schemas.get("toaster2_lst_cont1_cont11"); assertNotNull(configCont11); - final Schema configLst11Top = schemas.get("toaster2_lst_cont1_lst11_TOP"); - assertNotNull(configLst11Top); - DocGenTestHelper.containsReferences(configLst11Top, "toaster2:lst11", - "#/components/schemas/toaster2_lst_cont1_lst11"); - final Schema configLst11 = schemas.get("toaster2_lst_cont1_lst11"); assertNotNull(configLst11); } + /** + * Test that reference to schema in each path is valid (all referenced schemas exist). + */ + @Test + public void testSchemasExistenceSingleModule() { + final var document = generator.getApiDeclaration(TOASTER_2, REVISION_DATE, uriInfo); + assertNotNull(document); + final var referencedSchemas = new HashSet(); + for (final var path : document.paths().values()) { + referencedSchemas.addAll(extractSchemaRefFromPath(path)); + } + final var schemaNames = document.components().schemas().keySet(); + for (final var ref : referencedSchemas) { + assertTrue("Referenced schema " + ref + " does not exist", schemaNames.contains(ref)); + } + } + /** * Test that generated document contains RPC schemas for "make-toast" with correct input. */ @@ -168,14 +170,10 @@ public final class OpenApiGeneratorRFC8040Test { assertNotNull(doc); final Map schemas = doc.components().schemas(); - final Schema inputTop = schemas.get("toaster_make-toast_input_TOP"); - assertNotNull(inputTop); - final String testString = "{\"toaster:input\":{\"$ref\":\"#/components/schemas/toaster_make-toast_input\"}}"; - assertEquals(testString, inputTop.properties().toString()); final Schema input = schemas.get("toaster_make-toast_input"); - final JsonNode properties = input.properties(); - assertTrue(properties.has("toasterDoneness")); - assertTrue(properties.has("toasterToastType")); + final Map properties = input.properties(); + assertTrue(properties.containsKey("toasterDoneness")); + assertTrue(properties.containsKey("toasterToastType")); } @Test @@ -185,13 +183,12 @@ public final class OpenApiGeneratorRFC8040Test { final var schemas = doc.components().schemas(); final var firstContainer = schemas.get("choice-test_first-container"); - assertEquals("default-value", - firstContainer.properties().get("leaf-default").get("default").asText()); - assertFalse(firstContainer.properties().has("leaf-non-default")); + assertEquals("default-value", firstContainer.properties().get("leaf-default").defaultValue().toString()); + assertFalse(firstContainer.properties().containsKey("leaf-non-default")); final var secondContainer = schemas.get("choice-test_second-container"); - assertTrue(secondContainer.properties().has("leaf-first-case")); - assertFalse(secondContainer.properties().has("leaf-second-case")); + assertTrue(secondContainer.properties().containsKey("leaf-first-case")); + assertFalse(secondContainer.properties().containsKey("leaf-second-case")); } @Test @@ -201,23 +198,19 @@ public final class OpenApiGeneratorRFC8040Test { final var schemas = doc.components().schemas(); final var containersWithRequired = new ArrayList(); - final var reqRootContainerElements = Set.of("mandatory-root-leaf", "mandatory-container", + final var reqRootContainerElements = List.of("mandatory-root-leaf", "mandatory-container", "mandatory-first-choice", "mandatory-list"); verifyRequiredField(schemas.get(CONFIG_ROOT_CONTAINER), reqRootContainerElements); containersWithRequired.add(CONFIG_ROOT_CONTAINER); - final var reqMandatoryContainerElements = Set.of("mandatory-leaf", "leaf-list-with-min-elements"); + final var reqMandatoryContainerElements = List.of("mandatory-leaf", "leaf-list-with-min-elements"); verifyRequiredField(schemas.get(CONFIG_MANDATORY_CONTAINER), reqMandatoryContainerElements); containersWithRequired.add(CONFIG_MANDATORY_CONTAINER); - final var reqMandatoryListElements = Set.of("mandatory-list-field"); + final var reqMandatoryListElements = List.of("mandatory-list-field"); verifyRequiredField(schemas.get(CONFIG_MANDATORY_LIST), reqMandatoryListElements); containersWithRequired.add(CONFIG_MANDATORY_LIST); - final var testModuleMandatoryArray = Set.of("root-container", "root-mandatory-list"); - verifyRequiredField(schemas.get(MANDATORY_TEST_MODULE), testModuleMandatoryArray); - containersWithRequired.add(MANDATORY_TEST_MODULE); - verifyThatOthersNodeDoesNotHaveRequiredField(containersWithRequired, schemas); } @@ -255,14 +248,16 @@ public final class OpenApiGeneratorRFC8040Test { assertNotNull(delete); assertEquals(expectedSize, delete.parameters().size()); - final var post = path.post(); - assertNotNull(post); - assertEquals(expectedSize, post.parameters().size()); - final var patch = path.patch(); assertNotNull(patch); assertEquals(expectedSize, patch.parameters().size()); } + + // we do not generate POST for lists + final var path = paths.get("/rests/data/recursive:container-root"); + final var post = path.post(); + final int expectedSize = configPaths.get("/rests/data/recursive:container-root"); + assertEquals(expectedSize, post.parameters().size()); } /** @@ -277,23 +272,23 @@ public final class OpenApiGeneratorRFC8040Test { var pathToList1 = "/rests/data/path-params-test:cont/list1={name}"; assertTrue(doc.paths().containsKey(pathToList1)); - assertEquals(List.of("name"), getPathParameters(doc.paths(), pathToList1)); + assertEquals(List.of("name"), getPathGetParameters(doc.paths(), pathToList1)); var pathToList2 = "/rests/data/path-params-test:cont/list1={name}/list2={name1}"; assertTrue(doc.paths().containsKey(pathToList2)); - assertEquals(List.of("name", "name1"), getPathParameters(doc.paths(), pathToList2)); + assertEquals(List.of("name", "name1"), getPathGetParameters(doc.paths(), pathToList2)); var pathToList3 = "/rests/data/path-params-test:cont/list3={name}"; assertTrue(doc.paths().containsKey(pathToList3)); - assertEquals(List.of("name"), getPathParameters(doc.paths(), pathToList3)); + assertEquals(List.of("name"), getPathGetParameters(doc.paths(), pathToList3)); var pathToList4 = "/rests/data/path-params-test:cont/list1={name}/list4={name1}"; assertTrue(doc.paths().containsKey(pathToList4)); - assertEquals(List.of("name", "name1"), getPathParameters(doc.paths(), pathToList4)); + assertEquals(List.of("name", "name1"), getPathGetParameters(doc.paths(), pathToList4)); var pathToList5 = "/rests/data/path-params-test:cont/list1={name}/cont2"; assertTrue(doc.paths().containsKey(pathToList4)); - assertEquals(List.of("name"), getPathParameters(doc.paths(), pathToList5)); + assertEquals(List.of("name"), getPathGetParameters(doc.paths(), pathToList5)); } /** @@ -305,11 +300,11 @@ public final class OpenApiGeneratorRFC8040Test { final var pathWithParameters = "/rests/operations/action-types:list={name}/list-action"; assertTrue(doc.paths().containsKey(pathWithParameters)); - assertEquals(List.of("name"), getPathParameters(doc.paths(), pathWithParameters)); + assertEquals(List.of("name"), getPathPostParameters(doc.paths(), pathWithParameters)); final var pathWithoutParameters = "/rests/operations/action-types:multi-container/inner-container/action"; assertTrue(doc.paths().containsKey(pathWithoutParameters)); - assertEquals(List.of(), getPathParameters(doc.paths(), pathWithoutParameters)); + assertEquals(List.of(), getPathPostParameters(doc.paths(), pathWithoutParameters)); } @Test @@ -318,18 +313,13 @@ public final class OpenApiGeneratorRFC8040Test { assertEquals(Set.of("/rests/data", "/rests/data/my-yang:data"), doc.paths().keySet()); final var JsonNodeMyYangData = doc.paths().get("/rests/data/my-yang:data"); - verifyRequestRef(JsonNodeMyYangData.post(), "#/components/schemas/my-yang_data", - "#/components/schemas/my-yang_data"); - verifyRequestRef1(JsonNodeMyYangData.put(), "#/components/schemas/my-yang_data", CONTAINER); - verifyRequestRef(JsonNodeMyYangData.get(), "#/components/schemas/my-yang_data_TOP", - "#/components/schemas/my-yang_data"); + verifyRequestRef(JsonNodeMyYangData.put(), "#/components/schemas/my-yang_data", CONTAINER); + verifyRequestRef(JsonNodeMyYangData.get(), "#/components/schemas/my-yang_data", CONTAINER); // Test `components/schemas` objects final var definitions = doc.components().schemas(); - assertEquals(3, definitions.size()); + assertEquals(1, definitions.size()); assertTrue(definitions.containsKey("my-yang_data")); - assertTrue(definitions.containsKey("my-yang_data_TOP")); - assertTrue(definitions.containsKey("my-yang_module")); } @Test @@ -337,63 +327,45 @@ public final class OpenApiGeneratorRFC8040Test { final var doc = generator.getApiDeclaration(TOASTER_2, REVISION_DATE, uriInfo); final var jsonNodeToaster = doc.paths().get("/rests/data/toaster2:toaster"); - verifyRequestRef(jsonNodeToaster.post(), "#/components/schemas/toaster2_toaster", - "#/components/schemas/toaster2_toaster"); - verifyRequestRef1(jsonNodeToaster.put(), "#/components/schemas/toaster2_toaster", CONTAINER); - verifyRequestRef(jsonNodeToaster.get(), "#/components/schemas/toaster2_toaster_TOP", - "#/components/schemas/toaster2_toaster"); + verifyRequestRef(jsonNodeToaster.post(), "#/components/schemas/toaster2_toaster_toasterSlot", LIST); + verifyRequestRef(jsonNodeToaster.put(), "#/components/schemas/toaster2_toaster", CONTAINER); + verifyRequestRef(jsonNodeToaster.get(), "#/components/schemas/toaster2_toaster", CONTAINER); final var jsonNodeToasterSlot = doc.paths().get("/rests/data/toaster2:toaster/toasterSlot={slotId}"); - verifyRequestRef(jsonNodeToasterSlot.post(), "#/components/schemas/toaster2_toaster_toasterSlot", - "#/components/schemas/toaster2_toaster_toasterSlot"); - verifyRequestRef1(jsonNodeToasterSlot.put(), "#/components/schemas/toaster2_toaster_toasterSlot", LIST); - verifyRequestRef(jsonNodeToasterSlot.get(), "#/components/schemas/toaster2_toaster_toasterSlot_TOP", - "#/components/schemas/toaster2_toaster_toasterSlot"); + verifyRequestRef(jsonNodeToasterSlot.put(), "#/components/schemas/toaster2_toaster_toasterSlot", LIST); + verifyRequestRef(jsonNodeToasterSlot.get(), "#/components/schemas/toaster2_toaster_toasterSlot", LIST); final var jsonNodeSlotInfo = doc.paths().get( "/rests/data/toaster2:toaster/toasterSlot={slotId}/toaster-augmented:slotInfo"); - verifyRequestRef(jsonNodeSlotInfo.post(), - "#/components/schemas/toaster2_toaster_toasterSlot_slotInfo", - "#/components/schemas/toaster2_toaster_toasterSlot_slotInfo"); - verifyRequestRef1(jsonNodeSlotInfo.put(), "#/components/schemas/toaster2_toaster_toasterSlot_slotInfo", + verifyRequestRef(jsonNodeSlotInfo.put(), "#/components/schemas/toaster2_toaster_toasterSlot_slotInfo", + CONTAINER); + verifyRequestRef(jsonNodeSlotInfo.get(), "#/components/schemas/toaster2_toaster_toasterSlot_slotInfo", CONTAINER); - verifyRequestRef(jsonNodeSlotInfo.get(), - "#/components/schemas/toaster2_toaster_toasterSlot_slotInfo_TOP", - "#/components/schemas/toaster2_toaster_toasterSlot_slotInfo"); final var jsonNodeLst = doc.paths().get("/rests/data/toaster2:lst={lf1}"); - verifyRequestRef(jsonNodeLst.post(), "#/components/schemas/toaster2_lst", - "#/components/schemas/toaster2_lst"); - verifyRequestRef1(jsonNodeLst.put(), "#/components/schemas/toaster2_lst", LIST); - verifyRequestRef(jsonNodeLst.get(), "#/components/schemas/toaster2_lst_TOP", - "#/components/schemas/toaster2_lst"); + verifyRequestRef(jsonNodeLst.put(), "#/components/schemas/toaster2_lst", LIST); + verifyRequestRef(jsonNodeLst.get(), "#/components/schemas/toaster2_lst", LIST); final var jsonNodeLst1 = doc.paths().get("/rests/data/toaster2:lst={lf1}/lst1={key1},{key2}"); - verifyRequestRef(jsonNodeLst1.post(), "#/components/schemas/toaster2_lst_lst1", - "#/components/schemas/toaster2_lst_lst1"); - verifyRequestRef1(jsonNodeLst1.put(), "#/components/schemas/toaster2_lst_lst1", LIST); - verifyRequestRef(jsonNodeLst1.get(), "#/components/schemas/toaster2_lst_lst1_TOP", - "#/components/schemas/toaster2_lst_lst1"); + verifyRequestRef(jsonNodeLst1.put(), "#/components/schemas/toaster2_lst_lst1", LIST); + verifyRequestRef(jsonNodeLst1.get(), "#/components/schemas/toaster2_lst_lst1", LIST); final var jsonNodeMakeToast = doc.paths().get("/rests/operations/toaster2:make-toast"); assertNull(jsonNodeMakeToast.get()); - verifyRequestRef(jsonNodeMakeToast.post(), "#/components/schemas/toaster2_make-toast_input_TOP", - "#/components/schemas/toaster2_make-toast_input"); + verifyRequestRef(jsonNodeMakeToast.post(), "#/components/schemas/toaster2_make-toast_input", CONTAINER); final var jsonNodeCancelToast = doc.paths().get("/rests/operations/toaster2:cancel-toast"); assertNull(jsonNodeCancelToast.get()); // Test RPC with empty input - final var postContent = jsonNodeCancelToast.post().requestBody().get("content"); - final var jsonSchema = postContent.get("application/json").get("schema"); - assertNull(jsonSchema.get("$ref")); - assertEquals(2, jsonSchema.size()); - final var xmlSchema = postContent.get("application/xml").get("schema"); - assertNull(xmlSchema.get("$ref")); - assertEquals(2, xmlSchema.size()); + final var postContent = jsonNodeCancelToast.post().requestBody().content(); + final var jsonSchema = postContent.get("application/json").schema(); + assertNull(jsonSchema.ref()); + final var xmlSchema = postContent.get("application/xml").schema(); + assertNull(xmlSchema.ref()); // Test `components/schemas` objects final var definitions = doc.components().schemas(); - assertEquals(28, definitions.size()); + assertEquals(10, definitions.size()); } /** @@ -403,53 +375,86 @@ public final class OpenApiGeneratorRFC8040Test { public void testAuthenticationFeature() { final var doc = generator.getApiDeclaration(TOASTER_2, REVISION_DATE, uriInfo); - assertEquals("[{\"basicAuth\":[]}]", doc.security().toString()); - assertEquals("{\"type\":\"http\",\"scheme\":\"basic\"}", - doc.components().securitySchemes().basicAuth().toString()); + assertEquals("[{basicAuth=[]}]", doc.security().toString()); + assertEquals("Http[type=http, scheme=basic, description=null, bearerFormat=null]", + doc.components().securitySchemes().get(BASIC_AUTH_NAME).toString()); + + // take list of all defined security scheme objects => all names of registered SecuritySchemeObjects + final var securitySchemesObjectNames = doc.components().securitySchemes().keySet(); + assertTrue("No Security Schemes Object is defined", securitySchemesObjectNames.size() > 0); + + // collect all referenced security scheme objects + final var referencedSecurityObjects = new HashSet(); + doc.security().forEach(map -> referencedSecurityObjects.addAll(map.keySet())); + + // verify, that each reference references name of registered Security Scheme Object + for (final var secObjRef : referencedSecurityObjects) { + assertTrue(securitySchemesObjectNames.contains(secObjRef)); + } } /** - * Test JSON and XML references for request operation. + * Test that checks if namespace for rpc is present. */ - private static void verifyRequestRef(final Operation operation, final String expectedJsonRef, - final String expectedXmlRef) { - final JsonNode postContent; - if (operation.requestBody() != null) { - postContent = operation.requestBody().get("content"); - } else { - postContent = operation.responses().get("200").get("content"); - } - assertNotNull(postContent); - final var postJsonRef = postContent.get("application/json").get("schema").get("$ref"); - assertNotNull(postJsonRef); - assertEquals(expectedJsonRef, postJsonRef.textValue()); - final var postXmlRef = postContent.get("application/xml").get("schema").get("$ref"); - assertNotNull(postXmlRef); - assertEquals(expectedXmlRef, postXmlRef.textValue()); + @Test + public void testRpcNamespace() { + final var doc = generator.getApiDeclaration("toaster", "2009-11-20", uriInfo); + assertNotNull("Failed to find Datastore API", doc); + final var paths = doc.paths(); + final var path = paths.get("/rests/operations/toaster:cancel-toast"); + assertNotNull(path); + final var content = path.post().requestBody().content().get("application/xml"); + assertNotNull(content); + final var schema = content.schema(); + assertNotNull(schema); + final var xml = schema.xml(); + assertNotNull(xml); + final var namespace = xml.namespace(); + assertNotNull(namespace); + assertEquals("http://netconfcentral.org/ns/toaster", namespace); } - private static void verifyRequestRef1(final Operation operation, final String expectedRef, - final String nodeType) { - final JsonNode postContent; + /** + * Test that checks if namespace for actions is present. + */ + @Test + public void testActionsNamespace() { + final var doc = generator.getApiDeclaration("action-types", null, uriInfo); + assertNotNull("Failed to find Datastore API", doc); + final var paths = doc.paths(); + final var path = paths.get("/rests/operations/action-types:multi-container/inner-container/action"); + assertNotNull(path); + final var content = path.post().requestBody().content().get("application/xml"); + assertNotNull(content); + final var schema = content.schema(); + assertNotNull(schema); + final var xml = schema.xml(); + assertNotNull(xml); + final var namespace = xml.namespace(); + assertNotNull(namespace); + assertEquals("urn:ietf:params:xml:ns:yang:test:action:types", namespace); + } + + private static void verifyRequestRef(final Operation operation, final String expectedRef, final String nodeType) { + final Map postContent; if (operation.requestBody() != null) { - postContent = operation.requestBody().path("content"); + postContent = operation.requestBody().content(); } else { - postContent = operation.responses().path("200").path("content"); + postContent = operation.responses().get("200").content(); } assertNotNull(postContent); final String postJsonRef; if (nodeType.equals(CONTAINER)) { - postJsonRef = postContent.path("application/json").path("schema").path("properties").elements().next() - .path("$ref").textValue(); + postJsonRef = postContent.get("application/json").schema().properties().values().iterator().next().ref(); } else { - postJsonRef = postContent.path("application/json").path("schema").path("properties").elements().next() - .path("items").path("$ref").textValue(); + postJsonRef = postContent.get("application/json").schema().properties().values().iterator().next().items() + .ref(); } assertNotNull(postJsonRef); assertEquals(expectedRef, postJsonRef); - final var postXmlRef = postContent.path("application/xml").path("schema").path("$ref"); + final var postXmlRef = postContent.get("application/xml").schema().ref(); assertNotNull(postXmlRef); - assertEquals(expectedRef, postXmlRef.textValue()); + assertEquals(expectedRef, postXmlRef); } private static void verifyThatOthersNodeDoesNotHaveRequiredField(final List expected, @@ -463,14 +468,70 @@ public final class OpenApiGeneratorRFC8040Test { } } - private static void verifyRequiredField(final Schema rootContainer, final Set expected) { + private static void verifyRequiredField(final Schema rootContainer, final List expected) { assertNotNull(rootContainer); final var required = rootContainer.required(); assertNotNull(required); - assertTrue(required.isArray()); - final var actualContainerArray = StreamSupport.stream(required.spliterator(), false) - .map(JsonNode::textValue) - .collect(Collectors.toSet()); - assertEquals(expected, actualContainerArray); + assertEquals(expected, required); + } + + private static Set extractSchemaRefFromPath(final Path path) { + if (path == null) { + return Set.of(); + } + final var references = new HashSet(); + final var get = path.get(); + if (get != null) { + references.addAll(schemaRefFromContent(get.responses().get("200").content())); + } + final var post = path.post(); + if (post != null) { + references.addAll(schemaRefFromContent(post.requestBody().content())); + } + final var put = path.put(); + if (put != null) { + references.addAll(schemaRefFromContent(put.requestBody().content())); + } + final var patch = path.patch(); + if (patch != null) { + references.addAll(schemaRefFromContent(patch.requestBody().content())); + } + return references; + } + + /** + * The schema node does not have 1 specific structure and the "$ref" child is not always the first child after + * schema. Possible schema structures include: + *
    + *
  • schema/$ref/{reference}
  • + *
  • schema/properties/{nodeName}/$ref/{reference}
  • + *
  • schema/properties/{nodeName}/items/$ref/{reference}
  • + *
+ * @param content the element identified with key "content" + * @return the set of referenced schemas + */ + private static Set schemaRefFromContent(final Map content) { + final HashSet refs = new HashSet<>(); + content.values().forEach(mediaType -> { + final var schema = mediaType.schema(); + final var props = mediaType.schema().properties(); + final String ref; + if (props == null) { + // either there is no node with the key "properties", try to find immediate child of schema + ref = schema.ref(); + } else if (props.values().iterator().next().items() == null) { + // or the "properties" is defined and under that we didn't find the "items" node + // try to get "$ref" as immediate child under properties + ref = props.values().iterator().next().ref(); + } else { + // or the "items" node is defined, in which case we try to get the "$ref" from this node + ref = props.values().iterator().next().items().ref(); + } + + if (ref != null) { + refs.add(ref.replaceFirst(COMPONENTS_PREFIX, "")); + } + }); + return refs; } }