Improve coverage for primitives

DefaultAtomicCounterMap
DefaultAtomicCounter
DefaultConsistentTreeMap

Change-Id: I15ec01290377aa15ab5351065c33bf50e124b8a6
diff --git a/core/api/src/test/java/org/onosproject/store/service/TestAtomicCounter.java b/core/api/src/test/java/org/onosproject/store/primitives/AsyncAtomicCounterAdapter.java
similarity index 83%
rename from core/api/src/test/java/org/onosproject/store/service/TestAtomicCounter.java
rename to core/api/src/test/java/org/onosproject/store/primitives/AsyncAtomicCounterAdapter.java
index c09c223..36cb9f1 100644
--- a/core/api/src/test/java/org/onosproject/store/service/TestAtomicCounter.java
+++ b/core/api/src/test/java/org/onosproject/store/primitives/AsyncAtomicCounterAdapter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2015-present Open Networking Foundation
+ * Copyright 2018-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.
@@ -13,7 +13,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.onosproject.store.service;
+package org.onosproject.store.primitives;
+
+import org.onosproject.store.service.AsyncAtomicCounter;
+import org.onosproject.store.service.AtomicCounterBuilder;
 
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.atomic.AtomicLong;
@@ -21,15 +24,15 @@
 /**
  * Test implementation of atomic counter.
  */
-public final class TestAtomicCounter implements AsyncAtomicCounter {
-    final AtomicLong value;
+public class AsyncAtomicCounterAdapter implements AsyncAtomicCounter {
+    private final AtomicLong value;
 
     @Override
     public String name() {
         return null;
     }
 
-    private TestAtomicCounter() {
+    AsyncAtomicCounterAdapter() {
         value = new AtomicLong();
     }
 
@@ -76,7 +79,7 @@
     public static class Builder extends AtomicCounterBuilder {
         @Override
         public AsyncAtomicCounter build() {
-            return new TestAtomicCounter();
+            return new AsyncAtomicCounterAdapter();
         }
     }
 }
diff --git a/core/api/src/test/java/org/onosproject/store/primitives/AsyncAtomicCounterMapAdapter.java b/core/api/src/test/java/org/onosproject/store/primitives/AsyncAtomicCounterMapAdapter.java
new file mode 100644
index 0000000..f9a08f8
--- /dev/null
+++ b/core/api/src/test/java/org/onosproject/store/primitives/AsyncAtomicCounterMapAdapter.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2018-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;
+
+import org.onosproject.store.service.AsyncAtomicCounterMap;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+
+public class AsyncAtomicCounterMapAdapter<K> implements AsyncAtomicCounterMap<K> {
+    private Map<K, Long> map = new HashMap<>();
+
+    @Override
+    public CompletableFuture<Long> incrementAndGet(K key) {
+        Long value = map.getOrDefault(key, 0L) + 1;
+        map.put(key, value);
+        return CompletableFuture.completedFuture(value);
+
+    }
+
+    @Override
+    public CompletableFuture<Long> decrementAndGet(K key) {
+        Long value = map.getOrDefault(key, 0L) - 1;
+        map.put(key, value);
+        return CompletableFuture.completedFuture(value);
+
+    }
+
+    @Override
+    public CompletableFuture<Long> getAndIncrement(K key) {
+        Long value = map.getOrDefault(key, 0L);
+        map.put(key, value + 1);
+        return CompletableFuture.completedFuture(value);
+
+    }
+
+    @Override
+    public CompletableFuture<Long> getAndDecrement(K key) {
+        Long value = map.getOrDefault(key, 0L);
+        map.put(key, value - 1);
+        return CompletableFuture.completedFuture(value);
+    }
+
+    @Override
+    public CompletableFuture<Long> addAndGet(K key, long delta) {
+        Long value = map.getOrDefault(key, 0L) + delta;
+        map.put(key, value);
+        return CompletableFuture.completedFuture(value);
+    }
+
+    @Override
+    public CompletableFuture<Long> getAndAdd(K key, long delta) {
+        Long value = map.getOrDefault(key, 0L);
+        map.put(key, value + delta);
+        return CompletableFuture.completedFuture(value);
+    }
+
+    @Override
+    public CompletableFuture<Long> get(K key) {
+        Long value = map.getOrDefault(key, 0L);
+        return CompletableFuture.completedFuture(value);
+    }
+
+    @Override
+    public CompletableFuture<Long> put(K key, long newValue) {
+        Long value = map.getOrDefault(key, 0L);
+        map.put(key, newValue);
+        return CompletableFuture.completedFuture(value);
+    }
+
+    @Override
+    public CompletableFuture<Long> putIfAbsent(K key, long newValue) {
+        Long value = map.putIfAbsent(key, newValue);
+        if (value == null) {
+            value = 0L;
+        }
+        return CompletableFuture.completedFuture(value);
+    }
+
+    @Override
+    public CompletableFuture<Boolean> replace(K key, long expectedOldValue, long newValue) {
+        boolean value = map.replace(key, expectedOldValue, newValue);
+        return CompletableFuture.completedFuture(value);
+    }
+
+    @Override
+    public CompletableFuture<Long> remove(K key) {
+        Long value = map.remove(key);
+        return CompletableFuture.completedFuture(value);
+    }
+
+    @Override
+    public CompletableFuture<Boolean> remove(K key, long value) {
+        boolean result = map.remove(key, value);
+        return CompletableFuture.completedFuture(result);
+    }
+
+    @Override
+    public CompletableFuture<Integer> size() {
+        int value = map.size();
+        return CompletableFuture.completedFuture(value);
+    }
+
+    @Override
+    public CompletableFuture<Boolean> isEmpty() {
+        boolean value = map.isEmpty();
+        return CompletableFuture.completedFuture(value);
+    }
+
+
+
+    @Override
+    public CompletableFuture<Void> clear() {
+        map.clear();
+        return CompletableFuture.completedFuture(null);
+
+    }
+
+    @Override
+    public String name() {
+        return null;
+    }
+}
diff --git a/core/api/src/test/java/org/onosproject/store/primitives/AsyncConsistentTreeMapAdapter.java b/core/api/src/test/java/org/onosproject/store/primitives/AsyncConsistentTreeMapAdapter.java
new file mode 100644
index 0000000..9f6da1a
--- /dev/null
+++ b/core/api/src/test/java/org/onosproject/store/primitives/AsyncConsistentTreeMapAdapter.java
@@ -0,0 +1,370 @@
+/*
+ * Copyright 2018-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;
+
+import com.google.common.collect.Maps;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.store.service.AsyncConsistentTreeMap;
+import org.onosproject.store.service.ConsistentMap;
+import org.onosproject.store.service.ConsistentTreeMap;
+import org.onosproject.store.service.MapEventListener;
+import org.onosproject.store.service.TransactionLog;
+import org.onosproject.store.service.Version;
+import org.onosproject.store.service.Versioned;
+
+import java.util.AbstractMap;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.NavigableMap;
+import java.util.NavigableSet;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Executor;
+import java.util.function.BiFunction;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+public class AsyncConsistentTreeMapAdapter<V> implements AsyncConsistentTreeMap<V> {
+
+    private TreeMap<String, V> map = Maps.newTreeMap();
+
+    private CompletableFuture<Map.Entry<String, Versioned<V>>> makeVersionedEntry(Map.Entry<String, V> entry) {
+        return CompletableFuture.completedFuture(
+                new AbstractMap.SimpleImmutableEntry<>(entry.getKey(),
+                                                       makeVersioned(entry.getValue())));
+    }
+
+    private CompletableFuture<Versioned<V>> makeVersionedFuture(V value) {
+        return CompletableFuture.completedFuture(makeVersioned(value));
+    }
+
+    private Versioned<V> makeVersioned(V value) {
+        return new Versioned<>(value, 1);
+    }
+
+    @Override
+    public CompletableFuture<String> firstKey() {
+        return CompletableFuture.completedFuture(map.firstKey());
+    }
+
+    @Override
+    public CompletableFuture<String> lastKey() {
+        return CompletableFuture.completedFuture(map.lastKey());
+    }
+
+    @Override
+    public CompletableFuture<Map.Entry<String, Versioned<V>>> ceilingEntry(String key) {
+        return makeVersionedEntry(map.ceilingEntry(key));
+    }
+
+    @Override
+    public CompletableFuture<Map.Entry<String, Versioned<V>>> floorEntry(String key) {
+        return makeVersionedEntry(map.floorEntry(key));
+    }
+
+    @Override
+    public CompletableFuture<Map.Entry<String, Versioned<V>>> higherEntry(String key) {
+        return makeVersionedEntry(map.higherEntry(key));
+    }
+
+    @Override
+    public CompletableFuture<Map.Entry<String, Versioned<V>>> lowerEntry(String key) {
+        return makeVersionedEntry(map.lowerEntry(key));
+    }
+
+    @Override
+    public CompletableFuture<Map.Entry<String, Versioned<V>>> firstEntry() {
+        return makeVersionedEntry(map.firstEntry());
+    }
+
+    @Override
+    public CompletableFuture<Map.Entry<String, Versioned<V>>> lastEntry() {
+        return makeVersionedEntry(map.lastEntry());
+    }
+
+    @Override
+    public CompletableFuture<Map.Entry<String, Versioned<V>>> pollFirstEntry() {
+        return makeVersionedEntry(map.pollFirstEntry());
+    }
+
+    @Override
+    public CompletableFuture<Map.Entry<String, Versioned<V>>> pollLastEntry() {
+        return makeVersionedEntry(map.pollLastEntry());
+    }
+
+    @Override
+    public CompletableFuture<String> lowerKey(String key) {
+        return CompletableFuture.completedFuture(map.lowerKey(key));
+    }
+
+    @Override
+    public CompletableFuture<String> floorKey(String key) {
+        return CompletableFuture.completedFuture(map.floorKey(key));
+    }
+
+    @Override
+    public CompletableFuture<String> ceilingKey(String key) {
+        return CompletableFuture.completedFuture(map.ceilingKey(key));
+    }
+
+    @Override
+    public CompletableFuture<String> higherKey(String key) {
+        return CompletableFuture.completedFuture(map.higherKey(key));
+    }
+
+    @Override
+    public CompletableFuture<NavigableSet<String>> navigableKeySet() {
+        return CompletableFuture.completedFuture(map.navigableKeySet());
+    }
+
+    @Override
+    public CompletableFuture<NavigableMap<String, V>> subMap(String upperKey, String lowerKey,
+                                                             boolean inclusiveUpper, boolean inclusiveLower) {
+        NavigableMap<String, V> subMap = map.subMap(upperKey, inclusiveLower, lowerKey, inclusiveLower);
+        return CompletableFuture.completedFuture(subMap);
+    }
+
+    @Override
+    public ConsistentTreeMap<V> asTreeMap() {
+        return null;
+    }
+
+    @Override
+    public ConsistentTreeMap<V> asTreeMap(long timeoutMillis) {
+        return null;
+    }
+
+    @Override
+    public Type primitiveType() {
+        return null;
+    }
+
+    @Override
+    public CompletableFuture<Integer> size() {
+        return CompletableFuture.completedFuture(map.size());
+    }
+
+    @Override
+    public CompletableFuture<Boolean> isEmpty() {
+        return CompletableFuture.completedFuture(map.isEmpty());
+    }
+
+    @Override
+    public CompletableFuture<Boolean> containsKey(String key) {
+        return CompletableFuture.completedFuture(map.containsKey(key));
+    }
+
+    @Override
+    public CompletableFuture<Boolean> containsValue(V value) {
+        return CompletableFuture.completedFuture(map.containsValue(value));
+    }
+
+    @Override
+    public CompletableFuture<Versioned<V>> get(String key) {
+        return makeVersionedFuture(map.get(key));
+    }
+
+    @Override
+    public CompletableFuture<Versioned<V>> getOrDefault(String key, V defaultValue) {
+        return makeVersionedFuture(map.getOrDefault(key, defaultValue));
+    }
+
+    @Override
+    public CompletableFuture<Versioned<V>>
+           computeIfAbsent(String key, Function<? super String, ? extends V> mappingFunction) {
+        return makeVersionedFuture(map.computeIfAbsent(key, mappingFunction));
+    }
+
+    @Override
+    public CompletableFuture<Versioned<V>>
+           computeIfPresent(String key, BiFunction<? super String, ? super V, ? extends V> remappingFunction) {
+        return makeVersionedFuture(map.computeIfPresent(key, remappingFunction));
+    }
+
+    @Override
+    public CompletableFuture<Versioned<V>>
+           compute(String key, BiFunction<? super String, ? super V, ? extends V> remappingFunction) {
+        return makeVersionedFuture(map.compute(key, remappingFunction));
+    }
+
+    @Override
+    public CompletableFuture<Versioned<V>>
+    computeIf(String key, Predicate<? super V> condition,
+              BiFunction<? super String, ? super V, ? extends V> remappingFunction) {
+
+        V value = map.get(key);
+
+        if (condition.test(value)) {
+            value = map.compute(key, remappingFunction);
+        }
+        return makeVersionedFuture(value);
+    }
+
+    @Override
+    public CompletableFuture<Versioned<V>> put(String key, V value) {
+        return makeVersionedFuture(map.put(key, value));
+    }
+
+    @Override
+    public CompletableFuture<Versioned<V>> putAndGet(String key, V value) {
+        return makeVersionedFuture(map.put(key, value));
+    }
+
+    @Override
+    public CompletableFuture<Versioned<V>> remove(String key) {
+        return makeVersionedFuture(map.remove(key));
+    }
+
+    @Override
+    public CompletableFuture<Void> clear() {
+        map.clear();
+        return CompletableFuture.completedFuture(null);
+    }
+
+    @Override
+    public CompletableFuture<Set<String>> keySet() {
+        return CompletableFuture.completedFuture(map.keySet());
+    }
+
+    @Override
+    public CompletableFuture<Collection<Versioned<V>>> values() {
+        Set<Versioned<V>> valuesAsVersionedCollection =
+                map.values().stream().map(this::makeVersioned)
+                        .collect(Collectors.toSet());
+        return CompletableFuture.completedFuture(valuesAsVersionedCollection);
+    }
+
+    @Override
+    public CompletableFuture<Set<Map.Entry<String, Versioned<V>>>> entrySet() {
+        Map<String, Versioned<V>> valuesAsVersionedMap = new HashMap<>();
+        map.forEach((key, value) ->
+                valuesAsVersionedMap.put(key, makeVersioned(value))
+        );
+        return CompletableFuture.completedFuture(valuesAsVersionedMap.entrySet());
+    }
+
+    @Override
+    public CompletableFuture<Versioned<V>> putIfAbsent(String key, V value) {
+        return makeVersionedFuture(map.putIfAbsent(key, value));
+    }
+
+    @Override
+    public CompletableFuture<Boolean> remove(String key, V value) {
+        return CompletableFuture.completedFuture(map.remove(key, value));
+    }
+
+    @Override
+    public CompletableFuture<Boolean> remove(String key, long version) {
+        Object value = map.remove(key);
+        return CompletableFuture.completedFuture(value != null);
+    }
+
+    @Override
+    public CompletableFuture<Versioned<V>> replace(String key, V value) {
+        return makeVersionedFuture(map.replace(key, value));
+    }
+
+    @Override
+    public CompletableFuture<Boolean> replace(String key, V oldValue, V newValue) {
+        return CompletableFuture.completedFuture(map.replace(key, oldValue, newValue));
+    }
+
+    @Override
+    public CompletableFuture<Boolean> replace(String key, long oldVersion, V newValue) {
+        map.replace(key, newValue);
+        return CompletableFuture.completedFuture(true);
+    }
+
+    @Override
+    public CompletableFuture<Void> addListener(MapEventListener<String, V> listener) {
+        return null;
+    }
+
+    @Override
+    public CompletableFuture<Void> addListener(MapEventListener<String, V> listener, Executor executor) {
+        return null;
+    }
+
+    @Override
+    public CompletableFuture<Void> removeListener(MapEventListener<String, V> listener) {
+        return null;
+    }
+
+    @Override
+    public ConsistentMap<String, V> asConsistentMap() {
+        return null;
+    }
+
+    @Override
+    public ConsistentMap<String, V> asConsistentMap(long timeoutMillis) {
+        return null;
+    }
+
+    @Override
+    public String name() {
+        return null;
+    }
+
+    @Override
+    public ApplicationId applicationId() {
+        return null;
+    }
+
+    @Override
+    public void addStatusChangeListener(Consumer<Status> listener) {
+
+    }
+
+    @Override
+    public void removeStatusChangeListener(Consumer<Status> listener) {
+
+    }
+
+    @Override
+    public Collection<Consumer<Status>> statusChangeListeners() {
+        return null;
+    }
+
+    @Override
+    public CompletableFuture<Version> begin(TransactionId transactionId) {
+        return null;
+    }
+
+    @Override
+    public CompletableFuture<Boolean> prepare(TransactionLog<MapUpdate<String, V>> transactionLog) {
+        return null;
+    }
+
+    @Override
+    public CompletableFuture<Boolean> prepareAndCommit(TransactionLog<MapUpdate<String, V>> transactionLog) {
+        return null;
+    }
+
+    @Override
+    public CompletableFuture<Void> commit(TransactionId transactionId) {
+        return null;
+    }
+
+    @Override
+    public CompletableFuture<Void> rollback(TransactionId transactionId) {
+        return null;
+    }
+}
diff --git a/core/api/src/test/java/org/onosproject/store/primitives/DefaultAtomicCounterMapTest.java b/core/api/src/test/java/org/onosproject/store/primitives/DefaultAtomicCounterMapTest.java
new file mode 100644
index 0000000..55f70a0
--- /dev/null
+++ b/core/api/src/test/java/org/onosproject/store/primitives/DefaultAtomicCounterMapTest.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright 2018-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;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.onosproject.store.service.ConsistentMapException;
+
+import java.util.concurrent.CompletableFuture;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onosproject.store.primitives.TestingCompletableFutures.ErrorState.NONE;
+
+/**
+ * Unit tests for the DefaultAtomicCounter class.
+ */
+
+public class DefaultAtomicCounterMapTest {
+
+    private static final String KEY1 = "myKey1";
+    private static final long VALUE1 = 444L;
+    private static final long DELTA1 = 555L;
+
+    private DefaultAtomicCounterMap<String> atomicCounterMap;
+
+    private DefaultAtomicCounterMap<String> createMap() {
+        AsyncAtomicCounterMapAdapter<String> asyncMap = new AsyncAtomicCounterMapAdapter<>();
+        DefaultAtomicCounterMap<String> map = new DefaultAtomicCounterMap<>(asyncMap, 1000L);
+        assertThat(map, notNullValue());
+        assertThat(map.isEmpty(), is(true));
+        return map;
+    }
+
+    @Before
+    public void setUpMap() {
+        atomicCounterMap = createMap();
+    }
+
+    @Test
+    public void testConstruction() {
+        assertThat(atomicCounterMap.size(), is(0));
+    }
+
+    @Test
+    public void testPutAndGet() {
+        atomicCounterMap.put(KEY1, VALUE1);
+        long value = atomicCounterMap.get(KEY1);
+        assertThat(value, is(VALUE1));
+    }
+
+    @Test
+    public void testGetAndIncrement() {
+        atomicCounterMap.put(KEY1, VALUE1);
+        Long beforeIncrement = atomicCounterMap.getAndIncrement(KEY1);
+        assertThat(beforeIncrement, is(VALUE1));
+        Long afterIncrement = atomicCounterMap.get(KEY1);
+        assertThat(afterIncrement, is(VALUE1 + 1));
+    }
+
+    @Test
+    public void testIncrementAndGet() {
+        atomicCounterMap.put(KEY1, VALUE1);
+        Long afterIncrement = atomicCounterMap.incrementAndGet(KEY1);
+        assertThat(afterIncrement, is(VALUE1 + 1));
+    }
+
+    @Test
+    public void testGetAndDecrement() {
+        atomicCounterMap.put(KEY1, VALUE1);
+        Long beforeDecrement = atomicCounterMap.getAndDecrement(KEY1);
+        assertThat(beforeDecrement, is(VALUE1));
+        Long afterDecrement = atomicCounterMap.get(KEY1);
+        assertThat(afterDecrement, is(VALUE1 - 1));
+    }
+
+    @Test
+    public void testDecrementAndGet() {
+        atomicCounterMap.put(KEY1, VALUE1);
+        Long afterIncrement = atomicCounterMap.decrementAndGet(KEY1);
+        assertThat(afterIncrement, is(VALUE1 - 1));
+    }
+
+    @Test
+    public void testGetAndAdd() {
+        atomicCounterMap.put(KEY1, VALUE1);
+        Long beforeIncrement = atomicCounterMap.getAndAdd(KEY1, DELTA1);
+        assertThat(beforeIncrement, is(VALUE1));
+        Long afterIncrement = atomicCounterMap.get(KEY1);
+        assertThat(afterIncrement, is(VALUE1 + DELTA1));
+    }
+
+    @Test
+    public void testAddAndGet() {
+        atomicCounterMap.put(KEY1, VALUE1);
+        Long afterIncrement = atomicCounterMap.addAndGet(KEY1, DELTA1);
+        assertThat(afterIncrement, is(VALUE1 + DELTA1));
+    }
+
+    @Test
+    public void testPutIfAbsent() {
+        atomicCounterMap.putIfAbsent(KEY1, VALUE1);
+        Long afterIncrement = atomicCounterMap.addAndGet(KEY1, DELTA1);
+        assertThat(afterIncrement, is(VALUE1 + DELTA1));
+    }
+
+    @Test
+    public void testClear() {
+        atomicCounterMap.putIfAbsent(KEY1, VALUE1);
+        assertThat(atomicCounterMap.size(), is(1));
+        atomicCounterMap.clear();
+        assertThat(atomicCounterMap.size(), is(0));
+    }
+
+    @Test
+    public void testReplace() {
+        atomicCounterMap.putIfAbsent(KEY1, VALUE1);
+
+        boolean replaced = atomicCounterMap.replace(KEY1, VALUE1, VALUE1 * 2);
+        assertThat(replaced, is(true));
+        Long afterReplace = atomicCounterMap.get(KEY1);
+        assertThat(afterReplace, is(VALUE1 * 2));
+
+        boolean notReplaced = atomicCounterMap.replace(KEY1, VALUE1, VALUE1 * 2);
+        assertThat(notReplaced, is(false));
+        Long afterNotReplaced = atomicCounterMap.get(KEY1);
+        assertThat(afterNotReplaced, is(VALUE1 * 2));
+    }
+
+    @Test
+    public void testRemove() {
+        atomicCounterMap.putIfAbsent(KEY1, VALUE1);
+        assertThat(atomicCounterMap.size(), is(1));
+        atomicCounterMap.remove(KEY1);
+        assertThat(atomicCounterMap.size(), is(0));
+    }
+
+    @Test
+    public void testRemoveVale() {
+        atomicCounterMap.putIfAbsent(KEY1, VALUE1);
+        assertThat(atomicCounterMap.size(), is(1));
+        atomicCounterMap.remove(KEY1, VALUE1 * 2);
+        assertThat(atomicCounterMap.size(), is(1));
+        atomicCounterMap.remove(KEY1, VALUE1);
+        assertThat(atomicCounterMap.size(), is(0));
+    }
+
+    class AtomicCounterMapWithErrors<K> extends AsyncAtomicCounterMapAdapter<K> {
+
+        TestingCompletableFutures.ErrorState errorState = NONE;
+
+        void setErrorState(TestingCompletableFutures.ErrorState errorState) {
+            this.errorState = errorState;
+        }
+
+        AtomicCounterMapWithErrors() {
+            super();
+        }
+
+        @Override
+        public CompletableFuture<Long> get(K key) {
+            return TestingCompletableFutures.createFuture(errorState);
+        }
+    }
+
+    @Test(expected = ConsistentMapException.Timeout.class)
+    public void testTimeout() {
+        AtomicCounterMapWithErrors<String> atomicCounterMap =
+                new AtomicCounterMapWithErrors<>();
+        atomicCounterMap.setErrorState(TestingCompletableFutures.ErrorState.TIMEOUT_EXCEPTION);
+        DefaultAtomicCounterMap<String> map =
+                new DefaultAtomicCounterMap<>(atomicCounterMap, 1000);
+
+        map.get(KEY1);
+    }
+
+
+    @Test(expected = ConsistentMapException.Interrupted.class)
+    public void testInterrupted() {
+        AtomicCounterMapWithErrors<String> atomicCounterMap =
+                new AtomicCounterMapWithErrors<>();
+        atomicCounterMap.setErrorState(TestingCompletableFutures.ErrorState.INTERRUPTED_EXCEPTION);
+        DefaultAtomicCounterMap<String> map =
+                new DefaultAtomicCounterMap<>(atomicCounterMap, 1000);
+
+        map.get(KEY1);
+    }
+
+    @Test(expected = ConsistentMapException.class)
+    public void testExecutionError() {
+        AtomicCounterMapWithErrors<String> atomicCounterMap =
+                new AtomicCounterMapWithErrors<>();
+        atomicCounterMap.setErrorState(TestingCompletableFutures.ErrorState.EXECUTION_EXCEPTION);
+        DefaultAtomicCounterMap<String> map =
+                new DefaultAtomicCounterMap<>(atomicCounterMap, 1000);
+
+        map.get(KEY1);
+    }
+
+}
\ No newline at end of file
diff --git a/core/api/src/test/java/org/onosproject/store/primitives/DefaultAtomicCounterTest.java b/core/api/src/test/java/org/onosproject/store/primitives/DefaultAtomicCounterTest.java
new file mode 100644
index 0000000..12ab512
--- /dev/null
+++ b/core/api/src/test/java/org/onosproject/store/primitives/DefaultAtomicCounterTest.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2018-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;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.onosproject.store.service.AsyncAtomicCounter;
+import org.onosproject.store.service.StorageException;
+
+import java.util.concurrent.CompletableFuture;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onosproject.store.primitives.TestingCompletableFutures.ErrorState.NONE;
+
+
+/**
+ * Unit tests for the DefaultAtomicCounter class.
+ */
+
+public class DefaultAtomicCounterTest {
+
+    private static final long INITIAL_VALUE = 33L;
+    private static final long ADDED_VALUE = 44L;
+
+    private DefaultAtomicCounter atomicCounter;
+
+
+    private DefaultAtomicCounter create() {
+        AsyncAtomicCounter atomicCounter = AsyncAtomicCounterAdapter.builder().build();
+        DefaultAtomicCounter counter = new DefaultAtomicCounter(atomicCounter, 1000);
+        counter.set(INITIAL_VALUE);
+        assertThat(counter.get(), is(INITIAL_VALUE));
+        return counter;
+    }
+
+    @Before
+    public void setUpCounter() {
+        atomicCounter = create();
+    }
+
+    @Test
+    public void testConstruction() {
+        assertThat(atomicCounter, notNullValue());
+    }
+
+    @Test
+    public void testIncrements() {
+        long beforeIncrement = atomicCounter.getAndIncrement();
+        assertThat(beforeIncrement, is(INITIAL_VALUE));
+        assertThat(atomicCounter.get(), is(INITIAL_VALUE + 1));
+
+        atomicCounter.set(INITIAL_VALUE);
+        long afterIncrement = atomicCounter.incrementAndGet();
+        assertThat(afterIncrement, is(INITIAL_VALUE + 1));
+        assertThat(atomicCounter.get(), is(INITIAL_VALUE + 1));
+    }
+
+    @Test
+    public void testAdds() {
+        long beforeIncrement = atomicCounter.getAndAdd(ADDED_VALUE);
+        assertThat(beforeIncrement, is(INITIAL_VALUE));
+        assertThat(atomicCounter.get(), is(INITIAL_VALUE + ADDED_VALUE));
+
+        atomicCounter.set(INITIAL_VALUE);
+        long afterIncrement = atomicCounter.addAndGet(ADDED_VALUE);
+        assertThat(afterIncrement, is(INITIAL_VALUE + ADDED_VALUE));
+        assertThat(atomicCounter.get(), is(INITIAL_VALUE + ADDED_VALUE));
+    }
+
+    @Test
+    public void testCompareAndSet() {
+        boolean compareTrue = atomicCounter.compareAndSet(INITIAL_VALUE, ADDED_VALUE);
+        assertThat(compareTrue, is(true));
+
+        boolean compareFalse = atomicCounter.compareAndSet(INITIAL_VALUE, ADDED_VALUE);
+        assertThat(compareFalse, is(false));
+    }
+
+
+
+    class AtomicCounterWithErrors extends AsyncAtomicCounterAdapter {
+
+        TestingCompletableFutures.ErrorState errorState = NONE;
+
+        void setErrorState(TestingCompletableFutures.ErrorState errorState) {
+            this.errorState = errorState;
+        }
+
+        AtomicCounterWithErrors() {
+            super();
+        }
+
+        @Override
+        public CompletableFuture<Long> get() {
+            return TestingCompletableFutures.createFuture(errorState);
+        }
+    }
+
+    @Test(expected = StorageException.Timeout.class)
+    public void testTimeout() {
+        AtomicCounterWithErrors atomicCounter = new AtomicCounterWithErrors();
+        atomicCounter.setErrorState(TestingCompletableFutures.ErrorState.TIMEOUT_EXCEPTION);
+        DefaultAtomicCounter counter = new DefaultAtomicCounter(atomicCounter, 1000);
+
+        counter.get();
+    }
+
+    @Test(expected = StorageException.Interrupted.class)
+    public void testInterrupted() {
+        AtomicCounterWithErrors atomicCounter = new AtomicCounterWithErrors();
+        atomicCounter.setErrorState(TestingCompletableFutures.ErrorState.INTERRUPTED_EXCEPTION);
+        DefaultAtomicCounter counter = new DefaultAtomicCounter(atomicCounter, 1000);
+
+        counter.get();
+    }
+
+    @Test(expected = StorageException.class)
+    public void testExecutionError() {
+        AtomicCounterWithErrors atomicCounter = new AtomicCounterWithErrors();
+        atomicCounter.setErrorState(TestingCompletableFutures.ErrorState.EXECUTION_EXCEPTION);
+        DefaultAtomicCounter counter = new DefaultAtomicCounter(atomicCounter, 1000);
+
+        counter.get();
+    }
+}
\ No newline at end of file
diff --git a/core/api/src/test/java/org/onosproject/store/primitives/DefaultConsistentTreeMapTest.java b/core/api/src/test/java/org/onosproject/store/primitives/DefaultConsistentTreeMapTest.java
new file mode 100644
index 0000000..8bfc820
--- /dev/null
+++ b/core/api/src/test/java/org/onosproject/store/primitives/DefaultConsistentTreeMapTest.java
@@ -0,0 +1,320 @@
+/*
+ * Copyright 2018-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;
+
+import org.hamcrest.Description;
+import org.hamcrest.TypeSafeMatcher;
+import org.junit.Before;
+import org.junit.Test;
+import org.onosproject.store.service.ConsistentMapException;
+import org.onosproject.store.service.MapEvent;
+import org.onosproject.store.service.MapEventListener;
+import org.onosproject.store.service.Versioned;
+
+import java.util.LinkedList;
+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.stream.Collectors;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.hasItems;
+import static org.hamcrest.Matchers.hasSize;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onosproject.store.primitives.TestingCompletableFutures.ErrorState.NONE;
+
+public class DefaultConsistentTreeMapTest {
+
+    private static final String MIN_KEY = "0";
+    private static final String KEY1 = "A";
+    private static final String VALUE1 = "A";
+    private static final String KEY2 = "B";
+    private static final String VALUE2 = "B";
+    private static final String KEY3 = "C";
+    private static final String VALUE3 = "C";
+    private static final String KEY4 = "D";
+    private static final String VALUE4 = "D";
+    private static final String KEY5 = "E";
+    private static final String VALUE5 = "E";
+    private static final String MAX_KEY = "Z";
+    private static final String NO_SUCH_VALUE = "BAD VALUE";
+    private static final String NO_SUCH_KEY = "BAD KEY";
+    private static final String DEFAULT_VALUE = "DEFAULT";
+
+    private DefaultConsistentTreeMap<String> treeMap;
+    private TestAsyncConsistentTreeMap<String> asyncMap;
+
+    private static class TestAsyncConsistentTreeMap<V> extends AsyncConsistentTreeMapAdapter<V> {
+        LinkedList<MapEventListener<String, V>> listeners = new LinkedList<>();
+
+        @Override
+        public CompletableFuture<Void> addListener(MapEventListener<String, V> listener,
+                                                   Executor executor) {
+            listeners.add(listener);
+            return CompletableFuture.completedFuture(null);
+        }
+
+        @Override
+        public CompletableFuture<Void> removeListener(MapEventListener<String, V> listener) {
+            listeners.remove(listener);
+            return CompletableFuture.completedFuture(null);
+        }
+    }
+
+    class Listener implements MapEventListener<String, String> {
+        @Override
+        public void event(MapEvent<String, String> event) {
+            // Nothing to do here
+        }
+    }
+
+    private DefaultConsistentTreeMap<String> createMap() {
+        asyncMap = new TestAsyncConsistentTreeMap<>();
+        DefaultConsistentTreeMap<String> map = new DefaultConsistentTreeMap<>(asyncMap, 1000L);
+        assertThat(map, notNullValue());
+        assertThat(map.isEmpty(), is(true));
+        map.putIfAbsent(KEY1, VALUE1);
+        map.putIfAbsent(KEY2, VALUE2);
+        map.putIfAbsent(KEY3, VALUE3);
+        return map;
+    }
+
+    static class VersionedMatcher extends TypeSafeMatcher<Versioned<String>> {
+        String expectedValue;
+
+        VersionedMatcher(String expectedValue) {
+            this.expectedValue = expectedValue;
+        }
+
+        @Override
+        public boolean matchesSafely(Versioned<String> value) {
+            return expectedValue.equals(value.value());
+        }
+
+        @Override
+        public void describeTo(Description description) {
+            description.appendText("<Versioned{value=" + expectedValue + ",...");
+        }
+    }
+
+    private static VersionedMatcher matchesVersioned(String expectedValue) {
+        return new VersionedMatcher(expectedValue);
+    }
+
+    @Before
+    public void setUpMap() {
+        treeMap = createMap();
+    }
+
+    @Test
+    public void testKeys() {
+        assertThat(treeMap.size(), is(3));
+        assertThat(treeMap.navigableKeySet(), hasSize(3));
+
+        assertThat(treeMap.firstKey(), is(VALUE1));
+        assertThat(treeMap.lastKey(), is(VALUE3));
+        assertThat(treeMap.lowerKey(KEY2), is(VALUE1));
+        assertThat(treeMap.higherKey(KEY2), is(VALUE3));
+        assertThat(treeMap.floorKey(MAX_KEY), is(VALUE3));
+        assertThat(treeMap.ceilingKey(MIN_KEY), is(VALUE1));
+
+        assertThat(treeMap.containsKey(KEY2), is(true));
+        assertThat(treeMap.containsKey(MAX_KEY), is(false));
+    }
+
+    private void checkEntry(Map.Entry<String, Versioned<String>> entry,
+                            String expectedKey,
+                            String expectedValue) {
+        assertThat(entry.getKey(), is(expectedKey));
+        assertThat(entry.getValue(), matchesVersioned(expectedValue));
+    }
+
+    @Test
+    public void testEntries() {
+        assertThat(treeMap.size(), is(3));
+
+        checkEntry(treeMap.firstEntry(), KEY1, VALUE1);
+        checkEntry(treeMap.lastEntry(), KEY3, VALUE3);
+        checkEntry(treeMap.lowerEntry(KEY2), KEY1, VALUE1);
+        checkEntry(treeMap.higherEntry(KEY2), KEY3, VALUE3);
+        checkEntry(treeMap.floorEntry(MAX_KEY), KEY3, VALUE3);
+        checkEntry(treeMap.ceilingEntry(MIN_KEY), KEY1, VALUE1);
+
+        checkEntry(treeMap.pollFirstEntry(), KEY1, VALUE1);
+        assertThat(treeMap.size(), is(2));
+
+        checkEntry(treeMap.pollLastEntry(), KEY3, VALUE3);
+        assertThat(treeMap.size(), is(1));
+    }
+
+    @Test
+    public void testGets() {
+        assertThat(treeMap.get(KEY2), matchesVersioned(VALUE2));
+        assertThat(treeMap.containsValue(VALUE3), is(true));
+        assertThat(treeMap.getOrDefault(KEY3, DEFAULT_VALUE), matchesVersioned(VALUE3));
+        assertThat(treeMap.getOrDefault(NO_SUCH_KEY, DEFAULT_VALUE), matchesVersioned(DEFAULT_VALUE));
+        assertThat(treeMap.compute(KEY4, (k, v) -> v == null ? VALUE4 : ""), matchesVersioned(VALUE4));
+        assertThat(treeMap.computeIf(KEY4, Objects::isNull, (k, v) -> NO_SUCH_VALUE), matchesVersioned(VALUE4));
+        assertThat(treeMap.computeIfPresent(KEY4, (k, v) -> NO_SUCH_VALUE), matchesVersioned(NO_SUCH_VALUE));
+        assertThat(treeMap.computeIfAbsent(KEY2, (v) -> NO_SUCH_VALUE), matchesVersioned(VALUE2));
+        treeMap.put(KEY5, VALUE5);
+        assertThat(treeMap.putAndGet(KEY5, VALUE1), matchesVersioned(VALUE5));
+        assertThat(treeMap.get(KEY5), matchesVersioned(VALUE1));
+    }
+
+    @Test
+    public void testSets() {
+        Set<String> keys = treeMap.keySet();
+        assertThat(keys, hasSize(3));
+        assertThat(keys, hasItems(KEY1, KEY2, KEY3));
+
+        Set<String> values = treeMap.values().stream().map(Versioned::value).collect(Collectors.toSet());
+        assertThat(values, hasSize(3));
+        assertThat(values, hasItems(VALUE1, VALUE2, VALUE3));
+
+        Set<String> valuesFromEntries = treeMap.entrySet().stream()
+                .map(entry -> entry.getValue().value()).collect(Collectors.toSet());
+        assertThat(valuesFromEntries, hasSize(3));
+        assertThat(valuesFromEntries, hasItems(VALUE1, VALUE2, VALUE3));
+
+        Set<String> keysFromEntries = treeMap.entrySet().stream()
+                .map(Map.Entry::getKey).collect(Collectors.toSet());
+        assertThat(keysFromEntries, hasSize(3));
+        assertThat(keysFromEntries, hasItems(KEY1, KEY2, KEY3));
+    }
+
+    @Test
+    public void testRemoves() {
+        treeMap.remove(KEY1);
+        assertThat(treeMap.size(), is(2));
+
+        treeMap.remove(KEY2, 1L);
+        assertThat(treeMap.size(), is(1));
+
+        treeMap.remove(KEY3, VALUE3);
+        assertThat(treeMap.size(), is(0));
+    }
+
+    @Test
+    public void testClear() {
+        treeMap.clear();
+        assertThat(treeMap.size(), is(0));
+    }
+
+    @Test
+    public void testReplaces() {
+        treeMap.replace(KEY1, VALUE2);
+        assertThat(treeMap.get(KEY1), matchesVersioned(VALUE2));
+
+        treeMap.replace(KEY2, 1L, VALUE1);
+        assertThat(treeMap.get(KEY2), matchesVersioned(VALUE1));
+
+        treeMap.replace(KEY3, VALUE3, VALUE5);
+        assertThat(treeMap.get(KEY3), matchesVersioned(VALUE5));
+    }
+
+    @Test
+    public void testJavaMap() {
+        Map<String, String> javaMap = treeMap.asJavaMap();
+        assertThat(javaMap.entrySet(), hasSize(3));
+        assertThat(javaMap.values(), hasItems(VALUE1, VALUE2, VALUE3));
+        assertThat(javaMap.keySet(), hasItems(KEY1, KEY2, KEY3));
+    }
+
+    @Test
+    public void testSubMap() {
+        treeMap.putIfAbsent(KEY4, VALUE4);
+        treeMap.putIfAbsent(KEY5, VALUE5);
+
+        Map<String, String> subMap = treeMap.subMap(KEY2, KEY4, true, true);
+        assertThat(subMap.entrySet(), hasSize(3));
+        assertThat(subMap.values(), hasItems(VALUE2, VALUE3, VALUE4));
+        assertThat(subMap.keySet(), hasItems(KEY2, KEY3, KEY4));
+    }
+
+    @Test
+    public void testListeners() {
+        Listener listener1 = new Listener();
+        Listener listener2 = new Listener();
+
+        assertThat(asyncMap.listeners, hasSize(0));
+        treeMap.addListener(listener1);
+        assertThat(asyncMap.listeners, hasSize(1));
+        treeMap.addListener(listener2);
+        assertThat(asyncMap.listeners, hasSize(2));
+
+        treeMap.removeListener(listener1);
+        treeMap.removeListener(listener2);
+        assertThat(asyncMap.listeners, hasSize(0));
+    }
+
+    class ConsistentTreeMapWithError<K> extends AsyncConsistentTreeMapAdapter<K> {
+
+        TestingCompletableFutures.ErrorState errorState = NONE;
+
+        void setErrorState(TestingCompletableFutures.ErrorState errorState) {
+            this.errorState = errorState;
+        }
+
+        ConsistentTreeMapWithError() {
+            super();
+        }
+
+        @Override
+        public CompletableFuture<String> lowerKey(String key) {
+            return TestingCompletableFutures.createStringFuture(errorState);
+        }
+    }
+
+    @Test(expected = ConsistentMapException.Timeout.class)
+    public void testTimeout() {
+        ConsistentTreeMapWithError<String> consistentMap =
+                new ConsistentTreeMapWithError<>();
+        consistentMap.setErrorState(TestingCompletableFutures.ErrorState.TIMEOUT_EXCEPTION);
+        DefaultConsistentTreeMap<String> map =
+                new DefaultConsistentTreeMap<>(consistentMap, 1000);
+
+        map.lowerKey(KEY1);
+    }
+
+
+    @Test(expected = ConsistentMapException.Interrupted.class)
+    public void testInterrupted() {
+        ConsistentTreeMapWithError<String> consistentMap =
+                new ConsistentTreeMapWithError<>();
+        consistentMap.setErrorState(TestingCompletableFutures.ErrorState.INTERRUPTED_EXCEPTION);
+        DefaultConsistentTreeMap<String> map =
+                new DefaultConsistentTreeMap<>(consistentMap, 1000);
+
+        map.lowerKey(KEY1);
+    }
+
+    @Test(expected = ConsistentMapException.class)
+    public void testExecutionError() {
+        ConsistentTreeMapWithError<String> consistentMap =
+                new ConsistentTreeMapWithError<>();
+        consistentMap.setErrorState(TestingCompletableFutures.ErrorState.EXECUTION_EXCEPTION);
+        DefaultConsistentTreeMap<String> map =
+                new DefaultConsistentTreeMap<>(consistentMap, 1000);
+
+        map.lowerKey(KEY1);
+    }
+
+}
\ No newline at end of file
diff --git a/core/api/src/test/java/org/onosproject/store/primitives/TestingCompletableFutures.java b/core/api/src/test/java/org/onosproject/store/primitives/TestingCompletableFutures.java
new file mode 100644
index 0000000..0b5c0b5
--- /dev/null
+++ b/core/api/src/test/java/org/onosproject/store/primitives/TestingCompletableFutures.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2018-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;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+/**
+ * Completable Futures with known error states used for testing.
+ */
+public final class TestingCompletableFutures {
+
+    private TestingCompletableFutures() {
+    }
+
+    /** Indicates which kind of error to produce. */
+    public enum ErrorState { NONE, INTERRUPTED_EXCEPTION, TIMEOUT_EXCEPTION, EXECUTION_EXCEPTION }
+
+    private static class TimeoutExceptionFuture<T> extends CompletableFuture<T> {
+        @Override
+        public T get(long timeout, TimeUnit unit)
+                throws TimeoutException {
+            throw new TimeoutException();
+        }
+    }
+
+    private static class InterruptedFuture<T> extends CompletableFuture<T> {
+        @Override
+        public T get(long timeout, TimeUnit unit)
+                throws InterruptedException {
+            throw new InterruptedException();
+        }
+    }
+
+    private static class ExecutionExceptionFuture<T> extends CompletableFuture<T> {
+        @Override
+        public T get(long timeout, TimeUnit unit)
+                throws ExecutionException {
+            throw new ExecutionException("", new Exception());
+        }
+    }
+
+    /**
+     * Creates a Long Future for a given error type.
+     *
+     * @param errorState wht kind of error to produce
+     * @return new future that will generate the requested error
+     */
+    public static CompletableFuture<Long> createFuture(ErrorState errorState) {
+        switch (errorState) {
+            case TIMEOUT_EXCEPTION:
+                return new TimeoutExceptionFuture<>();
+            case INTERRUPTED_EXCEPTION:
+                return new InterruptedFuture<>();
+            case EXECUTION_EXCEPTION:
+                return new ExecutionExceptionFuture<>();
+            default:
+                return new CompletableFuture<>();
+        }
+    }
+
+    /**
+     * Creates a Long Future for a given error type.
+     *
+     * @param errorState wht kind of error to produce
+     * @return new future that will generate the requested error
+     */
+    public static CompletableFuture<String> createStringFuture(ErrorState errorState) {
+        switch (errorState) {
+            case TIMEOUT_EXCEPTION:
+                return new TimeoutExceptionFuture<>();
+            case INTERRUPTED_EXCEPTION:
+                return new InterruptedFuture<>();
+            case EXECUTION_EXCEPTION:
+                return new ExecutionExceptionFuture<>();
+            default:
+                return new CompletableFuture<>();
+        }
+    }
+}
diff --git a/core/api/src/test/java/org/onosproject/store/service/TestStorageService.java b/core/api/src/test/java/org/onosproject/store/service/TestStorageService.java
index e41d2ad..48ffeac 100644
--- a/core/api/src/test/java/org/onosproject/store/service/TestStorageService.java
+++ b/core/api/src/test/java/org/onosproject/store/service/TestStorageService.java
@@ -15,6 +15,8 @@
  */
 package org.onosproject.store.service;
 
+import org.onosproject.store.primitives.AsyncAtomicCounterAdapter;
+
 public class TestStorageService extends StorageServiceAdapter {
 
 
@@ -35,7 +37,7 @@
 
     @Override
     public AtomicCounterBuilder atomicCounterBuilder() {
-        return TestAtomicCounter.builder();
+        return AsyncAtomicCounterAdapter.builder();
     }
 
     @Override