5ca01ff2eba0b136ef03c5321b00bea77f8462b3
[netconf.git] / restconf / restconf-nb-rfc8040 / src / test / java / org / opendaylight / restconf / nb / rfc8040 / utils / parser / YangInstanceIdentifierDeserializerTest.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.nb.rfc8040.utils.parser;
10
11 import static org.junit.Assert.assertEquals;
12 import static org.junit.Assert.assertTrue;
13 import static org.junit.Assert.fail;
14
15 import com.google.common.collect.Iterables;
16 import com.google.common.collect.Sets;
17 import java.io.FileNotFoundException;
18 import java.util.Iterator;
19 import java.util.LinkedHashMap;
20 import java.util.Map;
21 import org.junit.Before;
22 import org.junit.Rule;
23 import org.junit.Test;
24 import org.junit.rules.ExpectedException;
25 import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
26 import org.opendaylight.restconf.common.errors.RestconfError;
27 import org.opendaylight.restconf.nb.rfc8040.TestRestconfUtils;
28 import org.opendaylight.yangtools.yang.common.QName;
29 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
30 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
31 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
32 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
33
34 /**
35  * Unit tests for {@link YangInstanceIdentifierDeserializer}.
36  */
37 public class YangInstanceIdentifierDeserializerTest {
38
39     @Rule
40     public ExpectedException thrown = ExpectedException.none();
41
42     // schema context
43     private SchemaContext schemaContext;
44
45     @Before
46     public void init() throws FileNotFoundException {
47         this.schemaContext =
48                 YangParserTestUtils.parseYangFiles(TestRestconfUtils.loadFiles("/restconf/parser/deserializer"));
49     }
50
51     /**
52      * Test of deserialization <code>String</code> URI with container to
53      * {@code Iterable<YangInstanceIdentifier.PathArgument>}.
54      */
55     @Test
56     public void deserializeContainerTest() {
57         final Iterable<YangInstanceIdentifier.PathArgument> result = YangInstanceIdentifierDeserializer
58                 .create(this.schemaContext, "deserializer-test:contA");
59
60         assertEquals("Result does not contains expected number of path arguments", 1, Iterables.size(result));
61         assertEquals("Not expected path argument",
62                 YangInstanceIdentifier.NodeIdentifier.create(QName.create("deserializer:test", "2016-06-06", "contA")),
63                 result.iterator().next());
64     }
65
66     /**
67      * Test of deserialization <code>String</code> URI with container containing leaf to
68      * {@code Iterable<YangInstanceIdentifier.PathArgument>}.
69      */
70     @Test
71     public void deserializeContainerWithLeafTest() {
72         final Iterable<YangInstanceIdentifier.PathArgument> result = YangInstanceIdentifierDeserializer
73                 .create(this.schemaContext, "deserializer-test:contA/leaf-A");
74
75         assertEquals("Result does not contains expected number of path arguments", 2, Iterables.size(result));
76
77         final Iterator<YangInstanceIdentifier.PathArgument> iterator = result.iterator();
78         assertEquals("Not expected path argument",
79                 YangInstanceIdentifier.NodeIdentifier.create(QName.create("deserializer:test", "2016-06-06", "contA")),
80                 iterator.next());
81         assertEquals("Not expected path argument",
82                 YangInstanceIdentifier.NodeIdentifier.create(QName.create("deserializer:test", "2016-06-06", "leaf-A")),
83                 iterator.next());
84     }
85
86     /**
87      * Test of deserialization <code>String</code> URI with container containing list with leaf list to
88      * {@code Iterable<YangInstanceIdentifier.PathArgument>}.
89      */
90     @Test
91     public void deserializeContainerWithListWithLeafListTest() {
92         final Iterable<YangInstanceIdentifier.PathArgument> result = YangInstanceIdentifierDeserializer
93                 .create(this.schemaContext, "deserializer-test:contA/list-A=100/leaf-list-AA=instance");
94
95         assertEquals("Result does not contains expected number of path arguments", 5, Iterables.size(result));
96
97         final Iterator<YangInstanceIdentifier.PathArgument> iterator = result.iterator();
98
99         // container
100         assertEquals("Not expected path argument",
101                 YangInstanceIdentifier.NodeIdentifier.create(QName.create("deserializer:test", "2016-06-06", "contA")),
102                 iterator.next());
103
104         // list
105         final QName list = QName.create("deserializer:test", "2016-06-06", "list-A");
106         assertEquals("Not expected path argument",
107                 YangInstanceIdentifier.NodeIdentifier.create(list),
108                 iterator.next());
109         assertEquals("Not expected path argument",
110                 new YangInstanceIdentifier.NodeIdentifierWithPredicates(
111                         list, QName.create(list, "list-key"), 100).toString(),
112                 iterator.next().toString());
113
114         // leaf list
115         final QName leafList = QName.create("deserializer:test", "2016-06-06", "leaf-list-AA");
116         assertEquals("Not expected path argument",
117                 YangInstanceIdentifier.NodeIdentifier.create(leafList),
118                 iterator.next());
119         assertEquals("Not expected path argument",
120                 new YangInstanceIdentifier.NodeWithValue<>(leafList, "instance"),
121                 iterator.next());
122     }
123
124     /**
125      * Test of deserialization <code>String</code> URI with container containing list with Action to
126      * {@code Iterable<YangInstanceIdentifier.PathArgument>}.
127      */
128     @Test
129     public void deserializeContainerWithListWithActionTest() {
130         final Iterable<YangInstanceIdentifier.PathArgument> result = YangInstanceIdentifierDeserializer
131             .create(this.schemaContext, "example-actions:interfaces/interface=eth0/reset");
132         assertEquals("Result does not contains expected number of path arguments", 4, Iterables.size(result));
133
134         final Iterator<YangInstanceIdentifier.PathArgument> iterator = result.iterator();
135
136         // container
137         assertEquals("Not expected path argument", YangInstanceIdentifier.NodeIdentifier
138                 .create(QName.create("https://example.com/ns/example-actions", "2016-07-07", "interfaces")),
139             iterator.next());
140
141         // list
142         final QName list = QName.create("https://example.com/ns/example-actions", "2016-07-07", "interface");
143         assertEquals("Not expected path argument", YangInstanceIdentifier.NodeIdentifier.create(list), iterator.next());
144         assertEquals("Not expected path argument",
145             new YangInstanceIdentifier.NodeIdentifierWithPredicates(list, QName.create(list, "name"), "eth0"),
146             iterator.next());
147
148         // action QName
149         final QName action = QName.create("https://example.com/ns/example-actions", "2016-07-07", "reset");
150         assertEquals("Not expected path argument", YangInstanceIdentifier.NodeIdentifier.create(action),
151             iterator.next());
152     }
153
154     /**
155      * Test of deserialization <code>String</code> URI containing list with no keys to
156      * {@code Iterable<YangInstanceIdentifier.PathArgument>}.
157      */
158     @Test
159     public void deserializeListWithNoKeysTest() {
160         final Iterable<YangInstanceIdentifier.PathArgument> result = YangInstanceIdentifierDeserializer
161                 .create(this.schemaContext, "deserializer-test:list-no-key");
162
163         assertEquals("Result does not contains expected number of path arguments", 2, Iterables.size(result));
164
165         final Iterator<YangInstanceIdentifier.PathArgument> iterator = result.iterator();
166         final QName list = QName.create("deserializer:test", "2016-06-06", "list-no-key");
167
168         assertEquals("Not expected path argument",
169                 YangInstanceIdentifier.NodeIdentifier.create(list),
170                 iterator.next());
171         assertEquals("Not expected path argument",
172                 YangInstanceIdentifier.NodeIdentifier.create(list),
173                 iterator.next());
174     }
175
176     /**
177      * Test of deserialization <code>String</code> URI containing list with one key to
178      * {@code Iterable<YangInstanceIdentifier.PathArgument>}.
179      */
180     @Test
181     public void deserializeListWithOneKeyTest() {
182         final Iterable<YangInstanceIdentifier.PathArgument> result = YangInstanceIdentifierDeserializer
183                 .create(this.schemaContext, "deserializer-test:list-one-key=value");
184
185         assertEquals("Result does not contains expected number of path arguments", 2, Iterables.size(result));
186
187         final Iterator<YangInstanceIdentifier.PathArgument> iterator = result.iterator();
188         final QName list = QName.create("deserializer:test", "2016-06-06", "list-one-key");
189
190         assertEquals("Not expected path argument",
191                 YangInstanceIdentifier.NodeIdentifier.create(list),
192                 iterator.next());
193         assertEquals("Not expected path argument",
194                 new YangInstanceIdentifier.NodeIdentifierWithPredicates(list, QName.create(list, "name"), "value"),
195                 iterator.next());
196     }
197
198     /**
199      * Test of deserialization <code>String</code> URI containing list with multiple keys to
200      * {@code Iterable<YangInstanceIdentifier.PathArgument>}.
201      */
202     @Test
203     public void deserializeListWithMultipleKeysTest() {
204         final QName list = QName.create("deserializer:test", "2016-06-06", "list-multiple-keys");
205         final Map<QName, Object> values = new LinkedHashMap<>();
206         values.put(QName.create(list, "name"), "value");
207         values.put(QName.create(list, "number"), 100);
208         values.put(QName.create(list, "enabled"), false);
209
210         final Iterable<YangInstanceIdentifier.PathArgument> result = YangInstanceIdentifierDeserializer
211                 .create(this.schemaContext, "deserializer-test:list-multiple-keys=value,100,false");
212
213         assertEquals("Result does not contains expected number of path arguments", 2, Iterables.size(result));
214
215         final Iterator<YangInstanceIdentifier.PathArgument> iterator = result.iterator();
216
217         assertEquals("Not expected path argument",
218                 YangInstanceIdentifier.NodeIdentifier.create(list),
219                 iterator.next());
220         assertEquals("Not expected path argument",
221                 new YangInstanceIdentifier.NodeIdentifierWithPredicates(list, values).toString(),
222                 iterator.next().toString());
223     }
224
225     /**
226      * Test of deserialization <code>String</code> URI containing leaf list to
227      * {@code Iterable<YangInstanceIdentifier.PathArgument>}.
228      */
229     @Test
230     public void deserializeLeafListTest() {
231         final Iterable<YangInstanceIdentifier.PathArgument> result = YangInstanceIdentifierDeserializer
232                 .create(this.schemaContext, "deserializer-test:leaf-list-0=true");
233
234         assertEquals("Result does not contains expected number of path arguments", 2, Iterables.size(result));
235
236         final Iterator<YangInstanceIdentifier.PathArgument> iterator = result.iterator();
237         final QName leafList = QName.create("deserializer:test", "2016-06-06", "leaf-list-0");
238
239         assertEquals("Not expected path argument",
240                 new YangInstanceIdentifier.NodeIdentifier(leafList),
241                 iterator.next());
242         assertEquals("Not expected path argument",
243                 new YangInstanceIdentifier.NodeWithValue<>(leafList, true).toString(),
244                 iterator.next().toString());
245     }
246
247     /**
248      * Test when empty <code>String</code> is supplied as an input. Test is expected to return empty result.
249      */
250     @Test
251     public void deserializeEmptyDataTest() {
252         final Iterable<PathArgument> result = YangInstanceIdentifierDeserializer.create(this.schemaContext, "");
253         assertTrue("Empty result expected", Iterables.isEmpty(result));
254     }
255
256     /**
257      * Test of deserialization <code>String</code> URI with identifiers separated by multiple slashes to
258      * {@code Iterable<YangInstanceIdentifier.PathArgument>}.
259      */
260     @Test
261     public void deserializeMultipleSlashesTest() {
262         final Iterable<PathArgument> result = YangInstanceIdentifierDeserializer
263                 .create(this.schemaContext, "deserializer-test:contA////list-A=40//list-key");
264
265         assertEquals("Result does not contains expected number of path arguments", 4, Iterables.size(result));
266
267         final Iterator<YangInstanceIdentifier.PathArgument> iterator = result.iterator();
268
269         // container
270         assertEquals("Not expected path argument",
271                 YangInstanceIdentifier.NodeIdentifier.create(QName.create("deserializer:test", "2016-06-06", "contA")),
272                 iterator.next());
273
274         // list
275         final QName list = QName.create("deserializer:test", "2016-06-06", "list-A");
276         assertEquals("Not expected path argument",
277                 YangInstanceIdentifier.NodeIdentifier.create(list),
278                 iterator.next());
279         assertEquals("Not expected path argument",
280                 new YangInstanceIdentifier.NodeIdentifierWithPredicates(
281                         list, QName.create(list, "list-key"), 40).toString(),
282                 iterator.next().toString());
283
284         // leaf
285         assertEquals("Not expected path argument",
286                 new YangInstanceIdentifier.NodeIdentifier(
287                         QName.create("deserializer:test", "2016-06-06", "list-key")),
288                 iterator.next());
289     }
290
291     /**
292      * Negative test when supplied <code>SchemaContext</code> is null. Test is expected to fail with
293      * <code>NullPointerException</code>.
294      */
295     @Test
296     public void deserializeNullSchemaContextNegativeTest() {
297         this.thrown.expect(NullPointerException.class);
298         YangInstanceIdentifierDeserializer.create(null, "deserializer-test:contA");
299     }
300
301     /**
302      * Negative test when supplied <code>String</code> data to deserialize is null. Test is expected to fail with
303      * <code>NullPointerException</code>.
304      */
305     @Test
306     public void nullDataNegativeNegativeTest() {
307         this.thrown.expect(NullPointerException.class);
308         YangInstanceIdentifierDeserializer.create(this.schemaContext, null);
309     }
310
311     /**
312      * Negative test when identifier is not followed by slash or equals. Test is expected to fail with
313      * <code>RestconfDocumentedException</code>.
314      */
315     @Test
316     public void deserializeBadCharMissingSlashOrEqualNegativeTest() {
317         this.thrown.expect(RestconfDocumentedException.class);
318         YangInstanceIdentifierDeserializer.create(this.schemaContext, "deserializer-test:cont*leaf-A");
319     }
320
321     /**
322      * Negative test of validating identifier when there is a slash after container without next identifier. Test
323      * is expected to fail with <code>RestconfDocumentedException</code>.
324      */
325     @Test
326     public void validArgIdentifierContainerEndsWithSlashNegativeTest() {
327         this.thrown.expect(RestconfDocumentedException.class);
328         YangInstanceIdentifierDeserializer.create(this.schemaContext, "deserializer-test:contA/");
329     }
330
331     /**
332      * Negative test of validating identifier when there are multiple slashes after container without next identifier.
333      * Test is expected to fail with <code>RestconfDocumentedException</code>.
334      */
335     @Test
336     public void validArgIdentifierContainerEndsWithMultipleSlashesNegativeTest() {
337         this.thrown.expect(RestconfDocumentedException.class);
338         YangInstanceIdentifierDeserializer.create(this.schemaContext, "deserializer-test:contA///");
339     }
340
341     /**
342      * Negative test of validating identifier when there is a slash after list key values without next identifier. Test
343      * is expected to fail with <code>RestconfDocumentedException</code>.
344      */
345     @Test
346     public void validArgIdentifierListEndsWithSlashLNegativeTest() {
347         this.thrown.expect(RestconfDocumentedException.class);
348         YangInstanceIdentifierDeserializer.create(this.schemaContext, "deserializer-test:list-one-key=value/");
349     }
350
351     /**
352      * Negative test of validating identifier when there are multiple slashes after list key values without next
353      * identifier. Test is expected to fail with <code>RestconfDocumentedException</code>.
354      */
355     @Test
356     public void validArgIdentifierListEndsWithSlashesNegativeTest() {
357         this.thrown.expect(RestconfDocumentedException.class);
358         YangInstanceIdentifierDeserializer.create(this.schemaContext, "deserializer-test:list-one-key=value//");
359     }
360
361     /**
362      * Negative test of creating <code>QName</code> when identifier is empty (example: '/'). Test is expected to fail
363      * with <code>RestconfDocumentedException</code>.
364      */
365     @Test
366     public void prepareQnameEmptyIdentifierNegativeTest() {
367         this.thrown.expect(RestconfDocumentedException.class);
368         YangInstanceIdentifierDeserializer.create(this.schemaContext, "/");
369     }
370
371     /**
372      * Negative test of creating <code>QName</code> when in identifier there is another sign than colon or equals.
373      * Test is expected to fail with <code>RestconfDocumentedException</code>.
374      */
375     @Test
376     public void prepareQnameBuildPathNegativeTest() {
377         this.thrown.expect(RestconfDocumentedException.class);
378         YangInstanceIdentifierDeserializer.create(this.schemaContext, "deserializer-test*contA");
379     }
380
381     /**
382      * Negative test of creating <code>QName</code> when it is not possible to find module for specified prefix. Test is
383      * expected to fail with <code>RestconfDocumentedException</code>.
384      */
385     @Test
386     public void prepareQnameNotExistingPrefixNegativeTest() {
387         this.thrown.expect(RestconfDocumentedException.class);
388         YangInstanceIdentifierDeserializer.create(this.schemaContext, "not-existing:contA");
389     }
390
391     /**
392      * Negative test of creating <code>QName</code> when after prefix and colon there is not parsable identifier as
393      * local name. Test is expected to fail with <code>RestconfDocumentedException</code>.
394      */
395     @Test
396     public void prepareQnameNotValidPrefixAndLocalNameNegativeTest() {
397         this.thrown.expect(RestconfDocumentedException.class);
398         YangInstanceIdentifierDeserializer.create(this.schemaContext, "deserializer-test:*not-parsable-identifier");
399     }
400
401     /**
402      * Negative test of creating <code>QName</code> when data ends after prefix and colon. Test is expected to fail
403      * with <code>StringIndexOutOfBoundsException</code>.
404      */
405     @Test
406     public void prepareQnameErrorParsingNegativeTest() {
407         this.thrown.expect(StringIndexOutOfBoundsException.class);
408         YangInstanceIdentifierDeserializer.create(this.schemaContext, "deserializer-test:");
409     }
410
411     /**
412      * Negative test of creating <code>QName</code> when after identifier and colon there is node name of unknown
413      * node in current container. Test is expected to fail with <code>RestconfDocumentedException</code> and error
414      * type, error tag and error status code are compared to expected values.
415      */
416     @Test
417     public void prepareQnameNotValidContainerNameNegativeTest() {
418         try {
419             YangInstanceIdentifierDeserializer.create(this.schemaContext, "deserializer-test:contA/leafB");
420             fail("Test should fail due to unknown child node in container");
421         } catch (final RestconfDocumentedException e) {
422             assertEquals("Not expected error type",
423                     RestconfError.ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
424             assertEquals("Not expected error tag",
425                     RestconfError.ErrorTag.DATA_MISSING, e.getErrors().get(0).getErrorTag());
426             assertEquals("Not expected error status code",
427                     404, e.getErrors().get(0).getErrorTag().getStatusCode());
428         }
429     }
430
431     /**
432      * Negative test of creating <code>QName</code> when after identifier and equals there is node name of unknown
433      * node in current list. Test is expected to fail with <code>RestconfDocumentedException</code> and error
434      * type, error tag and error status code are compared to expected values.
435      */
436     @Test
437     public void prepareQnameNotValidListNameNegativeTest() {
438         try {
439             YangInstanceIdentifierDeserializer
440                     .create(this.schemaContext, "deserializer-test:list-no-key/disabled=false");
441             fail("Test should fail due to unknown child node in list");
442         } catch (final RestconfDocumentedException e) {
443             assertEquals("Not expected error type",
444                     RestconfError.ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
445             assertEquals("Not expected error tag",
446                     RestconfError.ErrorTag.DATA_MISSING, e.getErrors().get(0).getErrorTag());
447             assertEquals("Not expected error status code",
448                     404, e.getErrors().get(0).getErrorTag().getStatusCode());
449         }
450     }
451
452     /**
453      * Negative test of getting next identifier when current node is keyed entry. Test is expected to
454      * fail with <code>RestconfDocumentedException</code>.
455      */
456     @Test
457     public void prepareIdentifierNotKeyedEntryNegativeTest() {
458         this.thrown.expect(RestconfDocumentedException.class);
459         YangInstanceIdentifierDeserializer.create(this.schemaContext, "deserializer-test:list-one-key");
460     }
461
462     /**
463      * Negative test when there is a comma also after the last key. Test is expected to fail with
464      * <code>RestconfDocumentedException</code>.
465      */
466     @Test
467     public void deserializeKeysEndsWithComaNegativeTest() {
468         this.thrown.expect(RestconfDocumentedException.class);
469         YangInstanceIdentifierDeserializer.create(this.schemaContext,
470                 "deserializer-test:list-multiple-keys=value,100,false,");
471     }
472
473     /**
474      * Positive when not all keys of list are encoded. The missing keys should be considered to has empty
475      * <code>String</code> values. Also value of next leaf must not be considered to be missing key value.
476      */
477     @Test
478     public void notAllListKeysEncodedPositiveTest() {
479         final QName list = QName.create("deserializer:test", "2016-06-06", "list-multiple-keys");
480         final Map<QName, Object> values = new LinkedHashMap<>();
481         values.put(QName.create(list, "name"), ":foo");
482         values.put(QName.create(list, "number"), "");
483         values.put(QName.create(list, "enabled"), "");
484
485         final Iterable<YangInstanceIdentifier.PathArgument> result = YangInstanceIdentifierDeserializer.create(
486                 this.schemaContext, "deserializer-test:list-multiple-keys=%3Afoo,,/string-value");
487
488         assertEquals("Result does not contains expected number of path arguments", 3, Iterables.size(result));
489
490         final Iterator<YangInstanceIdentifier.PathArgument> iterator = result.iterator();
491
492         // list
493         assertEquals("Not expected path argument",
494                 YangInstanceIdentifier.NodeIdentifier.create(list),
495                 iterator.next());
496         assertEquals("Not expected path argument",
497                 new YangInstanceIdentifier.NodeIdentifierWithPredicates(list, values).toString(),
498                 iterator.next().toString());
499
500         // leaf
501         assertEquals("Not expected path argument",
502                 new YangInstanceIdentifier.NodeIdentifier(
503                         QName.create("deserializer:test", "2016-06-06", "string-value")),
504                 iterator.next());
505     }
506
507     /**
508      * Negative test when not all keys of list are encoded and it is not possible to consider missing keys to be empty.
509      * Test is expected to fail with <code>RestconfDocumentedException</code> and error type, error tag and error
510      * status code are compared to expected values.
511      */
512     @Test
513     public void notAllListKeysEncodedNegativeTest() {
514         try {
515             YangInstanceIdentifierDeserializer.create(
516                     this.schemaContext, "deserializer-test:list-multiple-keys=%3Afoo/string-value");
517             fail("Test should fail due to missing list key values");
518         } catch (final RestconfDocumentedException e) {
519             assertEquals("Not expected error type",
520                     RestconfError.ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
521             assertEquals("Not expected error tag",
522                     RestconfError.ErrorTag.MISSING_ATTRIBUTE, e.getErrors().get(0).getErrorTag());
523             assertEquals("Not expected error status code",
524                     400, e.getErrors().get(0).getErrorTag().getStatusCode());
525         }
526     }
527
528     /**
529      * Test URI with list where key value starts with, ends with or contains percent encoded characters.The encoded
530      * value should be complete also with not percent-encoded parts.
531      */
532     @Test
533     public void percentEncodedKeyEndsWithNoPercentEncodedChars() {
534         final String URI = "deserializer-test:list-multiple-keys=%3Afoo,1,true";
535         final YangInstanceIdentifier result = YangInstanceIdentifier.create(
536                 YangInstanceIdentifierDeserializer.create(this.schemaContext, URI));
537
538         final Iterator<Map.Entry<QName, Object>> resultListKeys = ((YangInstanceIdentifier.NodeIdentifierWithPredicates)
539                 result.getLastPathArgument()).getKeyValues().entrySet().iterator();
540
541         assertEquals(":foo", resultListKeys.next().getValue());
542         assertEquals(new Short("1"), resultListKeys.next().getValue());
543         assertEquals(true, resultListKeys.next().getValue());
544     }
545
546     /**
547      * Positive test when all keys of list can be considered to be empty <code>String</code>.
548      */
549     @Test
550     public void deserializeAllKeysEmptyTest() {
551         final QName list = QName.create("deserializer:test", "2016-06-06", "list-multiple-keys");
552         final Map<QName, Object> values = new LinkedHashMap<>();
553         values.put(QName.create(list, "name"), "");
554         values.put(QName.create(list, "number"), "");
555         values.put(QName.create(list, "enabled"), "");
556
557         final Iterable<YangInstanceIdentifier.PathArgument> result = YangInstanceIdentifierDeserializer
558                 .create(this.schemaContext, "deserializer-test:list-multiple-keys=,,");
559
560         assertEquals("Result does not contains expected number of path arguments", 2, Iterables.size(result));
561
562         final Iterator<YangInstanceIdentifier.PathArgument> iterator = result.iterator();
563
564         assertEquals("Not expected path argument",
565                 YangInstanceIdentifier.NodeIdentifier.create(list),
566                 iterator.next());
567         assertEquals("Not expected path argument",
568                 new YangInstanceIdentifier.NodeIdentifierWithPredicates(list, values).toString(),
569                 iterator.next().toString());
570     }
571
572     /**
573      * Negative test of deserialization when for leaf list there is no specified instance value.
574      * <code>RestconfDocumentedException</code> is expected and error type, error tag and error status code are
575      * compared to expected values.
576      */
577     @Test
578     public void leafListMissingKeyNegativeTest() {
579         try {
580             YangInstanceIdentifierDeserializer.create(this.schemaContext, "deserializer-test:leaf-list-0=");
581             fail("Test should fail due to missing instance value");
582         } catch (final RestconfDocumentedException e) {
583             assertEquals("Not expected error type",
584                     RestconfError.ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
585             assertEquals("Not expected error tag",
586                     RestconfError.ErrorTag.MISSING_ATTRIBUTE, e.getErrors().get(0).getErrorTag());
587             assertEquals("Not expected error status code",
588                     400, e.getErrors().get(0).getErrorTag().getStatusCode());
589         }
590     }
591
592     /**
593      * Positive test of deserialization when parts of input URI <code>String</code> are defined in another module.
594      */
595     @Test
596     public void deserializePartInOtherModuleTest() {
597         final Iterable<YangInstanceIdentifier.PathArgument> result = YangInstanceIdentifierDeserializer.create(
598                 this.schemaContext, "deserializer-test-included:augmented-list=100/augmented-leaf");
599
600         assertEquals("Result does not contains expected number of path arguments", 4, Iterables.size(result));
601
602         final Iterator<YangInstanceIdentifier.PathArgument> iterator = result.iterator();
603         final QName list = QName.create("deserializer:test:included", "2016-06-06", "augmented-list");
604         final QName child = QName.create("deserializer:test", "2016-06-06", "augmented-leaf");
605
606         // list
607         assertEquals("Not expected path argument",
608                 YangInstanceIdentifier.NodeIdentifier.create(list),
609                 iterator.next());
610
611         assertEquals("Not expected path argument",
612                 new YangInstanceIdentifier.NodeIdentifierWithPredicates(list, QName.create(list, "list-key"), 100)
613                         .toString(),
614                 iterator.next()
615                         .toString());
616
617         // augmented leaf
618         assertEquals("Not expected path argument",
619                 new YangInstanceIdentifier.AugmentationIdentifier(Sets.newHashSet(child)),
620                 iterator.next());
621
622         assertEquals("Not expected path argument",
623                 YangInstanceIdentifier.NodeIdentifier.create(child),
624                 iterator.next());
625     }
626 }