blob: 5fc019aa96a3f986f6daf2899513a590ca4d0904 [file] [log] [blame]
Sbhat35a94259f2017-08-02 11:34:53 -07001/*
2 * Copyright 2015-present Open Networking Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package org.onosproject.store.primitives.impl;
17
18import com.google.common.collect.Lists;
19import com.google.common.hash.Hashing;
20import org.junit.Before;
21import org.junit.Test;
22import org.onosproject.cluster.PartitionId;
23import org.onosproject.store.serializers.KryoNamespaces;
24import org.onosproject.store.service.AsyncConsistentMap;
25import org.onosproject.store.service.AsyncConsistentMapAdapter;
26import org.onosproject.store.service.MapEventListener;
27import org.onosproject.store.service.Serializer;
28import org.onosproject.store.service.Versioned;
29
30import java.util.ArrayList;
31import java.util.Collection;
32import java.util.HashMap;
33import java.util.List;
34import java.util.Map;
35import java.util.Set;
36import java.util.concurrent.CompletableFuture;
37import java.util.concurrent.Executor;
38import java.util.function.BiFunction;
39import java.util.function.Consumer;
40import java.util.function.Predicate;
41import java.util.stream.Collectors;
42
43import static org.hamcrest.Matchers.hasItem;
44import static org.hamcrest.Matchers.is;
45import static org.junit.Assert.assertNotNull;
46import static org.junit.Assert.assertThat;
47
48
49public class PartitionedAsyncConsistentMapTest {
50
51 PartitionedAsyncConsistentMap<String, String> partitionedAsyncConsistentMap;
52
53 private AsyncConsistentMapMock asyncMap1;
54 private AsyncConsistentMapMock asyncMap2;
55 private Map<PartitionId, AsyncConsistentMap<String, String>> partitions;
56 private List<PartitionId> sortedMemberPartitionIds;
57
58
59 private Map<String, String> baseMap;
60 private String partitionName = "PartitionManager";
61 private PartitionId pid1;
62 private PartitionId pid2;
63 private Hasher<String> hasher;
64 private Serializer serializer;
65
66
67 private final List<String> allKeys = Lists.newArrayList(KEY1, KEY2);
68
69 private static final String KEY1 = "AAA";
70 private static final String VALUE1 = "one";
71 private static final String KEY2 = "BBB";
72 private static final String VALUE2 = "two";
73 private static final String TEST3 = "CCC";
74 private static final String VALUE3 = "three";
75 private static final String TEST4 = "DDD";
76 private static final String VALUE4 = "four";
77
78
79
80 public class AsyncConsistentMapMock<K, V> extends AsyncConsistentMapAdapter<K, V> {
81 private final List<MapEventListener<K, V>> listeners;
82 Collection<Consumer<Status>> statusChangeListeners = new ArrayList<>();
83 private final Map<K, V> baseMap;
84
85 Versioned<V> makeVersioned(V v) {
86 return new Versioned<>(v, 0, 0);
87 }
88
89 AsyncConsistentMapMock(Map<K, V> newBaseMap) {
90 baseMap = newBaseMap;
91 listeners = new ArrayList<>();
92 }
93
94 public CompletableFuture<Integer> size() {
95 return CompletableFuture.completedFuture(baseMap.size());
96 }
97
98 @Override
99 public CompletableFuture<Boolean> containsKey(K key) {
100 return CompletableFuture.completedFuture(baseMap.containsKey(key));
101 }
102
103 @Override
104 public CompletableFuture<Versioned<V>> getOrDefault(K key, V value) {
105 return CompletableFuture.completedFuture(makeVersioned(baseMap.getOrDefault(key, value)));
106 }
107 @Override
108 public CompletableFuture<Boolean> containsValue(V value) {
109 return CompletableFuture.completedFuture(baseMap.containsValue(value));
110 }
111
112 @Override
113 public CompletableFuture<Versioned<V>> get(K key) {
114 return CompletableFuture.completedFuture(makeVersioned(baseMap.get(key)));
115 }
116
117 @Override
118 public CompletableFuture<Versioned<V>>
119 computeIf(K key, Predicate<? super V> condition,
120 BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
121 return null;
122 }
123
124 @Override
125 public CompletableFuture<Versioned<V>> put(K key, V value) {
126 return CompletableFuture.completedFuture(makeVersioned(baseMap.put(key, value)));
127 }
128
129 @Override
130 public CompletableFuture<Versioned<V>> putAndGet(K key, V value) {
131 return CompletableFuture.completedFuture(makeVersioned(baseMap.put(key, value)));
132 }
133
134 @Override
135 public CompletableFuture<Versioned<V>> remove(K key) {
136 return CompletableFuture.completedFuture(makeVersioned(baseMap.remove(key)));
137 }
138
139 @Override
140 public CompletableFuture<Void> clear() {
141 baseMap.clear();
142 return CompletableFuture.allOf();
143 }
144
145 @Override
146 public CompletableFuture<Set<K>> keySet() {
147 return CompletableFuture.completedFuture(baseMap.keySet());
148 }
149
150 @Override
151 public CompletableFuture<Collection<Versioned<V>>> values() {
152 Set<Versioned<V>> valuesAsVersionedCollection =
153 baseMap.values().stream().map(this::makeVersioned)
154 .collect(Collectors.toSet());
155 return CompletableFuture.completedFuture(valuesAsVersionedCollection);
156 }
157
158 @Override
159 public CompletableFuture<Set<Map.Entry<K, Versioned<V>>>> entrySet() {
160 Map<K, Versioned<V>> valuesAsVersionedMap = new HashMap<>();
161 baseMap.entrySet()
162 .forEach(e -> valuesAsVersionedMap.put(e.getKey(),
163 makeVersioned(e.getValue())));
164 return CompletableFuture.completedFuture(valuesAsVersionedMap.entrySet());
165 }
166
167 @Override
168 public CompletableFuture<Versioned<V>> putIfAbsent(K key, V value) {
169 return CompletableFuture.completedFuture(makeVersioned(baseMap.putIfAbsent(key, value)));
170 }
171
172 @Override
173 public CompletableFuture<Boolean> remove(K key, V value) {
174 return CompletableFuture.completedFuture(baseMap.remove(key, value));
175 }
176
177 @Override
178 public CompletableFuture<Boolean> remove(K key, long version) {
179 Object value = baseMap.remove(key);
180 return CompletableFuture.completedFuture(value != null);
181 }
182
183 @Override
184 public CompletableFuture<Versioned<V>> replace(K key, V value) {
185 return CompletableFuture.completedFuture(makeVersioned(baseMap.replace(key, value)));
186 }
187
188 @Override
189 public CompletableFuture<Boolean> replace(K key, V oldValue, V newValue) {
190 return CompletableFuture.completedFuture(baseMap.replace(key, oldValue, newValue));
191 }
192
193 @Override
194 public CompletableFuture<Boolean> replace(K key, long oldVersion, V newValue) {
195 return CompletableFuture.completedFuture(baseMap.replace(key, newValue) != null);
196 }
197
198 @Override
199 public CompletableFuture<Void> addListener(MapEventListener<K, V> listener, Executor e) {
200 listeners.add(listener);
201 return CompletableFuture.allOf();
202 }
203
204 @Override
205 public CompletableFuture<Void> removeListener(MapEventListener<K, V> listener) {
206 listeners.remove(listener);
207 return CompletableFuture.allOf();
208 }
209
210 @Override
211 public void addStatusChangeListener(Consumer<Status> listener) {
212 statusChangeListeners.add(listener);
213 }
214
215 @Override
216 public void removeStatusChangeListener(Consumer<Status> listener) {
217 statusChangeListeners.remove(listener);
218 }
219
220 @Override
221 public Collection<Consumer<Status>> statusChangeListeners() {
222 return statusChangeListeners;
223 }
224 }
225
226 @Before
227 public void setUp() throws Exception {
228 baseMap = new HashMap<>();
229 asyncMap1 = new AsyncConsistentMapMock<>(baseMap);
230 asyncMap2 = new AsyncConsistentMapMock<>(baseMap);
231
232 pid1 = PartitionId.from(1);
233 pid2 = PartitionId.from(2);
234 partitions = new HashMap<>();
235 serializer = Serializer.using(KryoNamespaces.BASIC);
236
237 asyncMap1.put(KEY1, VALUE1);
238 asyncMap2.put(KEY2, VALUE2);
239 partitions.put(pid1, asyncMap1);
240 partitions.put(pid2, asyncMap2);
241
242 sortedMemberPartitionIds = Lists.newArrayList(partitions.keySet());
243
244 hasher = key -> {
245 int hashCode = Hashing.sha256().hashBytes(serializer.encode(key)).asInt();
246 return sortedMemberPartitionIds.get(Math.abs(hashCode) % partitions.size());
247 };
248
249 partitionedAsyncConsistentMap = new PartitionedAsyncConsistentMap(partitionName,
250 partitions, hasher);
251
252 }
253
254 @Test
255 public void tester() {
256 assertThat(partitionedAsyncConsistentMap.isEmpty().join(), is(false));
257 assertThat(partitionedAsyncConsistentMap.name(), is("PartitionManager"));
258 asyncMap1.put(TEST3, VALUE3);
259 partitions.put(pid1, asyncMap1);
260 assertThat(partitionedAsyncConsistentMap.size().join(), is(6));
261
262 assertThat(partitionedAsyncConsistentMap.entrySet().join().size(), is(3));
263
264 asyncMap2.put(TEST4, VALUE4);
265 partitions.put(pid2, asyncMap2);
266 assertThat(partitionedAsyncConsistentMap.size().join(), is(8));
267
268
269 assertThat(partitionedAsyncConsistentMap.containsValue(VALUE1).join(), is(true));
270 assertThat(partitionedAsyncConsistentMap.containsValue("newValue").join(), is(false));
271 assertThat(partitionedAsyncConsistentMap.containsKey(KEY2).join(), is(true));
272 assertThat(partitionedAsyncConsistentMap.containsKey("newKey").join(), is(false));
273
274 partitionedAsyncConsistentMap.putAndGet(KEY1, "newOne").join();
275 assertThat(partitionedAsyncConsistentMap.containsValue("newOne").join(), is(true));
276 partitionedAsyncConsistentMap.remove(KEY1).join();
277 assertThat(partitionedAsyncConsistentMap.containsKey(KEY1).join(), is(false));
278 partitionedAsyncConsistentMap.putIfAbsent(KEY1, "same").join();
279 partitionedAsyncConsistentMap.replace(KEY1, "same", "one").join();
280 assertThat(partitionedAsyncConsistentMap.containsValue("one").join(), is(true));
281 partitionedAsyncConsistentMap.putIfAbsent("EEE", "five");
282
283 assertThat(partitionedAsyncConsistentMap.get(KEY2).join().value(), is(VALUE2));
284 assertThat(partitionedAsyncConsistentMap.getOrDefault(KEY1, "nil").join().value(),
285 is(VALUE1));
286
287 assertThat(partitionedAsyncConsistentMap.getOrDefault("newKey", "testDefault").join().value(),
288 is("testDefault"));
289
290 assertNotNull(partitionedAsyncConsistentMap.keySet().join());
291 assertThat(partitionedAsyncConsistentMap.keySet().join().size(), is(5));
292 assertThat(partitionedAsyncConsistentMap.keySet().join(), hasItem("CCC"));
293
294
295 partitionedAsyncConsistentMap.clear().join();
296 assertThat(partitionedAsyncConsistentMap.size().join(), is(0));
297 assertThat(partitionedAsyncConsistentMap.isEmpty().join(), is(true));
298
299 }
300}