All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.microprofile.openapi.tck.ModelConstructionTest Maven / Gradle / Ivy

There is a newer version: 4.0.1
Show newest version
/**
 * Copyright (c) 2017 Contributors to the Eclipse Foundation
 * 

* Licensed 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 org.eclipse.microprofile.openapi.tck; // assertSame and assertNotSame are broken in TestNG 7.4.0 - https://github.com/cbeust/testng/issues/2486 // import static org.testng.Assert.assertNotSame; // import static org.testng.Assert.assertSame; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.anEmptyMap; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.sameInstance; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; import java.beans.Introspector; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.math.BigDecimal; import java.math.BigInteger; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.BiConsumer; import java.util.function.BiFunction; import java.util.function.Function; import java.util.function.Supplier; import org.eclipse.microprofile.openapi.OASFactory; import org.eclipse.microprofile.openapi.models.Components; import org.eclipse.microprofile.openapi.models.Constructible; import org.eclipse.microprofile.openapi.models.Extensible; import org.eclipse.microprofile.openapi.models.ExternalDocumentation; import org.eclipse.microprofile.openapi.models.OpenAPI; import org.eclipse.microprofile.openapi.models.Operation; import org.eclipse.microprofile.openapi.models.PathItem; import org.eclipse.microprofile.openapi.models.PathItem.HttpMethod; import org.eclipse.microprofile.openapi.models.Paths; import org.eclipse.microprofile.openapi.models.Reference; import org.eclipse.microprofile.openapi.models.callbacks.Callback; import org.eclipse.microprofile.openapi.models.examples.Example; import org.eclipse.microprofile.openapi.models.headers.Header; import org.eclipse.microprofile.openapi.models.info.Contact; import org.eclipse.microprofile.openapi.models.info.Info; import org.eclipse.microprofile.openapi.models.info.License; import org.eclipse.microprofile.openapi.models.links.Link; import org.eclipse.microprofile.openapi.models.media.Content; import org.eclipse.microprofile.openapi.models.media.Discriminator; import org.eclipse.microprofile.openapi.models.media.Encoding; import org.eclipse.microprofile.openapi.models.media.MediaType; import org.eclipse.microprofile.openapi.models.media.Schema; import org.eclipse.microprofile.openapi.models.media.XML; import org.eclipse.microprofile.openapi.models.parameters.Parameter; import org.eclipse.microprofile.openapi.models.parameters.RequestBody; import org.eclipse.microprofile.openapi.models.responses.APIResponse; import org.eclipse.microprofile.openapi.models.responses.APIResponses; import org.eclipse.microprofile.openapi.models.security.OAuthFlow; import org.eclipse.microprofile.openapi.models.security.OAuthFlows; import org.eclipse.microprofile.openapi.models.security.SecurityRequirement; import org.eclipse.microprofile.openapi.models.security.SecurityScheme; import org.eclipse.microprofile.openapi.models.servers.Server; import org.eclipse.microprofile.openapi.models.servers.ServerVariable; import org.eclipse.microprofile.openapi.models.tags.Tag; import org.jboss.arquillian.container.test.api.Deployment; import org.jboss.arquillian.testng.Arquillian; import org.jboss.shrinkwrap.api.ShrinkWrap; import org.jboss.shrinkwrap.api.spec.WebArchive; import org.testng.annotations.Test; /** * This test covers construction of the OpenAPI model. It verifies that the implementation can create instances of all * of the Constructible interfaces and then invokes methods (including getters, setters and builders) on those instances * to verify that they behave correctly. */ public class ModelConstructionTest extends Arquillian { // assertSame and assertNotSame are broken in TestNG 7.4.0 - https://github.com/cbeust/testng/issues/2486 // These are the same methods, re-implemented using Hamcrest Matchers // Should be removed when TestNG 7.5.0 is released // -------------------------------- /** * Asserts that two objects refer to the same object. If they do not, an AssertionError, with the given message, is * thrown. * * @param actual * the actual value * @param expected * the expected value * @param message * the assertion error message */ public static void assertSame(Object actual, Object expected, String message) { assertThat(message, actual, sameInstance(expected)); } /** * Asserts that two objects do not refer to the same objects. If they do, an AssertionError, with the given message, * is thrown. * * @param actual * the actual value * @param expected * the expected value * @param message * the assertion error message */ public static void assertNotSame(Object actual, Object expected, String message) { assertThat(message, actual, not(sameInstance(expected))); } // -------------------------------- @Deployment public static WebArchive createDeployment() { return ShrinkWrap.create(WebArchive.class) .addPackages(true, "org.eclipse.microprofile.openapi.reader") .addAsManifestResource("microprofile-reader.properties", "microprofile-config.properties"); } // Container for matched getter, setter and builder methods static final class Property { private final String name; private final Class type; private Method getter; private Method setter; private Method builder; public Property(String name, Class type) { this.name = name; this.type = type; } public void addGetter(Method getter) { this.getter = getter; } public void addSetter(Method setter) { this.setter = setter; } public void addBuilder(Method builder) { this.builder = builder; } public String getName() { return name; } public Class getType() { return type; } public boolean hasBuilder() { return builder != null; } public Object invokeGetter(Object target) { try { return getter.invoke(target); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { fail("Invocation of getter method \"" + getter.getName() + "\" failed: " + e.getMessage(), e); throw new RuntimeException(e); } } public void invokeSetter(Object target, Object value) { try { setter.invoke(target, value); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { fail("Invocation of setter method \"" + setter.getName() + "\" failed: " + e.getMessage(), e); throw new RuntimeException(e); } } public Object invokeBuilder(Object target, Object value) { try { return builder.invoke(target, value); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { fail("Invocation of builder method \"" + builder.getName() + "\" failed: " + e.getMessage(), e); throw new RuntimeException(e); } } public boolean isCompatible(Class type) { return this.type == type; } public boolean isPrimitive() { return type.isPrimitive(); } public boolean isComplete() { return getter != null && setter != null; } } @Test public void componentsTest() { final Components c = processConstructible(Components.class); final String callbackKey = "myCallback"; final Callback callbackValue = createConstructibleInstance(Callback.class); checkSameObject(c, c.addCallback(callbackKey, callbackValue)); checkMapEntry(c.getCallbacks(), callbackKey, callbackValue); assertEquals(c.getCallbacks().size(), 1, "The map is expected to contain one entry."); c.removeCallback(callbackKey); assertEquals(c.getCallbacks().size(), 0, "The map is expected to be empty."); final String callbackKey2 = "myCallbackKey2"; final Callback callbackValue2 = createConstructibleInstance(Callback.class); c.setCallbacks(Collections.singletonMap(callbackKey2, callbackValue2)); checkMapEntry(c.getCallbacks(), callbackKey2, callbackValue2); assertEquals(c.getCallbacks().size(), 1, "The map is expected to contain one entry."); checkSameObject(c, c.addCallback(callbackKey, callbackValue)); checkMapEntry(c.getCallbacks(), callbackKey, callbackValue); assertEquals(c.getCallbacks().size(), 2, "The map is expected to contain two entries."); Callback otherCallbackValue = createConstructibleInstance(Callback.class); checkMapImmutable(c, Components::getCallbacks, "otherCallback", otherCallbackValue); checkNullValueInAdd(c::getCallbacks, c::addCallback, "someCallback", callbackValue); final String exampleKey = "myExample"; final Example exampleValue = createConstructibleInstance(Example.class); checkSameObject(c, c.addExample(exampleKey, exampleValue)); checkMapEntry(c.getExamples(), exampleKey, exampleValue); assertEquals(c.getExamples().size(), 1, "The map is expected to contain one entry."); c.removeExample(exampleKey); assertEquals(c.getExamples().size(), 0, "The map is expected to be empty."); Example otherExampleValue = createConstructibleInstance(Example.class); final String exampleKey2 = "myExampleKey2"; final Example exampleValue2 = createConstructibleInstance(Example.class); c.setExamples(Collections.singletonMap(exampleKey2, exampleValue2)); checkMapEntry(c.getExamples(), exampleKey2, exampleValue2); assertEquals(c.getExamples().size(), 1, "The map is expected to contain one entry."); checkSameObject(c, c.addExample(exampleKey, exampleValue)); checkMapEntry(c.getExamples(), exampleKey, exampleValue); assertEquals(c.getExamples().size(), 2, "The map is expected to contain two entries."); checkMapImmutable(c, Components::getExamples, "otherExample", otherExampleValue); checkNullValueInAdd(c::getExamples, c::addExample, "someExample", exampleValue); final String headerKey = "myHeader"; final Header headerValue = createConstructibleInstance(Header.class); checkSameObject(c, c.addHeader(headerKey, headerValue)); checkMapEntry(c.getHeaders(), headerKey, headerValue); assertEquals(c.getHeaders().size(), 1, "The map is expected to contain one entry."); c.removeHeader(headerKey); assertEquals(c.getHeaders().size(), 0, "The map is expected to be empty."); Header otherHeaderValue = createConstructibleInstance(Header.class); final String headerKey2 = "myHeaderKey2"; final Header headerValue2 = createConstructibleInstance(Header.class); c.setHeaders(Collections.singletonMap(headerKey2, headerValue2)); checkMapEntry(c.getHeaders(), headerKey2, headerValue2); assertEquals(c.getHeaders().size(), 1, "The map is expected to contain one entry."); checkSameObject(c, c.addHeader(headerKey, headerValue)); checkMapEntry(c.getHeaders(), headerKey, headerValue); assertEquals(c.getHeaders().size(), 2, "The map is expected to contain two entries."); checkMapImmutable(c, Components::getHeaders, "otherHeader", otherHeaderValue); checkNullValueInAdd(c::getHeaders, c::addHeader, "some-header", headerValue); final String linkKey = "myLink"; final Link linkValue = createConstructibleInstance(Link.class); checkSameObject(c, c.addLink(linkKey, linkValue)); checkMapEntry(c.getLinks(), linkKey, linkValue); assertEquals(c.getLinks().size(), 1, "The map is expected to contain one entry."); c.removeLink(linkKey); assertEquals(c.getLinks().size(), 0, "The map is expected to be empty."); Link otherLinkValue = createConstructibleInstance(Link.class); final String linkKey2 = "myLinkKey2"; final Link linkValue2 = createConstructibleInstance(Link.class); c.setLinks(Collections.singletonMap(linkKey2, linkValue2)); checkMapEntry(c.getLinks(), linkKey2, linkValue2); assertEquals(c.getLinks().size(), 1, "The map is expected to contain one entry."); checkSameObject(c, c.addLink(linkKey, linkValue)); checkMapEntry(c.getLinks(), linkKey, linkValue); assertEquals(c.getLinks().size(), 2, "The map is expected to contain two entries."); checkMapImmutable(c, Components::getLinks, "otherLink", otherLinkValue); checkNullValueInAdd(c::getLinks, c::addLink, "someLink", linkValue); final String parameterKey = "myParameter"; final Parameter parameterValue = createConstructibleInstance(Parameter.class); checkSameObject(c, c.addParameter(parameterKey, parameterValue)); checkMapEntry(c.getParameters(), parameterKey, parameterValue); assertEquals(c.getParameters().size(), 1, "The list is expected to contain one entry."); c.removeParameter(parameterKey); assertEquals(c.getParameters().size(), 0, "The list is expected to be empty."); checkNullValueInAdd(c::getParameters, c::addParameter, "someParameter", parameterValue); final String parameterKey2 = "myParameterKey2"; final Parameter parameterValue2 = createConstructibleInstance(Parameter.class); c.setParameters(Collections.singletonMap(parameterKey2, parameterValue2)); checkMapEntry(c.getParameters(), parameterKey2, parameterValue2); assertEquals(c.getParameters().size(), 1, "The map is expected to contain one entry."); checkSameObject(c, c.addParameter(parameterKey, parameterValue)); checkMapEntry(c.getParameters(), parameterKey, parameterValue); assertEquals(c.getParameters().size(), 2, "The map is expected to contain two entries."); Parameter otherParameterValue = createConstructibleInstance(Parameter.class); checkMapImmutable(c, Components::getParameters, "otherParameter", otherParameterValue); final String requestBodyKey = "myRequestBody"; final RequestBody requestBodyValue = createConstructibleInstance(RequestBody.class); checkSameObject(c, c.addRequestBody(requestBodyKey, requestBodyValue)); checkMapEntry(c.getRequestBodies(), requestBodyKey, requestBodyValue); assertEquals(c.getRequestBodies().size(), 1, "The map is expected to contain one entry."); c.removeRequestBody(requestBodyKey); assertEquals(c.getRequestBodies().size(), 0, "The map is expected to be empty."); final String requestBodyKey2 = "myRequestBodyKey2"; final RequestBody requestBodyValue2 = createConstructibleInstance(RequestBody.class); c.setRequestBodies(Collections.singletonMap(requestBodyKey2, requestBodyValue2)); checkMapEntry(c.getRequestBodies(), requestBodyKey2, requestBodyValue2); assertEquals(c.getRequestBodies().size(), 1, "The map is expected to contain one entry."); checkSameObject(c, c.addRequestBody(requestBodyKey, requestBodyValue)); checkMapEntry(c.getRequestBodies(), requestBodyKey, requestBodyValue); assertEquals(c.getRequestBodies().size(), 2, "The map is expected to contain two entries."); RequestBody otherRequestBodyValue = createConstructibleInstance(RequestBody.class); checkMapImmutable(c, Components::getRequestBodies, "otherRequestBody", otherRequestBodyValue); checkNullValueInAdd(c::getRequestBodies, c::addRequestBody, "someRequestBody", requestBodyValue); final String responseKey = "myResponse"; final APIResponse responseValue = createConstructibleInstance(APIResponse.class); checkSameObject(c, c.addResponse(responseKey, responseValue)); checkMapEntry(c.getResponses(), responseKey, responseValue); assertEquals(c.getResponses().size(), 1, "The map is expected to contain one entry."); c.removeResponse(responseKey); assertEquals(c.getResponses().size(), 0, "The map is expected to be empty."); final String responseKey2 = "myResponseKey2"; final APIResponse responseValue2 = createConstructibleInstance(APIResponse.class); c.setResponses(Collections.singletonMap(responseKey2, responseValue2)); checkMapEntry(c.getResponses(), responseKey2, responseValue2); assertEquals(c.getResponses().size(), 1, "The map is expected to contain one entry."); checkSameObject(c, c.addResponse(responseKey, responseValue)); checkMapEntry(c.getResponses(), responseKey, responseValue); assertEquals(c.getResponses().size(), 2, "The map is expected to contain two entries."); APIResponse otherAPIResponseValue = createConstructibleInstance(APIResponse.class); checkMapImmutable(c, Components::getResponses, "otherAPIResponse", otherAPIResponseValue); checkNullValueInAdd(c::getResponses, c::addResponse, "someResponse", responseValue); final String schemaKey = "mySchema"; final Schema schemaValue = createConstructibleInstance(Schema.class); checkSameObject(c, c.addSchema(schemaKey, schemaValue)); checkMapEntry(c.getSchemas(), schemaKey, schemaValue); assertEquals(c.getSchemas().size(), 1, "The map is expected to contain one entry."); c.removeSchema(schemaKey); assertEquals(c.getSchemas().size(), 0, "The map is expected to be empty."); final String schemaKey2 = "mySchemaKey2"; final Schema schemaValue2 = createConstructibleInstance(Schema.class); c.setSchemas(Collections.singletonMap(schemaKey2, schemaValue2)); checkMapEntry(c.getSchemas(), schemaKey2, schemaValue2); assertEquals(c.getSchemas().size(), 1, "The map is expected to contain one entry."); checkSameObject(c, c.addSchema(schemaKey, schemaValue)); checkMapEntry(c.getSchemas(), schemaKey, schemaValue); assertEquals(c.getSchemas().size(), 2, "The map is expected to contain two entries."); Schema otherSchemaValue = createConstructibleInstance(Schema.class); checkMapImmutable(c, Components::getSchemas, "otherSchema", otherSchemaValue); checkNullValueInAdd(c::getSchemas, c::addSchema, "someSchema", schemaValue); final String securitySchemeKey = "mySecurityScheme"; final SecurityScheme securitySchemeValue = createConstructibleInstance(SecurityScheme.class); checkSameObject(c, c.addSecurityScheme(securitySchemeKey, securitySchemeValue)); checkMapEntry(c.getSecuritySchemes(), securitySchemeKey, securitySchemeValue); assertEquals(c.getSecuritySchemes().size(), 1, "The map is expected to contain one entry."); c.removeSecurityScheme(securitySchemeKey); assertEquals(c.getSecuritySchemes().size(), 0, "The map is expected to be empty."); final String securitySchemeKey2 = "mySecuritySchemeKey2"; final SecurityScheme securitySchemeValue2 = createConstructibleInstance(SecurityScheme.class); c.setSecuritySchemes(Collections.singletonMap(securitySchemeKey2, securitySchemeValue2)); checkMapEntry(c.getSecuritySchemes(), securitySchemeKey2, securitySchemeValue2); assertEquals(c.getSecuritySchemes().size(), 1, "The map is expected to contain one entry."); checkSameObject(c, c.addSecurityScheme(securitySchemeKey, securitySchemeValue)); checkMapEntry(c.getSecuritySchemes(), securitySchemeKey, securitySchemeValue); assertEquals(c.getSecuritySchemes().size(), 2, "The map is expected to contain two entries."); SecurityScheme otherSecuritySchemeValue = createConstructibleInstance(SecurityScheme.class); checkMapImmutable(c, Components::getSecuritySchemes, "otherSecurityScheme", otherSecuritySchemeValue); checkNullValueInAdd(c::getSecuritySchemes, c::addSecurityScheme, "someSecurityScheme", securitySchemeValue); final String pathItemKey = "myPathItem"; final PathItem pathItemValue = createConstructibleInstance(PathItem.class); checkSameObject(c, c.addPathItem(pathItemKey, pathItemValue)); checkMapEntry(c.getPathItems(), pathItemKey, pathItemValue); assertEquals(c.getPathItems().size(), 1, "The map is expected to contain one entry."); c.removePathItem(pathItemKey); assertEquals(c.getPathItems().size(), 0, "The map is expected to be empty."); final String pathItemKey2 = "myPathItem2"; final PathItem pathItemValue2 = createConstructibleInstance(PathItem.class); c.setPathItems(Collections.singletonMap(pathItemKey2, pathItemValue2)); checkMapEntry(c.getPathItems(), pathItemKey2, pathItemValue2); assertEquals(c.getPathItems().size(), 1, "The map is expected to contain one entry."); checkSameObject(c, c.addPathItem(pathItemKey, pathItemValue)); checkMapEntry(c.getPathItems(), pathItemKey, pathItemValue); assertEquals(c.getPathItems().size(), 2, "The map is expected to contain two entries."); PathItem otherPathItemValue = createConstructibleInstance(PathItem.class); checkMapImmutable(c, Components::getPathItems, "otherPathItem", otherPathItemValue); checkNullValueInAdd(c::getPathItems, c::addPathItem, "somePathItem", pathItemValue); } @Test public void externalDocumentationTest() { processConstructible(ExternalDocumentation.class); } @Test public void openAPITest() { final OpenAPI o = processConstructible(OpenAPI.class); final SecurityRequirement sr = createConstructibleInstance(SecurityRequirement.class); sr.addScheme("BasicAuth"); checkSameObject(o, o.addSecurityRequirement(sr)); checkListEntry(o.getSecurity(), sr); assertEquals(o.getSecurity().size(), 1, "The list is expected to contain one entry."); o.removeSecurityRequirement(sr); assertEquals(o.getSecurity().size(), 0, "The list is expected to be empty."); final SecurityRequirement sr2 = createConstructibleInstance(SecurityRequirement.class); sr2.addScheme("OAuth2", "read"); o.setSecurity(Collections.singletonList(sr2)); assertEquals(o.getSecurity().size(), 1, "The list is expected to contain one entry."); checkListEntry(o.getSecurity(), sr2); checkSameObject(o, o.addSecurityRequirement(sr)); assertEquals(o.getSecurity().size(), 2, "The list is expected to contain two entries."); checkListEntry(o.getSecurity(), sr); SecurityRequirement otherSecurityRequirementValue = createConstructibleInstance(SecurityRequirement.class); otherSecurityRequirementValue.addScheme("OAuth2", "admin"); checkListImmutable(o, OpenAPI::getSecurity, otherSecurityRequirementValue); final Server s = createConstructibleInstance(Server.class); checkSameObject(o, o.addServer(s)); checkListEntry(o.getServers(), s); assertEquals(o.getServers().size(), 1, "The list is expected to contain one entry."); o.removeServer(s); assertEquals(o.getServers().size(), 0, "The list is expected to be empty."); final Server s2 = createConstructibleInstance(Server.class); o.setServers(Collections.singletonList(s2)); assertEquals(o.getServers().size(), 1, "The list is expected to contain one entry."); checkListEntry(o.getServers(), s2); checkSameObject(o, o.addServer(s)); assertEquals(o.getSecurity().size(), 2, "The list is expected to contain two entries."); checkListEntry(o.getServers(), s); Server otherServer = createConstructibleInstance(Server.class); checkListImmutable(o, OpenAPI::getServers, otherServer); final Tag t = createConstructibleInstance(Tag.class); checkSameObject(o, o.addTag(t)); checkListEntry(o.getTags(), t); assertEquals(o.getTags().size(), 1, "The list is expected to contain one entry."); o.removeTag(t); assertEquals(o.getTags().size(), 0, "The list is expected to be empty."); final Tag t2 = createConstructibleInstance(Tag.class); o.setTags(Collections.singletonList(t2)); assertEquals(o.getTags().size(), 1, "The list is expected to contain one entry."); checkListEntry(o.getTags(), t2); checkSameObject(o, o.addTag(t)); assertEquals(o.getTags().size(), 2, "The list is expected to contain two entries."); checkListEntry(o.getTags(), t); Tag otherTag = createConstructibleInstance(Tag.class); checkListImmutable(o, OpenAPI::getTags, otherTag); } @Test public void operationTest() { final Operation o = processConstructible(Operation.class); final Parameter p = createConstructibleInstance(Parameter.class); checkSameObject(o, o.addParameter(p)); checkListEntry(o.getParameters(), p); assertEquals(o.getParameters().size(), 1, "The list is expected to contain one entry."); o.removeParameter(p); assertEquals(o.getParameters().size(), 0, "The list is expected to be empty."); final Parameter p2 = createConstructibleInstance(Parameter.class); o.setParameters(Collections.singletonList(p2)); assertEquals(o.getParameters().size(), 1, "The list is expected to contain one entry."); checkListEntry(o.getParameters(), p2); checkSameObject(o, o.addParameter(p)); assertEquals(o.getParameters().size(), 2, "The list is expected to contain two entries."); checkListEntry(o.getParameters(), p); Parameter otherParameter = createConstructibleInstance(Parameter.class); checkListImmutable(o, Operation::getParameters, otherParameter); final SecurityRequirement sr = createConstructibleInstance(SecurityRequirement.class); sr.addScheme("OAuth2", Arrays.asList("read", "write")); checkSameObject(o, o.addSecurityRequirement(sr)); checkListEntry(o.getSecurity(), sr); assertEquals(o.getSecurity().size(), 1, "The list is expected to contain one entry."); o.removeSecurityRequirement(sr); assertEquals(o.getSecurity().size(), 0, "The list is expected to be empty."); final SecurityRequirement sr2 = createConstructibleInstance(SecurityRequirement.class); sr2.addScheme("ApiKey"); o.setSecurity(Collections.singletonList(sr2)); assertEquals(o.getSecurity().size(), 1, "The list is expected to contain one entry."); checkListEntry(o.getSecurity(), sr2); checkSameObject(o, o.addSecurityRequirement(sr)); assertEquals(o.getSecurity().size(), 2, "The list is expected to contain two entries."); checkListEntry(o.getSecurity(), sr); SecurityRequirement otherSecurityRequirement = createConstructibleInstance(SecurityRequirement.class); otherSecurityRequirement.addScheme("BasicAuth"); checkListImmutable(o, Operation::getSecurity, otherSecurityRequirement); final Server s = createConstructibleInstance(Server.class); checkSameObject(o, o.addServer(s)); checkListEntry(o.getServers(), s); assertEquals(o.getServers().size(), 1, "The list is expected to contain one entry."); o.removeServer(s); assertEquals(o.getServers().size(), 0, "The list is expected to be empty."); final Server s2 = createConstructibleInstance(Server.class); o.setServers(Collections.singletonList(s2)); assertEquals(o.getServers().size(), 1, "The list is expected to contain one entry."); checkListEntry(o.getServers(), s2); checkSameObject(o, o.addServer(s)); assertEquals(o.getServers().size(), 2, "The list is expected to contain two entries."); checkListEntry(o.getServers(), s); Server otherServer = createConstructibleInstance(Server.class); checkListImmutable(o, Operation::getServers, otherServer); final String tag = new String("myTag"); checkSameObject(o, o.addTag(tag)); checkListEntry(o.getTags(), tag); assertEquals(o.getTags().size(), 1, "The list is expected to contain one entry."); o.removeTag(tag); assertEquals(o.getTags().size(), 0, "The list is expected to be empty."); final String tag2 = new String("myTag2"); o.setTags(Collections.singletonList(tag2)); assertEquals(o.getTags().size(), 1, "The list is expected to contain one entry."); checkListEntry(o.getTags(), tag2); checkSameObject(o, o.addTag(tag)); assertEquals(o.getTags().size(), 2, "The list is expected to contain two entries."); checkListEntry(o.getTags(), tag); String otherTag = new String("otherTag"); checkListImmutable(o, Operation::getTags, otherTag); final String callbackKey = "myCallback"; final Callback callbackValue = createConstructibleInstance(Callback.class); checkSameObject(o, o.addCallback(callbackKey, callbackValue)); checkMapEntry(o.getCallbacks(), callbackKey, callbackValue); assertEquals(o.getCallbacks().size(), 1, "The map is expected to contain one entry."); o.removeCallback(callbackKey); assertEquals(o.getCallbacks().size(), 0, "The map is expected to be empty."); final String callbackKey2 = "myCallbackKey2"; final Callback callbackValue2 = createConstructibleInstance(Callback.class); o.setCallbacks(Collections.singletonMap(callbackKey2, callbackValue2)); checkMapEntry(o.getCallbacks(), callbackKey2, callbackValue2); assertEquals(o.getCallbacks().size(), 1, "The map is expected to contain one entry."); checkSameObject(o, o.addCallback(callbackKey, callbackValue)); checkMapEntry(o.getCallbacks(), callbackKey, callbackValue); assertEquals(o.getCallbacks().size(), 2, "The map is expected to contain two entries."); Callback otherCallback = createConstructibleInstance(Callback.class); checkMapImmutable(o, Operation::getCallbacks, "otherCallback", otherCallback); checkNullValueInAdd(o::getCallbacks, o::addCallback, "someCallback", callbackValue); } @Test public void pathItemTest() { final PathItem pi = processConstructible(PathItem.class); final Parameter p = createConstructibleInstance(Parameter.class); checkSameObject(pi, pi.addParameter(p)); checkListEntry(pi.getParameters(), p); assertEquals(pi.getParameters().size(), 1, "The list is expected to contain one entry."); pi.removeParameter(p); assertEquals(pi.getParameters().size(), 0, "The list is expected to be empty."); final Parameter p2 = createConstructibleInstance(Parameter.class); pi.setParameters(Collections.singletonList(p2)); assertEquals(pi.getParameters().size(), 1, "The list is expected to contain one entry."); checkListEntry(pi.getParameters(), p2); checkSameObject(pi, pi.addParameter(p)); assertEquals(pi.getParameters().size(), 2, "The list is expected to contain two entries."); checkListEntry(pi.getParameters(), p); Parameter otherParameter = createConstructibleInstance(Parameter.class); checkListImmutable(pi, PathItem::getParameters, otherParameter); final Server s = createConstructibleInstance(Server.class); checkSameObject(pi, pi.addServer(s)); checkListEntry(pi.getServers(), s); assertEquals(pi.getServers().size(), 1, "The list is expected to contain one entry."); pi.removeServer(s); assertEquals(pi.getServers().size(), 0, "The list is expected to be empty."); final Server s2 = createConstructibleInstance(Server.class); pi.setServers(Collections.singletonList(s2)); assertEquals(pi.getServers().size(), 1, "The list is expected to contain one entry."); checkListEntry(pi.getServers(), s2); checkSameObject(pi, pi.addServer(s)); assertEquals(pi.getServers().size(), 2, "The list is expected to contain two entries."); checkListEntry(pi.getServers(), s); Server otherServer = createConstructibleInstance(Server.class); checkListImmutable(pi, PathItem::getServers, otherServer); final Operation o1 = createConstructibleInstance(Operation.class); checkSameObject(pi, pi.GET(o1)); checkSameObject(o1, pi.getGET()); final Operation o2 = createConstructibleInstance(Operation.class); checkSameObject(pi, pi.PUT(o2)); checkSameObject(o2, pi.getPUT()); final Operation o3 = createConstructibleInstance(Operation.class); checkSameObject(pi, pi.POST(o3)); checkSameObject(o3, pi.getPOST()); final Operation o4 = createConstructibleInstance(Operation.class); checkSameObject(pi, pi.DELETE(o4)); checkSameObject(o4, pi.getDELETE()); final Operation o5 = createConstructibleInstance(Operation.class); checkSameObject(pi, pi.OPTIONS(o5)); checkSameObject(o5, pi.getOPTIONS()); final Operation o6 = createConstructibleInstance(Operation.class); checkSameObject(pi, pi.HEAD(o6)); checkSameObject(o6, pi.getHEAD()); final Operation o7 = createConstructibleInstance(Operation.class); checkSameObject(pi, pi.PATCH(o7)); checkSameObject(o7, pi.getPATCH()); final Operation o8 = createConstructibleInstance(Operation.class); checkSameObject(pi, pi.TRACE(o8)); checkSameObject(o8, pi.getTRACE()); checkMapEntry(pi.getOperations(), PathItem.HttpMethod.GET, o1); checkMapEntry(pi.getOperations(), PathItem.HttpMethod.PUT, o2); checkMapEntry(pi.getOperations(), PathItem.HttpMethod.POST, o3); checkMapEntry(pi.getOperations(), PathItem.HttpMethod.DELETE, o4); checkMapEntry(pi.getOperations(), PathItem.HttpMethod.OPTIONS, o5); checkMapEntry(pi.getOperations(), PathItem.HttpMethod.HEAD, o6); checkMapEntry(pi.getOperations(), PathItem.HttpMethod.PATCH, o7); checkMapEntry(pi.getOperations(), PathItem.HttpMethod.TRACE, o8); // test with GET: PathItem pathItemGET = createConstructibleInstance(PathItem.class); Operation operationGET = createConstructibleInstance(Operation.class).description("This is some GET op"); pathItemGET.setOperation(HttpMethod.GET, operationGET); checkSameObject(pathItemGET.getGET(), operationGET); pathItemGET.setOperation(HttpMethod.GET, null); assertNull(pathItemGET.getGET()); // test with POST: PathItem pathItemPOST = createConstructibleInstance(PathItem.class); Operation operationPOST = createConstructibleInstance(Operation.class).description("This is some POST op"); pathItemPOST.setOperation(HttpMethod.POST, operationPOST); checkSameObject(pathItemPOST.getPOST(), operationPOST); pathItemPOST.setOperation(HttpMethod.POST, null); assertNull(pathItemPOST.getPOST()); // test with PUT: PathItem pathItemPUT = createConstructibleInstance(PathItem.class); Operation operationPUT = createConstructibleInstance(Operation.class).description("This is some PUT op"); pathItemPUT.setOperation(HttpMethod.PUT, operationPUT); checkSameObject(pathItemPUT.getPUT(), operationPUT); pathItemPUT.setOperation(HttpMethod.PUT, null); assertNull(pathItemPUT.getPUT()); // test with PATCH: PathItem pathItemPATCH = createConstructibleInstance(PathItem.class); Operation operationPATCH = createConstructibleInstance(Operation.class).description("This is some PATCH op"); pathItemPATCH.setOperation(HttpMethod.PATCH, operationPATCH); checkSameObject(pathItemPATCH.getPATCH(), operationPATCH); pathItemPATCH.setOperation(HttpMethod.PATCH, null); assertNull(pathItemPATCH.getPATCH()); // test with DELETE: PathItem pathItemDELETE = createConstructibleInstance(PathItem.class); Operation operationDELETE = createConstructibleInstance(Operation.class).description("This is some DELETE op"); pathItemDELETE.setOperation(HttpMethod.DELETE, operationDELETE); checkSameObject(pathItemDELETE.getDELETE(), operationDELETE); pathItemDELETE.setOperation(HttpMethod.DELETE, null); assertNull(pathItemDELETE.getDELETE()); // test with HEAD: PathItem pathItemHEAD = createConstructibleInstance(PathItem.class); Operation operationHEAD = createConstructibleInstance(Operation.class).description("This is some HEAD op"); pathItemHEAD.setOperation(HttpMethod.HEAD, operationHEAD); checkSameObject(pathItemHEAD.getHEAD(), operationHEAD); pathItemHEAD.setOperation(HttpMethod.HEAD, null); assertNull(pathItemHEAD.getHEAD()); // test with OPTIONS: PathItem pathItemOPTIONS = createConstructibleInstance(PathItem.class); Operation operationOPTIONS = createConstructibleInstance(Operation.class).description("This is some OPTIONS op"); pathItemOPTIONS.setOperation(HttpMethod.OPTIONS, operationOPTIONS); checkSameObject(pathItemOPTIONS.getOPTIONS(), operationOPTIONS); pathItemOPTIONS.setOperation(HttpMethod.OPTIONS, null); assertNull(pathItemOPTIONS.getOPTIONS()); // test with TRACE: PathItem pathItemTRACE = createConstructibleInstance(PathItem.class); Operation operationTRACE = createConstructibleInstance(Operation.class).description("This is some TRACE op"); pathItemTRACE.setOperation(HttpMethod.TRACE, operationTRACE); checkSameObject(pathItemTRACE.getTRACE(), operationTRACE); pathItemTRACE.setOperation(HttpMethod.TRACE, null); assertNull(pathItemTRACE.getTRACE()); } @Test public void pathsTest() { final Paths p = processConstructible(Paths.class); final String pathItemKey = "/myPathItem"; final PathItem pathItemValue = createConstructibleInstance(PathItem.class); p.setPathItems(Collections.singletonMap(pathItemKey, pathItemValue)); assertTrue(p.hasPathItem(pathItemKey), pathItemKey + " is present in the map"); assertEquals(p.getPathItems().size(), 1, "The map is expected to contain one entry."); assertSame(p.getPathItem(pathItemKey), pathItemValue, "The value associated with the key: " + pathItemKey + " is expected to be the same one that was added."); checkMapEntry(p.getPathItems(), pathItemKey, pathItemValue); final String pathItemKey2 = "/myPathItem2"; assertFalse(p.hasPathItem(pathItemKey2), pathItemKey2 + " is absent in the map"); final PathItem pathItemValue2 = createConstructibleInstance(PathItem.class); checkSameObject(p, p.addPathItem(pathItemKey2, pathItemValue2)); assertTrue(p.hasPathItem(pathItemKey2), pathItemKey2 + " is present in the map"); assertEquals(p.getPathItems().size(), 2, "The map is expected to contain two entries."); assertSame(p.getPathItem(pathItemKey2), pathItemValue2, "The value associated with the key: " + pathItemKey2 + " is expected to be the same one that was added."); checkMapEntry(p.getPathItems(), pathItemKey2, pathItemValue2); p.removePathItem(pathItemKey); assertFalse(p.hasPathItem(pathItemKey), pathItemKey + " is absent in the map"); assertEquals(p.getPathItems().size(), 1, "The map is expected to contain one entry."); p.removePathItem(pathItemKey2); assertFalse(p.hasPathItem(pathItemKey2), pathItemKey + " is absent in the map"); assertEquals(p.getPathItems().size(), 0, "The map is expected to contain 0 entries."); final PathItem otherValue = createConstructibleInstance(PathItem.class); checkMapImmutable(p, Paths::getPathItems, "/otherPathItem", otherValue); checkNullValueInAdd(p::getPathItems, p::addPathItem, "/other", otherValue); } @Test public void callbackTest() { final Callback c = processConstructible(Callback.class); final String pathItemKey = "myPathItem"; final PathItem pathItemValue = createConstructibleInstance(PathItem.class); c.setPathItems(Collections.singletonMap(pathItemKey, pathItemValue)); assertTrue(c.hasPathItem(pathItemKey), pathItemKey + " is present in the map"); assertEquals(c.getPathItems().size(), 1, "The map is expected to contain one entry."); assertSame(c.getPathItem(pathItemKey), pathItemValue, "The value associated with the key: " + pathItemKey + " is expected to be the same one that was added."); checkMapEntry(c.getPathItems(), pathItemKey, pathItemValue); final String pathItemKey2 = "myPathItem2"; assertFalse(c.hasPathItem(pathItemKey2), pathItemKey2 + " is absent in the map"); final PathItem pathItemValue2 = createConstructibleInstance(PathItem.class); checkSameObject(c, c.addPathItem(pathItemKey2, pathItemValue2)); assertTrue(c.hasPathItem(pathItemKey2), pathItemKey2 + " is present in the map"); assertEquals(c.getPathItems().size(), 2, "The map is expected to contain two entries."); assertSame(c.getPathItem(pathItemKey2), pathItemValue2, "The value associated with the key: " + pathItemKey2 + " is expected to be the same one that was added."); checkMapEntry(c.getPathItems(), pathItemKey2, pathItemValue2); c.removePathItem(pathItemKey); assertFalse(c.hasPathItem(pathItemKey), pathItemKey + " is absent in the map"); assertEquals(c.getPathItems().size(), 1, "The map is expected to contain one entry."); c.removePathItem(pathItemKey2); assertFalse(c.hasPathItem(pathItemKey2), pathItemKey + " is absent in the map"); assertEquals(c.getPathItems().size(), 0, "The map is expected to contain 0 entries."); final PathItem otherValue = createConstructibleInstance(PathItem.class); checkMapImmutable(c, Callback::getPathItems, "otherPathItem", otherValue); checkNullValueInAdd(c::getPathItems, c::addPathItem, "other", otherValue); } @Test public void exampleTest() { processConstructible(Example.class); } @Test public void headerTest() { final Header h = processConstructible(Header.class); final String exampleKey = "myExample"; final Example exampleValue = createConstructibleInstance(Example.class); checkSameObject(h, h.addExample(exampleKey, exampleValue)); checkMapEntry(h.getExamples(), exampleKey, exampleValue); assertEquals(h.getExamples().size(), 1, "The map is expected to contain one entry."); h.removeExample(exampleKey); assertEquals(h.getExamples().size(), 0, "The map is expected to be empty."); final String exampleKey2 = "myExampleKey2"; final Example exampleValue2 = createConstructibleInstance(Example.class); h.setExamples(Collections.singletonMap(exampleKey2, exampleValue2)); checkMapEntry(h.getExamples(), exampleKey2, exampleValue2); assertEquals(h.getExamples().size(), 1, "The map is expected to contain one entry."); checkSameObject(h, h.addExample(exampleKey, exampleValue)); checkMapEntry(h.getExamples(), exampleKey, exampleValue); assertEquals(h.getExamples().size(), 2, "The map is expected to contain two entries."); Example otherExampleValue = createConstructibleInstance(Example.class); checkMapImmutable(h, Header::getExamples, "otherExample", otherExampleValue); checkNullValueInAdd(h::getExamples, h::addExample, "otherExample", exampleValue); } @Test public void contactTest() { processConstructible(Contact.class); } @Test public void infoTest() { processConstructible(Info.class); } @Test public void licenseTest() { processConstructible(License.class); } @Test public void linkTest() { final Link l = processConstructible(Link.class); final String parameterKey = "myParameter"; final String parameterValue = "$request.parameter.id"; checkSameObject(l, l.addParameter(parameterKey, parameterValue)); checkMapEntry(l.getParameters(), parameterKey, parameterValue); assertEquals(l.getParameters().size(), 1, "The map is expected to contain one entry."); l.removeParameter(parameterKey); assertEquals(l.getParameters().size(), 0, "The map is expected to be empty."); final String parameterKey2 = "myParameterKey2"; final String parameterValue2 = "$request.parameter2.id"; l.setParameters(Collections.singletonMap(parameterKey2, parameterValue2)); checkMapEntry(l.getParameters(), parameterKey2, parameterValue2); assertEquals(l.getParameters().size(), 1, "The map is expected to contain one entry."); checkSameObject(l, l.addParameter(parameterKey, parameterValue)); checkMapEntry(l.getParameters(), parameterKey, parameterValue); assertEquals(l.getParameters().size(), 2, "The map is expected to contain two entries."); Object otherExampleValue = new Object(); checkMapImmutable(l, Link::getParameters, "otherParameter", otherExampleValue); checkNullValueInAdd(l::getParameters, l::addParameter, "otherParameter", parameterValue); } @Test public void contentTest() { final Content c = processConstructible(Content.class); final String mediaTypeKey = "application/json"; final MediaType mediaTypeValue = createConstructibleInstance(MediaType.class); c.setMediaTypes(Collections.singletonMap(mediaTypeKey, mediaTypeValue)); assertTrue(c.hasMediaType(mediaTypeKey), mediaTypeKey + " is present in the map"); assertEquals(c.getMediaTypes().size(), 1, "The map is expected to contain one entry."); assertSame(c.getMediaType(mediaTypeKey), mediaTypeValue, "The value associated with the key: " + mediaTypeKey + " is expected to be the same one that was added."); checkMapEntry(c.getMediaTypes(), mediaTypeKey, mediaTypeValue); final String mediaTypeKey2 = "*/*"; assertFalse(c.hasMediaType(mediaTypeKey2), mediaTypeKey2 + " is absent in the map"); final MediaType mediaTypeValue2 = createConstructibleInstance(MediaType.class); checkSameObject(c, c.addMediaType(mediaTypeKey2, mediaTypeValue2)); assertTrue(c.hasMediaType(mediaTypeKey2), mediaTypeKey2 + " is present in the map"); assertEquals(c.getMediaTypes().size(), 2, "The map is expected to contain two entries."); assertSame(c.getMediaType(mediaTypeKey2), mediaTypeValue2, "The value associated with the key: " + mediaTypeKey2 + " is expected to be the same one that was added."); checkMapEntry(c.getMediaTypes(), mediaTypeKey2, mediaTypeValue2); c.removeMediaType(mediaTypeKey); assertFalse(c.hasMediaType(mediaTypeKey), mediaTypeKey + " is absent in the map"); assertEquals(c.getMediaTypes().size(), 1, "The map is expected to contain one entry."); c.removeMediaType(mediaTypeKey2); assertFalse(c.hasMediaType(mediaTypeKey2), mediaTypeKey + " is absent in the map"); assertEquals(c.getMediaTypes().size(), 0, "The map is expected to contain 0 entries."); final MediaType otherValue = createConstructibleInstance(MediaType.class); checkMapImmutable(c, Content::getMediaTypes, "application/txt", otherValue); } @Test public void discriminatorTest() { final Discriminator d = processConstructible(Discriminator.class); final String key = "myKey"; final String value = new String("myValue"); checkSameObject(d, d.addMapping(key, value)); checkMapEntry(d.getMapping(), key, value); assertEquals(d.getMapping().size(), 1, "The map is expected to contain one entry."); d.removeMapping(key); assertEquals(d.getMapping().size(), 0, "The map is expected to be empty."); final String key2 = "myCallbackKey2"; final String value2 = new String("myValue2"); d.setMapping(Collections.singletonMap(key2, value2)); checkMapEntry(d.getMapping(), key2, value2); assertEquals(d.getMapping().size(), 1, "The map is expected to contain one entry."); checkSameObject(d, d.addMapping(key, value)); checkMapEntry(d.getMapping(), key, value); assertEquals(d.getMapping().size(), 2, "The map is expected to contain two entries."); final String otherValue = new String("otherValue"); checkMapImmutable(d, Discriminator::getMapping, "otherValue", otherValue); checkNullValueInAdd(d::getMapping, d::addMapping, "otherKey", value); } @Test public void encodingTest() { Encoding e = processConstructible(Encoding.class); final String headerKey = "myHeaderKey"; final Header headerValue = createConstructibleInstance(Header.class); checkSameObject(e, e.addHeader(headerKey, headerValue)); checkMapEntry(e.getHeaders(), headerKey, headerValue); assertEquals(e.getHeaders().size(), 1, "The map is expected to contain one entry."); e.removeHeader(headerKey); assertEquals(e.getHeaders().size(), 0, "The map is expected to be empty."); final String headerKey2 = "myHeaderKey2"; final Header headerValue2 = createConstructibleInstance(Header.class); e.setHeaders(Collections.singletonMap(headerKey2, headerValue2)); checkMapEntry(e.getHeaders(), headerKey2, headerValue2); assertEquals(e.getHeaders().size(), 1, "The map is expected to contain one entry."); checkSameObject(e, e.addHeader(headerKey, headerValue)); checkMapEntry(e.getHeaders(), headerKey, headerValue); assertEquals(e.getHeaders().size(), 2, "The map is expected to contain two entries."); final Header otherHeaderValue = createConstructibleInstance(Header.class); checkMapImmutable(e, Encoding::getHeaders, "otherHeader", otherHeaderValue); checkNullValueInAdd(e::getHeaders, e::addHeader, "otherHeaderKey", headerValue); } @Test public void mediaTypeTest() { final MediaType mt = processConstructible(MediaType.class); final String encodingKey = "myEncoding"; final Encoding encodingValue = createConstructibleInstance(Encoding.class); checkSameObject(mt, mt.addEncoding(encodingKey, encodingValue)); checkMapEntry(mt.getEncoding(), encodingKey, encodingValue); assertEquals(mt.getEncoding().size(), 1, "The map is expected to contain one entry."); mt.removeEncoding(encodingKey); assertEquals(mt.getEncoding().size(), 0, "The map is expected to be empty."); final String encodingKey2 = "myEncodingKey2"; final Encoding encodingValue2 = createConstructibleInstance(Encoding.class); mt.setEncoding(Collections.singletonMap(encodingKey2, encodingValue2)); checkMapEntry(mt.getEncoding(), encodingKey2, encodingValue2); assertEquals(mt.getEncoding().size(), 1, "The map is expected to contain one entry."); checkSameObject(mt, mt.addEncoding(encodingKey, encodingValue)); checkMapEntry(mt.getEncoding(), encodingKey, encodingValue); assertEquals(mt.getEncoding().size(), 2, "The map is expected to contain two entries."); Encoding otherEncodingValue = createConstructibleInstance(Encoding.class); checkMapImmutable(mt, MediaType::getEncoding, "otherEncoding", otherEncodingValue); checkNullValueInAdd(mt::getEncoding, mt::addEncoding, "otherEncoding", encodingValue); final String exampleKey = "myExample"; final Example exampleValue = createConstructibleInstance(Example.class); checkSameObject(mt, mt.addExample(exampleKey, exampleValue)); checkMapEntry(mt.getExamples(), exampleKey, exampleValue); assertEquals(mt.getExamples().size(), 1, "The map is expected to contain one entry."); mt.removeExample(exampleKey); assertEquals(mt.getExamples().size(), 0, "The map is expected to be empty."); final String exampleKey2 = "myExampleKey2"; final Example exampleValue2 = createConstructibleInstance(Example.class); mt.setExamples(Collections.singletonMap(exampleKey2, exampleValue2)); checkMapEntry(mt.getExamples(), exampleKey2, exampleValue2); assertEquals(mt.getExamples().size(), 1, "The map is expected to contain one entry."); checkSameObject(mt, mt.addExample(exampleKey, exampleValue)); checkMapEntry(mt.getExamples(), exampleKey, exampleValue); assertEquals(mt.getExamples().size(), 2, "The map is expected to contain two entries."); Example otherExampleValue = createConstructibleInstance(Example.class); checkMapImmutable(mt, MediaType::getExamples, "otherExample", otherExampleValue); checkNullValueInAdd(mt::getExamples, mt::addExample, "otherExample", exampleValue); } @SuppressWarnings("deprecation") // Testing deprecated Schema methods @Test public void schemaTest() { final Schema s = processConstructible(Schema.class, Set.of("booleanSchema")); s.setBooleanSchema(Boolean.TRUE); assertSame(s.getBooleanSchema(), Boolean.TRUE, "Schema.getBooleanSchema should return the value that was set"); Schema s2 = s.booleanSchema(Boolean.FALSE); assertSame(s2, s, "Schema.booleanSchema should return the same object"); assertSame(s.getBooleanSchema(), Boolean.FALSE, "Schema.getBooleanSchema should return the value that was set with the builder method"); s.setBooleanSchema(null); assertNull(s.getBooleanSchema(), "Should be able to set Schema.booleanSchema to null"); final Schema ap = createConstructibleInstance(Schema.class); checkSameObject(s, s.additionalPropertiesSchema(ap)); checkSameObject(ap, s.getAdditionalPropertiesSchema()); assertEquals(s.getAdditionalPropertiesBoolean(), null, "AdditionalProperties (Boolean type) is expected to be null"); checkSameObject(s, s.additionalPropertiesBoolean(Boolean.TRUE)); assertEquals(s.getAdditionalPropertiesBoolean(), Boolean.TRUE, "AdditionalProperties (Boolean type) is expected to be true"); s2 = s.getAdditionalPropertiesSchema(); assertNotNull(s2, "AdditionalProperties (Schema type) is expected to be non-null"); assertEquals(s2.getBooleanSchema(), Boolean.TRUE, "AdditionalProperties (Schema type) is expected to return a boolean-true schema"); s.setAdditionalPropertiesBoolean(Boolean.FALSE); assertEquals(s.getAdditionalPropertiesBoolean(), Boolean.FALSE, "AdditionalProperties (Boolean type) is expected to be false"); s2 = s.getAdditionalPropertiesSchema(); assertNotNull(s2, "AdditionalProperties (Schema type) is expected to be non-null"); assertEquals(s2.getBooleanSchema(), Boolean.FALSE, "AdditionalProperties (Schema type) is expected to return a boolean-false schema"); s.setAdditionalPropertiesSchema(null); assertEquals(s.getAdditionalPropertiesBoolean(), null, "AdditionalProperties (Boolean type) is expected to be null"); assertEquals(s.getAdditionalPropertiesSchema(), null, "AdditionalProperties (Schema type) is expected to be null"); s.setExamples(null); s.setExample("example1"); assertEquals(s.getExample(), "example1", "Example is expected to be set"); assertNull(s.getExamples(), "Examples should be null"); s.setExamples(Arrays.asList("example2", "example3")); assertEquals(s.getExample(), "example1", "Example should not be affected by settings examples"); assertThat("Examples should be set", s.getExamples(), contains("example2", "example3")); s.setExample("example4"); assertEquals(s.getExample(), "example4", "Example should be set"); assertThat("Examples should not be affected by example", s.getExamples(), contains("example2", "example3")); final Schema allOf = createConstructibleInstance(Schema.class); checkSameObject(s, s.addAllOf(allOf)); checkListEntry(s.getAllOf(), allOf); assertEquals(s.getAllOf().size(), 1, "The list is expected to contain one entry."); s.removeAllOf(allOf); assertEquals(s.getAllOf().size(), 0, "The list is expected to be empty."); final Schema allOf2 = createConstructibleInstance(Schema.class); s.setAllOf(Collections.singletonList(allOf2)); assertEquals(s.getAllOf().size(), 1, "The list is expected to contain one entry."); checkListEntry(s.getAllOf(), allOf2); checkSameObject(s, s.addAllOf(allOf)); assertEquals(s.getAllOf().size(), 2, "The list is expected to contain two entries."); checkListEntry(s.getAllOf(), allOf); final Schema otherAllOfValue = createConstructibleInstance(Schema.class); checkListImmutable(s, Schema::getAllOf, otherAllOfValue); final Schema anyOf = createConstructibleInstance(Schema.class); checkSameObject(s, s.addAnyOf(anyOf)); checkListEntry(s.getAnyOf(), anyOf); assertEquals(s.getAnyOf().size(), 1, "The list is expected to contain one entry."); s.removeAnyOf(anyOf); assertEquals(s.getAnyOf().size(), 0, "The list is expected to be empty."); final Schema anyOf2 = createConstructibleInstance(Schema.class); s.setAnyOf(Collections.singletonList(anyOf2)); assertEquals(s.getAnyOf().size(), 1, "The list is expected to contain one entry."); checkListEntry(s.getAnyOf(), anyOf2); checkSameObject(s, s.addAnyOf(anyOf)); assertEquals(s.getAnyOf().size(), 2, "The list is expected to contain two entries."); checkListEntry(s.getAnyOf(), anyOf); final Schema otherAnyOfValue = createConstructibleInstance(Schema.class); checkListImmutable(s, Schema::getAnyOf, otherAnyOfValue); final String enumeration = new String("enumValue"); checkSameObject(s, s.addEnumeration(enumeration)); checkListEntry(s.getEnumeration(), enumeration); assertEquals(s.getEnumeration().size(), 1, "The list is expected to contain one entry."); s.removeEnumeration(enumeration); assertEquals(s.getEnumeration().size(), 0, "The list is expected to be empty."); final String enumeration2 = new String("enumValue2"); s.setEnumeration(Collections.singletonList(enumeration2)); assertEquals(s.getEnumeration().size(), 1, "The list is expected to contain one entry."); checkListEntry(s.getEnumeration(), enumeration2); checkSameObject(s, s.addEnumeration(enumeration)); assertEquals(s.getEnumeration().size(), 2, "The list is expected to contain two entries."); checkListEntry(s.getEnumeration(), enumeration); final String otherEnumerationValue = new String("otherValue"); checkListImmutable(s, Schema::getEnumeration, otherEnumerationValue); final Schema oneOf = createConstructibleInstance(Schema.class); checkSameObject(s, s.addOneOf(oneOf)); checkListEntry(s.getOneOf(), oneOf); assertEquals(s.getOneOf().size(), 1, "The list is expected to contain one entry."); s.removeOneOf(oneOf); assertEquals(s.getOneOf().size(), 0, "The list is expected to be empty."); final Schema oneOf2 = createConstructibleInstance(Schema.class); s.setOneOf(Collections.singletonList(oneOf2)); assertEquals(s.getOneOf().size(), 1, "The list is expected to contain one entry."); checkListEntry(s.getOneOf(), oneOf2); checkSameObject(s, s.addOneOf(oneOf)); assertEquals(s.getOneOf().size(), 2, "The list is expected to contain two entries."); checkListEntry(s.getOneOf(), oneOf); final Schema otherOneOfValue = createConstructibleInstance(Schema.class); checkListImmutable(s, Schema::getOneOf, otherOneOfValue); final String propertySchemaKey = "myPropertySchemaKey"; final Schema propertySchemaValue = createConstructibleInstance(Schema.class); checkSameObject(s, s.addProperty(propertySchemaKey, propertySchemaValue)); checkMapEntry(s.getProperties(), propertySchemaKey, propertySchemaValue); assertEquals(s.getProperties().size(), 1, "The map is expected to contain one entry."); s.removeProperty(propertySchemaKey); assertEquals(s.getProperties().size(), 0, "The map is expected to be empty."); final String propertySchemaKey2 = "myPropertySchemaKey2"; final Schema propertySchemaValue2 = createConstructibleInstance(Schema.class); s.setProperties(Collections.singletonMap(propertySchemaKey2, propertySchemaValue2)); checkMapEntry(s.getProperties(), propertySchemaKey2, propertySchemaValue2); assertEquals(s.getProperties().size(), 1, "The map is expected to contain one entry."); checkSameObject(s, s.addProperty(propertySchemaKey, propertySchemaValue)); checkMapEntry(s.getProperties(), propertySchemaKey, propertySchemaValue); assertEquals(s.getProperties().size(), 2, "The map is expected to contain two entries."); final Schema otherPropertyValue = createConstructibleInstance(Schema.class); checkMapImmutable(s, Schema::getProperties, "otherPropertyKey", otherPropertyValue); checkNullValueInAdd(s::getProperties, s::addProperty, "otherProperty", propertySchemaValue); final String required = new String("required"); checkSameObject(s, s.addRequired(required)); checkListEntry(s.getRequired(), required); assertEquals(s.getRequired().size(), 1, "The list is expected to contain one entry."); s.removeRequired(required); assertEquals(s.getRequired().size(), 0, "The list is expected to be empty."); final String required2 = new String("required2"); s.setRequired(Collections.singletonList(required2)); assertEquals(s.getRequired().size(), 1, "The list is expected to contain one entry."); checkListEntry(s.getRequired(), required2); checkSameObject(s, s.addRequired(required)); assertEquals(s.getRequired().size(), 2, "The list is expected to contain two entries."); checkListEntry(s.getRequired(), required); final String otherRequiredValue = new String("otherRequired"); checkListImmutable(s, Schema::getRequired, otherRequiredValue); final String dependentSchemaKey = "myDependentSchemaKey"; final Schema dependentSchemaValue = createConstructibleInstance(Schema.class); checkSameObject(s, s.addDependentSchema(dependentSchemaKey, dependentSchemaValue)); checkMapEntry(s.getDependentSchemas(), dependentSchemaKey, dependentSchemaValue); assertEquals(s.getDependentSchemas().size(), 1, "The map is expected to contain one entry."); s.removeDependentSchema(dependentSchemaKey); assertEquals(s.getDependentSchemas().size(), 0, "The map is expected to be empty."); final String dependentSchemaKey2 = "myDependentSchemaKey2"; final Schema dependentSchemaValue2 = createConstructibleInstance(Schema.class); s.setDependentSchemas(Collections.singletonMap(dependentSchemaKey2, dependentSchemaValue2)); checkMapEntry(s.getDependentSchemas(), dependentSchemaKey2, dependentSchemaValue2); assertEquals(s.getDependentSchemas().size(), 1, "The map is expected to contain one entry."); checkSameObject(s, s.addDependentSchema(dependentSchemaKey, dependentSchemaValue)); checkMapEntry(s.getDependentSchemas(), dependentSchemaKey, dependentSchemaValue); assertEquals(s.getDependentSchemas().size(), 2, "The map is expected to contain two entries."); final Schema otherDependentSchemaValue = createConstructibleInstance(Schema.class); checkMapImmutable(s, Schema::getDependentSchemas, "otherDependentSchemaKey", otherDependentSchemaValue); checkNullValueInAdd(s::getDependentSchemas, s::addDependentSchema, "otherDependentSchemaKey", dependentSchemaValue); final Schema prefixItem = createConstructibleInstance(Schema.class); checkSameObject(s, s.addPrefixItem(prefixItem)); checkListEntry(s.getPrefixItems(), prefixItem); assertEquals(s.getPrefixItems().size(), 1, "The list is expected to contain one entry."); s.removePrefixItem(prefixItem); assertEquals(s.getPrefixItems().size(), 0, "The list is expected to be empty."); final Schema prefixItem2 = createConstructibleInstance(Schema.class); s.setPrefixItems(Collections.singletonList(prefixItem2)); assertEquals(s.getPrefixItems().size(), 1, "The list is expected to contain one entry."); checkListEntry(s.getPrefixItems(), prefixItem2); checkSameObject(s, s.addPrefixItem(prefixItem)); assertEquals(s.getPrefixItems().size(), 2, "The list is expected to contain two entries."); checkListEntry(s.getPrefixItems(), prefixItem); final Schema otherPrefixItemValue = createConstructibleInstance(Schema.class); checkListImmutable(s, Schema::getPrefixItems, otherPrefixItemValue); final String patternPropertyKey = "myPatternPropertyKey"; final Schema patternPropertyValue = createConstructibleInstance(Schema.class); checkSameObject(s, s.addPatternProperty(patternPropertyKey, patternPropertyValue)); checkMapEntry(s.getPatternProperties(), patternPropertyKey, patternPropertyValue); assertEquals(s.getPatternProperties().size(), 1, "The map is expected to contain one entry."); s.removePatternProperty(patternPropertyKey); assertEquals(s.getPatternProperties().size(), 0, "The map is expected to be empty."); final String patternPropertyKey2 = "myPatternPropertyKey2"; final Schema patternPropertyValue2 = createConstructibleInstance(Schema.class); s.setPatternProperties(Collections.singletonMap(patternPropertyKey2, patternPropertyValue2)); checkMapEntry(s.getPatternProperties(), patternPropertyKey2, patternPropertyValue2); assertEquals(s.getPatternProperties().size(), 1, "The map is expected to contain one entry."); checkSameObject(s, s.addPatternProperty(patternPropertyKey, patternPropertyValue)); checkMapEntry(s.getPatternProperties(), patternPropertyKey, patternPropertyValue); assertEquals(s.getPatternProperties().size(), 2, "The map is expected to contain two entries."); final Schema otherPatternPropertyValue = createConstructibleInstance(Schema.class); checkMapImmutable(s, Schema::getPatternProperties, "otherPatternPropertyKey", otherPatternPropertyValue); checkNullValueInAdd(s::getPatternProperties, s::addPatternProperty, "otherPatternPropertyKey", patternPropertyValue); final String dependentRequiredKey = "myDependentRequiredKey"; final List dependentRequiredValue = Collections.singletonList("myDependentRequired"); checkSameObject(s, s.addDependentRequired(dependentRequiredKey, dependentRequiredValue)); checkMapEntry(s.getDependentRequired(), dependentRequiredKey, dependentRequiredValue); assertEquals(s.getDependentRequired().size(), 1, "The map is expected to contain one entry."); s.removeDependentRequired(dependentRequiredKey); assertEquals(s.getDependentRequired().size(), 0, "The map is expected to be empty."); final String dependentRequiredKey2 = "myDependentRequiredKey2"; final List dependentRequiredValue2 = Collections.singletonList("myDependentRequired2"); s.setDependentRequired(Collections.singletonMap(dependentRequiredKey2, dependentRequiredValue2)); checkMapEntry(s.getDependentRequired(), dependentRequiredKey2, dependentRequiredValue2); assertEquals(s.getDependentRequired().size(), 1, "The map is expected to contain one entry."); checkSameObject(s, s.addDependentRequired(dependentRequiredKey, dependentRequiredValue)); checkMapEntry(s.getDependentRequired(), dependentRequiredKey, dependentRequiredValue); assertEquals(s.getDependentRequired().size(), 2, "The map is expected to contain two entries."); final List otherDependentRequiredValue = Collections.singletonList("myOtherDependentRequired"); checkMapImmutable(s, Schema::getDependentRequired, "otherDependentRequiredKey", otherDependentRequiredValue); checkNullValueInAdd(s::getDependentRequired, s::addDependentRequired, "otherDependentRequiredKey", dependentRequiredValue); } @SuppressWarnings("deprecation") // Testing deprecated Schema methods @Test public void testSchemaArbitraryProperties() { Schema s = createConstructibleInstance(Schema.class); testSchemaProperty(s, "discriminator", Schema::getDiscriminator, Schema::setDiscriminator, createConstructibleInstance(Discriminator.class)); testSchemaProperty(s, "title", Schema::getTitle, Schema::setTitle, "test title"); testSchemaProperty(s, "default", Schema::getDefaultValue, Schema::setDefaultValue, "test"); testSchemaListProperty(s, "enum", Schema::getEnumeration, Schema::setEnumeration, "a"); testSchemaProperty(s, "multipleOf", Schema::getMultipleOf, Schema::setMultipleOf, new BigDecimal("3")); testSchemaProperty(s, "maximum", Schema::getMaximum, Schema::setMaximum, new BigDecimal("3")); testSchemaProperty(s, "exclusiveMaximum", Schema::getExclusiveMaximum, Schema::setExclusiveMaximum, new BigDecimal("3")); testSchemaProperty(s, "minimum", Schema::getMinimum, Schema::setMinimum, new BigDecimal("3")); testSchemaProperty(s, "exclusiveMinimum", Schema::getExclusiveMinimum, Schema::setExclusiveMinimum, new BigDecimal("3")); testSchemaProperty(s, "maxLength", Schema::getMaxLength, Schema::setMaxLength, 17); testSchemaProperty(s, "minLength", Schema::getMinLength, Schema::setMinLength, 5); testSchemaProperty(s, "pattern", Schema::getPattern, Schema::setPattern, "[a-z]+"); testSchemaProperty(s, "maxItems", Schema::getMaxItems, Schema::setMaxItems, 5); testSchemaProperty(s, "minItems", Schema::getMinItems, Schema::setMinItems, 3); testSchemaProperty(s, "uniqueItems", Schema::getUniqueItems, Schema::setUniqueItems, true); testSchemaProperty(s, "maxProperties", Schema::getMaxProperties, Schema::setMaxProperties, 10); testSchemaProperty(s, "minProperties", Schema::getMinProperties, Schema::setMinProperties, 8); testSchemaListProperty(s, "required", Schema::getRequired, Schema::setRequired, "propName"); testSchemaListProperty(s, "type", Schema::getType, Schema::setType, Schema.SchemaType.OBJECT); testSchemaProperty(s, "not", Schema::getNot, Schema::setNot, createConstructibleInstance(Schema.class)); testSchemaMapProperty(s, "properties", Schema::getProperties, Schema::setProperties, createConstructibleInstance(Schema.class)); testSchemaProperty(s, "additionalProperties", Schema::getAdditionalPropertiesSchema, Schema::setAdditionalPropertiesSchema, createConstructibleInstance(Schema.class)); testSchemaProperty(s, "description", Schema::getDescription, Schema::setDescription, "test schema"); testSchemaProperty(s, "format", Schema::getFormat, Schema::setFormat, "date-time"); testSchemaProperty(s, "readOnly", Schema::getReadOnly, Schema::setReadOnly, true); testSchemaProperty(s, "writeOnly", Schema::getWriteOnly, Schema::setWriteOnly, true); testSchemaProperty(s, "example", Schema::getExample, Schema::setExample, "test"); testSchemaProperty(s, "externalDocs", Schema::getExternalDocs, Schema::setExternalDocs, createConstructibleInstance(ExternalDocumentation.class)); testSchemaProperty(s, "deprecated", Schema::getDeprecated, Schema::setDeprecated, true); testSchemaProperty(s, "xml", Schema::getXml, Schema::setXml, createConstructibleInstance(XML.class)); testSchemaProperty(s, "items", Schema::getItems, Schema::setItems, createConstructibleInstance(Schema.class)); testSchemaListProperty(s, "allOf", Schema::getAllOf, Schema::setAllOf, createConstructibleInstance(Schema.class)); testSchemaListProperty(s, "anyOf", Schema::getAnyOf, Schema::setAnyOf, createConstructibleInstance(Schema.class)); testSchemaListProperty(s, "oneOf", Schema::getOneOf, Schema::setOneOf, createConstructibleInstance(Schema.class)); testSchemaProperty(s, "$schema", Schema::getSchemaDialect, Schema::setSchemaDialect, "http://test.dialect"); testSchemaProperty(s, "$comment", Schema::getComment, Schema::setComment, "about this schema"); testSchemaProperty(s, "if", Schema::getIfSchema, Schema::setIfSchema, createConstructibleInstance(Schema.class)); testSchemaProperty(s, "then", Schema::getThenSchema, Schema::setThenSchema, createConstructibleInstance(Schema.class)); testSchemaProperty(s, "else", Schema::getElseSchema, Schema::setElseSchema, createConstructibleInstance(Schema.class)); testSchemaMapProperty(s, "dependentSchemas", Schema::getDependentSchemas, Schema::setDependentSchemas, createConstructibleInstance(Schema.class)); testSchemaListProperty(s, "prefixItems", Schema::getPrefixItems, Schema::setPrefixItems, createConstructibleInstance(Schema.class)); testSchemaProperty(s, "contains", Schema::getContains, Schema::setContains, createConstructibleInstance(Schema.class)); testSchemaMapProperty(s, "patternProperties", Schema::getPatternProperties, Schema::setPatternProperties, createConstructibleInstance(Schema.class)); testSchemaProperty(s, "propertyNames", Schema::getPropertyNames, Schema::setPropertyNames, createConstructibleInstance(Schema.class)); testSchemaProperty(s, "unevaluatedItems", Schema::getUnevaluatedItems, Schema::setUnevaluatedItems, createConstructibleInstance(Schema.class)); testSchemaProperty(s, "unevaluatedProperties", Schema::getUnevaluatedProperties, Schema::setUnevaluatedProperties, createConstructibleInstance(Schema.class)); testSchemaProperty(s, "const", Schema::getConstValue, Schema::setConstValue, "value"); testSchemaProperty(s, "maxContains", Schema::getMaxContains, Schema::setMaxContains, 5); testSchemaProperty(s, "minContains", Schema::getMinContains, Schema::setMinContains, 3); testSchemaMapProperty(s, "dependentRequired", Schema::getDependentRequired, Schema::setDependentRequired, Arrays.asList("a", "b")); testSchemaProperty(s, "contentEncoding", Schema::getContentEncoding, Schema::setContentEncoding, "base64"); testSchemaProperty(s, "contentMediaType", Schema::getContentMediaType, Schema::setContentMediaType, "test/plain"); testSchemaProperty(s, "contentSchema", Schema::getContentSchema, Schema::setContentSchema, createConstructibleInstance(Schema.class)); testSchemaListProperty(s, "examples", Schema::getExamples, Schema::setExamples, "foo"); } public void testSchemaProperty(Schema testSchema, String name, Function getter, BiConsumer setter, V testValue) { // Set with the setter setter.accept(testSchema, testValue); assertSame(getter.apply(testSchema), testValue, "Getter should return the same instance as was set for property " + name); assertSame(testSchema.get(name), testValue, "Generic getter should return same instance as was set for property " + name); // Clear with the setter setter.accept(testSchema, null); assertNull(getter.apply(testSchema), "Getter should return null for property " + name); assertNull(testSchema.get(name), "Generic access should return null for property " + name); // Set with generic access testSchema.set(name, testValue); assertSame(getter.apply(testSchema), testValue, "Getter should return the same instance as was set for property " + name); assertSame(testSchema.get(name), testValue, "Generic getter should return same instance as was set for property " + name); // Clear with generic access testSchema.set(name, null); assertNull(getter.apply(testSchema), "Getter should return null for property " + name); assertNull(testSchema.get(name), "Generic access should return null for property " + name); } public void testSchemaMapProperty(Schema testSchema, String name, Function> getter, BiConsumer> setter, V testValue) { // Set with the setter Map testMap = new HashMap<>(); testMap.put("test1", testValue); setter.accept(testSchema, testMap); testMapFromGetter(() -> getter.apply(testSchema), testMap, name); testMapFromGetter(() -> testSchema.get(name), testMap, name); // Clear with the setter setter.accept(testSchema, null); assertNull(getter.apply(testSchema), "Getter should return null for property " + name); assertNull(testSchema.get(name), "Generic access should return null for property " + name); // Set with generic access testSchema.set(name, testMap); testMapFromGetter(() -> getter.apply(testSchema), testMap, name); testMapFromGetter(() -> testSchema.get(name), testMap, name); // Clear with generic access testSchema.set(name, null); assertNull(getter.apply(testSchema), "Getter should return null for property " + name); assertNull(testSchema.get(name), "Generic access should return null for property " + name); } private void testMapFromGetter(Supplier getter, Map expected, String name) { assertThat("Test error: expected may not be empty", expected, not(anEmptyMap())); Object actualObj = getter.get(); assertEquals(actualObj, expected, "Getter should return value that was set for property " + name); // Check that all values are the same instance Map actualMap = (Map) actualObj; expected.forEach((k, v) -> { assertSame(v, actualMap.get(k), "Getter should return value with same instance for key " + v + " property " + name); }); } public void testSchemaListProperty(Schema testSchema, String name, Function> getter, BiConsumer> setter, V testValue) { // Set with the setter List testList = new ArrayList<>(); testList.add(testValue); setter.accept(testSchema, testList); testListFromGetter(() -> getter.apply(testSchema), testList, name); testListFromGetter(() -> testSchema.get(name), testList, name); // Clear with the setter setter.accept(testSchema, null); assertNull(getter.apply(testSchema), "Getter should return null for property " + name); assertNull(testSchema.get(name), "Generic access should return null for property " + name); // Set with generic access testSchema.set(name, testList); testListFromGetter(() -> getter.apply(testSchema), testList, name); testListFromGetter(() -> testSchema.get(name), testList, name); // Clear with generic access testSchema.set(name, null); assertNull(getter.apply(testSchema), "Getter should return null for property " + name); assertNull(testSchema.get(name), "Generic access should return null for property " + name); } private void testListFromGetter(Supplier getter, List expected, String name) { assertThat("Test error: expected may not be empty", expected, not(empty())); Object actualObj = getter.get(); assertEquals(actualObj, expected, "Getter should return value that was set for property " + name); // Check that all values are the same instance List actualList = (List) actualObj; expected.forEach((expectedV) -> { assertTrue(actualList.stream().anyMatch((actualV) -> expectedV == actualV), "Getter should return value containing " + expectedV + " for property " + name); }); } @Test public void xmlTest() { processConstructible(XML.class); } @Test public void parameterTest() { final Parameter p = processConstructible(Parameter.class); final String exampleKey = "myExample"; final Example exampleValue = createConstructibleInstance(Example.class); checkSameObject(p, p.addExample(exampleKey, exampleValue)); checkMapEntry(p.getExamples(), exampleKey, exampleValue); assertEquals(p.getExamples().size(), 1, "The map is expected to contain one entry."); p.removeExample(exampleKey); assertEquals(p.getExamples().size(), 0, "The map is expected to be empty."); final String exampleKey2 = "myExampleKey2"; final Example exampleValue2 = createConstructibleInstance(Example.class); p.setExamples(Collections.singletonMap(exampleKey2, exampleValue2)); checkMapEntry(p.getExamples(), exampleKey2, exampleValue2); assertEquals(p.getExamples().size(), 1, "The map is expected to contain one entry."); checkSameObject(p, p.addExample(exampleKey, exampleValue)); checkMapEntry(p.getExamples(), exampleKey, exampleValue); assertEquals(p.getExamples().size(), 2, "The map is expected to contain two entries."); Example otherExampleValue = createConstructibleInstance(Example.class); checkMapImmutable(p, Parameter::getExamples, "otherExample", otherExampleValue); checkNullValueInAdd(p::getExamples, p::addExample, "otherExample", exampleValue); } @Test public void requestBodyTest() { processConstructible(RequestBody.class); } @Test public void apiResponseTest() { final APIResponse response = processConstructible(APIResponse.class); final String headerKey = "myHeaderKey"; final Header headerValue = createConstructibleInstance(Header.class); checkSameObject(response, response.addHeader(headerKey, headerValue)); checkMapEntry(response.getHeaders(), headerKey, headerValue); assertEquals(response.getHeaders().size(), 1, "The map is expected to contain one entry."); response.removeHeader(headerKey); assertEquals(response.getHeaders().size(), 0, "The map is expected to be empty."); final String headerKey2 = "myHeaderKey2"; final Header headerValue2 = createConstructibleInstance(Header.class); response.setHeaders(Collections.singletonMap(headerKey2, headerValue2)); checkMapEntry(response.getHeaders(), headerKey2, headerValue2); assertEquals(response.getHeaders().size(), 1, "The map is expected to contain one entry."); checkSameObject(response, response.addHeader(headerKey, headerValue)); checkMapEntry(response.getHeaders(), headerKey, headerValue); assertEquals(response.getHeaders().size(), 2, "The map is expected to contain two entries."); Header otherHeaderValue = createConstructibleInstance(Header.class); checkMapImmutable(response, APIResponse::getHeaders, "otherHeader", otherHeaderValue); checkNullValueInAdd(response::getHeaders, response::addHeader, "some-header", headerValue); final String linkKey = "myLinkKey"; final Link linkValue = createConstructibleInstance(Link.class); checkSameObject(response, response.addLink(linkKey, linkValue)); checkMapEntry(response.getLinks(), linkKey, linkValue); assertEquals(response.getLinks().size(), 1, "The map is expected to contain one entry."); response.removeLink(linkKey); assertEquals(response.getLinks().size(), 0, "The map is expected to be empty."); Link otherLinkValue = createConstructibleInstance(Link.class); final String linkKey2 = "myLinkKey2"; final Link linkValue2 = createConstructibleInstance(Link.class); response.setLinks(Collections.singletonMap(linkKey2, linkValue2)); checkMapEntry(response.getLinks(), linkKey2, linkValue2); assertEquals(response.getLinks().size(), 1, "The map is expected to contain one entry."); checkSameObject(response, response.addLink(linkKey, linkValue)); checkMapEntry(response.getLinks(), linkKey, linkValue); assertEquals(response.getLinks().size(), 2, "The map is expected to contain two entries."); checkMapImmutable(response, APIResponse::getLinks, "otherLink", otherLinkValue); checkNullValueInAdd(response::getLinks, response::addLink, "someLinkKey", linkValue); } @Test public void apiResponsesTest() { final APIResponses responses = processConstructible(APIResponses.class); final String responseKey = "200"; final APIResponse pathItemValue = createConstructibleInstance(APIResponse.class); responses.setAPIResponses(Collections.singletonMap(responseKey, pathItemValue)); assertTrue(responses.hasAPIResponse(responseKey), responseKey + " is present in the map"); assertEquals(responses.getAPIResponses().size(), 1, "The map is expected to contain one entry."); assertSame(responses.getAPIResponse(responseKey), pathItemValue, "The value associated with the key: " + responseKey + " is expected to be the same one that was added."); checkMapEntry(responses.getAPIResponses(), responseKey, pathItemValue); final String responseKey2 = "4XX"; assertFalse(responses.hasAPIResponse(responseKey2), responseKey2 + " is absent in the map"); final APIResponse pathItemValue2 = createConstructibleInstance(APIResponse.class); checkSameObject(responses, responses.addAPIResponse(responseKey2, pathItemValue2)); assertTrue(responses.hasAPIResponse(responseKey2), responseKey2 + " is present in the map"); assertEquals(responses.getAPIResponses().size(), 2, "The map is expected to contain two entries."); assertSame(responses.getAPIResponse(responseKey2), pathItemValue2, "The value associated with the key: " + responseKey2 + " is expected to be the same one that was added."); checkMapEntry(responses.getAPIResponses(), responseKey2, pathItemValue2); responses.removeAPIResponse(responseKey); assertFalse(responses.hasAPIResponse(responseKey), responseKey + " is absent in the map"); assertEquals(responses.getAPIResponses().size(), 1, "The map is expected to contain one entry."); responses.removeAPIResponse(responseKey2); assertFalse(responses.hasAPIResponse(responseKey2), responseKey + " is absent in the map"); assertEquals(responses.getAPIResponses().size(), 0, "The map is expected to contain 0 entries."); final APIResponse otherValue = createConstructibleInstance(APIResponse.class); checkMapImmutable(responses, APIResponses::getAPIResponses, "500", otherValue); assertNull(responses.getDefaultValue(), "No default value expected."); final String responseKey3 = APIResponses.DEFAULT; final APIResponse responseValue3 = createConstructibleInstance(APIResponse.class); checkSameObject(responses, responses.addAPIResponse(responseKey3, responseValue3)); checkMapEntry(responses.getAPIResponses(), responseKey3, responseValue3); checkSameObject(responseValue3, responses.getDefaultValue()); assertEquals(responses.getAPIResponses().size(), 1, "The map is expected to contain one entry."); responses.setDefaultValue(null); assertNull(responses.getAPIResponse(APIResponses.DEFAULT), "No default value expected."); assertNull(responses.getDefaultValue(), "No default value expected."); final APIResponse responseValue4 = createConstructibleInstance(APIResponse.class); responses.setDefaultValue(responseValue4); checkMapEntry(responses.getAPIResponses(), APIResponses.DEFAULT, responseValue4); checkSameObject(responseValue4, responses.getDefaultValue()); checkNullValueInAdd(responses::getAPIResponses, responses::addAPIResponse, "4XX", otherValue); } @Test public void oAuthFlowTest() { final OAuthFlow o = processConstructible(OAuthFlow.class); final String key = "myKey"; final String value = new String("myValue"); o.setScopes(Collections.singletonMap(key, value)); Map scopes = o.getScopes(); assertEquals(scopes.size(), 1, "The list is expected to contain one entry."); assertTrue(scopes.containsKey("myKey"), "The map is expected to contain a 'myKey' entry."); assertEquals(scopes.get(key), value, "The value corresponding to the 'myKey' is wrong."); o.setScopes((Map) null); assertNull(o.getScopes(), "The value is expected to be null."); } @Test public void oAuthFlowsTest() { processConstructible(OAuthFlows.class); } @Test public void securityRequirementTest() { final SecurityRequirement sr = processConstructible(SecurityRequirement.class); final String schemeKey = "myScheme"; final List schemeValue = new ArrayList(); sr.setSchemes(Collections.singletonMap(schemeKey, schemeValue)); assertTrue(sr.hasScheme(schemeKey), schemeKey + " is present in the map"); assertEquals(sr.getSchemes().size(), 1, "The map is expected to contain one entry."); assertSame(sr.getScheme(schemeKey), schemeValue, "The value associated with the key: " + schemeKey + " is expected to be the same one that was added."); checkMapEntry(sr.getSchemes(), schemeKey, schemeValue); final String schemeKey2 = "myScheme2"; assertFalse(sr.hasScheme(schemeKey2), schemeKey2 + " is absent in the map"); final List schemeValue2 = new ArrayList(); checkSameObject(sr, sr.addScheme(schemeKey2, schemeValue2)); assertTrue(sr.hasScheme(schemeKey2), schemeKey2 + " is present in the map"); assertEquals(sr.getSchemes().size(), 2, "The map is expected to contain two entries."); assertSame(sr.getScheme(schemeKey2), schemeValue2, "The value associated with the key: " + schemeKey2 + " is expected to be the same one that was added."); checkMapEntry(sr.getSchemes(), schemeKey2, schemeValue2); sr.removeScheme(schemeKey); assertFalse(sr.hasScheme(schemeKey), schemeKey + " is absent in the map"); assertEquals(sr.getSchemes().size(), 1, "The map is expected to contain one entry."); sr.removeScheme(schemeKey2); assertFalse(sr.hasScheme(schemeKey2), schemeKey + " is absent in the map"); assertEquals(sr.getSchemes().size(), 0, "The map is expected to contain 0 entries."); final List otherValue = new ArrayList(); checkMapImmutable(sr, SecurityRequirement::getSchemes, "otherScheme", otherValue); final String schemeKey3 = "myScheme3"; sr.addScheme(schemeKey3, (String) null); assertTrue(sr.hasScheme(schemeKey3), "Expected " + schemeKey3 + " to be present"); final List schemeValue3 = Collections.emptyList(); assertEquals(sr.getScheme(schemeKey3), schemeValue3, "The value associated with the key: " + schemeKey3 + " is expected to be an empty list."); final String schemeKey4 = "myScheme3"; sr.addScheme(schemeKey4, (List) null); assertTrue(sr.hasScheme(schemeKey4), "Expected " + schemeKey4 + " to be present"); final List schemeValue4 = Collections.emptyList(); assertEquals(sr.getScheme(schemeKey4), schemeValue4, "The value associated with the key: " + schemeKey4 + " is expected to be an empty list."); // Test a requirement with roles final String schemeKey5 = "myScheme5"; final List schemeValue5 = Arrays.asList("myRole1", "myRole2"); sr.addScheme(schemeKey5, schemeValue5); assertTrue(sr.hasScheme(schemeKey5), "Expected " + schemeKey5 + " to be present"); assertEquals(sr.getScheme(schemeKey5), schemeValue5, "The value associated with the key: " + schemeKey5 + " is expected to have two roles."); } @Test public void securitySchemeTest() { processConstructible(SecurityScheme.class); } @Test public void serverTest() { Server server = processConstructible(Server.class); final ServerVariable sv1 = createConstructibleInstance(ServerVariable.class); server.setVariables(Collections.singletonMap("var1", sv1)); Map variables = server.getVariables(); assertEquals(variables.size(), 1, "The map is expected to contain one entry."); assertTrue(variables.containsKey("var1"), "The map is expected to contain a 'var1' entry."); assertEquals(variables.get("var1"), sv1, "The value corresponding to the 'var1' is wrong."); checkMapEntry(server.getVariables(), "var1", sv1); final ServerVariable sv2 = createConstructibleInstance(ServerVariable.class); checkMapImmutable(server, Server::getVariables, "sv2", sv2); final ServerVariable sv3 = createConstructibleInstance(ServerVariable.class); checkNullValueInAdd(server::getVariables, server::addVariable, "sv3", sv3); server.setVariables((Map) null); assertNull(server.getVariables(), "The value is expected to be null."); } @Test public void serverVariableTest() { final ServerVariable sv = processConstructible(ServerVariable.class); final String enumeration = new String("enumValue"); checkSameObject(sv, sv.addEnumeration(enumeration)); checkListEntry(sv.getEnumeration(), enumeration); assertEquals(sv.getEnumeration().size(), 1, "The list is expected to contain one entry."); sv.removeEnumeration(enumeration); assertEquals(sv.getEnumeration().size(), 0, "The list is expected to be empty."); final String enumeration2 = new String("enumValue2"); sv.setEnumeration(Collections.singletonList(enumeration2)); assertEquals(sv.getEnumeration().size(), 1, "The list is expected to contain one entry."); checkListEntry(sv.getEnumeration(), enumeration2); checkSameObject(sv, sv.addEnumeration(enumeration)); assertEquals(sv.getEnumeration().size(), 2, "The list is expected to contain two entries."); checkListEntry(sv.getEnumeration(), enumeration); final String otherEnumerationValue = new String("otherValue"); checkListImmutable(sv, ServerVariable::getEnumeration, otherEnumerationValue); } @Test public void tagTest() { processConstructible(Tag.class); } private T processConstructible(Class clazz) { return processConstructible(clazz, Collections.emptySet()); } private T processConstructible(Class clazz, Set propertiesToIgnore) { final T o = createConstructibleInstance(clazz); if (o instanceof Extensible && Extensible.class.isAssignableFrom(clazz)) { processExtensible((Extensible) o); } if (o instanceof Reference && Reference.class.isAssignableFrom(clazz)) { processReference((Reference) o); } final Map properties = collectProperties(clazz); properties.values().stream() .filter((p) -> p.isComplete()) .filter((p) -> !propertiesToIgnore.contains(p.getName())) .forEach((p) -> { processConstructibleProperty(o, p, clazz); }); return o; } private T createConstructibleInstance(Class clazz) { // Check that the OASFactory is able to create an instance of the given Class. final T o1 = OASFactory.createObject(clazz); assertNotNull(o1, "The return value of OASFactory.createObject(" + clazz.getName() + ") must not be null."); assertTrue(clazz.isInstance(o1), "The return value of OASFactory.createObject() is expected to be an instance of: " + clazz.getName()); final T o2 = OASFactory.createObject(clazz); assertNotNull(o2, "The return value of OASFactory.createObject(" + clazz.getName() + ") must not be null."); assertTrue(clazz.isInstance(o2), "The return value of OASFactory.createObject() is expected to be an instance of: " + clazz.getName()); assertNotSame(o2, o1, "OASFactory.createObject(" + clazz.getName() + ") is expected to create a new object on each invocation."); return o1; } private void processExtensible(Extensible e) { final String extensionName1 = "x-" + e.getClass().getName() + "-1"; final Object obj1 = new Object(); final String extensionName2 = "x-" + e.getClass().getName() + "-2"; final Object obj2 = new Object(); // Check that extensions can be added to and retrieved from the map. e.addExtension(extensionName1, obj1); e.addExtension(extensionName2, obj2); final Map map = e.getExtensions(); assertEquals(map.size(), 2, "The extensions map is expected to contain two entries."); assertTrue(map.containsKey(extensionName1), "The extensions map is expected to contain the key: " + extensionName1); assertTrue(map.containsKey(extensionName2), "The extensions map is expected to contain the key: " + extensionName2); assertSame(map.get(extensionName1), obj1, "The value associated with the key: " + extensionName1 + " is expected to be the same one that was added."); assertSame(map.get(extensionName2), obj2, "The value associated with the key: " + extensionName2 + " is expected to be the same one that was added."); e.removeExtension(extensionName1); assertEquals(e.getExtensions().size(), 1, "The extensions map is expected to contain one entry."); // Check that the extension map can be replaced with the setter and that it is returned by the getter. final Map newMap = new HashMap<>(); e.setExtensions(newMap); final Map map2 = e.getExtensions(); assertEquals(map2.size(), 0, "The extensions map is expected to contain no entries."); assertEquals(map2, newMap, "The return value of getExtensions() is expected to be the same value that was set."); // Check that the extension map can be replaced with the builder method and that it is returned by the getter. final Map newOtherMap = Collections.singletonMap("x-test", 42); e.setExtensions(newOtherMap); final Map map3 = e.getExtensions(); assertEquals(map3.size(), 1, "The extensions map is expected to contain one entry."); assertEquals(map3, newOtherMap, "The return value of getExtensions() is expected to be the same value that was set."); // Check that a value can be added, even if the map was immutable e.addExtension(extensionName1, obj1); assertEquals(e.getExtensions().size(), 2, "The extensions map is expected to contain two entries."); checkMapImmutable(e, Extensible::getExtensions, "x-other", new Object()); } private void processReference(Reference r) { // Check that the ref value can be set using the setter method and that the getter method returns the same // value. final String myRef1 = createReference(r, "myRef1"); r.setRef(myRef1); assertEquals(r.getRef(), myRef1, "The return value of getRef() is expected to be equal to the value that was set."); // Check that the short name ref value can be set using the setter method and that the getter method returns the // expanded value. final String shortName2 = "myRef2"; final String myRef2 = createReference(r, shortName2); r.setRef(shortName2); assertEquals(r.getRef(), myRef2, "The return value of getRef() is expected to be a fully expanded name."); // Check that the ref value can be set using the builder method and that the getter method returns the same // value. final String myRef3 = createReference(r, "myRef3"); final Reference self = r.ref(myRef3); assertSame(self, r, "The return value of ref() is expected to return the current instance."); assertEquals(r.getRef(), myRef3, "The return value of getRef() is expected to be equal to the value that was set."); // Check that the short name ref value can be set using the builder method and that the getter method returns // the expanded value. final String shortName4 = "myRef4"; final String myRef4 = createReference(r, shortName4); final Reference self2 = r.ref(shortName4); assertSame(self2, r, "The return value of ref() is expected to return the current instance."); assertEquals(r.getRef(), myRef4, "The return value of getRef() is expected to be a fully expanded name."); } private void processConstructibleProperty(Constructible o, Property p, Class enclosingInterface) { final Object value1 = getInstanceOf(p.getType(), false); p.invokeSetter(o, value1); if (!p.isPrimitive() && !p.isCompatible(Map.class) && !p.isCompatible(List.class)) { assertSame(p.invokeGetter(o), value1, "The return value of the getter method for property \"" + p.getName() + "\" of interface \"" + enclosingInterface.getName() + "\" is expected to be the same as the value that was set."); } else { assertEquals(p.invokeGetter(o), value1, "The return value of the getter method for property \"" + p.getName() + "\" of interface \"" + enclosingInterface.getName() + "\" is expected to be equal to the value that was set."); } if (p.hasBuilder()) { final Object value2 = getInstanceOf(p.getType(), true); final Object self = p.invokeBuilder(o, value2); assertSame(self, o, "The return value of the builder method for property \"" + p.getName() + "\" of interface \"" + enclosingInterface.getName() + "\" is expected to be the same as the value that was set."); if (!p.isPrimitive() && !p.isCompatible(Map.class) && !p.isCompatible(List.class)) { assertSame(p.invokeGetter(o), value2, "The return value of the getter method for property \"" + p.getName() + "\" of interface \"" + enclosingInterface.getName() + "\" is expected to be the same as the value that was set."); } else { assertEquals(p.invokeGetter(o), value2, "The return value of the getter method for property \"" + p.getName() + "\" of interface \"" + enclosingInterface.getName() + "\" is expected to be equal to the value that was set."); } } p.invokeSetter(o, null); } // Returns instances for testing getter, setter and builder methods. @SuppressWarnings("unchecked") private Object getInstanceOf(Class clazz, boolean alternateEnumValue) { if (Constructible.class.isAssignableFrom(clazz)) { return createConstructibleInstance((Class) clazz); } else if (Enum.class.isAssignableFrom(clazz)) { final Object[] enumConstants = clazz.getEnumConstants(); if (enumConstants != null && enumConstants.length > 0) { if (alternateEnumValue && enumConstants.length > 1) { return enumConstants[1]; } return enumConstants[0]; } } else if (clazz == List.class) { return new ArrayList(); } else if (clazz == Map.class) { return new HashMap(); } else if (clazz == String.class) { return new String("value"); } else if (clazz == Boolean.class || clazz == Boolean.TYPE) { return Boolean.valueOf(true); } else if (clazz == Byte.class || clazz == Byte.TYPE) { return Byte.valueOf((byte) 1); } else if (clazz == Short.class || clazz == Short.TYPE) { return Short.valueOf((short) 1); } else if (clazz == Integer.class || clazz == Integer.TYPE) { return Integer.valueOf(1); } else if (clazz == Long.class || clazz == Long.TYPE) { return Long.valueOf(1L); } else if (clazz == Float.class || clazz == Float.TYPE) { return Float.valueOf(1); } else if (clazz == Double.class || clazz == Double.TYPE) { return Double.valueOf(1); } else if (clazz == Character.class || clazz == Character.TYPE) { return Character.valueOf('a'); } else if (clazz == BigInteger.class) { return new BigInteger("1"); } else if (clazz == BigDecimal.class) { return new BigDecimal("1.0"); } else if (clazz == Object.class) { return new String("object"); } return null; } private String createReference(Reference r, String v) { final StringBuilder sb = new StringBuilder(); if (r instanceof APIResponse) { sb.append("#/components/responses/"); } else if (r instanceof Callback) { sb.append("#/components/callbacks/"); } else if (r instanceof Example) { sb.append("#/components/examples/"); } else if (r instanceof Header) { sb.append("#/components/headers/"); } else if (r instanceof Link) { sb.append("#/components/links/"); } else if (r instanceof Parameter) { sb.append("#/components/parameters/"); } else if (r instanceof PathItem) { sb.append("#/components/pathItems/"); } else if (r instanceof RequestBody) { sb.append("#/components/requestBodies/"); } else if (r instanceof Schema) { sb.append("#/components/schemas/"); } else if (r instanceof SecurityScheme) { sb.append("#/components/securitySchemes/"); } sb.append(v); return sb.toString(); } private Map collectProperties(Class clazz) { final Map properties = new HashMap<>(); final Method[] methods = clazz.getDeclaredMethods(); Arrays.stream(methods).forEach(m -> { Class returnType = m.getReturnType(); int parameterCount = m.getParameterCount(); String name = m.getName(); Property p; Class type; // Possible builder method if (returnType == clazz) { if (parameterCount == 1) { type = m.getParameterTypes()[0]; p = properties.get(name); if (p == null) { p = new Property(name, type); properties.put(name, p); } if (p.isCompatible(type)) { p.addBuilder(m); } } } else if (returnType == Void.TYPE) { if (name.startsWith("set") && parameterCount == 1) { // Possible setter method name = Introspector.decapitalize(name.substring(3)); type = m.getParameterTypes()[0]; p = properties.get(name); if (p == null) { p = new Property(name, type); properties.put(name, p); } if (p.isCompatible(type)) { p.addSetter(m); } } } else { if (name.startsWith("get") && parameterCount == 0) { // Possible getter method name = Introspector.decapitalize(name.substring(3)); type = returnType; p = properties.get(name); if (p == null) { p = new Property(name, type); properties.put(name, p); } if (p.isCompatible(type)) { p.addGetter(m); } } } }); return properties; } private void checkMapEntry(Map map, K key, T value) { assertNotNull(map, "The map must not be null."); assertTrue(map.containsKey(key), "The map is expected to contain the key: " + key); assertSame(map.get(key), value, "The value associated with the key: " + key + " is expected to be the same one that was added."); } private void checkMapImmutable(O container, Function> mapGetter, K key, T otherValue) { Map map = mapGetter.apply(container); assertNotNull(map, "The map must not be null."); assertFalse(map.containsKey(key), "The map is expected to not contain the key: " + key); int originalSize = map.size(); try { map.put(key, otherValue); } catch (Exception e) { // It is allowed to throw an exception } Map map2 = mapGetter.apply(container); assertNotNull(map2, "The map must not be null."); assertFalse(map2.containsKey(key), "The map is expected to not contain the key: " + key); assertEquals(map2.size(), originalSize, "The map is expected to have a size of " + originalSize); } private void checkNullValueInAdd(Supplier> mapGetter, BiFunction mapAdd, String key, T value) { // add null as value for 'key' try { mapAdd.apply(key, null); } catch (Exception e) { // It is allowed to throw an exception } assertFalse(mapGetter.get().containsKey(key), "The map is expected to not contain the key: " + key); // add value as value for 'key' mapAdd.apply(key, value); assertTrue(mapGetter.get().containsKey(key), "The map is expected to contain the key: " + key); // add null again as value for 'key' try { mapAdd.apply(key, null); } catch (Exception e) { // It is allowed to throw an exception } assertTrue(mapGetter.get().containsKey(key), "The map is expected to contain the key: " + key); } private void checkListEntry(List list, T value) { assertNotNull(list, "The list must not be null."); assertTrue(list.stream().anyMatch((v) -> v == value), "The list is expected to contain the value: " + value); } private void checkListEntryAbsent(List list, T value) { assertNotNull(list, "The list must not be null."); assertTrue(list.stream().noneMatch((v) -> v == value), "The list is expected not to contain the value: " + value); } private void checkListImmutable(O container, Function> listGetter, V otherValue) { List list = listGetter.apply(container); checkListEntryAbsent(list, otherValue); int originalSize = list.size(); try { list.add(otherValue); } catch (Exception e) { // It is allowed to throw an exception } List list2 = listGetter.apply(container); checkListEntryAbsent(list2, otherValue); assertEquals(list2.size(), originalSize, "The list is expected to have a size of " + originalSize); } private void checkSameObject(T expected, T actual) { assertSame(actual, expected, "Expecting same object."); } }