-Onos store refactoring
-Added unit tests for TranscodingAsyncConsistMap, AsyncDistributedSet

Change-Id: I744aef36a7086a941f7a3809ab632dbf7ec2c89b
diff --git a/core/store/primitives/src/test/java/org/onosproject/store/primitives/impl/AsyncConsistentMapMock.java b/core/store/primitives/src/test/java/org/onosproject/store/primitives/impl/AsyncConsistentMapMock.java
new file mode 100644
index 0000000..9391f8d
--- /dev/null
+++ b/core/store/primitives/src/test/java/org/onosproject/store/primitives/impl/AsyncConsistentMapMock.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.store.primitives.impl;
+
+import org.onosproject.store.service.AsyncConsistentMapAdapter;
+import org.onosproject.store.service.MapEventListener;
+import org.onosproject.store.service.Versioned;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Executor;
+import java.util.function.BiFunction;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+/*Simple template for asynchronous map
+Serializer must be defined independently
+ */
+public class AsyncConsistentMapMock<K, V> extends AsyncConsistentMapAdapter<K, V> {
+    private final Map<K, V> baseMap = new HashMap<>();
+    private final List<MapEventListener<K, V>> listeners;
+
+    Versioned<V> makeVersioned(V v) {
+        return new Versioned<>(v, 1, 0);
+    }
+
+    public AsyncConsistentMapMock() {
+        this.listeners = new ArrayList<>();
+    }
+
+    public CompletableFuture<Integer> size() {
+        return CompletableFuture.completedFuture(baseMap.size());
+    }
+
+    @Override
+    public CompletableFuture<Boolean> containsKey(K key) {
+        return CompletableFuture.completedFuture(baseMap.containsKey(key));
+    }
+
+    @Override
+    public CompletableFuture<Boolean> containsValue(V value) {
+        return CompletableFuture.completedFuture(baseMap.values()
+                .stream()
+                .anyMatch(v -> {
+                    if (v instanceof byte[] && value instanceof byte[]) {
+                        return Arrays.equals((byte[]) v, (byte[]) value);
+                    } else {
+                        return Objects.equals(v, value);
+                    }
+                }));
+    }
+
+    @Override
+    public CompletableFuture<Versioned<V>> get(K key) {
+        return CompletableFuture.completedFuture(makeVersioned(baseMap.get(key)));
+    }
+
+    @Override
+    public CompletableFuture<Versioned<V>> getOrDefault(K key, V defaultValue) {
+        return CompletableFuture.completedFuture(makeVersioned(baseMap.getOrDefault(key, defaultValue)));
+    }
+
+    @Override
+    public CompletableFuture<Versioned<V>>
+    computeIf(K key, Predicate<? super V> condition,
+              BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
+
+        V value = baseMap.get(key);
+
+        if (condition.test(value)) {
+            value = baseMap.compute(key, remappingFunction);
+        }
+        return CompletableFuture.completedFuture(makeVersioned(value));
+    }
+
+    @Override
+    public CompletableFuture<Versioned<V>> put(K key, V value) {
+        return CompletableFuture.completedFuture(makeVersioned(baseMap.put(key, value)));
+    }
+
+    @Override
+    public CompletableFuture<Versioned<V>> putAndGet(K key, V value) {
+        return CompletableFuture.completedFuture(makeVersioned(baseMap.put(key, value)));
+    }
+
+    @Override
+    public CompletableFuture<Versioned<V>> remove(K key) {
+        return CompletableFuture.completedFuture(makeVersioned(baseMap.remove(key)));
+    }
+
+    @Override
+    public CompletableFuture<Void> clear() {
+        baseMap.clear();
+        return CompletableFuture.allOf();
+    }
+
+    @Override
+    public CompletableFuture<Set<K>> keySet() {
+        return CompletableFuture.completedFuture(baseMap.keySet());
+    }
+
+    @Override
+    public CompletableFuture<Collection<Versioned<V>>> values() {
+        Set<Versioned<V>> valuesAsVersionedCollection =
+                baseMap.values().stream().map(this::makeVersioned)
+                        .collect(Collectors.toSet());
+        return CompletableFuture.completedFuture(valuesAsVersionedCollection);
+    }
+
+    @Override
+    public CompletableFuture<Set<Map.Entry<K, Versioned<V>>>> entrySet() {
+        Map<K, Versioned<V>> valuesAsVersionedMap = new HashMap<>();
+        baseMap.entrySet()
+                .forEach(e -> valuesAsVersionedMap.put(e.getKey(),
+                        makeVersioned(e.getValue())));
+        return CompletableFuture.completedFuture(valuesAsVersionedMap.entrySet());
+    }
+
+    @Override
+    public CompletableFuture<Versioned<V>> putIfAbsent(K key, V value) {
+        return CompletableFuture.completedFuture(makeVersioned(baseMap.putIfAbsent(key, value)));
+    }
+
+    @Override
+    public CompletableFuture<Boolean> remove(K key, V value) {
+        return CompletableFuture.completedFuture(baseMap.remove(key, value));
+    }
+
+    @Override
+    public CompletableFuture<Boolean> remove(K key, long version) {
+        Object value = baseMap.remove(key);
+        return CompletableFuture.completedFuture(value != null);
+    }
+
+    @Override
+    public CompletableFuture<Versioned<V>> replace(K key, V value) {
+        return CompletableFuture.completedFuture(makeVersioned(baseMap.replace(key, value)));
+    }
+
+    @Override
+    public CompletableFuture<Boolean> replace(K key, V oldValue, V newValue) {
+        V current = baseMap.get(key);
+            if (current instanceof byte[] && oldValue instanceof byte[]) {
+                baseMap.put(key, newValue);
+                return CompletableFuture.completedFuture(Arrays.equals((byte[]) current, (byte[]) oldValue));
+            } else {
+                return CompletableFuture.completedFuture(Objects.equals(current, oldValue));
+            }
+    }
+
+    @Override
+    public CompletableFuture<Boolean> replace(K key, long oldVersion, V newValue) {
+        return CompletableFuture.completedFuture(baseMap.replace(key, newValue) != null);
+    }
+
+    @Override
+    public CompletableFuture<Void> addListener(MapEventListener<K, V> listener, Executor e) {
+        listeners.add(listener);
+        return CompletableFuture.allOf();
+    }
+
+    @Override
+    public CompletableFuture<Void> removeListener(MapEventListener<K, V> listener) {
+        listeners.remove(listener);
+        return CompletableFuture.allOf();
+    }
+}
+
diff --git a/core/store/primitives/src/test/java/org/onosproject/store/primitives/impl/DefaultAsyncAtomicValueTest.java b/core/store/primitives/src/test/java/org/onosproject/store/primitives/impl/DefaultAsyncAtomicValueTest.java
index c2c1f9f..a34cf98 100644
--- a/core/store/primitives/src/test/java/org/onosproject/store/primitives/impl/DefaultAsyncAtomicValueTest.java
+++ b/core/store/primitives/src/test/java/org/onosproject/store/primitives/impl/DefaultAsyncAtomicValueTest.java
@@ -19,43 +19,26 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.onlab.util.Tools;
-import org.onosproject.store.primitives.MapUpdate;
-import org.onosproject.store.primitives.TransactionId;
 import org.onosproject.store.serializers.KryoNamespaces;
 import org.onosproject.store.service.AsyncConsistentMap;
-import org.onosproject.store.service.MapEventListener;
 import org.onosproject.store.service.Serializer;
-import org.onosproject.store.service.TransactionLog;
-import org.onosproject.store.service.Version;
-import org.onosproject.store.service.Versioned;
 import org.onosproject.utils.MeteringAgent;
 
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.Executor;
-import java.util.function.BiFunction;
-import java.util.function.Predicate;
-
 import static org.hamcrest.core.Is.is;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertThat;
 
 
 public class DefaultAsyncAtomicValueTest {
-    DefaultAsyncAtomicValue defaultAsyncAtomicValue;
-    DefaultAsyncAtomicValue defaultAsyncAtomicValue1;
-
+    DefaultAsyncAtomicValue<String> defaultAsyncAtomicValue;
 
     private AsyncConsistentMap<String, byte[]> asyncMap;
-    private Map<String, Versioned<byte[]>> map;
 
     private Serializer serializer;
     private MeteringAgent meteringAgent;
 
+    private static final String MAPNAME = "map1";
+
 
     private static final String NAME = "atomicValue";
     private static final String NAME1 = "atomicValue1";
@@ -71,175 +54,11 @@
 
     @Before
     public void setUp() throws Exception {
-        map = new HashMap<>();
-        asyncMap = new AsyncConsistentMap<String, byte[]>() {
-            @Override
-            public CompletableFuture<Integer> size() {
-                return CompletableFuture.completedFuture(map.size());
-            }
-
-            @Override
-            public CompletableFuture<Boolean> containsKey(String key) {
-                return CompletableFuture.completedFuture(map.containsKey(key));
-            }
-
-            @Override
-            public CompletableFuture<Boolean> containsValue(byte[] value) {
-                return CompletableFuture.completedFuture(map.containsValue(value));
-            }
-
-            @Override
-            public CompletableFuture<Versioned<byte[]>> get(String key) {
-                return CompletableFuture.completedFuture(map.get(key));
-            }
-
-            @Override
-            public CompletableFuture<Versioned<byte[]>> getOrDefault(String key, byte[] defaultValue) {
-                return CompletableFuture.completedFuture(map.getOrDefault(key, new Versioned<byte[]>(defaultValue,
-                        VERSION1)));
-            }
-
-            @Override
-            public CompletableFuture<Versioned<byte[]>> computeIf(String key, Predicate<? super byte[]> condition,
-                                                                  BiFunction<? super String, ? super byte[],
-                                                                          ? extends byte[]> remappingFunction) {
-                return null;
-            }
-
-            @Override
-            public CompletableFuture<Versioned<byte[]>> put(String key, byte[] value) {
-                return CompletableFuture.completedFuture(map.put(key, new Versioned<byte[]>(value, VERSION1)));
-            }
-
-
-            @Override
-            public CompletableFuture<Versioned<byte[]>> putAndGet(String key, byte[] value) {
-                return null;
-            }
-
-            @Override
-            public CompletableFuture<Versioned<byte[]>> remove(String key) {
-                return CompletableFuture.completedFuture(map.remove(key));
-            }
-
-            @Override
-            public CompletableFuture<Void> clear() {
-                return null;
-            }
-
-            @Override
-            public CompletableFuture<Set<String>> keySet() {
-                return null;
-            }
-
-            @Override
-            public CompletableFuture<Collection<Versioned<byte[]>>> values() {
-                return CompletableFuture.completedFuture(map.values());
-            }
-
-            @Override
-            public CompletableFuture<Set<Map.Entry<String, Versioned<byte[]>>>> entrySet() {
-                return CompletableFuture.completedFuture(map.entrySet());
-            }
-
-            @Override
-            public CompletableFuture<Versioned<byte[]>> putIfAbsent(String key, byte[] value) {
-                return CompletableFuture.completedFuture(map.putIfAbsent(key, new Versioned<byte[]>(value, 2)));
-            }
-
-            @Override
-            public CompletableFuture<Boolean> remove(String key, byte[] value) {
-                return CompletableFuture.completedFuture(map.remove(key, value));
-            }
-
-            @Override
-            public CompletableFuture<Boolean> remove(String key, long version) {
-                Versioned versioned = map.get(key);
-                if (versioned.version() == version) {
-                    map.remove(key);
-                    return CompletableFuture.completedFuture(true);
-                }
-                return CompletableFuture.completedFuture(false);
-            }
-
-            @Override
-            public CompletableFuture<Versioned<byte[]>> replace(String key, byte[] value) {
-                return CompletableFuture.completedFuture(map.replace(key, new Versioned<byte[]>(value, VERSION1)));
-            }
-
-            @Override
-            public CompletableFuture<Boolean> replace(String key, byte[] oldValue, byte[] newValue) {
-                Versioned<byte[]> currentValue = map.get(key);
-                if (currentValue == null) {
-                    return CompletableFuture.completedFuture(false);
-                }
-
-                if (Arrays.equals(currentValue.value(), oldValue)) {
-                    map.put(key, new Versioned<>(newValue, VERSION1));
-                    return CompletableFuture.completedFuture(true);
-                }
-                return CompletableFuture.completedFuture(false);
-            }
-
-            @Override
-            public CompletableFuture<Boolean> replace(String key, long oldVersion, byte[] newValue) {
-                Versioned versioned = map.get(key);
-                if (versioned != null && versioned.version() == oldVersion) {
-                    map.put(key, new Versioned<byte[]>(newValue, VERSION1));
-                    return CompletableFuture.completedFuture(true);
-                }
-                return CompletableFuture.completedFuture(false);
-            }
-
-            @Override
-            public CompletableFuture<Void> addListener(MapEventListener<String, byte[]> listener, Executor executor) {
-                return null;
-            }
-
-            @Override
-            public CompletableFuture<Void> removeListener(MapEventListener<String, byte[]> listener) {
-                return null;
-            }
-
-            @Override
-            public String name() {
-                return null;
-            }
-
-            @Override
-            public CompletableFuture<Version> begin(TransactionId transactionId) {
-                return null;
-            }
-
-            @Override
-            public CompletableFuture<Boolean> prepare(TransactionLog<MapUpdate<String, byte[]>> transactionLog) {
-                return null;
-            }
-
-            @Override
-            public CompletableFuture<Boolean> prepareAndCommit(TransactionLog<MapUpdate<String,
-                    byte[]>> transactionLog) {
-                return null;
-            }
-
-            @Override
-            public CompletableFuture<Void> commit(TransactionId transactionId) {
-                return null;
-            }
-
-            @Override
-            public CompletableFuture<Void> rollback(TransactionId transactionId) {
-                return null;
-            }
-        };
-
+        asyncMap = new AsyncConsistentMapMock<>();
         serializer = Serializer.using(KryoNamespaces.BASIC);
         meteringAgent = new MeteringAgent(NAME, "*", false);
-        defaultAsyncAtomicValue = new DefaultAsyncAtomicValue(NAME, serializer,
+        defaultAsyncAtomicValue = new DefaultAsyncAtomicValue(MAPNAME, serializer,
                 asyncMap, meteringAgent);
-        defaultAsyncAtomicValue1 = new DefaultAsyncAtomicValue(NAME1, serializer,
-                asyncMap, meteringAgent);
-
     }
 
     @After
@@ -295,26 +114,25 @@
         defaultAsyncAtomicValue = new DefaultAsyncAtomicValue(NAME, serializer,
                 asyncMap, meteringAgent);
         assertThat(defaultAsyncAtomicValue.name(), is(NAME));
-        defaultAsyncAtomicValue.set(null);
+        defaultAsyncAtomicValue.set(null).join();
         assertNull(defaultAsyncAtomicValue.get().join());
 
-        defaultAsyncAtomicValue.set(INTNAME);
-        assertThat(defaultAsyncAtomicValue.get().join(), is(INTNAME));
+        defaultAsyncAtomicValue.set(NAME).join();
+        assertThat(defaultAsyncAtomicValue.get().join(), is(NAME));
 
-        defaultAsyncAtomicValue.set(value1);
-        assertThat(defaultAsyncAtomicValue.get().join(), is(value1));
+        defaultAsyncAtomicValue.set(NAME1).join();
+        assertThat(defaultAsyncAtomicValue.get().join(), is(NAME1));
+        defaultAsyncAtomicValue.compareAndSet(NAME1, NAME).join();
+        assertThat(defaultAsyncAtomicValue.get().join(), is(NAME));
 
-        defaultAsyncAtomicValue.compareAndSet(value1, value3).join();
-        assertThat(defaultAsyncAtomicValue.get().join(), is(value3));
 
-        assertThat(defaultAsyncAtomicValue.compareAndSet(value3, value1).join(),
-                is(true));
-        assertThat(defaultAsyncAtomicValue.get().join(), is(value1));
-
-        defaultAsyncAtomicValue.getAndSet(null);
+        defaultAsyncAtomicValue.getAndSet(null).join();
         assertNull(defaultAsyncAtomicValue.get().join());
 
-        defaultAsyncAtomicValue.getAndSet(value3);
-        assertThat(defaultAsyncAtomicValue.get().join(), is(value3));
+        defaultAsyncAtomicValue.set(NAME1).join();
+        assertThat(defaultAsyncAtomicValue.getAndSet(NAME).join(), is(NAME1));
+        assertThat(defaultAsyncAtomicValue.getAndSet("new").join(), is(NAME));
+
+        assertThat(defaultAsyncAtomicValue.get().join(), is("new"));
     }
 }
\ No newline at end of file
diff --git a/core/store/primitives/src/test/java/org/onosproject/store/primitives/impl/DefaultAsyncDistributedSetTest.java b/core/store/primitives/src/test/java/org/onosproject/store/primitives/impl/DefaultAsyncDistributedSetTest.java
new file mode 100644
index 0000000..899ff47
--- /dev/null
+++ b/core/store/primitives/src/test/java/org/onosproject/store/primitives/impl/DefaultAsyncDistributedSetTest.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.store.primitives.impl;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onosproject.store.serializers.KryoNamespaces;
+import org.onosproject.store.service.AsyncConsistentMap;
+import org.onosproject.store.service.Serializer;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+public class DefaultAsyncDistributedSetTest {
+    DefaultAsyncDistributedSet<String> defaultAsyncDistributedSet;
+
+    private static String name;
+    private static Serializer serializer;
+    private static AsyncConsistentMap<String, Boolean> asyncConsistentMap;
+    private static AsyncConsistentMap<String, byte[]> baseMap;
+    private static Map<Integer, String> map;
+    private static Collection<String> collection;
+    private static Collection<String> collection1;
+    private static Set<String> set;
+
+    private static final Boolean MAGENT = false;
+    private static final String TEST1 = "one";
+    private static final String TEST2 = "two";
+    private static final String TEST3 = "three";
+    private static final String TEST4 = "four";
+    private static final String TEST5 = "five";
+
+    @Before
+    public void setUp() throws Exception {
+        serializer = Serializer.using(KryoNamespaces.API);
+        asyncConsistentMap = new AsyncConsistentMapMock<>();
+        name = "Default Name";
+        map = new HashMap<>();
+        collection = new ArrayList<>();
+        set = new HashSet<>();
+
+        defaultAsyncDistributedSet = new DefaultAsyncDistributedSet<>(asyncConsistentMap,
+                name, MAGENT);
+    }
+    @After
+    public void clear() throws Exception {
+        defaultAsyncDistributedSet.clear().join();
+        assertThat(defaultAsyncDistributedSet.size().join(), is(0));
+        assertTrue(defaultAsyncDistributedSet.isEmpty().join());
+    }
+    @Test
+    public void testProperties() {
+        assertThat(defaultAsyncDistributedSet.name(), is(name));
+        assertTrue(defaultAsyncDistributedSet.isEmpty().join());
+
+        collection.add(TEST1);
+        collection.add(TEST2);
+        collection.add(TEST3);
+        set.add(TEST4);
+        set.add(TEST5);
+
+        assertThat(defaultAsyncDistributedSet.size().join(), is(0));
+        defaultAsyncDistributedSet.add(TEST1).join();
+        defaultAsyncDistributedSet.add(TEST2).join();
+        assertThat(defaultAsyncDistributedSet.size().join(), is(2));
+        defaultAsyncDistributedSet.add(TEST3).join();
+        assertThat(defaultAsyncDistributedSet.size().join(), is(3));
+
+        defaultAsyncDistributedSet.remove(TEST1);
+        assertThat(defaultAsyncDistributedSet.size().join(), is(2));
+        assertFalse(defaultAsyncDistributedSet.contains(TEST1).join());
+        assertTrue(defaultAsyncDistributedSet.contains(TEST2).join());
+
+        defaultAsyncDistributedSet.addAll(collection).join();
+        assertTrue(defaultAsyncDistributedSet.containsAll(collection).join());
+        assertFalse(defaultAsyncDistributedSet.retainAll(collection).join());
+
+        assertThat(defaultAsyncDistributedSet.size().join(), is(3));
+
+        defaultAsyncDistributedSet.addAll(set).join();
+        assertThat(defaultAsyncDistributedSet.size().join(), is(5));
+        assertTrue(defaultAsyncDistributedSet.contains(TEST4).join());
+        defaultAsyncDistributedSet.retainAll(set);
+
+        assertTrue(defaultAsyncDistributedSet.contains(TEST4).join());
+        assertThat(defaultAsyncDistributedSet.contains(TEST1).join(), is(false));
+
+        assertThat(defaultAsyncDistributedSet.getAsImmutableSet().join().size(),
+                is(2));
+    }
+
+}
\ No newline at end of file
diff --git a/core/store/primitives/src/test/java/org/onosproject/store/primitives/impl/TranscodingAsyncConsistentMapTest.java b/core/store/primitives/src/test/java/org/onosproject/store/primitives/impl/TranscodingAsyncConsistentMapTest.java
new file mode 100644
index 0000000..2cc9631
--- /dev/null
+++ b/core/store/primitives/src/test/java/org/onosproject/store/primitives/impl/TranscodingAsyncConsistentMapTest.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2016-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.store.primitives.impl;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.onosproject.net.DeviceId;
+import org.onosproject.store.serializers.KryoNamespaces;
+import org.onosproject.store.service.AsyncConsistentMap;
+import org.onosproject.store.service.Serializer;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.Function;
+
+import static org.hamcrest.Matchers.hasItem;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+public class TranscodingAsyncConsistentMapTest {
+
+    private static Serializer serializer;
+    private static AsyncConsistentMap<String, DeviceId> transcodingMap;
+    private static AsyncConsistentMap<String, byte[]> baseMap;
+    private static Map<String, byte[]> map;
+
+
+    private static final String KEY1 = "Key1";
+    private static final String KEY2 = "Key2";
+    private static final String KEY3 = "Key3";
+    private static final DeviceId DEV1 = DeviceId.deviceId("Device1");
+    private static final DeviceId DEV2 = DeviceId.deviceId("Device2");
+    private static final DeviceId DEV3 = DeviceId.deviceId("foo");
+    private static final DeviceId DEV4 = DeviceId.deviceId("bar");
+
+    @Before
+    public void setUp() throws Exception {
+        serializer = Serializer.using(KryoNamespaces.API);
+        map = new HashMap<>();
+        baseMap = new AsyncConsistentMapMock<>();
+
+        transcodingMap =  DistributedPrimitives.newTranscodingMap(
+                baseMap,
+                Function.identity(),
+                Function.identity(),
+                serializer::encode,
+                serializer::decode);
+    }
+
+    @Test
+    public void testSize() throws Exception {
+
+        assertThat(transcodingMap.size().join(), is(0));
+        transcodingMap.put(KEY1, DEV1).join();
+        assertThat(transcodingMap.size().join(), is(1));
+        transcodingMap.put(KEY1, DEV2).join();
+        assertThat(transcodingMap.size().join(), is(1));
+
+        transcodingMap.put(KEY2, DEV2).join();
+        assertThat(transcodingMap.size().join(), is(2));
+        for (int i = 0; i < 20; i++) {
+            transcodingMap.put("KEY" + i + 1, DeviceId.deviceId("Device" + i + 1)).join();
+        }
+        assertThat(transcodingMap.size().join(), is(22));
+    }
+
+    @Test
+    public void testEmpty() throws Exception {
+        assertTrue(transcodingMap.isEmpty().join());
+        transcodingMap.put(KEY1, DEV1).join();
+        assertFalse(transcodingMap.isEmpty().join());
+        transcodingMap.remove(KEY1).join();
+        assertTrue(transcodingMap.isEmpty().join());
+        transcodingMap.put(KEY1, DEV1).join();
+
+        transcodingMap.remove(KEY1, DEV1).join();
+        transcodingMap.put(KEY2, DEV2).join();
+
+        transcodingMap.remove(KEY1, 1).join();
+        assertThat(transcodingMap.size().join(), is(1));
+
+        transcodingMap.clear().join();
+        assertThat(transcodingMap.isEmpty().join(), is(true));
+
+    }
+
+    @Test
+    public void testContains() throws Exception {
+        assertFalse(transcodingMap.containsKey(KEY1).join());
+        transcodingMap.put(KEY1, DEV1);
+        assertTrue(transcodingMap.containsKey(KEY1).join());
+        assertTrue(transcodingMap.containsValue(DEV1).join());
+
+        transcodingMap.put(KEY2, DEV2);
+        assertTrue(transcodingMap.containsValue(DEV2).join());
+
+        transcodingMap.remove(KEY1);
+        assertFalse(transcodingMap.containsKey(KEY1).join());
+        assertFalse(transcodingMap.containsValue(DEV1).join());
+    }
+
+    public void testGet() throws Exception {
+        assertNull(transcodingMap.get(KEY1).join().value());
+        transcodingMap.put(KEY2, DEV1).join();
+        transcodingMap.put(KEY2, DEV3).join();
+
+        assertThat(transcodingMap.get(KEY2).join().value(), is(DEV3));
+
+        assertThat(transcodingMap.getOrDefault(KEY1, DeviceId.deviceId("bar")).join().value(),
+                is(DEV4));
+        transcodingMap.put(KEY1, DEV2).join();
+        assertThat(transcodingMap.getOrDefault(KEY1, DEV1).join().value(), is(DEV2));
+        assertThat(transcodingMap.get(KEY1).join().value(), is(DEV2));
+    }
+
+    @Test
+    public void testSwitch() throws Exception {
+        transcodingMap.put(KEY1, DEV1).join();
+        transcodingMap.put(KEY2, DEV2).join();
+
+        transcodingMap.replace(KEY1, DEV1, DEV3).join();
+        assertThat(transcodingMap.containsValue(DEV2).join(), is(true));
+        transcodingMap.putAndGet(KEY1, DEV3).join();
+        assertThat(transcodingMap.get(KEY1).join().value(), is(DEV3));
+
+        transcodingMap.replace(KEY1, DEV1);
+        assertThat(transcodingMap.get(KEY1).join().value(), is(DEV1));
+
+        transcodingMap.replace(KEY1, 1, DEV4);
+        assertThat(transcodingMap.get(KEY1).join().value(), is(DEV4));
+
+        assertNull(transcodingMap.remove("keyTest").join().value());
+
+    }
+
+    @Test
+    public void testEntry() throws Exception {
+        assertThat(transcodingMap.entrySet().join().size(), is(0));
+        transcodingMap.put(KEY2, DEV2).join();
+        transcodingMap.put(KEY1, DEV1).join();
+        assertThat(transcodingMap.entrySet().join().size(), is(2));
+        transcodingMap.put(KEY3, DEV3).join();
+        transcodingMap.put(KEY3, DEV4).join();
+        assertThat(transcodingMap.entrySet().join().size(), (is(3)));
+
+        transcodingMap.put(KEY3, null).join();
+        transcodingMap.putIfAbsent(KEY3, DEV3).join();
+        assertThat(transcodingMap.entrySet().join().size(), is(3));
+        assertThat(transcodingMap.get(KEY3).join().value(), is(DEV3));
+    }
+
+    @Test
+    public void keyTest() throws Exception {
+        assertThat(transcodingMap.keySet().join().size(), is(0));
+        transcodingMap.putIfAbsent(KEY1, DEV1).join();
+        transcodingMap.putIfAbsent(KEY2, DEV2).join();
+        transcodingMap.putIfAbsent(KEY3, DEV3).join();
+        assertThat(transcodingMap.keySet().join().size(), is(3));
+        assertThat(transcodingMap.keySet().join(), hasItem(KEY1));
+        assertThat(transcodingMap.keySet().join(), hasItem(KEY2));
+    }
+
+}
\ No newline at end of file