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