Throws RDE exception in case model was not found
[netconf.git] / restconf / restconf-nb / src / test / java / org / opendaylight / restconf / nb / rfc8040 / rests / services / impl / RestconfSchemaServiceTest.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.restconf.nb.rfc8040.rests.services.impl;
9
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertNotNull;
12 import static org.junit.Assert.assertThrows;
13 import static org.mockito.Mockito.when;
14
15 import java.io.FileNotFoundException;
16 import org.junit.AfterClass;
17 import org.junit.Before;
18 import org.junit.BeforeClass;
19 import org.junit.Test;
20 import org.junit.runner.RunWith;
21 import org.mockito.Mock;
22 import org.mockito.junit.MockitoJUnitRunner;
23 import org.opendaylight.mdsal.dom.api.DOMMountPointService;
24 import org.opendaylight.mdsal.dom.api.DOMSchemaService;
25 import org.opendaylight.mdsal.dom.api.DOMYangTextSourceProvider;
26 import org.opendaylight.mdsal.dom.broker.DOMMountPointServiceImpl;
27 import org.opendaylight.mdsal.dom.spi.FixedDOMSchemaService;
28 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
29 import org.opendaylight.restconf.nb.rfc8040.TestRestconfUtils;
30 import org.opendaylight.restconf.nb.rfc8040.handlers.SchemaContextHandler;
31 import org.opendaylight.restconf.nb.rfc8040.rests.services.api.RestconfSchemaService;
32 import org.opendaylight.restconf.nb.rfc8040.rests.services.api.SchemaExportContext;
33 import org.opendaylight.yangtools.yang.common.ErrorTag;
34 import org.opendaylight.yangtools.yang.common.ErrorType;
35 import org.opendaylight.yangtools.yang.common.QName;
36 import org.opendaylight.yangtools.yang.common.Revision;
37 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
38 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
39 import org.opendaylight.yangtools.yang.model.api.Module;
40 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
41
42 /**
43  * Unit tests for {@code RestconfSchemaService}.
44  */
45 @RunWith(MockitoJUnitRunner.StrictStubs.class)
46 public class RestconfSchemaServiceTest {
47     private static final String MOUNT_POINT = "mount-point-1:cont/yang-ext:mount/";
48     private static final String NULL_MOUNT_POINT = "mount-point-2:cont/yang-ext:mount/";
49     private static final String NOT_EXISTING_MOUNT_POINT = "mount-point-3:cont/yang-ext:mount/";
50
51     private static final String TEST_MODULE = "module1/2014-01-01";
52     private static final String TEST_MODULE_BEHIND_MOUNT_POINT = "module1-behind-mount-point/2014-02-03";
53     private static final String NOT_EXISTING_MODULE = "not-existing/2016-01-01";
54
55     // schema context with modules
56     private static EffectiveModelContext SCHEMA_CONTEXT;
57     // schema context with modules behind mount point
58     private static EffectiveModelContext SCHEMA_CONTEXT_BEHIND_MOUNT_POINT;
59     // schema context with mount points
60     private static EffectiveModelContext SCHEMA_CONTEXT_WITH_MOUNT_POINTS;
61
62     // service under test
63     private RestconfSchemaService schemaService;
64
65     // handlers
66     @Mock
67     private SchemaContextHandler mockContextHandler;
68     @Mock
69     private DOMYangTextSourceProvider sourceProvider;
70     // mount point service
71     private DOMMountPointService mountPointService;
72
73     @BeforeClass
74     public static void beforeClass() throws FileNotFoundException {
75         SCHEMA_CONTEXT = YangParserTestUtils.parseYangFiles(TestRestconfUtils.loadFiles("/modules"));
76         SCHEMA_CONTEXT_BEHIND_MOUNT_POINT = YangParserTestUtils.parseYangFiles(
77             TestRestconfUtils.loadFiles("/modules/modules-behind-mount-point"));
78         SCHEMA_CONTEXT_WITH_MOUNT_POINTS = YangParserTestUtils.parseYangFiles(
79             TestRestconfUtils.loadFiles("/modules/mount-points"));
80     }
81
82     @AfterClass
83     public static void afterClass() {
84         SCHEMA_CONTEXT = null;
85         SCHEMA_CONTEXT_BEHIND_MOUNT_POINT = null;
86         SCHEMA_CONTEXT_WITH_MOUNT_POINTS = null;
87     }
88
89     @Before
90     public void setup() throws Exception {
91         this.mountPointService = new DOMMountPointServiceImpl();
92         // create and register mount points
93         mountPointService
94                 .createMountPoint(YangInstanceIdentifier.of(QName.create("mount:point:1", "2016-01-01", "cont")))
95                 .addService(DOMSchemaService.class, FixedDOMSchemaService.of(SCHEMA_CONTEXT_BEHIND_MOUNT_POINT))
96                 .register();
97         mountPointService
98                 .createMountPoint(YangInstanceIdentifier.of(QName.create("mount:point:2", "2016-01-01", "cont")))
99                 .register();
100
101         this.schemaService = new RestconfSchemaServiceImpl(this.mockContextHandler, mountPointService, sourceProvider);
102     }
103
104     /**
105      * Get schema with identifier of existing module and check if correct module was found.
106      */
107     @Test
108     public void getSchemaTest() {
109         // prepare conditions - return not-mount point schema context
110         when(this.mockContextHandler.get()).thenReturn(SCHEMA_CONTEXT);
111
112         // make test
113         final SchemaExportContext exportContext = schemaService.getSchema(TEST_MODULE);
114
115         // verify
116         assertNotNull("Export context should not be null", exportContext);
117
118         final Module module = exportContext.getModule();
119         assertNotNull("Existing module should be found", module);
120
121         assertEquals("Not expected module name", "module1", module.getName());
122         assertEquals("Not expected module revision", Revision.ofNullable("2014-01-01"), module.getRevision());
123         assertEquals("Not expected module namespace", "module:1", module.getNamespace().toString());
124     }
125
126     /**
127      * Get schema with identifier of not-existing module. Trying to create <code>SchemaExportContext</code> with
128      * not-existing module should result in error.
129      */
130     @Test
131     public void getSchemaForNotExistingModuleTest() {
132         // prepare conditions - return not-mount point schema context
133         when(this.mockContextHandler.get()).thenReturn(SCHEMA_CONTEXT);
134
135         // make test & verify
136         final var ex = assertThrows(RestconfDocumentedException.class, () ->
137             schemaService.getSchema(NOT_EXISTING_MODULE));
138         assertEquals("Not expected error tag", ErrorTag.DATA_MISSING, ex.getErrors().get(0).getErrorTag());
139         assertEquals("Not expected error type", ErrorType.APPLICATION, ex.getErrors().get(0).getErrorType());
140     }
141
142     /**
143      * Get schema with identifier of existing module behind mount point and check if correct module was found.
144      */
145     @Test
146     public void getSchemaMountPointTest() {
147         // prepare conditions - return schema context with mount points
148         when(this.mockContextHandler.get()).thenReturn(SCHEMA_CONTEXT_WITH_MOUNT_POINTS);
149
150         // make test
151         final SchemaExportContext exportContext =
152                 schemaService.getSchema(MOUNT_POINT + TEST_MODULE_BEHIND_MOUNT_POINT);
153
154         // verify
155         assertNotNull("Export context should not be null", exportContext);
156
157         final Module module = exportContext.getModule();
158         assertNotNull("Existing module should be found", module);
159
160         assertEquals("Not expected module name", "module1-behind-mount-point", module.getName());
161         assertEquals("Not expected module revision", Revision.ofNullable("2014-02-03"), module.getRevision());
162         assertEquals("Not expected module namespace", "module:1:behind:mount:point", module.getNamespace().toString());
163     }
164
165     /**
166      * Get schema with identifier of not-existing module behind mount point. Trying to create
167      * <code>SchemaExportContext</code> with not-existing module behind mount point should result in error.
168      */
169     @Test
170     public void getSchemaForNotExistingModuleMountPointTest() {
171         // prepare conditions - return schema context with mount points
172         when(this.mockContextHandler.get()).thenReturn(SCHEMA_CONTEXT_WITH_MOUNT_POINTS);
173
174         // make test & verify
175         final var ex = assertThrows(RestconfDocumentedException.class, () ->
176             schemaService.getSchema(MOUNT_POINT + NOT_EXISTING_MODULE));
177         assertEquals("Not expected error tag", ErrorTag.DATA_MISSING, ex.getErrors().get(0).getErrorTag());
178         assertEquals("Not expected error type", ErrorType.APPLICATION, ex.getErrors().get(0).getErrorType());
179     }
180
181     /**
182      * Try to get schema with <code>null</code> <code>SchemaContext</code> expecting <code>NullPointerException</code>.
183      */
184     @Test
185     public void getSchemaWithNullSchemaContextTest() {
186         // prepare conditions - returned schema context is null
187         when(this.mockContextHandler.get()).thenReturn(null);
188
189         // make test
190         assertThrows(NullPointerException.class, () -> schemaService.getSchema(TEST_MODULE));
191     }
192
193     /**
194      * Try to get schema with <code>null</code> <code>SchemaContext</code> for mount points.
195      * <code>NullPointerException</code> is expected.
196      */
197     @Test
198     public void getSchemaWithNullSchemaContextMountPointTest() {
199         // prepare conditions - returned schema context for mount points is null
200         when(this.mockContextHandler.get()).thenReturn(null);
201
202         // make test
203         assertThrows(NullPointerException.class,
204             () -> schemaService.getSchema(MOUNT_POINT + TEST_MODULE_BEHIND_MOUNT_POINT));
205     }
206
207     /**
208      * Try to get schema with <code>null</code> <code>SchemaContext</code> behind mount point when using
209      * <code>NULL_MOUNT_POINT</code>. Test is expected to fail with <code>NullPointerException</code>.
210      */
211     @Test
212     public void getSchemaNullSchemaContextBehindMountPointTest() {
213         // prepare conditions - return correct schema context for mount points (this is not null)
214         when(this.mockContextHandler.get()).thenReturn(SCHEMA_CONTEXT_WITH_MOUNT_POINTS);
215
216         // make test - call service on mount point with null schema context
217         assertThrows(IllegalStateException.class,
218             // NULL_MOUNT_POINT contains null schema context
219             () -> this.schemaService.getSchema(NULL_MOUNT_POINT + TEST_MODULE_BEHIND_MOUNT_POINT));
220     }
221
222     /**
223      * Try to get schema with null identifier expecting <code>NullPointerException</code>. The same processing is for
224      * server and also for mount point.
225      */
226     @Test
227     public void getSchemaWithNullIdentifierTest() {
228         // prepare conditions - return correct schema context
229         when(this.mockContextHandler.get()).thenReturn(SCHEMA_CONTEXT);
230
231         // make test
232         assertThrows(NullPointerException.class, () -> this.schemaService.getSchema(null));
233     }
234
235     /**
236      * Try to get schema with empty (not valid) identifier catching <code>RestconfDocumentedException</code>. Error
237      * type, error tag and error status code are compared to expected values.
238      */
239     @Test
240     public void getSchemaWithEmptyIdentifierTest() {
241         // prepare conditions - return correct schema context
242         when(this.mockContextHandler.get()).thenReturn(SCHEMA_CONTEXT);
243
244         // make test and verify
245         final RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class,
246             () -> schemaService.getSchema(""));
247         assertEquals(ErrorType.PROTOCOL, ex.getErrors().get(0).getErrorType());
248         assertEquals(ErrorTag.INVALID_VALUE, ex.getErrors().get(0).getErrorTag());
249     }
250
251     /**
252      * Try to get schema with empty (not valid) identifier behind mount point catching
253      * <code>RestconfDocumentedException</code>. Error type, error tag and error status code are compared to expected
254      * values.
255      */
256     @Test
257     public void getSchemaWithEmptyIdentifierMountPointTest() {
258         // prepare conditions - return correct schema context with mount points
259         when(this.mockContextHandler.get()).thenReturn(SCHEMA_CONTEXT_WITH_MOUNT_POINTS);
260
261         // make test and verify
262         final RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class,
263             () -> schemaService.getSchema(MOUNT_POINT + ""));
264         assertEquals(ErrorType.PROTOCOL, ex.getErrors().get(0).getErrorType());
265         assertEquals(ErrorTag.INVALID_VALUE, ex.getErrors().get(0).getErrorTag());
266     }
267
268     /**
269      * Try to get schema with not-parsable identifier catching <code>RestconfDocumentedException</code>. Error type,
270      * error tag and error status code are compared to expected values.
271      */
272     @Test
273     public void getSchemaWithNotParsableIdentifierTest() {
274         // prepare conditions - return correct schema context without mount points
275         when(this.mockContextHandler.get()).thenReturn(SCHEMA_CONTEXT);
276
277         // make test and verify
278         final RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class,
279             () -> schemaService.getSchema("01_module/2016-01-01"));
280         assertEquals(ErrorType.PROTOCOL, ex.getErrors().get(0).getErrorType());
281         assertEquals(ErrorTag.INVALID_VALUE, ex.getErrors().get(0).getErrorTag());
282     }
283
284     /**
285      * Try to get schema behind mount point with not-parsable identifier catching
286      * <code>RestconfDocumentedException</code>. Error type, error tag and error status code are compared to expected
287      * values.
288      */
289     @Test
290     public void getSchemaWithNotParsableIdentifierMountPointTest() {
291         // prepare conditions - return correct schema context with mount points
292         when(this.mockContextHandler.get()).thenReturn(SCHEMA_CONTEXT_WITH_MOUNT_POINTS);
293
294         // make test and verify
295         final RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class,
296             () -> schemaService.getSchema(MOUNT_POINT + "01_module/2016-01-01"));
297         assertEquals(ErrorType.PROTOCOL, ex.getErrors().get(0).getErrorType());
298         assertEquals(ErrorTag.INVALID_VALUE, ex.getErrors().get(0).getErrorTag());
299     }
300
301     /**
302      * Try to get schema with wrong (not valid) identifier catching <code>RestconfDocumentedException</code>. Error
303      * type, error tag and error status code are compared to expected values.
304      *
305      * <p>
306      * Not valid identifier contains only revision without module name.
307      */
308     @Test
309     public void getSchemaWrongIdentifierTest() {
310         // prepare conditions - return correct schema context without mount points
311         when(this.mockContextHandler.get()).thenReturn(SCHEMA_CONTEXT);
312
313         // make test and verify
314         final RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class,
315             () -> schemaService.getSchema("2014-01-01"));
316         assertEquals(ErrorType.PROTOCOL, ex.getErrors().get(0).getErrorType());
317         assertEquals(ErrorTag.INVALID_VALUE, ex.getErrors().get(0).getErrorTag());
318     }
319
320     /**
321      * Try to get schema with wrong (not valid) identifier behind mount point catching
322      * <code>RestconfDocumentedException</code>. Error type, error tag and error status code are compared to expected
323      * values.
324      *
325      * <p>
326      * Not valid identifier contains only revision without module name.
327      */
328     @Test
329     public void getSchemaWrongIdentifierMountPointTest() {
330         // prepare conditions - return correct schema context with mount points
331         when(this.mockContextHandler.get()).thenReturn(SCHEMA_CONTEXT_WITH_MOUNT_POINTS);
332
333         // make test and verify
334         final RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class,
335             () -> schemaService.getSchema(MOUNT_POINT + "2014-01-01"));
336         assertEquals(ErrorType.PROTOCOL, ex.getErrors().get(0).getErrorType());
337         assertEquals(ErrorTag.INVALID_VALUE, ex.getErrors().get(0).getErrorTag());
338     }
339
340     /**
341      * Try to get schema with identifier which does not contain revision catching
342      * <code>RestconfDocumentedException</code>. Error type, error tag and error status code are compared to expected
343      * values.
344      */
345     @Test
346     public void getSchemaWithoutRevisionTest() {
347         // prepare conditions - return correct schema context without mount points
348         when(this.mockContextHandler.get()).thenReturn(SCHEMA_CONTEXT);
349
350         // make test and verify
351         final RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class,
352             () -> schemaService.getSchema("module"));
353         assertEquals(ErrorType.PROTOCOL, ex.getErrors().get(0).getErrorType());
354         assertEquals(ErrorTag.INVALID_VALUE, ex.getErrors().get(0).getErrorTag());
355     }
356
357     /**
358      * Try to get schema behind mount point with identifier when does not contain revision catching
359      * <code>RestconfDocumentedException</code>. Error type, error tag and error status code are compared to expected
360      * values.
361      */
362     @Test
363     public void getSchemaWithoutRevisionMountPointTest() {
364         // prepare conditions - return correct schema context with mount points
365         when(this.mockContextHandler.get()).thenReturn(SCHEMA_CONTEXT_WITH_MOUNT_POINTS);
366
367         // make test and verify
368         final RestconfDocumentedException ex = assertThrows(RestconfDocumentedException.class,
369             () -> schemaService.getSchema(MOUNT_POINT + "module"));
370         assertEquals(ErrorType.PROTOCOL, ex.getErrors().get(0).getErrorType());
371         assertEquals(ErrorTag.INVALID_VALUE, ex.getErrors().get(0).getErrorTag());
372     }
373
374     /**
375      * Negative test when mount point module is not found in current <code>SchemaContext</code> for mount points.
376      * <code>IllegalArgumentException</code> exception is expected.
377      */
378     @Test
379     public void getSchemaContextWithNotExistingMountPointTest() {
380         // prepare conditions - return schema context with mount points
381         when(this.mockContextHandler.get()).thenReturn(SCHEMA_CONTEXT_WITH_MOUNT_POINTS);
382
383         // make test
384         assertThrows(RestconfDocumentedException.class,
385             () -> schemaService.getSchema(NOT_EXISTING_MOUNT_POINT + TEST_MODULE_BEHIND_MOUNT_POINT));
386     }
387 }