2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.restconf.nb.jaxrs;
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertSame;
12 import static org.mockito.Mockito.doReturn;
13 import static org.opendaylight.restconf.nb.jaxrs.AbstractRestconfTest.assertEntity;
14 import static org.opendaylight.restconf.nb.jaxrs.AbstractRestconfTest.assertError;
16 import com.google.common.io.CharStreams;
17 import com.google.common.util.concurrent.Futures;
18 import java.io.Reader;
19 import org.junit.Before;
20 import org.junit.Test;
21 import org.junit.runner.RunWith;
22 import org.mockito.Mock;
23 import org.mockito.junit.MockitoJUnitRunner;
24 import org.opendaylight.mdsal.dom.api.DOMActionService;
25 import org.opendaylight.mdsal.dom.api.DOMDataBroker;
26 import org.opendaylight.mdsal.dom.api.DOMRpcService;
27 import org.opendaylight.mdsal.dom.api.DOMSchemaService;
28 import org.opendaylight.mdsal.dom.api.DOMYangTextSourceProvider;
29 import org.opendaylight.mdsal.dom.broker.DOMMountPointServiceImpl;
30 import org.opendaylight.mdsal.dom.spi.FixedDOMSchemaService;
31 import org.opendaylight.restconf.nb.rfc8040.databind.DatabindContext;
32 import org.opendaylight.restconf.nb.rfc8040.legacy.ErrorTags;
33 import org.opendaylight.restconf.server.mdsal.DOMSourceResolver;
34 import org.opendaylight.restconf.server.mdsal.MdsalRestconfServer;
35 import org.opendaylight.yangtools.yang.common.ErrorTag;
36 import org.opendaylight.yangtools.yang.common.ErrorType;
37 import org.opendaylight.yangtools.yang.common.QName;
38 import org.opendaylight.yangtools.yang.common.Revision;
39 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
40 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
41 import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
42 import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
43 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
46 * Unit tests for {@code RestconfSchemaService}.
48 @RunWith(MockitoJUnitRunner.StrictStubs.class)
49 public class RestconfSchemaServiceTest {
50 private static final String MOUNT_POINT = "mount-point-1:cont/yang-ext:mount/";
51 private static final String NULL_MOUNT_POINT = "mount-point-2:cont/yang-ext:mount/";
52 private static final String NOT_EXISTING_MOUNT_POINT = "mount-point-3:cont/yang-ext:mount/";
54 private static final String TEST_MODULE = "module1/2014-01-01";
55 private static final String TEST_MODULE_BEHIND_MOUNT_POINT = "module1-behind-mount-point/2014-02-03";
56 private static final String NOT_EXISTING_MODULE = "not-existing/2016-01-01";
58 // schema context with modules
59 private static final EffectiveModelContext SCHEMA_CONTEXT =
60 YangParserTestUtils.parseYangResourceDirectory("/modules");
61 // schema context with modules behind mount point
62 private static final EffectiveModelContext SCHEMA_CONTEXT_BEHIND_MOUNT_POINT =
63 YangParserTestUtils.parseYangResourceDirectory("/modules/modules-behind-mount-point");
64 // schema context with mount points
65 private static final EffectiveModelContext SCHEMA_CONTEXT_WITH_MOUNT_POINTS =
66 YangParserTestUtils.parseYangResourceDirectory("/modules/mount-points");
70 private DOMSchemaService schemaService;
72 private DOMYangTextSourceProvider sourceProvider;
74 private DOMDataBroker dataBroker;
76 private DOMActionService actionService;
78 private DOMRpcService rpcService;
80 private YangTextSchemaSource yangSource;
82 private Reader yangReader;
85 private JaxRsRestconf restconf;
88 public void setup() throws Exception {
89 final var mountPointService = new DOMMountPointServiceImpl();
90 // create and register mount points
92 .createMountPoint(YangInstanceIdentifier.of(QName.create("mount:point:1", "2016-01-01", "cont")))
93 .addService(DOMSchemaService.class, FixedDOMSchemaService.of(SCHEMA_CONTEXT_BEHIND_MOUNT_POINT))
96 .createMountPoint(YangInstanceIdentifier.of(QName.create("mount:point:2", "2016-01-01", "cont")))
99 restconf = new JaxRsRestconf(new MdsalRestconfServer(
100 () -> DatabindContext.ofModel(schemaService.getGlobalContext(), new DOMSourceResolver(sourceProvider)),
101 dataBroker, rpcService, actionService, mountPointService));
105 * Get schema with identifier of existing module and check if correct module was found.
108 public void getSchemaTest() throws Exception {
109 // prepare conditions - return not-mount point schema context
110 doReturn(SCHEMA_CONTEXT).when(schemaService).getGlobalContext();
111 doReturn(Futures.immediateFuture(yangSource)).when(sourceProvider)
112 .getSource(new SourceIdentifier("module1", Revision.of("2014-01-01")));
113 doReturn(yangReader).when(yangSource).openStream();
115 assertSame(yangReader, assertEntity(Reader.class, 200, ar -> restconf.modulesYangGET(TEST_MODULE, ar)));
119 * Get schema with identifier of not-existing module. Trying to create <code>SchemaExportContext</code> with
120 * not-existing module should result in error.
123 public void getSchemaForNotExistingModuleTest() {
124 // prepare conditions - return not-mount point schema context
125 doReturn(SCHEMA_CONTEXT).when(schemaService).getGlobalContext();
127 final var error = assertError(ar -> restconf.modulesYinGET(NOT_EXISTING_MODULE, ar));
128 assertEquals("Source not-existing@2016-01-01 not found", error.getErrorMessage());
129 assertEquals(ErrorTag.DATA_MISSING, error.getErrorTag());
130 assertEquals(ErrorType.APPLICATION, error.getErrorType());
134 * Get schema with identifier of existing module behind mount point and check if correct module was found.
137 public void getSchemaMountPointTest() throws Exception {
138 // prepare conditions - return schema context with mount points
139 doReturn(SCHEMA_CONTEXT_WITH_MOUNT_POINTS).when(schemaService).getGlobalContext();
141 final var reader = assertEntity(Reader.class, 200,
142 ar -> restconf.modulesYangGET(MOUNT_POINT + TEST_MODULE_BEHIND_MOUNT_POINT, ar));
144 module module1-behind-mount-point {
145 namespace module:1:behind:mount:point;
148 rpc rpc-behind-module1;
150 """, CharStreams.toString(reader));
154 * Get schema with identifier of not-existing module behind mount point. Trying to create
155 * <code>SchemaExportContext</code> with not-existing module behind mount point should result in error.
158 public void getSchemaForNotExistingModuleMountPointTest() {
159 // prepare conditions - return schema context with mount points
160 doReturn(SCHEMA_CONTEXT_WITH_MOUNT_POINTS).when(schemaService).getGlobalContext();
162 final var error = assertError(ar -> restconf.modulesYangGET(MOUNT_POINT + NOT_EXISTING_MODULE, ar));
163 assertEquals("Source not-existing@2016-01-01 not found", error.getErrorMessage());
164 assertEquals(ErrorTag.DATA_MISSING, error.getErrorTag());
165 assertEquals(ErrorType.APPLICATION, error.getErrorType());
169 * Try to get schema with <code>null</code> <code>SchemaContext</code> behind mount point when using
170 * <code>NULL_MOUNT_POINT</code>. Test is expected to fail with <code>NullPointerException</code>.
173 public void getSchemaNullSchemaContextBehindMountPointTest() {
174 // prepare conditions - return correct schema context for mount points (this is not null)
175 doReturn(SCHEMA_CONTEXT_WITH_MOUNT_POINTS).when(schemaService).getGlobalContext();
177 // make test - call service on mount point with null schema context
178 // NULL_MOUNT_POINT contains null schema context
179 final var error = assertError(
180 ar -> restconf.modulesYangGET(NULL_MOUNT_POINT + TEST_MODULE_BEHIND_MOUNT_POINT, ar));
181 assertEquals("Mount point mount-point-2:cont does not expose DOMSchemaService", error.getErrorMessage());
182 assertEquals(ErrorType.PROTOCOL, error.getErrorType());
183 assertEquals(ErrorTags.RESOURCE_DENIED_TRANSPORT, error.getErrorTag());
187 * Try to get schema with empty (not valid) identifier catching <code>RestconfDocumentedException</code>. Error
188 * type, error tag and error status code are compared to expected values.
191 public void getSchemaWithEmptyIdentifierTest() {
192 // prepare conditions - return correct schema context
193 doReturn(SCHEMA_CONTEXT).when(schemaService).getGlobalContext();
195 final var error = assertError(ar -> restconf.modulesYangGET("", ar));
196 assertEquals("Identifier must start with character from set 'a-zA-Z_", error.getErrorMessage());
197 assertEquals(ErrorType.PROTOCOL, error.getErrorType());
198 assertEquals(ErrorTag.INVALID_VALUE, error.getErrorTag());
202 * Try to get schema with empty (not valid) identifier behind mount point catching
203 * <code>RestconfDocumentedException</code>. Error type, error tag and error status code are compared to expected
207 public void getSchemaWithEmptyIdentifierMountPointTest() {
208 // prepare conditions - return correct schema context with mount points
209 doReturn(SCHEMA_CONTEXT_WITH_MOUNT_POINTS).when(schemaService).getGlobalContext();
211 // make test and verify
212 final var error = assertError(ar -> restconf.modulesYangGET(MOUNT_POINT + "", ar));
213 assertEquals("Identifier must start with character from set 'a-zA-Z_", error.getErrorMessage());
214 assertEquals(ErrorType.PROTOCOL, error.getErrorType());
215 assertEquals(ErrorTag.INVALID_VALUE, error.getErrorTag());
219 * Try to get schema with not-parsable identifier catching <code>RestconfDocumentedException</code>. Error type,
220 * error tag and error status code are compared to expected values.
223 public void getSchemaWithNotParsableIdentifierTest() {
224 // prepare conditions - return correct schema context without mount points
225 doReturn(SCHEMA_CONTEXT).when(schemaService).getGlobalContext();
227 // make test and verify
228 final var error = assertError(ar -> restconf.modulesYangGET("01_module/2016-01-01", ar));
229 assertEquals("Identifier must start with character from set 'a-zA-Z_", error.getErrorMessage());
230 assertEquals(ErrorType.PROTOCOL, error.getErrorType());
231 assertEquals(ErrorTag.INVALID_VALUE, error.getErrorTag());
235 * Try to get schema behind mount point with not-parsable identifier catching
236 * <code>RestconfDocumentedException</code>. Error type, error tag and error status code are compared to expected
240 public void getSchemaWithNotParsableIdentifierMountPointTest() {
241 // prepare conditions - return correct schema context with mount points
242 doReturn(SCHEMA_CONTEXT_WITH_MOUNT_POINTS).when(schemaService).getGlobalContext();
244 // make test and verify
245 final var error = assertError(ar -> restconf.modulesYangGET(MOUNT_POINT + "01_module/2016-01-01", ar));
246 assertEquals("Identifier must start with character from set 'a-zA-Z_", error.getErrorMessage());
247 assertEquals(ErrorType.PROTOCOL, error.getErrorType());
248 assertEquals(ErrorTag.INVALID_VALUE, error.getErrorTag());
252 * Try to get schema with wrong (not valid) identifier catching <code>RestconfDocumentedException</code>. Error
253 * type, error tag and error status code are compared to expected values.
256 * Not valid identifier contains only revision without module name.
259 public void getSchemaWrongIdentifierTest() {
260 // prepare conditions - return correct schema context without mount points
261 doReturn(SCHEMA_CONTEXT).when(schemaService).getGlobalContext();
263 // make test and verify
264 final var error = assertError(ar -> restconf.modulesYangGET("2014-01-01", ar));
265 assertEquals("Identifier must start with character from set 'a-zA-Z_", error.getErrorMessage());
266 assertEquals(ErrorType.PROTOCOL, error.getErrorType());
267 assertEquals(ErrorTag.INVALID_VALUE, error.getErrorTag());
271 * Try to get schema with wrong (not valid) identifier behind mount point catching
272 * <code>RestconfDocumentedException</code>. Error type, error tag and error status code are compared to expected
276 * Not valid identifier contains only revision without module name.
279 public void getSchemaWrongIdentifierMountPointTest() {
280 // prepare conditions - return correct schema context with mount points
281 doReturn(SCHEMA_CONTEXT_WITH_MOUNT_POINTS).when(schemaService).getGlobalContext();
283 // make test and verify
284 final var error = assertError(ar -> restconf.modulesYangGET(MOUNT_POINT + "2014-01-01", ar));
285 assertEquals("Identifier must start with character from set 'a-zA-Z_", error.getErrorMessage());
286 assertEquals(ErrorType.PROTOCOL, error.getErrorType());
287 assertEquals(ErrorTag.INVALID_VALUE, error.getErrorTag());
291 * Try to get schema with identifier which does not contain revision catching
292 * <code>RestconfDocumentedException</code>. Error type, error tag and error status code are compared to expected
296 public void getSchemaWithoutRevisionTest() {
297 // prepare conditions - return correct schema context without mount points
298 doReturn(SCHEMA_CONTEXT).when(schemaService).getGlobalContext();
300 // make test and verify
301 final var error = assertError(ar -> restconf.modulesYangGET("module", ar));
302 assertEquals("Revision date must be supplied.", error.getErrorMessage());
303 assertEquals(ErrorType.PROTOCOL, error.getErrorType());
304 assertEquals(ErrorTag.INVALID_VALUE, error.getErrorTag());
308 * Try to get schema behind mount point with identifier when does not contain revision catching
309 * <code>RestconfDocumentedException</code>. Error type, error tag and error status code are compared to expected
313 public void getSchemaWithoutRevisionMountPointTest() {
314 // prepare conditions - return correct schema context with mount points
315 doReturn(SCHEMA_CONTEXT_WITH_MOUNT_POINTS).when(schemaService).getGlobalContext();
317 // make test and verify
318 final var error = assertError(ar -> restconf.modulesYangGET(MOUNT_POINT + "module", ar));
319 assertEquals("Revision date must be supplied.", error.getErrorMessage());
320 assertEquals(ErrorType.PROTOCOL, error.getErrorType());
321 assertEquals(ErrorTag.INVALID_VALUE, error.getErrorTag());
325 * Negative test when mount point module is not found in current <code>SchemaContext</code> for mount points.
326 * <code>IllegalArgumentException</code> exception is expected.
329 public void getSchemaContextWithNotExistingMountPointTest() {
330 // prepare conditions - return schema context with mount points
331 doReturn(SCHEMA_CONTEXT_WITH_MOUNT_POINTS).when(schemaService).getGlobalContext();
333 final var error = assertError(
334 ar -> restconf.modulesYangGET(NOT_EXISTING_MOUNT_POINT + TEST_MODULE_BEHIND_MOUNT_POINT, ar));
335 assertEquals("Failed to lookup for module with name 'mount-point-3'.", error.getErrorMessage());
336 assertEquals(ErrorType.PROTOCOL, error.getErrorType());
337 assertEquals(ErrorTag.UNKNOWN_ELEMENT, error.getErrorTag());