8050fadf344a33dab03d1b8060def0a50fc4243a
[mdsal.git] / binding / mdsal-binding-dom-codec / src / test / java / org / opendaylight / mdsal / binding / dom / codec / impl / InstanceIdentifierSerializeDeserializeTest.java
1 /*
2  * Copyright (c) 2014 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.mdsal.binding.dom.codec.impl;
9
10 import static org.hamcrest.CoreMatchers.startsWith;
11 import static org.hamcrest.MatcherAssert.assertThat;
12 import static org.junit.Assert.assertEquals;
13 import static org.junit.Assert.assertFalse;
14 import static org.junit.Assert.assertNull;
15 import static org.junit.Assert.assertThrows;
16 import static org.junit.Assert.assertTrue;
17
18 import com.google.common.collect.Iterables;
19 import org.junit.Test;
20 import org.opendaylight.mdsal.binding.dom.codec.api.IncorrectNestingException;
21 import org.opendaylight.yang.gen.v1.urn.odl.actions.norev.Lst;
22 import org.opendaylight.yang.gen.v1.urn.odl.actions.norev.lst.Foo;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.bi.ba.notification.rev150205.OutOfPixieDustNotification;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.md.sal.knock.knock.rev180723.KnockKnockInput;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.Top;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.two.level.list.TopLevelList;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.two.level.list.TopLevelListKey;
28 import org.opendaylight.yang.gen.v1.urn.test.opendaylight.mdsal45.aug.norev.cont.cont.choice.ContAug;
29 import org.opendaylight.yang.gen.v1.urn.test.opendaylight.mdsal45.aug.norev.root.RootAug;
30 import org.opendaylight.yang.gen.v1.urn.test.opendaylight.mdsal45.base.norev.Cont;
31 import org.opendaylight.yang.gen.v1.urn.test.opendaylight.mdsal45.base.norev.Root;
32 import org.opendaylight.yang.gen.v1.urn.test.opendaylight.mdsal45.base.norev.cont.ContChoice;
33 import org.opendaylight.yang.gen.v1.urn.test.opendaylight.mdsal45.base.norev.cont.cont.choice.ContBase;
34 import org.opendaylight.yang.gen.v1.urn.test.opendaylight.mdsal45.base.norev.grp.GrpCont;
35 import org.opendaylight.yang.gen.v1.urn.test.opendaylight.mdsal45.base.norev.root.RootBase;
36 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
37 import org.opendaylight.yangtools.yang.binding.Key;
38 import org.opendaylight.yangtools.yang.common.QName;
39 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
40 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
41 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
42
43 public class InstanceIdentifierSerializeDeserializeTest extends AbstractBindingCodecTest {
44     public static final String TOP_LEVEL_LIST_KEY_VALUE = "foo";
45
46     private static final TopLevelListKey TOP_FOO_KEY = new TopLevelListKey("foo");
47     private static final InstanceIdentifier<TopLevelList> BA_TOP_LEVEL_LIST = InstanceIdentifier
48             .builder(Top.class).child(TopLevelList.class, TOP_FOO_KEY).build();
49
50     public static final QName TOP_QNAME = Top.QNAME;
51     public static final QName TOP_LEVEL_LIST_QNAME = QName.create(TOP_QNAME, "top-level-list");
52     public static final QName TOP_LEVEL_LIST_KEY = QName.create(TOP_QNAME, "name");
53
54     public static final YangInstanceIdentifier BI_TOP_PATH = YangInstanceIdentifier.of(TOP_QNAME);
55     public static final YangInstanceIdentifier BI_TOP_LEVEL_LIST_PATH = BI_TOP_PATH.node(TOP_LEVEL_LIST_QNAME);
56     public static final YangInstanceIdentifier BI_TOP_LEVEL_LIST_1_PATH = BI_TOP_LEVEL_LIST_PATH
57             .node(NodeIdentifierWithPredicates.of(TOP_LEVEL_LIST_QNAME, TOP_LEVEL_LIST_KEY,
58                 TOP_LEVEL_LIST_KEY_VALUE));
59
60     @Test
61     public void testYangIIToBindingAwareII() {
62         final var instanceIdentifier = codecContext.fromYangInstanceIdentifier(BI_TOP_PATH);
63         assertEquals(Top.class, instanceIdentifier.getTargetType());
64     }
65
66     @Test
67     public void testYangIIToBindingAwareIIListWildcarded() {
68         final var instanceIdentifier = codecContext.fromYangInstanceIdentifier(BI_TOP_LEVEL_LIST_PATH);
69         assertNull(instanceIdentifier);
70     }
71
72     @Test
73     public void testYangIIToBindingAwareIIListWithKey() {
74         final var instanceIdentifier = codecContext.fromYangInstanceIdentifier(BI_TOP_LEVEL_LIST_1_PATH);
75         final var last = Iterables.getLast(instanceIdentifier.getPathArguments());
76         assertEquals(TopLevelList.class, instanceIdentifier.getTargetType());
77         assertFalse(instanceIdentifier.isWildcarded());
78         assertTrue(last instanceof InstanceIdentifier.IdentifiableItem);
79         final Key<?> key = ((InstanceIdentifier.IdentifiableItem<?, ?>) last).getKey();
80         assertEquals(TopLevelListKey.class, key.getClass());
81         assertEquals(TOP_LEVEL_LIST_KEY_VALUE, ((TopLevelListKey)key).getName());
82     }
83
84     @Test
85     public void testBindingAwareIIToYangIContainer() {
86         final var yangInstanceIdentifier = codecContext.toYangInstanceIdentifier(
87                 InstanceIdentifier.create(Top.class).child(TopLevelList.class));
88         final var lastPathArgument = yangInstanceIdentifier.getLastPathArgument();
89         assertTrue(lastPathArgument instanceof NodeIdentifier);
90         assertEquals(TopLevelList.QNAME, lastPathArgument.getNodeType());
91     }
92
93     @Test
94     public void testBindingAwareIIToYangIIWildcard() {
95         final var yangInstanceIdentifier = codecContext.toYangInstanceIdentifier(
96                 InstanceIdentifier.create(Top.class).child(TopLevelList.class));
97         final var lastPathArgument = yangInstanceIdentifier.getLastPathArgument();
98         assertTrue(lastPathArgument instanceof NodeIdentifier);
99         assertEquals(TopLevelList.QNAME, lastPathArgument.getNodeType());
100     }
101
102     @Test
103     public void testBindingAwareIIToYangIIListWithKey() {
104         final var yangInstanceIdentifier = codecContext.toYangInstanceIdentifier(
105                 InstanceIdentifier.create(Top.class).child(TopLevelList.class, TOP_FOO_KEY));
106         final var lastPathArgument = yangInstanceIdentifier.getLastPathArgument();
107         assertTrue(lastPathArgument instanceof NodeIdentifierWithPredicates);
108         assertTrue(((NodeIdentifierWithPredicates) lastPathArgument).values().contains(TOP_LEVEL_LIST_KEY_VALUE));
109         assertEquals(TopLevelList.QNAME, lastPathArgument.getNodeType());
110     }
111
112     @Test
113     public void testChoiceCaseGroupingFromBinding() {
114         final var contBase = codecContext.toYangInstanceIdentifier(
115             InstanceIdentifier.builder(Cont.class).child(ContBase.class, GrpCont.class).build());
116         assertEquals(YangInstanceIdentifier.of(NodeIdentifier.create(Cont.QNAME),
117             NodeIdentifier.create(ContChoice.QNAME), NodeIdentifier.create(GrpCont.QNAME)), contBase);
118
119         final var contAug = codecContext.toYangInstanceIdentifier(
120             InstanceIdentifier.builder(Cont.class).child(ContAug.class, GrpCont.class).build());
121         assertEquals(YangInstanceIdentifier.of(NodeIdentifier.create(Cont.QNAME),
122             NodeIdentifier.create(ContChoice.QNAME),
123             NodeIdentifier.create(GrpCont.QNAME.bindTo(ContAug.QNAME.getModule()))), contAug);
124
125         // Legacy: downcast the child to Class, losing type safety but still working. Faced with ambiguity, it will
126         //         select the lexically-lower class
127         assertEquals(1, ContBase.class.getCanonicalName().compareTo(ContAug.class.getCanonicalName()));
128         final var contAugLegacy = codecContext.toYangInstanceIdentifier(
129             InstanceIdentifier.builder(Cont.class).child((Class) GrpCont.class).build());
130         assertEquals(contAug, contAugLegacy);
131
132         final var rootBase = codecContext.toYangInstanceIdentifier(
133             InstanceIdentifier.builder(RootBase.class, GrpCont.class).build());
134         assertEquals(YangInstanceIdentifier.of(NodeIdentifier.create(Root.QNAME),
135             NodeIdentifier.create(GrpCont.QNAME)), rootBase);
136
137         final var rootAug = codecContext.toYangInstanceIdentifier(
138             InstanceIdentifier.builder(RootAug.class, GrpCont.class).build());
139         assertEquals(YangInstanceIdentifier.of(NodeIdentifier.create(Root.QNAME),
140             NodeIdentifier.create(GrpCont.QNAME.bindTo(RootAug.QNAME.getModule()))), rootAug);
141     }
142
143     @Test
144     public void testChoiceCaseGroupingToBinding() {
145         final var contBase = codecContext.fromYangInstanceIdentifier(
146             YangInstanceIdentifier.of(Cont.QNAME, ContChoice.QNAME, GrpCont.QNAME));
147         assertEquals(InstanceIdentifier.builder(Cont.class).child(ContBase.class, GrpCont.class).build(), contBase);
148
149         final var contAug = codecContext.fromYangInstanceIdentifier(
150             YangInstanceIdentifier.of(Cont.QNAME, ContChoice.QNAME, GrpCont.QNAME.bindTo(ContAug.QNAME.getModule())));
151         assertEquals(InstanceIdentifier.builder(Cont.class).child(ContAug.class, GrpCont.class).build(), contAug);
152
153         final var rootBase = codecContext.fromYangInstanceIdentifier(
154             YangInstanceIdentifier.of(Root.QNAME, GrpCont.QNAME));
155         assertEquals(InstanceIdentifier.builder(RootBase.class, GrpCont.class).build(), rootBase);
156
157         final var rootAug = codecContext.fromYangInstanceIdentifier(
158             YangInstanceIdentifier.of(Root.QNAME, GrpCont.QNAME.bindTo(RootAug.QNAME.getModule())));
159         assertEquals(InstanceIdentifier.builder(RootAug.class, GrpCont.class).build(), rootAug);
160     }
161
162     @Test
163     public void testRejectNotificationQName() {
164         // A purposely-wrong YangInstanceIdentifier
165         final var yiid = YangInstanceIdentifier.of(OutOfPixieDustNotification.QNAME);
166         final var ex = assertThrows(IncorrectNestingException.class,
167             () -> codecContext.fromYangInstanceIdentifier(yiid));
168         assertThat(ex.getMessage(),
169             startsWith("Argument (urn:opendaylight:params:xml:ns:yang:controller:md:sal:test:bi:ba:notification"
170                 + "?revision=2015-02-05)out-of-pixie-dust-notification is not valid data tree child of "));
171     }
172
173     @Test
174     public void testRejectRpcQName() {
175         // A purposely-wrong YangInstanceIdentifier
176         final var yiid = YangInstanceIdentifier.of(
177             // TODO: use the RPC interface once we are generating it
178             QName.create(KnockKnockInput.QNAME, "knock-knock"));
179         final var ex = assertThrows(IncorrectNestingException.class,
180             () -> codecContext.fromYangInstanceIdentifier(yiid));
181         assertThat(ex.getMessage(), startsWith("Argument (urn:opendaylight:params:xml:ns:yang:md:sal:knock-knock"
182             + "?revision=2018-07-23)knock-knock is not valid data tree child of "));
183     }
184
185     @Test
186     public void testRejectActionQName() {
187         // A purposely-wrong YangInstanceIdentifier
188         final var yiid = YangInstanceIdentifier.of(
189             NodeIdentifier.create(Lst.QNAME),
190             NodeIdentifierWithPredicates.of(Lst.QNAME, QName.create(Lst.QNAME, "key"), "foo"),
191             NodeIdentifier.create(Foo.QNAME));
192         final var ex = assertThrows(IncorrectNestingException.class,
193             () -> codecContext.fromYangInstanceIdentifier(yiid));
194         assertEquals("Argument (urn:odl:actions)foo is not valid child of "
195             + "EmptyListEffectiveStatement{argument=(urn:odl:actions)lst}", ex.getMessage());
196     }
197 }