X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=restconf%2Frestconf-nb%2Fsrc%2Ftest%2Fjava%2Forg%2Fopendaylight%2Frestconf%2Fnb%2Fjaxrs%2FRestconfSchemaServiceTest.java;fp=restconf%2Frestconf-nb%2Fsrc%2Ftest%2Fjava%2Forg%2Fopendaylight%2Frestconf%2Fnb%2Fjaxrs%2FRestconfSchemaServiceTest.java;h=22756b53ab901a245a239bdbcd74881eb62ba33b;hb=b7dd1dd96b40665cad4b38d6b23b32be7ef9a744;hp=0000000000000000000000000000000000000000;hpb=b35cf934cb55f2dbcf4a834eb754c997196d0e39;p=netconf.git diff --git a/restconf/restconf-nb/src/test/java/org/opendaylight/restconf/nb/jaxrs/RestconfSchemaServiceTest.java b/restconf/restconf-nb/src/test/java/org/opendaylight/restconf/nb/jaxrs/RestconfSchemaServiceTest.java new file mode 100644 index 0000000000..22756b53ab --- /dev/null +++ b/restconf/restconf-nb/src/test/java/org/opendaylight/restconf/nb/jaxrs/RestconfSchemaServiceTest.java @@ -0,0 +1,339 @@ +/* + * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ +package org.opendaylight.restconf.nb.jaxrs; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; +import static org.mockito.Mockito.doReturn; +import static org.opendaylight.restconf.nb.jaxrs.AbstractRestconfTest.assertEntity; +import static org.opendaylight.restconf.nb.jaxrs.AbstractRestconfTest.assertError; + +import com.google.common.io.CharStreams; +import com.google.common.util.concurrent.Futures; +import java.io.Reader; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; +import org.opendaylight.mdsal.dom.api.DOMActionService; +import org.opendaylight.mdsal.dom.api.DOMDataBroker; +import org.opendaylight.mdsal.dom.api.DOMRpcService; +import org.opendaylight.mdsal.dom.api.DOMSchemaService; +import org.opendaylight.mdsal.dom.api.DOMYangTextSourceProvider; +import org.opendaylight.mdsal.dom.broker.DOMMountPointServiceImpl; +import org.opendaylight.mdsal.dom.spi.FixedDOMSchemaService; +import org.opendaylight.restconf.nb.rfc8040.databind.DatabindContext; +import org.opendaylight.restconf.nb.rfc8040.legacy.ErrorTags; +import org.opendaylight.restconf.server.mdsal.DOMSourceResolver; +import org.opendaylight.restconf.server.mdsal.MdsalRestconfServer; +import org.opendaylight.yangtools.yang.common.ErrorTag; +import org.opendaylight.yangtools.yang.common.ErrorType; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.common.Revision; +import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier; +import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext; +import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier; +import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource; +import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils; + +/** + * Unit tests for {@code RestconfSchemaService}. + */ +@RunWith(MockitoJUnitRunner.StrictStubs.class) +public class RestconfSchemaServiceTest { + private static final String MOUNT_POINT = "mount-point-1:cont/yang-ext:mount/"; + private static final String NULL_MOUNT_POINT = "mount-point-2:cont/yang-ext:mount/"; + private static final String NOT_EXISTING_MOUNT_POINT = "mount-point-3:cont/yang-ext:mount/"; + + private static final String TEST_MODULE = "module1/2014-01-01"; + private static final String TEST_MODULE_BEHIND_MOUNT_POINT = "module1-behind-mount-point/2014-02-03"; + private static final String NOT_EXISTING_MODULE = "not-existing/2016-01-01"; + + // schema context with modules + private static final EffectiveModelContext SCHEMA_CONTEXT = + YangParserTestUtils.parseYangResourceDirectory("/modules"); + // schema context with modules behind mount point + private static final EffectiveModelContext SCHEMA_CONTEXT_BEHIND_MOUNT_POINT = + YangParserTestUtils.parseYangResourceDirectory("/modules/modules-behind-mount-point"); + // schema context with mount points + private static final EffectiveModelContext SCHEMA_CONTEXT_WITH_MOUNT_POINTS = + YangParserTestUtils.parseYangResourceDirectory("/modules/mount-points"); + + // handlers + @Mock + private DOMSchemaService schemaService; + @Mock + private DOMYangTextSourceProvider sourceProvider; + @Mock + private DOMDataBroker dataBroker; + @Mock + private DOMActionService actionService; + @Mock + private DOMRpcService rpcService; + @Mock + private YangTextSchemaSource yangSource; + @Mock + private Reader yangReader; + + // service under test + private JaxRsRestconf restconf; + + @Before + public void setup() throws Exception { + final var mountPointService = new DOMMountPointServiceImpl(); + // create and register mount points + mountPointService + .createMountPoint(YangInstanceIdentifier.of(QName.create("mount:point:1", "2016-01-01", "cont"))) + .addService(DOMSchemaService.class, FixedDOMSchemaService.of(SCHEMA_CONTEXT_BEHIND_MOUNT_POINT)) + .register(); + mountPointService + .createMountPoint(YangInstanceIdentifier.of(QName.create("mount:point:2", "2016-01-01", "cont"))) + .register(); + + restconf = new JaxRsRestconf(new MdsalRestconfServer( + () -> DatabindContext.ofModel(schemaService.getGlobalContext(), new DOMSourceResolver(sourceProvider)), + dataBroker, rpcService, actionService, mountPointService)); + } + + /** + * Get schema with identifier of existing module and check if correct module was found. + */ + @Test + public void getSchemaTest() throws Exception { + // prepare conditions - return not-mount point schema context + doReturn(SCHEMA_CONTEXT).when(schemaService).getGlobalContext(); + doReturn(Futures.immediateFuture(yangSource)).when(sourceProvider) + .getSource(new SourceIdentifier("module1", Revision.of("2014-01-01"))); + doReturn(yangReader).when(yangSource).openStream(); + + assertSame(yangReader, assertEntity(Reader.class, 200, ar -> restconf.modulesYangGET(TEST_MODULE, ar))); + } + + /** + * Get schema with identifier of not-existing module. Trying to create SchemaExportContext with + * not-existing module should result in error. + */ + @Test + public void getSchemaForNotExistingModuleTest() { + // prepare conditions - return not-mount point schema context + doReturn(SCHEMA_CONTEXT).when(schemaService).getGlobalContext(); + + final var error = assertError(ar -> restconf.modulesYinGET(NOT_EXISTING_MODULE, ar)); + assertEquals("Source not-existing@2016-01-01 not found", error.getErrorMessage()); + assertEquals(ErrorTag.DATA_MISSING, error.getErrorTag()); + assertEquals(ErrorType.APPLICATION, error.getErrorType()); + } + + /** + * Get schema with identifier of existing module behind mount point and check if correct module was found. + */ + @Test + public void getSchemaMountPointTest() throws Exception { + // prepare conditions - return schema context with mount points + doReturn(SCHEMA_CONTEXT_WITH_MOUNT_POINTS).when(schemaService).getGlobalContext(); + + final var reader = assertEntity(Reader.class, 200, + ar -> restconf.modulesYangGET(MOUNT_POINT + TEST_MODULE_BEHIND_MOUNT_POINT, ar)); + assertEquals(""" + module module1-behind-mount-point { + namespace module:1:behind:mount:point; + prefix mod1bemopo; + revision 2014-02-03; + rpc rpc-behind-module1; + } + """, CharStreams.toString(reader)); + } + + /** + * Get schema with identifier of not-existing module behind mount point. Trying to create + * SchemaExportContext with not-existing module behind mount point should result in error. + */ + @Test + public void getSchemaForNotExistingModuleMountPointTest() { + // prepare conditions - return schema context with mount points + doReturn(SCHEMA_CONTEXT_WITH_MOUNT_POINTS).when(schemaService).getGlobalContext(); + + final var error = assertError(ar -> restconf.modulesYangGET(MOUNT_POINT + NOT_EXISTING_MODULE, ar)); + assertEquals("Source not-existing@2016-01-01 not found", error.getErrorMessage()); + assertEquals(ErrorTag.DATA_MISSING, error.getErrorTag()); + assertEquals(ErrorType.APPLICATION, error.getErrorType()); + } + + /** + * Try to get schema with null SchemaContext behind mount point when using + * NULL_MOUNT_POINT. Test is expected to fail with NullPointerException. + */ + @Test + public void getSchemaNullSchemaContextBehindMountPointTest() { + // prepare conditions - return correct schema context for mount points (this is not null) + doReturn(SCHEMA_CONTEXT_WITH_MOUNT_POINTS).when(schemaService).getGlobalContext(); + + // make test - call service on mount point with null schema context + // NULL_MOUNT_POINT contains null schema context + final var error = assertError( + ar -> restconf.modulesYangGET(NULL_MOUNT_POINT + TEST_MODULE_BEHIND_MOUNT_POINT, ar)); + assertEquals("Mount point mount-point-2:cont does not expose DOMSchemaService", error.getErrorMessage()); + assertEquals(ErrorType.PROTOCOL, error.getErrorType()); + assertEquals(ErrorTags.RESOURCE_DENIED_TRANSPORT, error.getErrorTag()); + } + + /** + * Try to get schema with empty (not valid) identifier catching RestconfDocumentedException. Error + * type, error tag and error status code are compared to expected values. + */ + @Test + public void getSchemaWithEmptyIdentifierTest() { + // prepare conditions - return correct schema context + doReturn(SCHEMA_CONTEXT).when(schemaService).getGlobalContext(); + + final var error = assertError(ar -> restconf.modulesYangGET("", ar)); + assertEquals("Identifier must start with character from set 'a-zA-Z_", error.getErrorMessage()); + assertEquals(ErrorType.PROTOCOL, error.getErrorType()); + assertEquals(ErrorTag.INVALID_VALUE, error.getErrorTag()); + } + + /** + * Try to get schema with empty (not valid) identifier behind mount point catching + * RestconfDocumentedException. Error type, error tag and error status code are compared to expected + * values. + */ + @Test + public void getSchemaWithEmptyIdentifierMountPointTest() { + // prepare conditions - return correct schema context with mount points + doReturn(SCHEMA_CONTEXT_WITH_MOUNT_POINTS).when(schemaService).getGlobalContext(); + + // make test and verify + final var error = assertError(ar -> restconf.modulesYangGET(MOUNT_POINT + "", ar)); + assertEquals("Identifier must start with character from set 'a-zA-Z_", error.getErrorMessage()); + assertEquals(ErrorType.PROTOCOL, error.getErrorType()); + assertEquals(ErrorTag.INVALID_VALUE, error.getErrorTag()); + } + + /** + * Try to get schema with not-parsable identifier catching RestconfDocumentedException. Error type, + * error tag and error status code are compared to expected values. + */ + @Test + public void getSchemaWithNotParsableIdentifierTest() { + // prepare conditions - return correct schema context without mount points + doReturn(SCHEMA_CONTEXT).when(schemaService).getGlobalContext(); + + // make test and verify + final var error = assertError(ar -> restconf.modulesYangGET("01_module/2016-01-01", ar)); + assertEquals("Identifier must start with character from set 'a-zA-Z_", error.getErrorMessage()); + assertEquals(ErrorType.PROTOCOL, error.getErrorType()); + assertEquals(ErrorTag.INVALID_VALUE, error.getErrorTag()); + } + + /** + * Try to get schema behind mount point with not-parsable identifier catching + * RestconfDocumentedException. Error type, error tag and error status code are compared to expected + * values. + */ + @Test + public void getSchemaWithNotParsableIdentifierMountPointTest() { + // prepare conditions - return correct schema context with mount points + doReturn(SCHEMA_CONTEXT_WITH_MOUNT_POINTS).when(schemaService).getGlobalContext(); + + // make test and verify + final var error = assertError(ar -> restconf.modulesYangGET(MOUNT_POINT + "01_module/2016-01-01", ar)); + assertEquals("Identifier must start with character from set 'a-zA-Z_", error.getErrorMessage()); + assertEquals(ErrorType.PROTOCOL, error.getErrorType()); + assertEquals(ErrorTag.INVALID_VALUE, error.getErrorTag()); + } + + /** + * Try to get schema with wrong (not valid) identifier catching RestconfDocumentedException. Error + * type, error tag and error status code are compared to expected values. + * + *

+ * Not valid identifier contains only revision without module name. + */ + @Test + public void getSchemaWrongIdentifierTest() { + // prepare conditions - return correct schema context without mount points + doReturn(SCHEMA_CONTEXT).when(schemaService).getGlobalContext(); + + // make test and verify + final var error = assertError(ar -> restconf.modulesYangGET("2014-01-01", ar)); + assertEquals("Identifier must start with character from set 'a-zA-Z_", error.getErrorMessage()); + assertEquals(ErrorType.PROTOCOL, error.getErrorType()); + assertEquals(ErrorTag.INVALID_VALUE, error.getErrorTag()); + } + + /** + * Try to get schema with wrong (not valid) identifier behind mount point catching + * RestconfDocumentedException. Error type, error tag and error status code are compared to expected + * values. + * + *

+ * Not valid identifier contains only revision without module name. + */ + @Test + public void getSchemaWrongIdentifierMountPointTest() { + // prepare conditions - return correct schema context with mount points + doReturn(SCHEMA_CONTEXT_WITH_MOUNT_POINTS).when(schemaService).getGlobalContext(); + + // make test and verify + final var error = assertError(ar -> restconf.modulesYangGET(MOUNT_POINT + "2014-01-01", ar)); + assertEquals("Identifier must start with character from set 'a-zA-Z_", error.getErrorMessage()); + assertEquals(ErrorType.PROTOCOL, error.getErrorType()); + assertEquals(ErrorTag.INVALID_VALUE, error.getErrorTag()); + } + + /** + * Try to get schema with identifier which does not contain revision catching + * RestconfDocumentedException. Error type, error tag and error status code are compared to expected + * values. + */ + @Test + public void getSchemaWithoutRevisionTest() { + // prepare conditions - return correct schema context without mount points + doReturn(SCHEMA_CONTEXT).when(schemaService).getGlobalContext(); + + // make test and verify + final var error = assertError(ar -> restconf.modulesYangGET("module", ar)); + assertEquals("Revision date must be supplied.", error.getErrorMessage()); + assertEquals(ErrorType.PROTOCOL, error.getErrorType()); + assertEquals(ErrorTag.INVALID_VALUE, error.getErrorTag()); + } + + /** + * Try to get schema behind mount point with identifier when does not contain revision catching + * RestconfDocumentedException. Error type, error tag and error status code are compared to expected + * values. + */ + @Test + public void getSchemaWithoutRevisionMountPointTest() { + // prepare conditions - return correct schema context with mount points + doReturn(SCHEMA_CONTEXT_WITH_MOUNT_POINTS).when(schemaService).getGlobalContext(); + + // make test and verify + final var error = assertError(ar -> restconf.modulesYangGET(MOUNT_POINT + "module", ar)); + assertEquals("Revision date must be supplied.", error.getErrorMessage()); + assertEquals(ErrorType.PROTOCOL, error.getErrorType()); + assertEquals(ErrorTag.INVALID_VALUE, error.getErrorTag()); + } + + /** + * Negative test when mount point module is not found in current SchemaContext for mount points. + * IllegalArgumentException exception is expected. + */ + @Test + public void getSchemaContextWithNotExistingMountPointTest() { + // prepare conditions - return schema context with mount points + doReturn(SCHEMA_CONTEXT_WITH_MOUNT_POINTS).when(schemaService).getGlobalContext(); + + final var error = assertError( + ar -> restconf.modulesYangGET(NOT_EXISTING_MOUNT_POINT + TEST_MODULE_BEHIND_MOUNT_POINT, ar)); + assertEquals("Failed to lookup for module with name 'mount-point-3'.", error.getErrorMessage()); + assertEquals(ErrorType.PROTOCOL, error.getErrorType()); + assertEquals(ErrorTag.UNKNOWN_ELEMENT, error.getErrorTag()); + } +}