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