2 * Copyright (c) 2015 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
8 package org.opendaylight.mdsal.binding.dom.codec.impl;
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;
17 import com.google.common.collect.ImmutableMap;
18 import com.google.common.collect.ImmutableSet;
19 import java.util.Collection;
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;
45 public class CachingCodecTest extends AbstractBindingCodecTest {
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);
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();
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);
58 private static final Cont CONT_DATA = new ContBuilder().setCaching(new MyType(dataValue())).setNonCaching("test")
60 private static final Cont CONT2_DATA = new ContBuilder().setCaching(new MyType(dataValue())).setNonCaching("test2")
63 private BindingDataObjectCodecTreeNode<Top> topNode;
64 private BindingDataObjectCodecTreeNode<Cont> contNode;
66 private static String dataValue() {
67 // We are battling interning here
68 return new StringBuilder("foo").toString();
73 public void before() {
75 topNode = codecContext.getDataObjectCodec(TOP_PATH);
76 contNode = codecContext.getDataObjectCodec(CONT_PATH);
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());
85 return builder.build();
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);
94 assertNotSame(first, second);
95 assertEquals(first, second);
96 verifyListItemSame(first, second);
98 final NormalizedNode third = cachingCodec.serialize(TOP_THREE_LIST_DATA);
99 verifyListItemSame(first, third);
100 verifyListItemSame(second, third);
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);
109 assertEquals(first, second);
110 assertSame(first, second);
112 final NormalizedNode third = cachingCodec.serialize(TOP_THREE_LIST_DATA);
113 verifyListItemSame(first, third);
117 public void testLeafCache() {
118 // The integers should be distinct
119 assertNotSame(CONT_DATA.getCaching().getValue(), CONT2_DATA.getCaching().getValue());
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);
125 assertNotEquals(first, second);
126 verifyLeafItemSame(first, second);
130 public void testDefaultInvocation() {
131 final BindingNormalizedNodeCachingCodec<Top> cachingCodec = createCachingCodec(Top.class, TopLevelList.class);
133 final Top input = new TopBuilder().build();
134 assertNull(input.getTopLevelList());
135 assertEquals(ImmutableMap.of(), input.nonnullTopLevelList());
137 final NormalizedNode dom = cachingCodec.serialize(input);
138 final Top output = cachingCodec.deserialize(dom);
139 assertTrue(input.equals(output));
140 assertTrue(output.equals(input));
142 assertNull(output.getTopLevelList());
143 assertEquals(ImmutableMap.of(), output.nonnullTopLevelList());
147 private final BindingNormalizedNodeCachingCodec<Top> createCachingCodec(
148 final Class<? extends DataObject>... classes) {
149 return topNode.createCachingCodec(ImmutableSet.copyOf(classes));
153 private final BindingNormalizedNodeCachingCodec<Cont> createContCachingCodec(
154 final Class<? extends BindingObject>... classes) {
155 return contNode.createCachingCodec(ImmutableSet.copyOf(classes));
158 private static void verifyListItemSame(final NormalizedNode firstTop, final NormalizedNode secondTop) {
159 final Collection<MapEntryNode> initialNodes = getListItems(firstTop).body();
160 final MapNode secondMap = getListItems(secondTop);
162 for (final MapEntryNode initial : initialNodes) {
163 final MapEntryNode second = secondMap.childByArg(initial.name());
164 assertEquals(initial, second);
165 assertSame(initial, second);
169 private static MapNode getListItems(final NormalizedNode top) {
170 return (MapNode) ((DataContainerNode) top).getChildByArg(TOP_LEVEL_LIST_ARG);
173 private static void verifyLeafItemSame(final NormalizedNode firstCont, final NormalizedNode secondCont) {
174 final DataContainerChild first = ((DataContainerNode) firstCont).childByArg(LEAF_ARG);
175 assertTrue(first instanceof LeafNode);
177 final DataContainerChild second = ((DataContainerNode) secondCont).childByArg(LEAF_ARG);
178 assertTrue(second instanceof LeafNode);
180 // The leaf nodes are transient, but the values should be the same
181 assertEquals(first, second);
182 assertSame(first.body(), second.body());