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