Adjust to {Container,Input,Output}SchemaNode split
[mdsal.git] / binding / mdsal-binding-dom-codec / src / test / java / org / opendaylight / mdsal / binding / dom / codec / impl / CachingCodecTest.java
1 /*
2  * Copyright (c) 2015 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.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertNotEquals;
12 import static org.junit.Assert.assertNotSame;
13 import static org.junit.Assert.assertNull;
14 import static org.junit.Assert.assertSame;
15 import static org.junit.Assert.assertTrue;
16
17 import com.google.common.collect.ImmutableMap;
18 import com.google.common.collect.ImmutableSet;
19 import java.util.Collection;
20 import java.util.Map;
21 import org.junit.Before;
22 import org.junit.Test;
23 import org.opendaylight.mdsal.binding.dom.codec.api.BindingDataObjectCodecTreeNode;
24 import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeCachingCodec;
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.TopBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.two.level.list.TopLevelList;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.two.level.list.TopLevelListBuilder;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.two.level.list.TopLevelListKey;
30 import org.opendaylight.yang.gen.v1.urn.test.leaf.caching.codec.rev190201.Cont;
31 import org.opendaylight.yang.gen.v1.urn.test.leaf.caching.codec.rev190201.ContBuilder;
32 import org.opendaylight.yang.gen.v1.urn.test.leaf.caching.codec.rev190201.MyType;
33 import org.opendaylight.yangtools.yang.binding.BindingObject;
34 import org.opendaylight.yangtools.yang.binding.DataObject;
35 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
36 import org.opendaylight.yangtools.yang.common.QName;
37 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
38 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
39 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
40 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
41 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
42 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
43 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
44
45 public class CachingCodecTest extends AbstractBindingCodecTest {
46
47     private static final NodeIdentifier TOP_LEVEL_LIST_ARG = new NodeIdentifier(TopLevelList.QNAME);
48     private static final InstanceIdentifier<Top> TOP_PATH = InstanceIdentifier.create(Top.class);
49     private static final Map<TopLevelListKey, TopLevelList> TWO_LIST = createList(2);
50     private static final Map<TopLevelListKey, TopLevelList> THREE_LIST = createList(3);
51
52     private static final Top TOP_TWO_LIST_DATA = new TopBuilder().setTopLevelList(TWO_LIST).build();
53     private static final Top TOP_THREE_LIST_DATA = new TopBuilder().setTopLevelList(THREE_LIST).build();
54
55     private static final NodeIdentifier LEAF_ARG = new NodeIdentifier(QName.create(Cont.QNAME, "caching"));
56     private static final InstanceIdentifier<Cont> CONT_PATH = InstanceIdentifier.create(Cont.class);
57
58     private static final Cont CONT_DATA = new ContBuilder().setCaching(new MyType(dataValue())).setNonCaching("test")
59             .build();
60     private static final Cont CONT2_DATA = new ContBuilder().setCaching(new MyType(dataValue())).setNonCaching("test2")
61             .build();
62
63     private BindingDataObjectCodecTreeNode<Top> topNode;
64     private BindingDataObjectCodecTreeNode<Cont> contNode;
65
66     private static String dataValue() {
67         // We are battling interning here
68         return new StringBuilder("foo").toString();
69     }
70
71     @Override
72     @Before
73     public void before() {
74         super.before();
75         topNode = codecContext.getSubtreeCodec(TOP_PATH);
76         contNode = codecContext.getSubtreeCodec(CONT_PATH);
77     }
78
79     private static Map<TopLevelListKey, TopLevelList> createList(final int num) {
80         final ImmutableMap.Builder<TopLevelListKey, TopLevelList> builder = ImmutableMap.builder();
81         for (int i = 0; i < num; i++) {
82             final TopLevelListKey key = new TopLevelListKey("test-" + i);
83             builder.put(key, new TopLevelListBuilder().withKey(key).build());
84         }
85         return builder.build();
86     }
87
88     @Test
89     public void testListCache() {
90         final BindingNormalizedNodeCachingCodec<Top> cachingCodec = createCachingCodec(TopLevelList.class);
91         final NormalizedNode<?, ?> first = cachingCodec.serialize(TOP_TWO_LIST_DATA);
92         final NormalizedNode<?, ?> second = cachingCodec.serialize(TOP_TWO_LIST_DATA);
93
94         assertNotSame(first, second);
95         assertEquals(first, second);
96         verifyListItemSame(first, second);
97
98         final NormalizedNode<?, ?> third = cachingCodec.serialize(TOP_THREE_LIST_DATA);
99         verifyListItemSame(first, third);
100         verifyListItemSame(second, third);
101     }
102
103     @Test
104     public void testTopAndListCache() {
105         final BindingNormalizedNodeCachingCodec<Top> cachingCodec = createCachingCodec(Top.class, TopLevelList.class);
106         final NormalizedNode<?, ?> first = cachingCodec.serialize(TOP_TWO_LIST_DATA);
107         final NormalizedNode<?, ?> second = cachingCodec.serialize(TOP_TWO_LIST_DATA);
108
109         assertEquals(first, second);
110         assertSame(first, second);
111
112         final NormalizedNode<?, ?> third = cachingCodec.serialize(TOP_THREE_LIST_DATA);
113         verifyListItemSame(first, third);
114     }
115
116     @Test
117     public void testLeafCache() {
118         // The integers should be distinct
119         assertNotSame(CONT_DATA.getCaching().getValue(), CONT2_DATA.getCaching().getValue());
120
121         final BindingNormalizedNodeCachingCodec<Cont> cachingCodec = createContCachingCodec(Cont.class, MyType.class);
122         final NormalizedNode<?, ?> first = cachingCodec.serialize(CONT_DATA);
123         final NormalizedNode<?, ?> second = cachingCodec.serialize(CONT2_DATA);
124
125         assertNotEquals(first, second);
126         verifyLeafItemSame(first, second);
127     }
128
129     @Test
130     public void testDefaultInvocation() {
131         final BindingNormalizedNodeCachingCodec<Top> cachingCodec = createCachingCodec(Top.class, TopLevelList.class);
132
133         final Top input = new TopBuilder().build();
134         assertNull(input.getTopLevelList());
135         assertEquals(ImmutableMap.of(), input.nonnullTopLevelList());
136
137         final NormalizedNode<?, ?> dom = cachingCodec.serialize(input);
138         final Top output = cachingCodec.deserialize(dom);
139         assertTrue(input.equals(output));
140         assertTrue(output.equals(input));
141
142         assertNull(output.getTopLevelList());
143         assertEquals(ImmutableMap.of(), output.nonnullTopLevelList());
144     }
145
146     @SafeVarargs
147     private final BindingNormalizedNodeCachingCodec<Top> createCachingCodec(
148             final Class<? extends DataObject>... classes) {
149         return topNode.createCachingCodec(ImmutableSet.copyOf(classes));
150     }
151
152     @SafeVarargs
153     private final BindingNormalizedNodeCachingCodec<Cont> createContCachingCodec(
154             final Class<? extends BindingObject>... classes) {
155         return contNode.createCachingCodec(ImmutableSet.copyOf(classes));
156     }
157
158     private static void verifyListItemSame(final NormalizedNode<?, ?> firstTop, final NormalizedNode<?, ?> secondTop) {
159         final Collection<MapEntryNode> initialNodes = getListItems(firstTop).getValue();
160         final MapNode secondMap = getListItems(secondTop);
161
162         for (final MapEntryNode initial : initialNodes) {
163             final MapEntryNode second = secondMap.getChild(initial.getIdentifier()).get();
164             assertEquals(initial, second);
165             assertSame(initial, second);
166         }
167     }
168
169     private static MapNode getListItems(final NormalizedNode<?, ?> top) {
170         return (MapNode) ((DataContainerNode<?>) top).getChild(TOP_LEVEL_LIST_ARG).get();
171     }
172
173     private static void verifyLeafItemSame(final NormalizedNode<?, ?> firstCont,
174             final NormalizedNode<?, ?> secondCont) {
175         final DataContainerChild<?, ?> first = ((DataContainerNode<?>) firstCont).getChild(LEAF_ARG).get();
176         assertTrue(first instanceof LeafNode);
177
178         final DataContainerChild<?, ?> second = ((DataContainerNode<?>) secondCont).getChild(LEAF_ARG).get();
179         assertTrue(second instanceof LeafNode);
180
181         // The leaf nodes are transient, but the values should be the same
182         assertEquals(first, second);
183         assertSame(first.getValue(), second.getValue());
184     }
185 }