2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
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
9 package org.opendaylight.restconf.parser.builder;
11 import static org.junit.Assert.assertEquals;
12 import static org.junit.Assert.assertTrue;
13 import static org.junit.Assert.fail;
15 import com.google.common.collect.Iterables;
16 import com.google.common.collect.Sets;
17 import java.util.Iterator;
18 import java.util.LinkedHashMap;
20 import org.junit.Before;
21 import org.junit.Rule;
22 import org.junit.Test;
23 import org.junit.rules.ExpectedException;
24 import org.opendaylight.controller.md.sal.rest.common.TestRestconfUtils;
25 import org.opendaylight.netconf.sal.restconf.impl.RestconfDocumentedException;
26 import org.opendaylight.netconf.sal.restconf.impl.RestconfError;
27 import org.opendaylight.yangtools.yang.common.QName;
28 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
29 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
30 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
31 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
34 * Unit tests for {@link YangInstanceIdentifierDeserializer}
36 public class YangInstanceIdentifierDeserializerTest {
39 public ExpectedException thrown = ExpectedException.none();
42 private SchemaContext schemaContext;
45 public void init() throws Exception {
47 YangParserTestUtils.parseYangSources(TestRestconfUtils.loadFiles("/restconf/parser/deserializer"));
51 * Test of deserialization <code>String</code> URI with container to
52 * <code>Iterable<YangInstanceIdentifier.PathArgument></code>.
55 public void deserializeContainerTest() {
56 final Iterable<YangInstanceIdentifier.PathArgument> result = YangInstanceIdentifierDeserializer
57 .create(this.schemaContext, "deserializer-test:contA");
59 assertEquals("Result does not contains expected number of path arguments", 1, Iterables.size(result));
60 assertEquals("Not expected path argument",
61 YangInstanceIdentifier.NodeIdentifier.create(QName.create("deserializer:test", "2016-06-06", "contA")),
62 result.iterator().next());
66 * Test of deserialization <code>String</code> URI with container containing leaf to
67 * <code>Iterable<YangInstanceIdentifier.PathArgument></code>.
70 public void deserializeContainerWithLeafTest() {
71 final Iterable<YangInstanceIdentifier.PathArgument> result = YangInstanceIdentifierDeserializer
72 .create(this.schemaContext, "deserializer-test:contA/leaf-A");
74 assertEquals("Result does not contains expected number of path arguments", 2, Iterables.size(result));
76 final Iterator<YangInstanceIdentifier.PathArgument> iterator = result.iterator();
77 assertEquals("Not expected path argument",
78 YangInstanceIdentifier.NodeIdentifier.create(QName.create("deserializer:test", "2016-06-06", "contA")),
80 assertEquals("Not expected path argument",
81 YangInstanceIdentifier.NodeIdentifier.create(QName.create("deserializer:test", "2016-06-06", "leaf-A")),
86 * Test of deserialization <code>String</code> URI with container containing list with leaf list to
87 * <code>Iterable<YangInstanceIdentifier.PathArgument></code>.
90 public void deserializeContainerWithListWithLeafListTest() {
91 final Iterable<YangInstanceIdentifier.PathArgument> result = YangInstanceIdentifierDeserializer
92 .create(this.schemaContext, "deserializer-test:contA/list-A=100/leaf-list-AA=instance");
94 assertEquals("Result does not contains expected number of path arguments", 5, Iterables.size(result));
96 final Iterator<YangInstanceIdentifier.PathArgument> iterator = result.iterator();
99 assertEquals("Not expected path argument",
100 YangInstanceIdentifier.NodeIdentifier.create(QName.create("deserializer:test", "2016-06-06", "contA")),
104 final QName list = QName.create("deserializer:test", "2016-06-06", "list-A");
105 assertEquals("Not expected path argument",
106 YangInstanceIdentifier.NodeIdentifier.create(list),
108 assertEquals("Not expected path argument",
109 new YangInstanceIdentifier.NodeIdentifierWithPredicates(
110 list, QName.create(list, "list-key"), 100).toString(),
111 iterator.next().toString());
114 final QName leafList = QName.create("deserializer:test", "2016-06-06", "leaf-list-AA");
115 assertEquals("Not expected path argument",
116 YangInstanceIdentifier.NodeIdentifier.create(leafList),
118 assertEquals("Not expected path argument",
119 new YangInstanceIdentifier.NodeWithValue(leafList, "instance"),
124 * Test of deserialization <code>String</code> URI containing list with no keys to
125 * <code>Iterable<YangInstanceIdentifier.PathArgument></code>.
128 public void deserializeListWithNoKeysTest() {
129 final Iterable<YangInstanceIdentifier.PathArgument> result = YangInstanceIdentifierDeserializer
130 .create(this.schemaContext, "deserializer-test:list-no-key");
132 assertEquals("Result does not contains expected number of path arguments", 2, Iterables.size(result));
134 final Iterator<YangInstanceIdentifier.PathArgument> iterator = result.iterator();
135 final QName list = QName.create("deserializer:test", "2016-06-06", "list-no-key");
137 assertEquals("Not expected path argument",
138 YangInstanceIdentifier.NodeIdentifier.create(list),
140 assertEquals("Not expected path argument",
141 YangInstanceIdentifier.NodeIdentifier.create(list),
146 * Test of deserialization <code>String</code> URI containing list with one key to
147 * <code>Iterable<YangInstanceIdentifier.PathArgument></code>.
150 public void deserializeListWithOneKeyTest() {
151 final Iterable<YangInstanceIdentifier.PathArgument> result = YangInstanceIdentifierDeserializer
152 .create(this.schemaContext, "deserializer-test:list-one-key=value");
154 assertEquals("Result does not contains expected number of path arguments", 2, Iterables.size(result));
156 final Iterator<YangInstanceIdentifier.PathArgument> iterator = result.iterator();
157 final QName list = QName.create("deserializer:test", "2016-06-06", "list-one-key");
159 assertEquals("Not expected path argument",
160 YangInstanceIdentifier.NodeIdentifier.create(list),
162 assertEquals("Not expected path argument",
163 new YangInstanceIdentifier.NodeIdentifierWithPredicates(list, QName.create(list, "name"), "value"),
168 * Test of deserialization <code>String</code> URI containing list with multiple keys to
169 * <code>Iterable<YangInstanceIdentifier.PathArgument></code>.
172 public void deserializeListWithMultipleKeysTest() {
173 final QName list = QName.create("deserializer:test", "2016-06-06", "list-multiple-keys");
174 final Map<QName, Object> values = new LinkedHashMap<>();
175 values.put(QName.create(list, "name"), "value");
176 values.put(QName.create(list, "number"), 100);
177 values.put(QName.create(list, "enabled"), false);
179 final Iterable<YangInstanceIdentifier.PathArgument> result = YangInstanceIdentifierDeserializer
180 .create(this.schemaContext, "deserializer-test:list-multiple-keys=value,100,false");
182 assertEquals("Result does not contains expected number of path arguments", 2, Iterables.size(result));
184 final Iterator<YangInstanceIdentifier.PathArgument> iterator = result.iterator();
186 assertEquals("Not expected path argument",
187 YangInstanceIdentifier.NodeIdentifier.create(list),
189 assertEquals("Not expected path argument",
190 new YangInstanceIdentifier.NodeIdentifierWithPredicates(list, values).toString(),
191 iterator.next().toString());
195 * Test of deserialization <code>String</code> URI containing leaf list to
196 * <code>Iterable<YangInstanceIdentifier.PathArgument></code>.
199 public void deserializeLeafListTest() {
200 final Iterable<YangInstanceIdentifier.PathArgument> result = YangInstanceIdentifierDeserializer
201 .create(this.schemaContext, "deserializer-test:leaf-list-0=true");
203 assertEquals("Result does not contains expected number of path arguments", 2, Iterables.size(result));
205 final Iterator<YangInstanceIdentifier.PathArgument> iterator = result.iterator();
206 final QName leafList = QName.create("deserializer:test", "2016-06-06", "leaf-list-0");
208 assertEquals("Not expected path argument",
209 new YangInstanceIdentifier.NodeIdentifier(leafList),
211 assertEquals("Not expected path argument",
212 new YangInstanceIdentifier.NodeWithValue(leafList, true).toString(),
213 iterator.next().toString());
217 * Test when empty <code>String</code> is supplied as an input. Test is expected to return empty result.
220 public void deserializeEmptyDataTest() {
221 final Iterable<PathArgument> result = YangInstanceIdentifierDeserializer.create(this.schemaContext, "");
222 assertTrue("Empty result expected", Iterables.isEmpty(result));
226 * Negative test when supplied <code>SchemaContext</code> is null. Test is expected to fail with
227 * <code>NullPointerException</code>.
230 public void deserializeNullSchemaContextNegativeTest() {
231 this.thrown.expect(NullPointerException.class);
232 YangInstanceIdentifierDeserializer.create(null, "deserializer-test:contA");
236 * Negative test when supplied <code>String</code> data to deserialize is null. Test is expected to fail with
237 * <code>NullPointerException</code>.
240 public void nullDataNegativeNegativeTest() {
241 this.thrown.expect(NullPointerException.class);
242 YangInstanceIdentifierDeserializer.create(this.schemaContext, null);
246 * Negative test when identifier is not followed by slash or equals. Test is expected to fail with
247 * <code>IllegalArgumentException</code>.
250 public void deserializeBadCharMissingSlashOrEqualNegativeTest() {
251 this.thrown.expect(IllegalArgumentException.class);
252 YangInstanceIdentifierDeserializer.create(this.schemaContext, "deserializer-test:cont*leaf-A");
256 * Negative test of validating identifier when there is a slash after container without next identifier. Test
257 * is expected to fail with <code>IllegalArgumentException</code>.
260 public void validArgIdentifierContainerEndsWithSlashNegativeTest() {
261 this.thrown.expect(IllegalArgumentException.class);
262 YangInstanceIdentifierDeserializer.create(this.schemaContext, "deserializer-test:contA/");
266 * Negative test of validating identifier when there is a slash after list key values without next identifier. Test
267 * is expected to fail with <code>IllegalArgumentException</code>.
270 public void validArgIdentifierListEndsWithSlashLNegativeTest() {
271 this.thrown.expect(IllegalArgumentException.class);
272 YangInstanceIdentifierDeserializer.create(this.schemaContext, "deserializer-test:list-one-key=value/");
276 * Negative test of creating <code>QName</code> when identifier is empty (example: '/'). Test is expected to fail
277 * with <code>IllegalArgumentException</code>.
280 public void prepareQnameEmptyIdentifierNegativeTest() {
281 this.thrown.expect(IllegalArgumentException.class);
282 YangInstanceIdentifierDeserializer.create(this.schemaContext, "/");
286 * Negative test of creating <code>QName</code> when two identifiers are separated by two slashes. Test is
287 * expected to fail with <code>IllegalArgumentException</code>.
290 public void prepareQnameTwoSlashesNegativeTest() {
291 this.thrown.expect(IllegalArgumentException.class);
292 YangInstanceIdentifierDeserializer.create(this.schemaContext, "deserializer-test:contA//leaf-A");
296 * Negative test of creating <code>QName</code> when in identifier there is another sign than colon or equals.
297 * Test is expected to fail with <code>IllegalArgumentException</code>.
300 public void prepareQnameBuildPathNegativeTest() {
301 this.thrown.expect(IllegalArgumentException.class);
302 YangInstanceIdentifierDeserializer.create(this.schemaContext, "deserializer-test*contA");
306 * Negative test of creating <code>QName</code> when it is not possible to find module for specified prefix. Test is
307 * expected to fail with <code>IllegalArgumentException</code>.
310 public void prepareQnameNotExistingPrefixNegativeTest() {
311 this.thrown.expect(IllegalArgumentException.class);
312 YangInstanceIdentifierDeserializer.create(this.schemaContext, "not-existing:contA");
316 * Negative test of creating <code>QName</code> when after prefix and colon there is not parsable identifier as
317 * local name. Test is expected to fail with <code>IllegalArgumentException</code>.
320 public void prepareQnameNotValidPrefixAndLocalNameNegativeTest() {
321 this.thrown.expect(IllegalArgumentException.class);
322 YangInstanceIdentifierDeserializer.create(this.schemaContext, "deserializer-test:*not-parsable-identifier");
326 * Negative test of creating <code>QName</code> when data ends after prefix and colon. Test is expected to fail
327 * with <code>StringIndexOutOfBoundsException</code>.
330 public void prepareQnameErrorParsingNegativeTest() {
331 this.thrown.expect(StringIndexOutOfBoundsException.class);
332 YangInstanceIdentifierDeserializer.create(this.schemaContext, "deserializer-test:");
336 * Negative test of creating <code>QName</code> when after identifier and colon there is node name of unknown
337 * node in current container. Test is expected to fail with <code>RestconfDocumentedException</code> and error
338 * type, error tag and error status code are compared to expected values.
341 public void prepareQnameNotValidContainerNameNegativeTest() {
343 YangInstanceIdentifierDeserializer.create(this.schemaContext, "deserializer-test:contA/leafB");
344 fail("Test should fail due to unknown child node in container");
345 } catch (final RestconfDocumentedException e) {
346 assertEquals("Not expected error type",
347 RestconfError.ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
348 assertEquals("Not expected error tag",
349 RestconfError.ErrorTag.DATA_MISSING, e.getErrors().get(0).getErrorTag());
350 assertEquals("Not expected error status code",
351 404, e.getErrors().get(0).getErrorTag().getStatusCode());
356 * Negative test of creating <code>QName</code> when after identifier and equals there is node name of unknown
357 * node in current list. Test is expected to fail with <code>RestconfDocumentedException</code> and error
358 * type, error tag and error status code are compared to expected values.
361 public void prepareQnameNotValidListNameNegativeTest() {
363 YangInstanceIdentifierDeserializer.create(this.schemaContext, "deserializer-test:list-no-key/disabled=false");
364 fail("Test should fail due to unknown child node in list");
365 } catch (final RestconfDocumentedException e) {
366 assertEquals("Not expected error type",
367 RestconfError.ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
368 assertEquals("Not expected error tag",
369 RestconfError.ErrorTag.DATA_MISSING, e.getErrors().get(0).getErrorTag());
370 assertEquals("Not expected error status code",
371 404, e.getErrors().get(0).getErrorTag().getStatusCode());
376 * Negative test of getting next identifier when current node is keyed entry. Test is expected to
377 * fail with <code>IllegalArgumentException</code>.
380 public void prepareIdentifierNotKeyedEntryNegativeTest() {
381 this.thrown.expect(IllegalArgumentException.class);
382 YangInstanceIdentifierDeserializer.create(this.schemaContext, "deserializer-test:list-one-key");
386 * Negative test when there is a comma also after the last key. Test is expected to fail with
387 * <code>IllegalArgumentException</code>.
390 public void deserializeKeysEndsWithComaNegativeTest() {
391 this.thrown.expect(IllegalArgumentException.class);
392 YangInstanceIdentifierDeserializer.create( this.schemaContext,
393 "deserializer-test:list-multiple-keys=value,100,false,");
397 * Positive when not all keys of list are encoded. The missing keys should be considered to has empty
398 * <code>String</code> values. Also value of next leaf must not be considered to be missing key value.
401 public void notAllListKeysEncodedPositiveTest() {
402 final QName list = QName.create("deserializer:test", "2016-06-06", "list-multiple-keys");
403 final Map<QName, Object> values = new LinkedHashMap<>();
404 values.put(QName.create(list, "name"), ":foo");
405 values.put(QName.create(list, "number"), "");
406 values.put(QName.create(list, "enabled"), "");
408 final Iterable<YangInstanceIdentifier.PathArgument> result = YangInstanceIdentifierDeserializer.create(
409 this.schemaContext, "deserializer-test:list-multiple-keys=%3Afoo,,/string-value");
411 assertEquals("Result does not contains expected number of path arguments", 3, Iterables.size(result));
413 final Iterator<YangInstanceIdentifier.PathArgument> iterator = result.iterator();
416 assertEquals("Not expected path argument",
417 YangInstanceIdentifier.NodeIdentifier.create(list),
419 assertEquals("Not expected path argument",
420 new YangInstanceIdentifier.NodeIdentifierWithPredicates(list, values).toString(),
421 iterator.next().toString());
424 assertEquals("Not expected path argument",
425 new YangInstanceIdentifier.NodeIdentifier(
426 QName.create("deserializer:test", "2016-06-06", "string-value")),
431 * Negative test when not all keys of list are encoded and it is not possible to consider missing keys to be empty.
432 * Test is expected to fail with <code>RestconfDocumentedException</code> and error type, error tag and error
433 * status code are compared to expected values.
436 public void notAllListKeysEncodedNegativeTest() {
438 YangInstanceIdentifierDeserializer.create(
439 this.schemaContext, "deserializer-test:list-multiple-keys=%3Afoo/string-value");
440 fail("Test should fail due to missing list key values");
441 } catch (final RestconfDocumentedException e) {
442 assertEquals("Not expected error type",
443 RestconfError.ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
444 assertEquals("Not expected error tag",
445 RestconfError.ErrorTag.MISSING_ATTRIBUTE, e.getErrors().get(0).getErrorTag());
446 assertEquals("Not expected error status code",
447 400, e.getErrors().get(0).getErrorTag().getStatusCode());
452 * Test URI with list where key value starts with, ends with or contains percent encoded characters.The encoded
453 * value should be complete also with not percent-encoded parts.
456 public void percentEncodedKeyEndsWithNoPercentEncodedChars() {
457 final String URI = "deserializer-test:list-multiple-keys=%3Afoo,1,true";
458 final YangInstanceIdentifier result = YangInstanceIdentifier.create(
459 YangInstanceIdentifierDeserializer.create(this.schemaContext, URI));
461 final Iterator<Map.Entry<QName, Object>> resultListKeys = ((YangInstanceIdentifier.NodeIdentifierWithPredicates)
462 result.getLastPathArgument()).getKeyValues().entrySet().iterator();
464 assertEquals(":foo", resultListKeys.next().getValue());
465 assertEquals(new Short("1"), resultListKeys.next().getValue());
466 assertEquals(true, resultListKeys.next().getValue());
470 * Positive test when all keys of list can be considered to be empty <code>String</code>.
473 public void deserializeAllKeysEmptyTest() {
474 final QName list = QName.create("deserializer:test", "2016-06-06", "list-multiple-keys");
475 final Map<QName, Object> values = new LinkedHashMap<>();
476 values.put(QName.create(list, "name"), "");
477 values.put(QName.create(list, "number"), "");
478 values.put(QName.create(list, "enabled"), "");
480 final Iterable<YangInstanceIdentifier.PathArgument> result = YangInstanceIdentifierDeserializer
481 .create(this.schemaContext, "deserializer-test:list-multiple-keys=,,");
483 assertEquals("Result does not contains expected number of path arguments", 2, Iterables.size(result));
485 final Iterator<YangInstanceIdentifier.PathArgument> iterator = result.iterator();
487 assertEquals("Not expected path argument",
488 YangInstanceIdentifier.NodeIdentifier.create(list),
490 assertEquals("Not expected path argument",
491 new YangInstanceIdentifier.NodeIdentifierWithPredicates(list, values).toString(),
492 iterator.next().toString());
496 * Negative test of deserialization when for leaf list there is no specified instance value.
497 * <code>RestconfDocumentedException</code> is expected and error type, error tag and error status code are
498 * compared to expected values.
501 public void leafListMissingKeyNegativeTest() {
503 YangInstanceIdentifierDeserializer.create(this.schemaContext, "deserializer-test:leaf-list-0=");
504 fail("Test should fail due to missing instance value");
505 } catch (final RestconfDocumentedException e) {
506 assertEquals("Not expected error type",
507 RestconfError.ErrorType.PROTOCOL, e.getErrors().get(0).getErrorType());
508 assertEquals("Not expected error tag",
509 RestconfError.ErrorTag.MISSING_ATTRIBUTE, e.getErrors().get(0).getErrorTag());
510 assertEquals("Not expected error status code",
511 400, e.getErrors().get(0).getErrorTag().getStatusCode());
516 * Positive test of deserialization when parts of input URI <code>String</code> are defined in another module.
519 public void deserializePartInOtherModuleTest() {
520 final Iterable<YangInstanceIdentifier.PathArgument> result = YangInstanceIdentifierDeserializer.create(
521 this.schemaContext, "deserializer-test-included:augmented-list=100/augmented-leaf");
523 assertEquals("Result does not contains expected number of path arguments", 4, Iterables.size(result));
525 final Iterator<YangInstanceIdentifier.PathArgument> iterator = result.iterator();
526 final QName list = QName.create("deserializer:test:included", "2016-06-06", "augmented-list");
527 final QName child = QName.create("deserializer:test", "2016-06-06", "augmented-leaf");
530 assertEquals("Not expected path argument",
531 YangInstanceIdentifier.NodeIdentifier.create(list),
534 assertEquals("Not expected path argument",
535 new YangInstanceIdentifier.NodeIdentifierWithPredicates(list, QName.create(list, "list-key"), 100)
541 assertEquals("Not expected path argument",
542 new YangInstanceIdentifier.AugmentationIdentifier(Sets.newHashSet(child)),
545 assertEquals("Not expected path argument",
546 YangInstanceIdentifier.NodeIdentifier.create(child),