blob: 68e7ecb3d2c4779c7ca9eab1407d175f3d41275e [file] [log] [blame]
HIGUCHI Yuta14e865d2015-11-25 20:42:32 -08001/*
2 * Copyright 2015 Open Networking Laboratory
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 */
Madan Jampanif4c88502016-01-21 12:35:36 -080016package org.onosproject.store.primitives.impl;
HIGUCHI Yuta14e865d2015-11-25 20:42:32 -080017
18import static java.util.Collections.unmodifiableCollection;
19import static java.util.Collections.unmodifiableSet;
20import static org.hamcrest.Matchers.is;
Madan Jampanif4c88502016-01-21 12:35:36 -080021import static org.junit.Assert.assertEquals;
22import static org.junit.Assert.assertThat;
HIGUCHI Yuta14e865d2015-11-25 20:42:32 -080023
24import java.util.Collection;
25import java.util.Map;
26import java.util.Map.Entry;
27import java.util.Objects;
28import java.util.Set;
29import java.util.concurrent.CompletableFuture;
30import java.util.concurrent.ConcurrentHashMap;
31import java.util.function.Consumer;
32
Madan Jampanif4c88502016-01-21 12:35:36 -080033import net.kuujo.copycat.Task;
34import net.kuujo.copycat.cluster.Cluster;
35import net.kuujo.copycat.resource.ResourceState;
36
HIGUCHI Yuta14e865d2015-11-25 20:42:32 -080037import org.junit.After;
38import org.junit.Before;
39import org.junit.Test;
Madan Jampanif2f086c2016-01-13 16:15:39 -080040import org.onlab.util.Match;
HIGUCHI Yuta14e865d2015-11-25 20:42:32 -080041import org.onosproject.core.ApplicationId;
42import org.onosproject.core.DefaultApplicationId;
43import org.onosproject.store.service.Serializer;
HIGUCHI Yuta14e865d2015-11-25 20:42:32 -080044import org.onosproject.store.service.Versioned;
45
46import com.google.common.base.MoreObjects;
47import com.google.common.collect.ImmutableMap;
48import com.google.common.collect.ImmutableSet;
HIGUCHI Yuta1c8493c2015-12-08 16:16:55 -080049import com.google.common.collect.Maps;
50
HIGUCHI Yuta14e865d2015-11-25 20:42:32 -080051/**
52 *
53 */
54public class DefaultAsyncConsistentMapTest {
55
56 private static final ApplicationId APP_ID = new DefaultApplicationId(42, "what");
57
58 private static final TestData KEY1A = new TestData("One", "a");
59 private static final TestData KEY1B = new TestData("One", "b");
60
61 private static final TestData VALUE2A = new TestData("Two", "a");
62 private static final TestData VALUE2B = new TestData("Two", "b");
63
64 @Before
65 public void setUp() throws Exception {
66 }
67
68 @After
69 public void tearDown() throws Exception {
70 }
71
72 @Test
73 public void testKeySet() throws Exception {
74 DefaultAsyncConsistentMap<TestData, TestData> map;
75 String name = "map_name";
76 Database database = new TestDatabase();
77 Serializer serializer = Serializer.forTypes(TestData.class);
78
79 map = new DefaultAsyncConsistentMap<>(name, APP_ID, database, serializer,
80 false, false, false);
81 map.put(KEY1A, VALUE2A);
82 map.put(KEY1B, VALUE2A);
83
84 Set<TestData> set = map.keySet().get();
85 assertEquals("Should contain 2 keys",
86 2, set.size());
87 assertThat(set.contains(KEY1A), is(true));
88 assertThat(set.contains(KEY1B), is(true));
89 assertThat(set.contains(new TestData("One", "a")), is(true));
90 }
91
92 @Test
93 public void testEntrySet() throws Exception {
94 DefaultAsyncConsistentMap<TestData, TestData> map;
95 String name = "map_name";
96 Database database = new TestDatabase();
97 Serializer serializer = Serializer.forTypes(TestData.class);
98
99 map = new DefaultAsyncConsistentMap<>(name, APP_ID, database, serializer,
100 false, false, false);
101 map.put(KEY1A, VALUE2A);
102 map.put(KEY1B, VALUE2A);
103
104 assertEquals("Should contain 2 entry",
105 2,
106 map.entrySet().get().size());
107 }
108
109 /**
110 * Object to be used as a test data.
111 *
112 * {@link Object#equals(Object)} use only part of it's fields.
113 *
114 * As a result there can be 2 instances which the
115 * serialized bytes are not-equal but
116 * {@link Object#equals(Object)}-wise they are equal.
117 */
118 public static class TestData {
119
120 private final String theKey;
121
122 @SuppressWarnings("unused")
123 private final String notUsedForEquals;
124
125 public TestData(String theKey, String notUsedForEquals) {
126 this.theKey = theKey;
127 this.notUsedForEquals = notUsedForEquals;
128 }
129
130 @Override
131 public int hashCode() {
132 return Objects.hashCode(theKey);
133 }
134
135 @Override
136 public boolean equals(Object obj) {
137 if (obj instanceof TestData) {
138 TestData that = (TestData) obj;
139 return Objects.equals(this.theKey, that.theKey);
140 }
141 return false;
142 }
143
144 @Override
145 public String toString() {
146 return MoreObjects.toStringHelper(this)
147 .add("theKey", theKey)
148 .add("notUsedForEquals", notUsedForEquals)
149 .toString();
150 }
151 }
152
153 /**
154 * {@link Database} implementation for testing.
155 *
156 * There is only 1 backing Map, {@code mapName} will be ignored.
157 */
158 public class TestDatabase implements Database {
159
160 Map<String, Versioned<byte[]>> map = new ConcurrentHashMap<>();
161
162 @Override
163 public CompletableFuture<Set<String>> maps() {
164 return CompletableFuture.completedFuture(ImmutableSet.of());
165 }
166
167 @Override
168 public CompletableFuture<Map<String, Long>> counters() {
169 return CompletableFuture.completedFuture(ImmutableMap.of());
170 }
171
172 @Override
173 public CompletableFuture<Integer> mapSize(String mapName) {
174 return CompletableFuture.completedFuture(map.size());
175 }
176
177 @Override
178 public CompletableFuture<Boolean> mapIsEmpty(String mapName) {
179 return CompletableFuture.completedFuture(map.isEmpty());
180 }
181
182 @Override
183 public CompletableFuture<Boolean> mapContainsKey(String mapName,
184 String key) {
185 return CompletableFuture.completedFuture(map.containsKey(key));
186 }
187
188 @Override
189 public CompletableFuture<Boolean> mapContainsValue(String mapName,
190 byte[] value) {
HIGUCHI Yuta1c8493c2015-12-08 16:16:55 -0800191 return CompletableFuture.completedFuture(Maps.transformValues(map, Versioned::value)
192 .containsValue(value));
HIGUCHI Yuta14e865d2015-11-25 20:42:32 -0800193 }
194
195 @Override
196 public CompletableFuture<Versioned<byte[]>> mapGet(String mapName,
197 String key) {
198 return CompletableFuture.completedFuture(map.get(key));
199 }
200
201 @Override
202 public synchronized CompletableFuture<Result<UpdateResult<String, byte[]>>> mapUpdate(String mapName,
203 String key,
204 Match<byte[]> valueMatch,
205 Match<Long> versionMatch,
206 byte[] value) {
207
208 boolean updated = false;
209 final Versioned<byte[]> oldValue;
210 final Versioned<byte[]> newValue;
211
212 Versioned<byte[]> old = map.getOrDefault(key, new Versioned<byte[]>(null, 0));
213 if (valueMatch.matches(old.value()) && versionMatch.matches(old.version())) {
214 updated = true;
215 oldValue = old;
216 newValue = new Versioned<>(value, old.version() + 1);
217 map.put(key, newValue);
218 } else {
219 updated = false;
220 oldValue = old;
221 newValue = old;
222 }
223 return CompletableFuture.completedFuture(
224 Result.ok(new UpdateResult<String, byte[]>(updated,
225 mapName, key, oldValue, newValue)));
226 }
227
228 @Override
229 public CompletableFuture<Result<Void>> mapClear(String mapName) {
230 throw new UnsupportedOperationException();
231 }
232
233 @Override
234 public CompletableFuture<Set<String>> mapKeySet(String mapName) {
235 return CompletableFuture.completedFuture(unmodifiableSet(map.keySet()));
236 }
237
238 @Override
239 public CompletableFuture<Collection<Versioned<byte[]>>> mapValues(String mapName) {
240 return CompletableFuture.completedFuture(unmodifiableCollection(map.values()));
241 }
242
243 @Override
244 public CompletableFuture<Set<Entry<String, Versioned<byte[]>>>> mapEntrySet(String mapName) {
245 return CompletableFuture.completedFuture(unmodifiableSet(map.entrySet()));
246 }
247
248 @Override
249 public CompletableFuture<Long> counterAddAndGet(String counterName,
250 long delta) {
251 throw new UnsupportedOperationException();
252 }
253
254 @Override
255 public CompletableFuture<Long> counterGetAndAdd(String counterName,
256 long delta) {
257 throw new UnsupportedOperationException();
258 }
259
260 @Override
261 public CompletableFuture<Void> counterSet(String counterName,
262 long value) {
263 throw new UnsupportedOperationException();
264 }
265
266 @Override
267 public CompletableFuture<Boolean> counterCompareAndSet(String counterName,
268 long expectedValue,
269 long update) {
270 throw new UnsupportedOperationException();
271 }
272
273 @Override
274 public CompletableFuture<Long> counterGet(String counterName) {
275 throw new UnsupportedOperationException();
276 }
277
278 @Override
279 public CompletableFuture<Long> queueSize(String queueName) {
280 throw new UnsupportedOperationException();
281 }
282
283 @Override
284 public CompletableFuture<Void> queuePush(String queueName,
285 byte[] entry) {
286 throw new UnsupportedOperationException();
287 }
288
289 @Override
290 public CompletableFuture<byte[]> queuePop(String queueName) {
291 throw new UnsupportedOperationException();
292 }
293
294 @Override
295 public CompletableFuture<byte[]> queuePeek(String queueName) {
296 throw new UnsupportedOperationException();
297 }
298
299 @Override
300 public CompletableFuture<CommitResponse> prepareAndCommit(Transaction transaction) {
301 throw new UnsupportedOperationException();
302 }
303
304 @Override
305 public CompletableFuture<Boolean> prepare(Transaction transaction) {
306 throw new UnsupportedOperationException();
307 }
308
309 @Override
310 public CompletableFuture<CommitResponse> commit(Transaction transaction) {
311 throw new UnsupportedOperationException();
312 }
313
314 @Override
315 public CompletableFuture<Boolean> rollback(Transaction transaction) {
316 throw new UnsupportedOperationException();
317 }
318
319 @Override
320 public String name() {
321 return "name";
322 }
323
324 @Override
325 public ResourceState state() {
326 return ResourceState.HEALTHY;
327 }
328
329 @Override
330 public Cluster cluster() {
331 throw new UnsupportedOperationException();
332 }
333
334 @Override
335 public Database addStartupTask(Task<CompletableFuture<Void>> task) {
336 throw new UnsupportedOperationException();
337 }
338
339 @Override
340 public Database addShutdownTask(Task<CompletableFuture<Void>> task) {
341 throw new UnsupportedOperationException();
342 }
343
344 @Override
345 public CompletableFuture<Database> open() {
346 return CompletableFuture.completedFuture(this);
347 }
348
349 @Override
350 public boolean isOpen() {
351 return true;
352 }
353
354 @Override
355 public CompletableFuture<Void> close() {
356 return CompletableFuture.completedFuture(null);
357 }
358
359 @Override
360 public boolean isClosed() {
361 return false;
362 }
363
364 @Override
365 public void registerConsumer(Consumer<StateMachineUpdate> consumer) {
366 }
367
368 @Override
369 public void unregisterConsumer(Consumer<StateMachineUpdate> consumer) {
370 }
371 }
372
373}