3d816655a82f852c2a7af5af1d6aeadf1d327a48
[netconf.git] / restconf / restconf-nb-bierman02 / src / test / java / org / opendaylight / restconf / utils / parser / ParserIdentifierTest.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
9 package org.opendaylight.restconf.utils.parser;
10
11 import static org.junit.Assert.assertEquals;
12 import static org.junit.Assert.assertNotNull;
13 import static org.junit.Assert.assertNull;
14 import static org.junit.Assert.fail;
15 import static org.mockito.Mockito.when;
16
17 import com.google.common.base.Optional;
18 import com.google.common.collect.ImmutableClassToInstanceMap;
19 import com.google.common.collect.Maps;
20 import org.junit.Before;
21 import org.junit.Rule;
22 import org.junit.Test;
23 import org.junit.rules.ExpectedException;
24 import org.mockito.Mock;
25 import org.mockito.MockitoAnnotations;
26 import org.opendaylight.controller.md.sal.dom.api.DOMMountPoint;
27 import org.opendaylight.controller.md.sal.dom.api.DOMMountPointService;
28 import org.opendaylight.controller.md.sal.dom.broker.impl.mount.DOMMountPointServiceImpl;
29 import org.opendaylight.controller.md.sal.dom.broker.spi.mount.SimpleDOMMountPoint;
30 import org.opendaylight.controller.md.sal.rest.common.TestRestconfUtils;
31 import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
32 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
33 import org.opendaylight.restconf.common.errors.RestconfError;
34 import org.opendaylight.restconf.common.errors.RestconfError.ErrorTag;
35 import org.opendaylight.restconf.common.errors.RestconfError.ErrorType;
36 import org.opendaylight.restconf.common.schema.SchemaExportContext;
37 import org.opendaylight.restconf.parser.IdentifierCodec;
38 import org.opendaylight.restconf.utils.RestconfConstants;
39 import org.opendaylight.yangtools.yang.common.QName;
40 import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
41 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
42 import org.opendaylight.yangtools.yang.model.api.Module;
43 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
44 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
45
46 /**
47  * Unit tests for {@link ParserIdentifier}.
48  */
49 public class ParserIdentifierTest {
50     // mount point identifier
51     private static final String MOUNT_POINT_IDENT =
52             "mount-point:mount-container/point-number" + "/" + RestconfConstants.MOUNT;
53
54     // invalid mount point identifier
55     private static final String INVALID_MOUNT_POINT_IDENT =
56             "mount-point:point-number" + "/" + RestconfConstants.MOUNT;
57
58     // test identifier + expected result
59     private static final String TEST_IDENT =
60             "parser-identifier:cont1/cont2/listTest/list-in-grouping=name/leaf-A.B";
61
62     private static final String TEST_IDENT_RESULT =
63             "/(parser:identifier?revision=2016-06-02)cont1/cont2/listTest/listTest/list-in-grouping/"
64             + "list-in-grouping[{(parser:identifier?revision=2016-06-02)name=name}]/leaf-A.B";
65
66     // test identifier with nodes defined in other modules using augmentation + expected result
67     private static final String TEST_IDENT_OTHERS =
68             "parser-identifier-included:list-1=name,2016-06-02/parser-identifier:augment-leaf";
69
70     private static final String TEST_IDENT_OTHERS_RESULT =
71             "/(parser:identifier:included?revision=2016-06-02)list-1/list-1"
72             + "[{(parser:identifier:included?revision=2016-06-02)name=name, "
73             + "(parser:identifier:included?revision=2016-06-02)revision=2016-06-02}]"
74             + "/AugmentationIdentifier{childNames=[(parser:identifier?revision=2016-06-02)augment-leaf]}/"
75             + "(parser:identifier?revision=2016-06-02)augment-leaf";
76
77     // invalid test identifier
78     private static final String INVALID_TEST_IDENT =
79             "parser-identifier:cont2/listTest/list-in-grouping=name/leaf-A.B";
80
81     // schema context with test modules
82     private SchemaContext schemaContext;
83     // contains the same modules but it is different object (it can be compared with equals)
84     private SchemaContext schemaContextOnMountPoint;
85
86     private static final String TEST_MODULE_NAME = "test-module";
87     private static final String TEST_MODULE_REVISION = "2016-06-02";
88     private static final String TEST_MODULE_NAMESPACE = "test:module";
89
90     private static final String INVOKE_RPC = "invoke-rpc-module:rpc-test";
91
92     // mount point and mount point service
93     private DOMMountPoint mountPoint;
94     private DOMMountPointService mountPointService;
95
96     // mock mount point and mount point service
97     @Mock
98     private DOMMountPoint mockMountPoint;
99     @Mock
100     private DOMMountPointService mockMountPointService;
101
102     @Rule
103     public final ExpectedException thrown = ExpectedException.none();
104
105     @Before
106     public void setup() throws Exception {
107         MockitoAnnotations.initMocks(this);
108         this.schemaContext = YangParserTestUtils.parseYangSources(TestRestconfUtils.loadFiles("/parser-identifier"));
109         this.schemaContextOnMountPoint =
110                 YangParserTestUtils.parseYangSources(TestRestconfUtils.loadFiles("/parser-identifier"));
111
112         // create and register mount point
113         this.mountPoint = SimpleDOMMountPoint.create(
114                 YangInstanceIdentifier.builder()
115                         .node(QName.create("mount:point", "2016-06-02", "mount-container"))
116                         .node(QName.create("mount:point", "2016-06-02", "point-number"))
117                         .build(),
118                 ImmutableClassToInstanceMap.copyOf(Maps.newHashMap()),
119                 this.schemaContextOnMountPoint
120         );
121
122         this.mountPointService = new DOMMountPointServiceImpl();
123         ((DOMMountPointServiceImpl) this.mountPointService).registerMountPoint(this.mountPoint);
124
125         // register mount point with null schema context
126         when(this.mockMountPoint.getSchemaContext()).thenReturn(null);
127         when(this.mockMountPointService.getMountPoint(YangInstanceIdentifier.EMPTY))
128                 .thenReturn(Optional.of(this.mockMountPoint));
129     }
130
131     /**
132      * {@link ParserIdentifier#toInstanceIdentifier(String, SchemaContext)} tests.
133      */
134
135     /**
136      * Positive test of creating <code>InstanceIdentifierContext</code> from identifier when all nodes are defined
137      * in one module.
138      */
139     @Test
140     public void toInstanceIdentifierTest() {
141         final InstanceIdentifierContext<?> context = ParserIdentifier.toInstanceIdentifier(
142                 TEST_IDENT, this.schemaContext, Optional.absent());
143
144         assertEquals("Returned not expected identifier",
145                 TEST_IDENT_RESULT, context .getInstanceIdentifier().toString());
146     }
147
148     /**
149      * Positive test of creating <code>InstanceIdentifierContext</code> from identifier when nodes are defined in
150      * multiple modules.
151      */
152     @Test
153     public void toInstanceIdentifierOtherModulesTest() {
154         final InstanceIdentifierContext<?> context = ParserIdentifier.toInstanceIdentifier(
155                 TEST_IDENT_OTHERS, this.schemaContext, Optional.absent());
156
157         assertEquals("Returned not expected identifier",
158                 TEST_IDENT_OTHERS_RESULT, context.getInstanceIdentifier().toString());
159     }
160
161     /**
162      * Positive test of creating <code>InstanceIdentifierContext</code> from identifier containing
163      * {@link RestconfConstants#MOUNT}.
164      */
165     @Test
166     public void toInstanceIdentifierMountPointTest() {
167         final InstanceIdentifierContext<?> context = ParserIdentifier.toInstanceIdentifier(
168                 MOUNT_POINT_IDENT + "/" + TEST_IDENT, this.schemaContext, Optional.of(this.mountPointService));
169
170         assertEquals("Returned not expected identifier",
171                 TEST_IDENT_RESULT.toString(), context.getInstanceIdentifier().toString());
172
173         assertEquals("Mount point not found",
174                 this.mountPoint, context.getMountPoint());
175
176         assertEquals("Schema context from mount point expected",
177                 this.schemaContextOnMountPoint, context.getSchemaContext());
178     }
179
180     /**
181      * Test of creating <code>InstanceIdentifierContext</code> when identifier is <code>null</code>.
182      * <code>{@link YangInstanceIdentifier#EMPTY}</code> should be returned.
183      */
184     @Test
185     public void toInstanceIdentifierNullIdentifierTest() {
186         final InstanceIdentifierContext<?> context = ParserIdentifier.toInstanceIdentifier(
187                 null, this.schemaContext, Optional.absent());
188         assertEquals("Returned not expected identifier",
189                 YangInstanceIdentifier.EMPTY, context.getInstanceIdentifier());
190     }
191
192     /**
193      * Negative test of creating <code>InstanceIdentifierContext</code> when <code>SchemaContext</code> is
194      * <code>null</code>. Test fails expecting <code>NullPointerException</code>.
195      */
196     @Test
197     public void toInstanceIdentifierNullSchemaContextNegativeTest() {
198         this.thrown.expect(NullPointerException.class);
199         ParserIdentifier.toInstanceIdentifier(TEST_IDENT, null, Optional.absent());
200     }
201
202     /**
203      * Api path can be empty. <code>YangInstanceIdentifier.EMPTY</code> is expected to be returned.
204      */
205     @Test
206     public void toInstanceIdentifierEmptyIdentifierTest() {
207         final InstanceIdentifierContext<?> context = ParserIdentifier.toInstanceIdentifier(
208                 "", this.schemaContext, Optional.absent());
209         assertEquals("Returned not expected identifier",
210                 YangInstanceIdentifier.EMPTY, context.getInstanceIdentifier());
211     }
212
213     /**
214      * Negative test with invalid test identifier. Test should fail with <code>IllegalArgumentException</code>.
215      */
216     @Test
217     public void toInstanceIdentifierInvalidIdentifierNegativeTest() {
218         this.thrown.expect(IllegalArgumentException.class);
219         ParserIdentifier.toInstanceIdentifier(INVALID_TEST_IDENT, this.schemaContext, Optional.absent());
220     }
221
222     /**
223      * Negative test when identifier contains {@link RestconfConstants#MOUNT} but identifier part is not valid. Test
224      * should fail with <code>IllegalArgumentException</code>.
225      */
226     @Test
227     public void toInstanceIdentifierMountPointInvalidIdentifierNegativeTest() {
228         this.thrown.expect(IllegalArgumentException.class);
229         ParserIdentifier.toInstanceIdentifier(
230                 INVALID_MOUNT_POINT_IDENT, this.schemaContext, Optional.of(this.mountPointService));
231     }
232
233     /**
234      * Negative test when <code>DOMMountPoint</code> cannot be found. Test is expected to fail with
235      * <code>RestconfDocumentedException</code> error type, error tag and error status code are
236      * compared to expected values.
237      */
238     @Test
239     public void toInstanceIdentifierMissingMountPointNegativeTest() {
240         try {
241             ParserIdentifier.toInstanceIdentifier(
242                     "" + "/" + RestconfConstants.MOUNT, this.schemaContext, Optional.of(this.mountPointService));
243             fail("Test should fail due to missing mount point");
244         } catch (final RestconfDocumentedException e) {
245             assertEquals("Not expected error type",
246                     RestconfError.ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
247             assertEquals("Not expected error tag",
248                     ErrorTag.DATA_MISSING, e.getErrors().get(0).getErrorTag());
249             assertEquals("Not expected error status code",
250                     404, e.getErrors().get(0).getErrorTag().getStatusCode());
251         }
252     }
253
254     /**
255      * Negative test when <code>{@link DOMMountPointService}</code> is absent. Test is expected to fail with
256      * <code>RestconfDocumentedException</code> error type, error tag and error status code are
257      * compared to expected values.
258      */
259     @Test
260     public void toInstanceIdentifierMissingMountPointServiceNegativeTest() {
261         try {
262             ParserIdentifier.toInstanceIdentifier(RestconfConstants.MOUNT, this.schemaContext, Optional.absent());
263             fail("Test should fail due to absent mount point service");
264         } catch (final RestconfDocumentedException e) {
265             assertEquals("Not expected error type",
266                     ErrorType.APPLICATION, e.getErrors().get(0).getErrorType());
267             assertEquals("Not expected error tag",
268                     ErrorTag.OPERATION_FAILED, e.getErrors().get(0).getErrorTag());
269             assertEquals("Not expected error status code",
270                     500, e.getErrors().get(0).getErrorTag().getStatusCode());
271         }
272     }
273
274     /**
275      * {@link ParserIdentifier#makeQNameFromIdentifier(String)} tests.
276      */
277
278     /**
279      * Positive test of making <code>QName</code> from identifier and compare values from returned <code>QName</code>
280      * to expected values.
281      */
282     @Test
283     public void makeQNameFromIdentifierTest() {
284         final QName qName = ParserIdentifier.makeQNameFromIdentifier(TEST_MODULE_NAME + "/" + TEST_MODULE_REVISION);
285
286         assertNotNull("QName should be created", qName);
287         assertEquals("Returned not expected module name",
288                 TEST_MODULE_NAME, qName.getLocalName());
289         assertEquals("Returned not expected module revision",
290                 TEST_MODULE_REVISION, qName.getFormattedRevision());
291     }
292
293     /**
294      * Negative test when supplied identifier is in invalid format and then revision is not parsable.
295      * <code>RestconfDocumentedException</code> is expected and error type, error tag and error status code are
296      * compared to expected values.
297      */
298     @Test
299     public void makeQNameFromIdentifierInvalidIdentifierNegativeTest() {
300         try {
301             ParserIdentifier.makeQNameFromIdentifier(TEST_MODULE_REVISION + "/" + TEST_MODULE_NAME);
302             fail("Test should fail due to invalid identifier format");
303         } catch (final RestconfDocumentedException e) {
304             assertEquals("Not expected error type",
305                     RestconfError.ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
306             assertEquals("Not expected error tag",
307                     RestconfError.ErrorTag.INVALID_VALUE, e.getErrors().get(0).getErrorTag());
308             assertEquals("Not expected error status code",
309                     400, e.getErrors().get(0).getErrorTag().getStatusCode());
310         }
311     }
312
313     /**
314      * Negative test when supplied identifier is too short (contains only module name).
315      * <code>RestconfDocumentedException</code> is expected and error type, error tag and error status code are
316      * compared to expected values.
317      */
318     @Test
319     public void makeQNameFromIdentifierTooShortIdentifierNegativeTest() {
320         try {
321             ParserIdentifier.makeQNameFromIdentifier(TEST_MODULE_NAME);
322             fail("Test should fail due to too short identifier format");
323         } catch (final RestconfDocumentedException e) {
324             assertEquals("Not expected error type",
325                     RestconfError.ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
326             assertEquals("Not expected error tag",
327                     RestconfError.ErrorTag.INVALID_VALUE, e.getErrors().get(0).getErrorTag());
328             assertEquals("Not expected error status code",
329                     400, e.getErrors().get(0).getErrorTag().getStatusCode());
330         }
331     }
332
333     /**
334      * Positive test of making <code>QName</code> from identifier for module behind mount point. Value from returned
335      * <code>QName</code> are compared to expected values.
336      */
337     @Test
338     public void makeQNameFromIdentifierMountTest() {
339         final QName qName = ParserIdentifier.makeQNameFromIdentifier(
340                 MOUNT_POINT_IDENT
341                 + "/"
342                 + TEST_MODULE_NAME
343                 + "/"
344                 + TEST_MODULE_REVISION);
345
346         assertNotNull("QName should be created", qName);
347         assertEquals("Returned not expected module name",
348                 TEST_MODULE_NAME, qName.getLocalName());
349         assertEquals("Returned not expected module revision",
350                 TEST_MODULE_REVISION, qName.getFormattedRevision());
351     }
352
353     /**
354      * Negative test when supplied identifier for module behind mount point is in invalid format and then revision is
355      * not parsable. <code>RestconfDocumentedException</code> is expected and error type, error tag and error status
356      * code are compared to expected values.
357      */
358     @Test
359     public void makeQNameFromIdentifierMountPointInvalidIdentifierNegativeTest() {
360         try {
361             ParserIdentifier.makeQNameFromIdentifier(
362                     MOUNT_POINT_IDENT
363                     + "/"
364                     + TEST_MODULE_REVISION
365                     + "/"
366                     + TEST_MODULE_NAME);
367
368             fail("Test should fail due to invalid identifier format");
369         } catch (final RestconfDocumentedException e) {
370             assertEquals("Not expected error type",
371                     RestconfError.ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
372             assertEquals("Not expected error tag",
373                     RestconfError.ErrorTag.INVALID_VALUE, e.getErrors().get(0).getErrorTag());
374             assertEquals("Not expected error status code",
375                     400, e.getErrors().get(0).getErrorTag().getStatusCode());
376         }
377     }
378
379     /**
380      * Negative test when supplied identifier for module behind mount point is too short (contains only module name).
381      * <code>RestconfDocumentedException</code> is expected and error type, error tag and error status code
382      * are compared to expected values.
383      */
384     @Test
385     public void makeQNameFromIdentifierMountPointTooShortIdentifierNegativeTest() {
386         try {
387             ParserIdentifier.makeQNameFromIdentifier(
388                     MOUNT_POINT_IDENT
389                     + "/"
390                     + TEST_MODULE_NAME);
391
392             fail("Test should fail due to too short identifier format");
393         } catch (final RestconfDocumentedException e) {
394             assertEquals("Not expected error type",
395                     RestconfError.ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
396             assertEquals("Not expected error tag",
397                     RestconfError.ErrorTag.INVALID_VALUE, e.getErrors().get(0).getErrorTag());
398             assertEquals("Not expected error status code",
399                     400, e.getErrors().get(0).getErrorTag().getStatusCode());
400         }
401     }
402
403     /**
404      * Negative test trying to make <code>QName</code> from <code>null</code> identifier. Test is expected to fail with
405      * <code>NullPointerException</code>.
406      */
407     @Test
408     public void makeQNameFromIdentifierNullIdentifierNegativeTest() {
409         this.thrown.expect(NullPointerException.class);
410         ParserIdentifier.makeQNameFromIdentifier(null);
411     }
412
413     /**
414      * Negative test trying to make <code>QName</code> from empty identifier. Test is expected to fail with
415      * <code>RestconfDocumentedException</code>. Error type, error tag and error status code is compared to expected
416      * values.
417      */
418     @Test
419     public void makeQNameFromIdentifierEmptyIdentifierNegativeTest() {
420         try {
421             ParserIdentifier.makeQNameFromIdentifier("");
422             fail("Test should fail due to empty identifier");
423         } catch (final RestconfDocumentedException e) {
424             assertEquals("Not expected error type",
425                     RestconfError.ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
426             assertEquals("Not expected error tag",
427                     RestconfError.ErrorTag.INVALID_VALUE, e.getErrors().get(0).getErrorTag());
428             assertEquals("Not expected error status code",
429                     400, e.getErrors().get(0).getErrorTag().getStatusCode());
430         }
431     }
432
433     /**
434      * Negative test with identifier containing double slash. Between // there is one empty string which will be
435      * incorrectly considered to be module revision. Test is expected to fail with
436      * <code>RestconfDocumentedException</code> and error type, error tag and error status code are compared to
437      * expected values.
438      */
439     @Test
440     public void makeQNameFromIdentifierDoubleSlashNegativeTest() {
441         try {
442             ParserIdentifier.makeQNameFromIdentifier(TEST_MODULE_NAME + "//" + TEST_MODULE_REVISION);
443             fail("Test should fail due to identifier containing double slash");
444         } catch (final RestconfDocumentedException e) {
445             assertEquals("Not expected error type",
446                     RestconfError.ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
447             assertEquals("Not expected error tag",
448                     RestconfError.ErrorTag.INVALID_VALUE, e.getErrors().get(0).getErrorTag());
449             assertEquals("Not expected error status code",
450                     400, e.getErrors().get(0).getErrorTag().getStatusCode());
451         }
452     }
453
454     /**
455      * {@link ParserIdentifier#toSchemaExportContextFromIdentifier(SchemaContext, String, DOMMountPointService)} tests.
456      */
457
458     /**
459      * Positive test of getting <code>SchemaExportContext</code>. Expected module name, revision and namespace are
460      * verified.
461      */
462     @Test
463     public void toSchemaExportContextFromIdentifierTest() {
464         final SchemaExportContext exportContext = ParserIdentifier.toSchemaExportContextFromIdentifier(
465                 this.schemaContext, TEST_MODULE_NAME + "/" + TEST_MODULE_REVISION, null);
466
467         assertNotNull("Export context should be parsed", exportContext);
468
469         final Module module = exportContext.getModule();
470         assertNotNull("Export context should contains test module", module);
471
472         assertEquals("Returned not expected module name",
473                 TEST_MODULE_NAME, module.getName());
474         assertEquals("Returned not expected module revision",
475                 TEST_MODULE_REVISION, SimpleDateFormatUtil.getRevisionFormat().format(module.getRevision()));
476         assertEquals("Returned not expected module namespace",
477                 TEST_MODULE_NAMESPACE, module.getNamespace().toString());
478     }
479
480     /**
481      * Test of getting <code>SchemaExportContext</code> when desired module is not found.
482      * <code>SchemaExportContext</code> should be created but module should be set to <code>null</code>.
483      */
484     @Test
485     public void toSchemaExportContextFromIdentifierNotFoundTest() {
486         final SchemaExportContext exportContext = ParserIdentifier.toSchemaExportContextFromIdentifier(
487                 this.schemaContext,
488                 "not-existing-module" + "/" + "2016-01-01",
489                 null);
490
491         assertNotNull("Export context should be parsed", exportContext);
492         assertNull("Not-existing module should be null", exportContext.getModule());
493     }
494
495     /**
496      * Negative test trying to get <code>SchemaExportContext</code> with invalid identifier. Test is expected to fail
497      * with <code>RestconfDocumentedException</code> error type, error tag and error status code are compared to
498      * expected values.
499      */
500     @Test
501     public void toSchemaExportContextFromIdentifierInvalidIdentifierNegativeTest() {
502         try {
503             ParserIdentifier.toSchemaExportContextFromIdentifier(
504                     this.schemaContext, TEST_MODULE_REVISION + "/" + TEST_MODULE_NAME, null);
505             fail("Test should fail due to invalid identifier supplied");
506         } catch (final RestconfDocumentedException e) {
507             assertEquals("Not expected error type",
508                     RestconfError.ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
509             assertEquals("Not expected error tag",
510                     RestconfError.ErrorTag.INVALID_VALUE, e.getErrors().get(0).getErrorTag());
511             assertEquals("Not expected error status code",
512                     400, e.getErrors().get(0).getErrorTag().getStatusCode());
513         }
514     }
515
516     /**
517      * Positive test of getting <code>SchemaExportContext</code> for module behind mount point.
518      * Expected module name, revision and namespace are verified.
519      */
520     @Test
521     public void toSchemaExportContextFromIdentifierMountPointTest() {
522         final SchemaExportContext exportContext = ParserIdentifier.toSchemaExportContextFromIdentifier(
523                 this.schemaContext,
524                 MOUNT_POINT_IDENT + "/" + TEST_MODULE_NAME + "/" + TEST_MODULE_REVISION,
525                 this.mountPointService);
526
527         final Module module = exportContext.getModule();
528         assertNotNull("Export context should contains test module", module);
529
530         assertEquals("Returned not expected module name",
531                 TEST_MODULE_NAME, module.getName());
532         assertEquals("Returned not expected module revision",
533                 TEST_MODULE_REVISION, SimpleDateFormatUtil.getRevisionFormat().format(module.getRevision()));
534         assertEquals("Returned not expected module namespace",
535                 TEST_MODULE_NAMESPACE, module.getNamespace().toString());
536     }
537
538     /**
539      * Negative test of getting <code>SchemaExportContext</code> when desired module is not found behind mount point.
540      * <code>SchemaExportContext</code> should be still created but module should be set to <code>null</code>.
541      */
542     @Test
543     public void toSchemaExportContextFromIdentifierMountPointNotFoundTest() {
544         final SchemaExportContext exportContext = ParserIdentifier.toSchemaExportContextFromIdentifier(
545                 this.schemaContext,
546                 MOUNT_POINT_IDENT + "/" + "not-existing-module" + "/" + "2016-01-01",
547                 this.mountPointService);
548
549         assertNotNull("Export context should be parsed", exportContext);
550         assertNull("Not-existing module should be null", exportContext.getModule());
551     }
552
553     /**
554      * Negative test trying to get <code>SchemaExportContext</code> behind mount point with invalid identifier. Test is
555      * expected to fail with <code>RestconfDocumentedException</code> error type, error tag and error status code are
556      * compared to expected values.
557      */
558     @Test
559     public void toSchemaExportContextFromIdentifierMountPointInvalidIdentifierNegativeTest() {
560         try {
561             ParserIdentifier.toSchemaExportContextFromIdentifier(
562                     this.schemaContext,
563                     MOUNT_POINT_IDENT + "/" + TEST_MODULE_REVISION + "/" + TEST_MODULE_NAME,
564                     this.mountPointService);
565
566             fail("Test should fail due to invalid identifier supplied");
567         } catch (final RestconfDocumentedException e) {
568             assertEquals("Not expected error type",
569                     RestconfError.ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
570             assertEquals("Not expected error tag",
571                     RestconfError.ErrorTag.INVALID_VALUE, e.getErrors().get(0).getErrorTag());
572             assertEquals("Not expected error status code",
573                     400, e.getErrors().get(0).getErrorTag().getStatusCode());
574         }
575     }
576
577     /**
578      * Negative test of getting <code>SchemaExportContext</code> when supplied identifier is null.
579      * <code>NullPointerException</code> is expected. <code>DOMMountPointService</code> is not used.
580      */
581     @Test
582     public void toSchemaExportContextFromIdentifierNullIdentifierNegativeTest() {
583         this.thrown.expect(NullPointerException.class);
584         ParserIdentifier.toSchemaExportContextFromIdentifier(this.schemaContext, null, null);
585     }
586
587     /**
588      * Negative test of of getting <code>SchemaExportContext</code> when supplied <code>SchemaContext</code> is
589      * <code>null</code>. Test is expected to fail with <code>NullPointerException</code>.
590      */
591     @Test
592     public void toSchemaExportContextFromIdentifierNullSchemaContextNegativeTest() {
593         this.thrown.expect(NullPointerException.class);
594         ParserIdentifier.toSchemaExportContextFromIdentifier(null, TEST_MODULE_NAME + "/" + TEST_MODULE_REVISION, null);
595     }
596
597     /**
598      * Negative test of of getting <code>SchemaExportContext</code> when supplied <code>SchemaContext</code> is
599      * <code>null</code> and identifier specifies module behind mount point. Test is expected to fail with
600      * <code>NullPointerException</code>.
601      */
602     @Test
603     public void toSchemaExportContextFromIdentifierMountPointNullSchemaContextNegativeTest() {
604         this.thrown.expect(NullPointerException.class);
605         ParserIdentifier.toSchemaExportContextFromIdentifier(
606                 null,
607                 MOUNT_POINT_IDENT
608                 + "/"
609                 + TEST_MODULE_NAME
610                 + "/"
611                 + TEST_MODULE_REVISION,
612                 this.mountPointService);
613     }
614
615     /**
616      * Negative test of of getting <code>SchemaExportContext</code> when supplied <code>DOMMountPointService</code>
617      * is <code>null</code> and identifier defines module behind mount point. Test is expected to fail with
618      * <code>NullPointerException</code>.
619      */
620     @Test
621     public void toSchemaExportContextFromIdentifierNullMountPointServiceNegativeTest() {
622         this.thrown.expect(NullPointerException.class);
623         ParserIdentifier.toSchemaExportContextFromIdentifier(
624                 this.schemaContext,
625                 MOUNT_POINT_IDENT
626                 + "/"
627                 + TEST_MODULE_NAME
628                 + "/"
629                 + TEST_MODULE_REVISION,
630                 null);
631     }
632
633     /**
634      * Negative test of of getting <code>SchemaExportContext</code> when <code>SchemaContext</code> behind mount
635      * point is <code>null</code>. Test is expected to fail with <code>NullPointerException</code>.
636      */
637     @Test
638     public void toSchemaExportContextFromIdentifierNullSchemaContextBehindMountPointNegativeTest() {
639         this.thrown.expect(NullPointerException.class);
640         ParserIdentifier.toSchemaExportContextFromIdentifier(
641                 this.schemaContext,
642                 "/"
643                 + RestconfConstants.MOUNT
644                 + "/"
645                 + TEST_MODULE_NAME
646                 + "/"
647                 + TEST_MODULE_REVISION,
648                 this.mockMountPointService);
649     }
650
651     /**
652      * Test invoke RPC.
653      *
654      * <p>
655      * Verify if RPC schema node was found.
656      */
657     @Test
658     public void invokeRpcTest() {
659         final InstanceIdentifierContext<?> result = ParserIdentifier.toInstanceIdentifier(
660                 INVOKE_RPC, this.schemaContext, Optional.absent());
661
662         // RPC schema node
663         final QName rpcQName = result.getSchemaNode().getQName();
664         assertEquals("invoke:rpc:module", rpcQName.getModule().getNamespace().toString());
665         assertEquals("rpc-test", rpcQName.getLocalName());
666
667         // other fields
668         assertEquals(IdentifierCodec.deserialize(INVOKE_RPC, schemaContext), result.getInstanceIdentifier());
669         assertEquals(null, result.getMountPoint());
670         assertEquals(this.schemaContext, result.getSchemaContext());
671     }
672
673     /**
674      * Test invoke RPC on mount point.
675      *
676      * <p>
677      * Verify if RPC schema node was found.
678      */
679     @Test
680     public void invokeRpcOnMountPointTest() {
681         final InstanceIdentifierContext<?> result = ParserIdentifier.toInstanceIdentifier(
682                 MOUNT_POINT_IDENT + "/" + INVOKE_RPC, this.schemaContext, Optional.of(this.mountPointService));
683
684         // RPC schema node
685         final QName rpcQName = result.getSchemaNode().getQName();
686         assertEquals("invoke:rpc:module", rpcQName.getModule().getNamespace().toString());
687         assertEquals("rpc-test", rpcQName.getLocalName());
688
689         // other fields
690         assertEquals(IdentifierCodec.deserialize(INVOKE_RPC, schemaContext), result.getInstanceIdentifier());
691         assertEquals(this.mountPoint, result.getMountPoint());
692         assertEquals(this.schemaContextOnMountPoint, result.getSchemaContext());
693     }
694 }