Split out yang-data-tree-impl
[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.create(FOO_NODEID, BAR_NODEID);
47     private static final YangInstanceIdentifier BAR_PATH = YangInstanceIdentifier.create(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.parseYangResource("/foo.yang");
57     }
58
59     @Before
60     public void before() {
61         dataTree = new InMemoryDataTreeFactory().create(DataTreeConfiguration.DEFAULT_CONFIGURATION, CONTEXT);
62     }
63
64     @Test
65     public void testWriteRoot() throws IOException {
66         assertSerialization(createCandidate(mod -> mod.write(YangInstanceIdentifier.empty(),
67             ImmutableNodes.containerNode(SchemaContext.NAME))));
68     }
69
70     @Test
71     public void testWrite() throws IOException {
72         assertSerialization(createCandidate(mod -> mod.write(BAR_PATH, ImmutableNodes.containerNode(BAR))));
73     }
74
75     @Test
76     public void testDelete() throws IOException {
77         createCandidate(mod -> mod.write(BAR_PATH, ImmutableNodes.containerNode(BAR)));
78         assertSerialization(createCandidate(mod -> mod.delete(BAR_PATH)));
79     }
80
81     @Test
82     public void testWriteAppear() throws IOException {
83         assertSerialization(createCandidate(mod -> mod.write(FOO_BAR_PATH, ImmutableNodes.leafNode(BAR, "value"))));
84     }
85
86     @Test
87     public void testDeleteDisappear() throws IOException {
88         createCandidate(mod -> mod.write(FOO_BAR_PATH, ImmutableNodes.leafNode(BAR, "value")));
89         assertSerialization(createCandidate(mod -> mod.delete(FOO_BAR_PATH)));
90     }
91
92     @Test
93     public void testUnmodifiedRoot() throws IOException {
94         assertSerialization(createCandidate(mod -> mod.merge(YangInstanceIdentifier.empty(),
95             ImmutableNodes.containerNode(SchemaContext.NAME))));
96     }
97
98     @Test
99     public void testUnmodifiedFoo() throws IOException {
100         assertSerialization(createCandidate(mod -> {
101             mod.write(FOO_BAR_PATH, ImmutableNodes.leafNode(BAR, "value"));
102             mod.delete(FOO_BAR_PATH);
103         }));
104     }
105
106     private DataTreeCandidate createCandidate(final Consumer<DataTreeModification> function) {
107         final DataTreeModification mod = dataTree.takeSnapshot().newModification();
108         function.accept(mod);
109         mod.ready();
110
111         final DataTreeCandidate ret;
112         try {
113             ret = dataTree.prepare(mod);
114         } catch (DataValidationFailedException e) {
115             throw new IllegalStateException(e);
116         }
117         dataTree.commit(ret);
118         return ret;
119     }
120
121     private static void assertSerialization(final DataTreeCandidate orig) throws IOException {
122         final ByteArrayOutputStream bos = new ByteArrayOutputStream();
123         final DataOutput dos = new DataOutputStream(bos);
124
125         try (NormalizedNodeDataOutput out = NormalizedNodeStreamVersion.current().newDataOutput(dos)) {
126             DataTreeCandidateInputOutput.writeDataTreeCandidate(out, orig);
127         }
128
129         final DataTreeCandidate read = DataTreeCandidateInputOutput.readDataTreeCandidate(
130             NormalizedNodeDataInput.newDataInput(new DataInputStream(new ByteArrayInputStream(bos.toByteArray()))));
131         assertEquals(orig.getRootPath(), read.getRootPath());
132         assertEqualMod(orig.getRootNode(), read.getRootNode());
133     }
134
135     private static void assertEqualMod(final DataTreeCandidateNode expected, final DataTreeCandidateNode actual) {
136         assertEquals(expected.getModificationType(), actual.getModificationType());
137
138         switch (expected.getModificationType()) {
139             case DELETE:
140             case UNMODIFIED:
141                 // No children to verify
142                 break;
143             default:
144                 final Collection<DataTreeCandidateNode> expectedChildren = expected.getChildNodes();
145                 final Collection<DataTreeCandidateNode> actualChildren = actual.getChildNodes();
146                 assertEquals(expectedChildren.size(), actualChildren.size());
147
148                 final Iterator<DataTreeCandidateNode> eit = expectedChildren.iterator();
149                 final Iterator<DataTreeCandidateNode> ait = actualChildren.iterator();
150
151                 while (eit.hasNext()) {
152                     assertEqualNodes(eit.next(), ait.next());
153                 }
154         }
155     }
156
157     private static void assertEqualNodes(final DataTreeCandidateNode expected, final DataTreeCandidateNode actual) {
158         assertEquals(expected.getIdentifier(), actual.getIdentifier());
159         assertEqualMod(expected, actual);
160     }
161 }