Bug 6325 - upgrade draft11 to draft15 - renaming
[netconf.git] / restconf / sal-rest-connector / src / test / java / org / opendaylight / restconf / utils / mapping / RestconfMappingNodeUtilTest.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.utils.mapping;
9
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertFalse;
12 import static org.junit.Assert.assertNotNull;
13 import static org.junit.Assert.fail;
14 import static org.mockito.Mockito.mock;
15 import static org.mockito.Mockito.when;
16
17 import com.google.common.collect.Sets;
18 import java.util.AbstractMap;
19 import java.util.Collections;
20 import java.util.HashMap;
21 import java.util.HashSet;
22 import java.util.Iterator;
23 import java.util.Map;
24 import java.util.Map.Entry;
25 import java.util.NoSuchElementException;
26 import java.util.Set;
27 import org.junit.Before;
28 import org.junit.BeforeClass;
29 import org.junit.Rule;
30 import org.junit.Test;
31 import org.junit.rules.ExpectedException;
32 import org.mockito.Mock;
33 import org.mockito.MockitoAnnotations;
34 import org.opendaylight.controller.md.sal.rest.common.TestRestconfUtils;
35 import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException;
36 import org.opendaylight.netconf.sal.restconf.impl.RestconfError.ErrorTag;
37 import org.opendaylight.netconf.sal.restconf.impl.RestconfError.ErrorType;
38 import org.opendaylight.restconf.Draft15;
39 import org.opendaylight.restconf.Draft15.MonitoringModule;
40 import org.opendaylight.restconf.Draft15.RestconfModule;
41 import org.opendaylight.restconf.utils.schema.context.RestconfSchemaUtil;
42 import org.opendaylight.yangtools.yang.common.QName;
43 import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
44 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
45 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
46 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
47 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
48 import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableDataContainerAttrNode;
49 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
50 import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
51 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
52 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
53 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
54 import org.opendaylight.yangtools.yang.model.api.Module;
55 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
56
57 /**
58  * Unit tests for {@link RestconfMappingNodeUtil}
59  */
60 public class RestconfMappingNodeUtilTest {
61     @Rule
62     public ExpectedException thrown = ExpectedException.none();
63
64     @Mock private ListSchemaNode mockStreamList;
65     @Mock private LeafSchemaNode leafName;
66     @Mock private LeafSchemaNode leafDescription;
67     @Mock private LeafSchemaNode leafReplaySupport;
68     @Mock private LeafSchemaNode leafReplayLog;
69     @Mock private LeafSchemaNode leafEvents;
70
71     private static Set<Module> modules;
72     private static SchemaContext schemaContext;
73     private Set<DataSchemaNode> allStreamChildNodes;
74
75     @BeforeClass
76     public static void loadTestSchemaContextAndModules() throws Exception {
77         RestconfMappingNodeUtilTest.schemaContext = TestRestconfUtils.loadSchemaContext(
78                 "/modules/restconf-module-testing");
79         RestconfMappingNodeUtilTest.modules = TestRestconfUtils.loadSchemaContext("/modules").getModules();
80     }
81
82     @Before
83     public void setup() throws Exception {
84         MockitoAnnotations.initMocks(this);
85
86         when(this.leafName.getQName()).thenReturn(QName.create("", RestconfMappingNodeConstants.NAME));
87         when(this.leafDescription.getQName()).thenReturn(QName.create("", RestconfMappingNodeConstants.DESCRIPTION));
88         when(this.leafReplaySupport.getQName()).thenReturn(
89                 QName.create("", RestconfMappingNodeConstants.REPLAY_SUPPORT));
90         when(this.leafReplayLog.getQName()).thenReturn(QName.create(RestconfMappingNodeConstants.REPLAY_LOG));
91         when(this.leafEvents.getQName()).thenReturn(QName.create("", RestconfMappingNodeConstants.EVENTS));
92
93         this.allStreamChildNodes = Sets.newHashSet(
94                 this.leafName, this.leafDescription, this.leafReplaySupport, this.leafReplayLog, this.leafEvents);
95     }
96
97     /**
98      * Test of writing modules into {@link RestconfModule#MODULE_LIST_SCHEMA_NODE} and checking if modules were
99      * correctly written.
100      */
101     @Test
102     public void restconfMappingNodeTest() {
103         // write modules into list module in Restconf
104         final MapNode modules = RestconfMappingNodeUtil.restconfMappingNode(
105                 getTestingRestconfModule("ietf-restconf"), RestconfMappingNodeUtilTest.modules);
106
107         // verify loaded modules
108         verifyLoadedModules(modules);
109     }
110
111     /**
112      * Positive test of writing one stream to {@link MonitoringModule#STREAM_LIST_SCHEMA_NODE} and checking if stream
113      * was correctly written.
114      */
115     @Test
116     public void toStreamEntryNodeTest() {
117         // test stream name
118         final String stream1 = "stream-1";
119
120         // get list stream node from Restconf module
121         final ListSchemaNode listStream = (ListSchemaNode) RestconfSchemaUtil.getRestconfSchemaNode(
122                 getTestingRestconfModule("ietf-restconf"), MonitoringModule.STREAM_LIST_SCHEMA_NODE);
123
124         // write stream to list stream node
125         final MapEntryNode mapEntryNode = RestconfMappingNodeUtil.toStreamEntryNode(stream1, listStream);
126
127         // verify
128         verifyStream(stream1, mapEntryNode);
129     }
130
131     /**
132      * Test mapping modules to list with <code>null</code> Restconf module. Test fails with
133      * <code>NullPointerException</code>.
134      */
135     @Test
136     public void restconfMappingNodeMissingRestconfModuleNegativeTest() {
137         thrown.expect(NullPointerException.class);
138         RestconfMappingNodeUtil.restconfMappingNode(null, RestconfMappingNodeUtilTest.modules);
139     }
140
141     /**
142      * Try to map modules into module list when Restconf module is available but does not contain node
143      * {@link RestconfModule#MODULE_LIST_SCHEMA_NODE}. <code>RestconfDocumentedException</code> is expected and error
144      * type, error tag and error status code are compared to expected values.
145      */
146     @Test
147     public void restconfMappingNodeMissingModuleListNegativeTest() {
148         try {
149             RestconfMappingNodeUtil.restconfMappingNode(
150                     getTestingRestconfModule("restconf-module-with-missing-list-module"),
151                     RestconfMappingNodeUtilTest.modules);
152             fail("Test should fail due to missing "
153                     + RestconfModule.MODULE_LIST_SCHEMA_NODE
154                     + " node in Restconf module");
155         } catch (final RestconfDocumentedException e) {
156             assertEquals("Error type is not correct",
157                     ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
158             assertEquals("Error tag is not correct",
159                     ErrorTag.DATA_MISSING, e.getErrors().get(0).getErrorTag());
160             assertEquals("Error status code is not correct",
161                     404, e.getErrors().get(0).getErrorTag().getStatusCode());
162         }
163     }
164
165     /**
166      * Try to map modules into module list when Restconf module is available and contains node
167      * {@link RestconfModule#MODULE_LIST_SCHEMA_NODE} but it is not of type list. <code>IllegalStateException</code>
168      * should be returned.
169      */
170     @Test
171     public void restconfMappingNodeIllegalModuleListNegativeTest() {
172         thrown.expect(IllegalStateException.class);
173         RestconfMappingNodeUtil.restconfMappingNode(
174                 getTestingRestconfModule("restconf-module-with-illegal-list-module"),
175                 RestconfMappingNodeUtilTest.modules);
176     }
177
178     /**
179      * Map <code>null</code> set of modules to module list. <code>NullPointerException</code> is expected.
180      */
181     @Test
182     public void restconfMappingNodeNullModulesNegativeTest() {
183         thrown.expect(NullPointerException.class);
184         RestconfMappingNodeUtil.restconfMappingNode(getTestingRestconfModule("ietf-restconf"), null);
185     }
186
187     /**
188      * Try to map modules into list module of Restconf module when Restconf module does not contain grouping
189      * {@link RestconfModule#RESTCONF_GROUPING_SCHEMA_NODE}. <code>RestconfDocumentedException</code> is expected and
190      * error type, error tag and error status code are compared to expected values.
191      */
192     @Test
193     public void restconfMappingNodeNoRestconfGroupingNegativeTest() {
194         try {
195             RestconfMappingNodeUtil.restconfMappingNode(
196                     getTestingRestconfModule("restconf-module-with-missing-grouping-restconf"),
197                     RestconfMappingNodeUtilTest.modules);
198             fail("Test should fail due to missing "
199                     + RestconfModule.RESTCONF_GROUPING_SCHEMA_NODE
200                     + " grouping in Restconf module groupings");
201         } catch (final RestconfDocumentedException e) {
202             assertEquals("Error type is not correct",
203                     ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
204             assertEquals("Error tag is not correct",
205                     ErrorTag.DATA_MISSING, e.getErrors().get(0).getErrorTag());
206             assertEquals("Error status code is not correct",
207                     404, e.getErrors().get(0).getErrorTag().getStatusCode());
208         }
209     }
210
211     /**
212      * Try to map modules into list module of Restconf module when Restconf module does not contain any grouping.
213      * Test is catching <code>RestconfDocumentedException</code> and checking error type, error and error status code.
214      */
215     @Test
216     public void restconfMappingNodeNoGroupingsNegativeTest() {
217         // prepare conditions
218         final Module mockRestconfModule = mock(Module.class);
219         when(mockRestconfModule.getGroupings()).thenReturn(Sets.newHashSet());
220
221         // test
222         try {
223             RestconfMappingNodeUtil.restconfMappingNode(mockRestconfModule, RestconfMappingNodeUtilTest.modules);
224             fail("Test should fail due to no child nodes in Restconf grouping");
225         } catch (final RestconfDocumentedException e) {
226             assertEquals("Error type is not correct",
227                     ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
228             assertEquals("Error tag is not correct",
229                     ErrorTag.DATA_MISSING, e.getErrors().get(0).getErrorTag());
230             assertEquals("Error status code is not correct",
231                     404, e.getErrors().get(0).getErrorTag().getStatusCode());
232         }
233     }
234
235     /**
236      * Test when there is a grouping with name {@link RestconfModule#RESTCONF_GROUPING_SCHEMA_NODE} in Restconf
237      * module but contains no child nodes. <code>NoSuchElementException</code> is expected.
238      */
239     @Test
240     public void restconfMappingNodeRestconfGroupingNoChildNegativeTest() {
241         // prepare conditions
242         final Module mockRestconfModule = mock(Module.class);
243         final GroupingDefinition mockRestconfGrouping = mock(GroupingDefinition.class);
244         when(mockRestconfGrouping.getQName()).thenReturn(QName.create(
245                 "", RestconfModule.RESTCONF_GROUPING_SCHEMA_NODE));
246         when(mockRestconfModule.getGroupings()).thenReturn(Sets.newHashSet(mockRestconfGrouping));
247         when(mockRestconfGrouping.getChildNodes()).thenReturn(Sets.newHashSet());
248
249         // test
250         thrown.expect(NoSuchElementException.class);
251         RestconfMappingNodeUtil.restconfMappingNode(mockRestconfModule, RestconfMappingNodeUtilTest.modules);
252     }
253
254     /**
255      * {@link RestconfModule#MODULE_LIST_SCHEMA_NODE} in Restconf module does not contain any child with name
256      * {@link RestconfMappingNodeConstants#NAME}. Test fails with <code>RestconfDocumentedException</code> checking
257      * error type, error tag and error status code.
258      */
259     @Test
260     public void restconfMappingNodeMissingNameNegativeTest() {
261         try {
262             RestconfMappingNodeUtil.restconfMappingNode(
263                     getTestingRestconfModule("restconf-module-with-missing-leaf-name-in-list-module"),
264                     RestconfMappingNodeUtilTest.modules);
265             fail("Test should fail due to missing leaf "
266                     + RestconfMappingNodeConstants.NAME
267                     + " in "
268                     + RestconfModule.MODULE_LIST_SCHEMA_NODE
269                     + " node");
270         } catch (final RestconfDocumentedException e) {
271             assertEquals("Error type is not correct",
272                     ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
273             assertEquals("Error tag is not correct",
274                     ErrorTag.DATA_MISSING, e.getErrors().get(0).getErrorTag());
275             assertEquals("Error status code is not correct",
276                     404, e.getErrors().get(0).getErrorTag().getStatusCode());
277         }
278     }
279
280     /**
281      * {@link RestconfModule#MODULE_LIST_SCHEMA_NODE} in Restconf module does not contain any child with name
282      * {@link RestconfMappingNodeConstants#REVISION}. Test fails with <code>RestconfDocumentedException</code> checking
283      * error type, error tag and error status code.
284      */
285     @Test
286     public void restconfMappingNodeMissingRevisionNegativeTest() {
287         try {
288             RestconfMappingNodeUtil.restconfMappingNode(
289                     getTestingRestconfModule("restconf-module-with-missing-leaf-revision-in-list-module"),
290                     RestconfMappingNodeUtilTest.modules);
291             fail("Test should fail due to missing leaf "
292                     + RestconfMappingNodeConstants.REVISION
293                     + " in "
294                     + RestconfModule.MODULE_LIST_SCHEMA_NODE
295                     + " node");
296         } catch (final RestconfDocumentedException e) {
297             assertEquals("Error type is not correct",
298                     ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
299             assertEquals("Error tag is not correct",
300                     ErrorTag.DATA_MISSING, e.getErrors().get(0).getErrorTag());
301             assertEquals("Error status code is not correct",
302                     404, e.getErrors().get(0).getErrorTag().getStatusCode());
303         }
304     }
305
306     /**
307      * {@link RestconfModule#MODULE_LIST_SCHEMA_NODE} in Restconf module does not contain any child with name
308      * {@link RestconfMappingNodeConstants#NAMESPACE}. Test fails with <code>RestconfDocumentedException</code>
309      * checking error type, error tag and error status code.
310      */
311     @Test
312     public void restconfMappingNodeMissingNamespaceNegativeTest() {
313         try {
314             RestconfMappingNodeUtil.restconfMappingNode(
315                     getTestingRestconfModule("restconf-module-with-missing-leaf-namespace-in-list-module"),
316                     RestconfMappingNodeUtilTest.modules);
317             fail("Test should fail due to missing leaf "
318                     + RestconfMappingNodeConstants.NAMESPACE
319                     + " in "
320                     + RestconfModule.MODULE_LIST_SCHEMA_NODE
321                     + " node");
322         } catch (final RestconfDocumentedException e) {
323             assertEquals("Error type is not correct",
324                     ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
325             assertEquals("Error tag is not correct",
326                     ErrorTag.DATA_MISSING, e.getErrors().get(0).getErrorTag());
327             assertEquals("Error status code is not correct",
328                     404, e.getErrors().get(0).getErrorTag().getStatusCode());
329         }
330     }
331
332     /**
333      * {@link RestconfModule#MODULE_LIST_SCHEMA_NODE} in Restconf module does not contain any child with name
334      * {@link RestconfMappingNodeConstants#FEATURE}. Test fails with <code>RestconfDocumentedException</code> checking
335      * error type, error tag and error status code.
336      */
337     @Test
338     public void restconfMappingNodeMissingFeaturesNegativeTest() {
339         try {
340             RestconfMappingNodeUtil.restconfMappingNode(
341                     getTestingRestconfModule("restconf-module-with-missing-leaf-list-feature-in-list-module"),
342                     RestconfMappingNodeUtilTest.modules);
343             fail("Test should fail due to missing leaf "
344                     + RestconfMappingNodeConstants.FEATURE
345                     + " in "
346                     + RestconfModule.MODULE_LIST_SCHEMA_NODE
347                     + " node");
348         } catch (final RestconfDocumentedException e) {
349             assertEquals("Error type is not correct",
350                     ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
351             assertEquals("Error tag is not correct",
352                     ErrorTag.DATA_MISSING, e.getErrors().get(0).getErrorTag());
353             assertEquals("Error status code is not correct",
354                     404, e.getErrors().get(0).getErrorTag().getStatusCode());
355         }
356     }
357
358     /**
359      *
360      * {@link RestconfModule#MODULE_LIST_SCHEMA_NODE} in Restconf module contains child with name
361      * {@link RestconfMappingNodeConstants#NAME} but it is not of type leaf. Test fails with
362      * <code>IllegalStateException</code>.
363      */
364     @Test
365     public void restconfMappingNodeIllegalNameNegativeTest() {
366         thrown.expect(IllegalStateException.class);
367         RestconfMappingNodeUtil.restconfMappingNode(
368                 getTestingRestconfModule("restconf-module-with-illegal-leaf-name-in-list-module"),
369                 RestconfMappingNodeUtilTest.modules);
370     }
371
372     /**
373      *
374      * {@link RestconfModule#MODULE_LIST_SCHEMA_NODE} in Restconf module contains child with name
375      * {@link RestconfMappingNodeConstants#REVISION} but it is not of type leaf. Test fails with
376      * <code>IllegalStateException</code>.
377      */
378     @Test
379     public void restconfMappingNodeIllegalRevisionNegativeTest() {
380         thrown.expect(IllegalStateException.class);
381         RestconfMappingNodeUtil.restconfMappingNode(
382                 getTestingRestconfModule("restconf-module-with-illegal-leaf-revision-in-list-module"),
383                 RestconfMappingNodeUtilTest.modules);
384     }
385
386     /**
387      * {@link RestconfModule#MODULE_LIST_SCHEMA_NODE} in Restconf module contains child with name
388      * {@link RestconfMappingNodeConstants#NAMESPACE} but it is not of type leaf. Test fails with
389      * <code>IllegalStateException</code>.
390      */
391     @Test
392     public void restconfMappingNodeIllegalNamespaceNegativeTest() {
393         thrown.expect(IllegalStateException.class);
394         RestconfMappingNodeUtil.restconfMappingNode(
395                 getTestingRestconfModule("restconf-module-with-illegal-leaf-namespace-in-list-module"),
396                 RestconfMappingNodeUtilTest.modules);
397     }
398
399     /**
400      * Module list in Restconf module contains child with name {@link RestconfMappingNodeConstants#FEATURE} but it is
401      * not of type leaf-list. Test fails with <code>IllegalStateException</code>.
402      */
403     @Test
404     public void restconfMappingNodeIllegalFeatureNegativeTest() {
405         thrown.expect(IllegalStateException.class);
406         RestconfMappingNodeUtil.restconfMappingNode(
407                 getTestingRestconfModule("restconf-module-with-illegal-leaf-list-feature-in-list-module"),
408                 RestconfMappingNodeUtilTest.modules);
409     }
410
411     /**
412      * Try to map streams when {@link MonitoringModule#STREAM_LIST_SCHEMA_NODE} is <code>null</code>.
413      * Test is expected to fail catching <code>IllegalStateException</code>.
414      */
415     @Test
416     public void toStreamEntryNodeNullListStreamNegativeTest() {
417         thrown.expect(IllegalStateException.class);
418         RestconfMappingNodeUtil.toStreamEntryNode("stream-1", null);
419     }
420
421     /**
422      * Test trying to map streams to {@link MonitoringModule#STREAM_LIST_SCHEMA_NODE} which is not of type list.
423      * Test is expected to fail with <code>IllegalStateException</code>.
424      */
425     @Test
426     public void toStreamEntryNodeIllegalListStreamNegativeTest() {
427         thrown.expect(IllegalStateException.class);
428         RestconfMappingNodeUtil.toStreamEntryNode("stream-1", mock(LeafSchemaNode.class));
429     }
430
431     /**
432      * Test case with target {@link MonitoringModule#STREAM_LIST_SCHEMA_NODE} which does not contain any child nodes.
433      * Test is catching <code>RestconfDocumentedException</code> and error type, error tag and error status code are
434      * compared to expected values.
435      */
436     @Test
437     public void toStreamEntryNodeSchemaNodeWithoutChildsNegativeTest() {
438         final ListSchemaNode mockListNode = mock(ListSchemaNode.class);
439         when(mockListNode.getChildNodes()).thenReturn(Collections.EMPTY_SET);
440
441        try {
442            RestconfMappingNodeUtil.toStreamEntryNode("stream-1", mockListNode);
443            fail("Test should fail due to no child nodes in"
444                    + MonitoringModule.STREAM_LIST_SCHEMA_NODE
445                    + " node");
446        } catch (final RestconfDocumentedException e) {
447            assertEquals("Error type is not correct",
448                    ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
449            assertEquals("Error tag is not correct",
450                    ErrorTag.DATA_MISSING, e.getErrors().get(0).getErrorTag());
451            assertEquals("Error status code is not correct",
452                    404, e.getErrors().get(0).getErrorTag().getStatusCode());
453        }
454     }
455
456     /**
457      * Test case when target list stream does not contain child with name {@link RestconfMappingNodeConstants#NAME}.
458      * Test is catching <code>RestconfDocumentedException</code> and error type, error tag and error status code are
459      * compared to expected values.
460      */
461     @Test
462     public void toStreamEntryNodeMissingStreamNameNegativeTest() {
463         prepareMockListWithMissingLeaf(this.leafName);
464
465         try {
466             RestconfMappingNodeUtil.toStreamEntryNode("stream-1", this.mockStreamList);
467             fail("Test should fail due to missing "
468                     + RestconfMappingNodeConstants.NAME
469                     + " node in " + MonitoringModule.STREAM_LIST_SCHEMA_NODE);
470         } catch (final RestconfDocumentedException e) {
471             assertEquals("Error type is not correct",
472                     ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
473             assertEquals("Error tag is not correct",
474                     ErrorTag.DATA_MISSING, e.getErrors().get(0).getErrorTag());
475             assertEquals("Error status code is not correct",
476                     404, e.getErrors().get(0).getErrorTag().getStatusCode());
477         }
478     }
479
480     /**
481      * Test case when target list stream does not contain child with name
482      * {@link RestconfMappingNodeConstants#DESCRIPTION}. Test is catching <code>RestconfDocumentedException</code> and
483      * checking error type and error tag.
484      */
485     @Test
486     public void toStreamEntryNodeMissingStreamDescriptionNegativeTest() {
487         prepareMockListWithMissingLeaf(this.leafDescription);
488
489         try {
490             RestconfMappingNodeUtil.toStreamEntryNode("stream-1", this.mockStreamList);
491             fail("Test should fail due to missing "
492                     + RestconfMappingNodeConstants.DESCRIPTION
493                     + " node in " + MonitoringModule.STREAM_LIST_SCHEMA_NODE);
494         } catch (final RestconfDocumentedException e) {
495             assertEquals("Error type is not correct",
496                     ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
497             assertEquals("Error tag is not correct",
498                     ErrorTag.DATA_MISSING, e.getErrors().get(0).getErrorTag());
499             assertEquals("Error status code is not correct",
500                     404, e.getErrors().get(0).getErrorTag().getStatusCode());
501         }
502     }
503
504     /**
505      * Test case when target list stream does not contain child with name
506      * {@link RestconfMappingNodeConstants#REPLAY_SUPPORT}. Test is catching <code>RestconfDocumentedException</code>
507      * and checking error type and error tag.
508      */
509     @Test
510     public void toStreamEntryNodeMissingStreamReplaySupportNegativeTest() {
511         prepareMockListWithMissingLeaf(this.leafReplaySupport);
512
513         try {
514             RestconfMappingNodeUtil.toStreamEntryNode("stream-1", this.mockStreamList);
515             fail("Test should fail due to missing "
516                     + RestconfMappingNodeConstants.REPLAY_SUPPORT
517                     + " node in " + MonitoringModule.STREAM_LIST_SCHEMA_NODE);
518         } catch (final RestconfDocumentedException e) {
519             assertEquals("Error type is not correct",
520                     ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
521             assertEquals("Error tag is not correct",
522                     ErrorTag.DATA_MISSING, e.getErrors().get(0).getErrorTag());
523             assertEquals("Error status code is not correct",
524                     404, e.getErrors().get(0).getErrorTag().getStatusCode());
525         }
526     }
527
528     /**
529      * Test case when target list stream does not contain child with name
530      * {@link RestconfMappingNodeConstants#REPLAY_LOG}. Test is catching <code>RestconfDocumentedException</code> and
531      * checking error type and error tag.
532      */
533     @Test
534     public void toStreamEntryNodeMissingStreamReplayLogNegativeTest() {
535         prepareMockListWithMissingLeaf(this.leafReplayLog);
536
537         try {
538             RestconfMappingNodeUtil.toStreamEntryNode("stream-1", this.mockStreamList);
539             fail("Test should fail due to missing "
540                     + RestconfMappingNodeConstants.REPLAY_LOG
541                     + " node in " + MonitoringModule.STREAM_LIST_SCHEMA_NODE);
542         } catch (final RestconfDocumentedException e) {
543             assertEquals("Error type is not correct",
544                     ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
545             assertEquals("Error tag is not correct",
546                     ErrorTag.DATA_MISSING, e.getErrors().get(0).getErrorTag());
547             assertEquals("Error status code is not correct",
548                     404, e.getErrors().get(0).getErrorTag().getStatusCode());
549         }
550     }
551
552     /**
553      * Test case when target list stream does not contain child with name {@link RestconfMappingNodeConstants#EVENTS}.
554      * Test is catching <code>RestconfDocumentedException</code> and checking error type, error tag and error status
555      * code.
556      */
557     @Test
558     public void toStreamEntryNodeMissingStreamEventsNegativeTest() {
559         prepareMockListWithMissingLeaf(this.leafEvents);
560
561         try {
562             RestconfMappingNodeUtil.toStreamEntryNode("stream-1", this.mockStreamList);
563             fail("Test should fail due to missing "
564                     + RestconfMappingNodeConstants.EVENTS
565                     + " node in " + MonitoringModule.STREAM_LIST_SCHEMA_NODE);
566         } catch (final RestconfDocumentedException e) {
567             assertEquals("Error type is not correct",
568                     ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
569             assertEquals("Error tag is not correct",
570                     ErrorTag.DATA_MISSING, e.getErrors().get(0).getErrorTag());
571             assertEquals("Error status code is not correct",
572                     404, e.getErrors().get(0).getErrorTag().getStatusCode());
573         }
574     }
575
576     /**
577      * Test case when target list stream contains child with name {@link RestconfMappingNodeConstants#NAME}. Test is
578      * expecting <code>IllegalStateException</code>.
579      */
580     @Test
581     public void toStreamEntryNodeStreamNameNegativeTest() {
582         prepareMockListWithIllegalLeaf(this.leafName);
583
584         thrown.expect(IllegalStateException.class);
585         RestconfMappingNodeUtil.toStreamEntryNode("stream-1", this.mockStreamList);
586     }
587
588     /**
589      * Test case when target list stream contains child with name {@link RestconfMappingNodeConstants#DESCRIPTION}.
590      * Test is expecting <code>IllegalStateException</code>.
591      */
592     @Test
593     public void toStreamEntryNodeStreamDescriptionNegativeTest() {
594         prepareMockListWithIllegalLeaf(this.leafDescription);
595
596         thrown.expect(IllegalStateException.class);
597         RestconfMappingNodeUtil.toStreamEntryNode("stream-1", this.mockStreamList);
598     }
599
600     /**
601      * Test case when target list stream contains child with name {@link RestconfMappingNodeConstants#REPLAY_SUPPORT}.
602      * Test is expecting <code>IllegalStateException</code>.
603      */
604     @Test
605     public void toStreamEntryNodeStreamReplaySupportNegativeTest() {
606         prepareMockListWithIllegalLeaf(this.leafReplaySupport);
607
608         thrown.expect(IllegalStateException.class);
609         RestconfMappingNodeUtil.toStreamEntryNode("stream-1", this.mockStreamList);
610     }
611
612     /**
613      * Test case when target list stream contains child with name {@link RestconfMappingNodeConstants#REPLAY_LOG}.
614      * Test is expecting <code>IllegalStateException</code>.
615      */
616     @Test
617     public void toStreamEntryNodeStreamReplayLogNegativeTest() {
618         prepareMockListWithIllegalLeaf(this.leafReplayLog);
619
620         thrown.expect(IllegalStateException.class);
621         RestconfMappingNodeUtil.toStreamEntryNode("stream-1", this.mockStreamList);
622     }
623
624     /**
625      * Test case when target list stream contains child with name {@link RestconfMappingNodeConstants#EVENTS}. Test is
626      * expecting <code>IllegalStateException</code>.
627      */
628     @Test
629     public void toStreamEntryNodeStreamEventsNegativeTest() {
630         prepareMockListWithIllegalLeaf(this.leafEvents);
631
632         thrown.expect(IllegalStateException.class);
633         RestconfMappingNodeUtil.toStreamEntryNode("stream-1", this.mockStreamList);
634     }
635
636     /**
637      * Utils
638      */
639
640     /**
641      * Verify loaded modules from Restconf module
642      * @param modules Returned modules node
643      */
644     private void verifyLoadedModules(final MapNode modules) {
645         final Iterator<MapEntryNode> iterator = modules.getValue().iterator();
646         final Map<String, String> loadedModules = new HashMap<>();
647
648         while (iterator.hasNext()) {
649             final Iterator entries = ((AbstractImmutableDataContainerAttrNode) iterator.next())
650                     .getChildren().entrySet().iterator();
651
652             String name = null;
653             String revision = null;
654
655             boolean notAllowedKey = false;
656             while (entries.hasNext()) {
657                 final Entry e = ((AbstractMap.SimpleImmutableEntry) entries.next());
658                 final String key = ((YangInstanceIdentifier.NodeIdentifier) e.getKey()).getNodeType().getLocalName();
659
660                 switch (key) {
661                     case RestconfMappingNodeConstants.NAME:
662                         name = (String) ((LeafNode) e.getValue()).getValue();
663                         break;
664                     case RestconfMappingNodeConstants.REVISION:
665                         revision = (String) ((LeafNode) e.getValue()).getValue();
666                         break;
667                     case RestconfMappingNodeConstants.NAMESPACE:
668                         // fall through
669                     case RestconfMappingNodeConstants.FEATURE:
670                         break;
671                     default:
672                         notAllowedKey = true;
673                         break;
674                 }
675             }
676
677             assertFalse("Not allowed key in list module found", notAllowedKey);
678             loadedModules.put(name, revision);
679         }
680
681         verifyLoadedModules(RestconfMappingNodeUtilTest.modules, loadedModules);
682     }
683
684     /**
685      * Verify if correct modules were loaded into Restconf module by comparison with modules from
686      * <code>SchemaContext</code>.
687      * @param expectedModules Modules from <code>SchemaContext</code>
688      * @param loadedModules Loaded modules into Restconf module
689      */
690     private final void verifyLoadedModules(final Set<Module> expectedModules,
691                                            final Map<String, String> loadedModules) {
692         assertEquals("Number of loaded modules is not as expected", expectedModules.size(), loadedModules.size());
693         for (final Module m : expectedModules) {
694             final String name = m.getName();
695
696             final String revision = loadedModules.get(name);
697             assertNotNull("Expected module not found", revision);
698             assertEquals("Not correct revision of loaded module",
699                     SimpleDateFormatUtil.getRevisionFormat().format(m.getRevision()), revision);
700
701             loadedModules.remove(name);
702         }
703     }
704
705     /**
706      * Verify if a stream was correctly written into {@link MonitoringModule#STREAM_LIST_SCHEMA_NODE} node in Restconf
707      * module.
708      * @param streamName Expected stream name
709      * @param streamNode Writetn strem node from Restconf module
710      */
711     private final void verifyStream(final String streamName, final MapEntryNode streamNode) {
712         assertNotNull("Stream node can not be null", streamNode);
713         final Iterator entries = ((AbstractImmutableDataContainerAttrNode) streamNode)
714                 .getChildren().entrySet().iterator();
715         boolean notAllowedKey = false;
716
717         while (entries.hasNext()) {
718             final Entry e = ((AbstractMap.SimpleImmutableEntry) entries.next());
719             final String key = ((YangInstanceIdentifier.NodeIdentifier) e.getKey()).getNodeType().getLocalName();
720
721             switch (key) {
722                 case RestconfMappingNodeConstants.NAME :
723                     assertEquals("Stream name value is not as expected",
724                             streamName, ((LeafNode) e.getValue()).getValue());
725                     break;
726                 case RestconfMappingNodeConstants.DESCRIPTION :
727                     assertEquals("Stream description value is not as expected",
728                             RestconfMappingStreamConstants.DESCRIPTION, ((LeafNode) e.getValue()).getValue());
729                     break;
730                 case RestconfMappingNodeConstants.REPLAY_SUPPORT :
731                     assertEquals("Stream replay support value is not as expected",
732                             RestconfMappingStreamConstants.REPLAY_SUPPORT, ((LeafNode) e.getValue()).getValue());
733                     break;
734                 case RestconfMappingNodeConstants.REPLAY_LOG :
735                     assertEquals("Stream replay log value is not as expected",
736                             RestconfMappingStreamConstants.REPLAY_LOG, ((LeafNode) e.getValue()).getValue());
737                     break;
738                 case RestconfMappingNodeConstants.EVENTS :
739                     assertEquals("Stream events value is not as expected",
740                             RestconfMappingStreamConstants.EVENTS, ((LeafNode) e.getValue()).getValue());
741                     break;
742                 default:
743                     notAllowedKey = true;
744                     break;
745             }
746         }
747
748         assertFalse("Not allowed key in list stream found", notAllowedKey);
749     }
750
751     /**
752      * There are multiple testing Restconf modules for different test cases. It is possible to distinguish them by
753      * name or by namespace. This method is looking for Restconf test module by its name.
754      * @param s Testing Restconf module name
755      * @return Restconf module
756      */
757     private Module getTestingRestconfModule(final String s) {
758         return RestconfMappingNodeUtilTest.schemaContext.findModuleByName(
759                 s, Draft15.RestconfModule.IETF_RESTCONF_QNAME.getRevision());
760     }
761
762     /**
763      * Updates {@link this#mockStreamList} to NOT contains specified leaf.
764      * @param leaf Leaf to be missing
765      */
766     private void prepareMockListWithMissingLeaf(final LeafSchemaNode leaf) {
767         // prepare set of leaf without selected leaf
768         final Set childLeafs = new HashSet<>(this.allStreamChildNodes);
769         childLeafs.remove(leaf);
770
771         // mock list leaf nodes
772         when(this.mockStreamList.getChildNodes()).thenReturn(childLeafs);
773     }
774
775     /**
776      * Updates {@link this#mockStreamList} to contains specified leaf which is not of type {@link LeafSchemaNode}.
777      * @param leaf Leaf to be changes
778      */
779     private void prepareMockListWithIllegalLeaf(final LeafSchemaNode leaf) {
780         // prepare set of leaf without selected leaf
781         final Set childLeafs = new HashSet<>(this.allStreamChildNodes);
782         childLeafs.remove(leaf);
783
784         // add leaf-list with the same local name as removed leaf
785         final String localName = leaf.getQName().getLocalName();
786         final LeafListSchemaNode mockLeafList = mock(LeafListSchemaNode.class);
787         when(mockLeafList.getQName()).thenReturn(QName.create("", localName));
788         childLeafs.add(mockLeafList);
789
790         // mock list leaf nodes
791         when(this.mockStreamList.getChildNodes()).thenReturn(childLeafs);
792     }
793 }