Map system-ordered keyed lists to Map
[mdsal.git] / binding / mdsal-binding-dom-codec / src / test / java / org / opendaylight / mdsal / binding / dom / codec / test / CachingCodecTest.java
index 650179e02083a27083170bc6d0f40b8f265e13b8..7c8fa7a72950b820315c06dc8de13df81f6b90f7 100644 (file)
@@ -8,63 +8,80 @@
 package org.opendaylight.mdsal.binding.dom.codec.test;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
 
-import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import java.util.Collection;
-import java.util.List;
-import javassist.ClassPool;
+import java.util.Map;
+import org.junit.Before;
 import org.junit.Test;
-import org.opendaylight.mdsal.binding.dom.codec.api.BindingCodecTreeNode;
+import org.opendaylight.mdsal.binding.dom.codec.api.BindingDataObjectCodecTreeNode;
 import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeCachingCodec;
-import org.opendaylight.mdsal.binding.dom.codec.gen.impl.StreamWriterGenerator;
-import org.opendaylight.mdsal.binding.dom.codec.impl.BindingNormalizedNodeCodecRegistry;
-import org.opendaylight.mdsal.binding.generator.util.JavassistUtils;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.Top;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.TopBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.two.level.list.TopLevelList;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.two.level.list.TopLevelListBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.two.level.list.TopLevelListKey;
+import org.opendaylight.yang.gen.v1.urn.test.leaf.caching.codec.rev190201.Cont;
+import org.opendaylight.yang.gen.v1.urn.test.leaf.caching.codec.rev190201.ContBuilder;
+import org.opendaylight.yang.gen.v1.urn.test.leaf.caching.codec.rev190201.MyType;
+import org.opendaylight.yangtools.yang.binding.BindingObject;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.nodes.LazyLeafOperations;
 
-public class CachingCodecTest extends AbstractBindingRuntimeTest {
+public class CachingCodecTest extends AbstractBindingCodecTest {
 
     private static final NodeIdentifier TOP_LEVEL_LIST_ARG = new NodeIdentifier(TopLevelList.QNAME);
     private static final InstanceIdentifier<Top> TOP_PATH = InstanceIdentifier.create(Top.class);
-    private static final List<TopLevelList> TWO_LIST = createList(2);
-    private static final List<TopLevelList> THREE_LIST = createList(3);
+    private static final Map<TopLevelListKey, TopLevelList> TWO_LIST = createList(2);
+    private static final Map<TopLevelListKey, TopLevelList> THREE_LIST = createList(3);
 
     private static final Top TOP_TWO_LIST_DATA = new TopBuilder().setTopLevelList(TWO_LIST).build();
     private static final Top TOP_THREE_LIST_DATA = new TopBuilder().setTopLevelList(THREE_LIST).build();
 
-    private BindingNormalizedNodeCodecRegistry registry;
-    private BindingCodecTreeNode<Top> topNode;
+    private static final NodeIdentifier LEAF_ARG = new NodeIdentifier(QName.create(Cont.QNAME, "caching"));
+    private static final InstanceIdentifier<Cont> CONT_PATH = InstanceIdentifier.create(Cont.class);
 
-    @Override
-    public void setup() {
-        super.setup();
-        final JavassistUtils utils = JavassistUtils.forClassPool(ClassPool.getDefault());
-        registry = new BindingNormalizedNodeCodecRegistry(StreamWriterGenerator.create(utils));
-        registry.onBindingRuntimeContextUpdated(getRuntimeContext());
-        topNode = registry.getCodecContext().getSubtreeCodec(TOP_PATH);
+    private static final Cont CONT_DATA = new ContBuilder().setCaching(new MyType(dataValue())).setNonCaching("test")
+            .build();
+    private static final Cont CONT2_DATA = new ContBuilder().setCaching(new MyType(dataValue())).setNonCaching("test2")
+            .build();
 
-    }
+    private BindingDataObjectCodecTreeNode<Top> topNode;
+    private BindingDataObjectCodecTreeNode<Cont> contNode;
 
+    private static String dataValue() {
+        // We are battling interning here
+        return new StringBuilder("foo").toString();
+    }
 
-    private static List<TopLevelList> createList(final int num) {
+    @Override
+    @Before
+    public void before() {
+        super.before();
+        topNode = registry.getCodecContext().getSubtreeCodec(TOP_PATH);
+        contNode = registry.getCodecContext().getSubtreeCodec(CONT_PATH);
+    }
 
-        final ImmutableList.Builder<TopLevelList> builder = ImmutableList.builder();
+    private static Map<TopLevelListKey, TopLevelList> createList(final int num) {
+        final ImmutableMap.Builder<TopLevelListKey, TopLevelList> builder = ImmutableMap.builder();
         for (int i = 0; i < num; i++) {
             final TopLevelListKey key = new TopLevelListKey("test-" + i);
-            builder.add(new TopLevelListBuilder().withKey(key).build());
+            builder.put(key, new TopLevelListBuilder().withKey(key).build());
         }
         return builder.build();
     }
@@ -84,7 +101,6 @@ public class CachingCodecTest extends AbstractBindingRuntimeTest {
         verifyListItemSame(second, third);
     }
 
-
     @Test
     public void testTopAndListCache() {
         final BindingNormalizedNodeCachingCodec<Top> cachingCodec = createCachingCodec(Top.class, TopLevelList.class);
@@ -98,10 +114,46 @@ public class CachingCodecTest extends AbstractBindingRuntimeTest {
         verifyListItemSame(first, third);
     }
 
+    @Test
+    public void testLeafCache() {
+        // The integers should be distinct
+        assertNotSame(CONT_DATA.getCaching().getValue(), CONT2_DATA.getCaching().getValue());
+
+        final BindingNormalizedNodeCachingCodec<Cont> cachingCodec = createContCachingCodec(Cont.class, MyType.class);
+        final NormalizedNode<?, ?> first = cachingCodec.serialize(CONT_DATA);
+        final NormalizedNode<?, ?> second = cachingCodec.serialize(CONT2_DATA);
+
+        assertNotEquals(first, second);
+        verifyLeafItemSame(first, second);
+    }
+
+    @Test
+    public void testDefaultInvocation() {
+        final BindingNormalizedNodeCachingCodec<Top> cachingCodec = createCachingCodec(Top.class, TopLevelList.class);
+
+        final Top input = new TopBuilder().build();
+        assertNull(input.getTopLevelList());
+        assertEquals(ImmutableMap.of(), input.nonnullTopLevelList());
+
+        final NormalizedNode<?, ?> dom = cachingCodec.serialize(input);
+        final Top output = cachingCodec.deserialize(dom);
+        assertTrue(input.equals(output));
+        assertTrue(output.equals(input));
+
+        assertNull(output.getTopLevelList());
+        assertEquals(ImmutableMap.of(), output.nonnullTopLevelList());
+    }
+
     @SafeVarargs
     private final BindingNormalizedNodeCachingCodec<Top> createCachingCodec(
             final Class<? extends DataObject>... classes) {
-        return topNode.createCachingCodec(ImmutableSet.<Class<? extends DataObject>>copyOf(classes));
+        return topNode.createCachingCodec(ImmutableSet.copyOf(classes));
+    }
+
+    @SafeVarargs
+    private final BindingNormalizedNodeCachingCodec<Cont> createContCachingCodec(
+            final Class<? extends BindingObject>... classes) {
+        return contNode.createCachingCodec(ImmutableSet.copyOf(classes));
     }
 
     private static void verifyListItemSame(final NormalizedNode<?, ?> firstTop, final NormalizedNode<?, ?> secondTop) {
@@ -115,9 +167,24 @@ public class CachingCodecTest extends AbstractBindingRuntimeTest {
         }
     }
 
-
     private static MapNode getListItems(final NormalizedNode<?, ?> top) {
         return (MapNode) ((DataContainerNode<?>) top).getChild(TOP_LEVEL_LIST_ARG).get();
     }
 
+    private static void verifyLeafItemSame(final NormalizedNode<?, ?> firstCont,
+            final NormalizedNode<?, ?> secondCont) {
+        final DataContainerChild<?, ?> first = ((DataContainerNode<?>) firstCont).getChild(LEAF_ARG).get();
+        assertTrue(first instanceof LeafNode);
+
+        final DataContainerChild<?, ?> second = ((DataContainerNode<?>) secondCont).getChild(LEAF_ARG).get();
+        assertTrue(second instanceof LeafNode);
+
+        if (LazyLeafOperations.isEnabled()) {
+            // The leaf nodes are transient, but the values should be the same
+            assertEquals(first, second);
+            assertSame(first.getValue(), second.getValue());
+        } else {
+            assertSame(first, second);
+        }
+    }
 }