Migrate YANG inputs for yang-data-codec-binfmt
[yangtools.git] / codec / yang-data-codec-binfmt / src / test / java / org / opendaylight / yangtools / yang / data / codec / binfmt / DataTreeCandidateInputOutputTest.java
1 /*
2  * Copyright (c) 2021 PANTHEON.tech, s.r.o. 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.yangtools.yang.data.codec.binfmt;
9
10 import static org.junit.Assert.assertEquals;
11
12 import java.io.ByteArrayInputStream;
13 import java.io.ByteArrayOutputStream;
14 import java.io.DataInputStream;
15 import java.io.DataOutput;
16 import java.io.DataOutputStream;
17 import java.io.IOException;
18 import java.util.Collection;
19 import java.util.Iterator;
20 import java.util.function.Consumer;
21 import org.junit.Before;
22 import org.junit.BeforeClass;
23 import org.junit.Test;
24 import org.opendaylight.yangtools.yang.common.QName;
25 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
26 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
27 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
28 import org.opendaylight.yangtools.yang.data.tree.api.DataTree;
29 import org.opendaylight.yangtools.yang.data.tree.api.DataTreeCandidate;
30 import org.opendaylight.yangtools.yang.data.tree.api.DataTreeCandidateNode;
31 import org.opendaylight.yangtools.yang.data.tree.api.DataTreeConfiguration;
32 import org.opendaylight.yangtools.yang.data.tree.api.DataTreeModification;
33 import org.opendaylight.yangtools.yang.data.tree.api.DataValidationFailedException;
34 import org.opendaylight.yangtools.yang.data.tree.impl.di.InMemoryDataTreeFactory;
35 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
36 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
37 import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
38
39 public class DataTreeCandidateInputOutputTest {
40     private static final QName FOO = QName.create("foo", "foo");
41     private static final QName BAR = QName.create(FOO, "bar");
42     private static final QName BAZ = QName.create(FOO, "baz");
43     private static final NodeIdentifier FOO_NODEID = new NodeIdentifier(FOO);
44     private static final NodeIdentifier BAR_NODEID = new NodeIdentifier(BAR);
45     private static final NodeIdentifier BAZ_NODEID = new NodeIdentifier(BAZ);
46     private static final YangInstanceIdentifier FOO_BAR_PATH = YangInstanceIdentifier.of(FOO_NODEID, BAR_NODEID);
47     private static final YangInstanceIdentifier BAR_PATH = YangInstanceIdentifier.of(BAR_NODEID);
48     private static final YangInstanceIdentifier BAR_BAZ_PATH = BAR_PATH.node(BAZ_NODEID);
49
50     private static EffectiveModelContext CONTEXT;
51
52     private DataTree dataTree;
53
54     @BeforeClass
55     public static void beforeClass() {
56         CONTEXT = YangParserTestUtils.parseYang("""
57             module foo {
58               namespace foo;
59               prefix foo;
60               container foo {
61                 leaf bar {
62                   type string;
63                 }
64               }
65               container bar {
66                 presence "is explicit";
67                 leaf baz {
68                   type string;
69                 }
70               }
71             }""");
72     }
73
74     @Before
75     public void before() {
76         dataTree = new InMemoryDataTreeFactory().create(DataTreeConfiguration.DEFAULT_CONFIGURATION, CONTEXT);
77     }
78
79     @Test
80     public void testWriteRoot() throws IOException {
81         assertSerialization(createCandidate(mod -> mod.write(YangInstanceIdentifier.of(),
82             ImmutableNodes.containerNode(SchemaContext.NAME))));
83     }
84
85     @Test
86     public void testWrite() throws IOException {
87         assertSerialization(createCandidate(mod -> mod.write(BAR_PATH, ImmutableNodes.containerNode(BAR))));
88     }
89
90     @Test
91     public void testDelete() throws IOException {
92         createCandidate(mod -> mod.write(BAR_PATH, ImmutableNodes.containerNode(BAR)));
93         assertSerialization(createCandidate(mod -> mod.delete(BAR_PATH)));
94     }
95
96     @Test
97     public void testWriteAppear() throws IOException {
98         assertSerialization(createCandidate(mod -> mod.write(FOO_BAR_PATH, ImmutableNodes.leafNode(BAR, "value"))));
99     }
100
101     @Test
102     public void testDeleteDisappear() throws IOException {
103         createCandidate(mod -> mod.write(FOO_BAR_PATH, ImmutableNodes.leafNode(BAR, "value")));
104         assertSerialization(createCandidate(mod -> mod.delete(FOO_BAR_PATH)));
105     }
106
107     @Test
108     public void testUnmodifiedRoot() throws IOException {
109         assertSerialization(createCandidate(mod -> mod.merge(YangInstanceIdentifier.of(),
110             ImmutableNodes.containerNode(SchemaContext.NAME))));
111     }
112
113     @Test
114     public void testUnmodifiedFoo() throws IOException {
115         assertSerialization(createCandidate(mod -> {
116             mod.write(FOO_BAR_PATH, ImmutableNodes.leafNode(BAR, "value"));
117             mod.delete(FOO_BAR_PATH);
118         }));
119     }
120
121     private DataTreeCandidate createCandidate(final Consumer<DataTreeModification> function) {
122         final DataTreeModification mod = dataTree.takeSnapshot().newModification();
123         function.accept(mod);
124         mod.ready();
125
126         final DataTreeCandidate ret;
127         try {
128             ret = dataTree.prepare(mod);
129         } catch (DataValidationFailedException e) {
130             throw new IllegalStateException(e);
131         }
132         dataTree.commit(ret);
133         return ret;
134     }
135
136     private static void assertSerialization(final DataTreeCandidate orig) throws IOException {
137         final ByteArrayOutputStream bos = new ByteArrayOutputStream();
138         final DataOutput dos = new DataOutputStream(bos);
139
140         try (NormalizedNodeDataOutput out = NormalizedNodeStreamVersion.current().newDataOutput(dos)) {
141             DataTreeCandidateInputOutput.writeDataTreeCandidate(out, orig);
142         }
143
144         final DataTreeCandidate read = DataTreeCandidateInputOutput.readDataTreeCandidate(
145             NormalizedNodeDataInput.newDataInput(new DataInputStream(new ByteArrayInputStream(bos.toByteArray()))));
146         assertEquals(orig.getRootPath(), read.getRootPath());
147         assertEqualMod(orig.getRootNode(), read.getRootNode());
148     }
149
150     private static void assertEqualMod(final DataTreeCandidateNode expected, final DataTreeCandidateNode actual) {
151         assertEquals(expected.getModificationType(), actual.getModificationType());
152
153         switch (expected.getModificationType()) {
154             case DELETE:
155             case UNMODIFIED:
156                 // No children to verify
157                 break;
158             default:
159                 final Collection<DataTreeCandidateNode> expectedChildren = expected.getChildNodes();
160                 final Collection<DataTreeCandidateNode> actualChildren = actual.getChildNodes();
161                 assertEquals(expectedChildren.size(), actualChildren.size());
162
163                 final Iterator<DataTreeCandidateNode> ait = actualChildren.iterator();
164
165                 for (DataTreeCandidateNode expectedChild : expectedChildren) {
166                     assertEqualNodes(expectedChild, ait.next());
167                 }
168         }
169     }
170
171     private static void assertEqualNodes(final DataTreeCandidateNode expected, final DataTreeCandidateNode actual) {
172         assertEquals(expected.getIdentifier(), actual.getIdentifier());
173         assertEqualMod(expected, actual);
174     }
175 }