blob: bbaaf57aa2d61ebdadebbd7008a1ed757f42a6cf [file] [log] [blame]
Aaron Kruglikov3e29f662016-07-13 10:18:10 -07001/*
Brian O'Connor0a4e6742016-09-15 23:03:10 -07002 * Copyright 2016-present Open Networking Laboratory
Aaron Kruglikov3e29f662016-07-13 10:18:10 -07003 *
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.resources.impl;
17
18import com.google.common.base.Throwables;
19import com.google.common.collect.Lists;
20import io.atomix.resource.ResourceType;
21import org.junit.AfterClass;
22import org.junit.BeforeClass;
23import org.junit.Test;
24import org.onlab.util.Tools;
25import org.onosproject.store.service.MapEvent;
26import org.onosproject.store.service.MapEventListener;
27
28import java.util.Arrays;
29import java.util.Collection;
30import java.util.List;
31import java.util.Map;
32import java.util.concurrent.ArrayBlockingQueue;
33import java.util.concurrent.BlockingQueue;
34import java.util.stream.Collectors;
35
36import static org.junit.Assert.assertArrayEquals;
37import static org.junit.Assert.assertEquals;
38import static org.junit.Assert.assertFalse;
Jordan Haltermanf6272442017-04-20 02:18:08 -070039import static org.junit.Assert.assertNotEquals;
Aaron Kruglikov3e29f662016-07-13 10:18:10 -070040import static org.junit.Assert.assertNotNull;
41import static org.junit.Assert.assertNull;
42import static org.junit.Assert.assertTrue;
43
44/**
45 * Unit tests for {@link AtomixConsistentTreeMap}.
46 */
47public class AtomixConsistentTreeMapTest extends AtomixTestBase {
48 private final String keyFour = "hello";
49 private final String keyThree = "goodbye";
50 private final String keyTwo = "foo";
51 private final String keyOne = "bar";
52 private final byte[] valueOne = Tools.getBytesUtf8(keyOne);
53 private final byte[] valueTwo = Tools.getBytesUtf8(keyTwo);
54 private final byte[] valueThree = Tools.getBytesUtf8(keyThree);
55 private final byte[] valueFour = Tools.getBytesUtf8(keyFour);
56 private final byte[] spareValue = Tools.getBytesUtf8("spareValue");
57 private final List<String> allKeys = Lists.newArrayList(keyOne, keyTwo,
58 keyThree, keyFour);
59 private final List<byte[]> allValues = Lists.newArrayList(valueOne,
60 valueTwo,
61 valueThree,
62 valueFour);
63 @BeforeClass
64 public static void preTestSetup() throws Throwable {
65 createCopycatServers(3);
66 }
67
68 @AfterClass
69 public static void postTestCleanup() throws Throwable {
70 clearTests();
71 }
72
73 @Override
74 protected ResourceType resourceType() {
75 return new ResourceType(AtomixConsistentTreeMap.class);
76 }
77
78 /**
79 * Tests of the functionality associated with the
80 * {@link org.onosproject.store.service.AsyncConsistentMap} interface
81 * except transactions and listeners.
82 */
83 @Test
84 public void testBasicMapOperations() throws Throwable {
85 //Throughout the test there are isEmpty queries, these are intended to
86 //make sure that the previous section has been cleaned up, they serve
87 //the secondary purpose of testing isEmpty but that is not their
88 //primary purpose.
89 AtomixConsistentTreeMap map = createResource("basicTestMap");
90 //test size
91 map.size().thenAccept(result -> assertEquals(0, (int) result)).join();
92 map.isEmpty().thenAccept(result -> assertTrue(result)).join();
Jordan Haltermanf6272442017-04-20 02:18:08 -070093
Aaron Kruglikov3e29f662016-07-13 10:18:10 -070094 //test contains key
95 allKeys.forEach(key -> map.containsKey(key).
96 thenAccept(result -> assertFalse(result)).join());
Jordan Haltermanf6272442017-04-20 02:18:08 -070097
Aaron Kruglikov3e29f662016-07-13 10:18:10 -070098 //test contains value
99 allValues.forEach(value -> map.containsValue(value)
100 .thenAccept(result -> assertFalse(result)).join());
Jordan Haltermanf6272442017-04-20 02:18:08 -0700101
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700102 //test get
103 allKeys.forEach(key -> map.get(key).
104 thenAccept(result -> assertNull(result)).join());
105
Jordan Haltermanf6272442017-04-20 02:18:08 -0700106 //test getOrDefault
107 allKeys.forEach(key -> map.getOrDefault(key, null).thenAccept(result -> {
108 assertEquals(0, result.version());
109 assertNull(result.value());
110 }).join());
111
112 allKeys.forEach(key -> map.getOrDefault(key, "bar".getBytes()).thenAccept(result -> {
113 assertEquals(0, result.version());
114 assertArrayEquals("bar".getBytes(), result.value());
115 }).join());
116
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700117 //populate and redo prior three tests
Jordan Haltermanf6272442017-04-20 02:18:08 -0700118 allKeys.forEach(key -> map.put(key, allValues.get(allKeys.indexOf(key)))
119 .thenAccept(result -> assertNull(result)).join());
120
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700121 //test contains key
Jordan Haltermanf6272442017-04-20 02:18:08 -0700122 allKeys.forEach(key -> map.containsKey(key)
123 .thenAccept(result -> assertTrue(result)).join());
124
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700125 //test contains value
126 allValues.forEach(value -> map.containsValue(value)
127 .thenAccept(result -> assertTrue(result)).join());
Jordan Haltermanf6272442017-04-20 02:18:08 -0700128
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700129 //test get
Jordan Haltermanf6272442017-04-20 02:18:08 -0700130 allKeys.forEach(key -> map.get(key).thenAccept(result -> {
131 assertArrayEquals(allValues.get(allKeys.indexOf(key)), result.value());
132 }).join());
133
134 allKeys.forEach(key -> map.getOrDefault(key, null).thenAccept(result -> {
135 assertNotEquals(0, result.version());
136 assertArrayEquals(allValues.get(allKeys.indexOf(key)), result.value());
137 }).join());
138
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700139 //test all compute methods in this section
Jordan Haltermanf6272442017-04-20 02:18:08 -0700140 allKeys.forEach(key -> map.computeIfAbsent(key, v -> allValues.get(allKeys.indexOf(key)))
141 .thenAccept(result -> {
142 assertArrayEquals(allValues.get(allKeys.indexOf(key)), result.value());
143 }).join());
144
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700145 map.size().thenAccept(result -> assertEquals(4, (int) result)).join();
146 map.isEmpty().thenAccept(result -> assertFalse(result)).join();
Jordan Haltermanf6272442017-04-20 02:18:08 -0700147
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700148 allKeys.forEach(key -> map.computeIfPresent(key, (k, v) -> null).
149 thenAccept(result -> assertNull(result)).join());
Jordan Haltermanf6272442017-04-20 02:18:08 -0700150
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700151 map.isEmpty().thenAccept(result -> assertTrue(result)).join();
Jordan Haltermanf6272442017-04-20 02:18:08 -0700152
153 allKeys.forEach(key -> map.compute(key, (k, v) -> allValues.get(allKeys.indexOf(key)))
154 .thenAccept(result -> assertArrayEquals(allValues.get(allKeys.indexOf(key)), result.value())).join());
155
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700156 map.size().thenAccept(result -> assertEquals(4, (int) result)).join();
157 map.isEmpty().thenAccept(result -> assertFalse(result)).join();
Jordan Haltermanf6272442017-04-20 02:18:08 -0700158
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700159 allKeys.forEach(key -> map.computeIf(key,
Jordan Haltermanf6272442017-04-20 02:18:08 -0700160 (k) -> allKeys.indexOf(key) < 2, (k, v) -> null).thenAccept(result -> {
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700161 if (allKeys.indexOf(key) < 2) {
162 assertNull(result);
163 } else {
Jordan Haltermanf6272442017-04-20 02:18:08 -0700164 assertArrayEquals(allValues.get(allKeys.indexOf(key)), result.value());
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700165 }
Jordan Haltermanf6272442017-04-20 02:18:08 -0700166 }).join());
167
168 map.size().thenAccept(result -> assertEquals(2, (int) result)).join();
169 map.isEmpty().thenAccept(result -> assertFalse(result)).join();
170
171 //test simple put
172 allKeys.forEach(key -> map.put(key, allValues.get(allKeys.indexOf(key))).thenAccept(result -> {
173 if (allKeys.indexOf(key) < 2) {
174 assertNull(result);
175 } else {
176 assertArrayEquals(allValues.get(allKeys.indexOf(key)), result.value());
177 }
178 }).join());
179
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700180 map.size().thenAccept(result -> assertEquals(4, (int) result)).join();
181 map.isEmpty().thenAccept(result -> assertFalse(result)).join();
Jordan Haltermanf6272442017-04-20 02:18:08 -0700182
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700183 //test put and get for version retrieval
Jordan Haltermanf6272442017-04-20 02:18:08 -0700184 allKeys.forEach(key -> map.putAndGet(key, allValues.get(allKeys.indexOf(key))).thenAccept(firstResult -> {
185 map.putAndGet(key, allValues.get(allKeys.indexOf(key))).thenAccept(secondResult -> {
186 assertArrayEquals(allValues.get(allKeys.indexOf(key)), firstResult.value());
187 assertArrayEquals(allValues.get(allKeys.indexOf(key)), secondResult.value());
188 assertTrue((firstResult.version() + 1) == secondResult.version());
189 });
190 }).join());
191
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700192 //test removal
193 allKeys.forEach(key -> map.remove(key).thenAccept(
194 result -> assertArrayEquals(
195 allValues.get(allKeys.indexOf(key)), result.value()))
196 .join());
197 map.isEmpty().thenAccept(result -> assertTrue(result));
Jordan Haltermanf6272442017-04-20 02:18:08 -0700198
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700199 //repopulating, this is not mainly for testing
Jordan Haltermanf6272442017-04-20 02:18:08 -0700200 allKeys.forEach(key -> map.put(key, allValues.get(allKeys.indexOf(key))).thenAccept(result -> {
201 assertNull(result);
202 }).join());
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700203
204 //Test various collections of keys, values and entries
Jordan Haltermanf6272442017-04-20 02:18:08 -0700205 map.keySet().thenAccept(keys -> assertTrue(stringArrayCollectionIsEqual(keys, allKeys))).join();
206 map.values().thenAccept(values -> assertTrue(
207 byteArrayCollectionIsEqual(values.stream().map(v -> v.value())
208 .collect(Collectors.toSet()), allValues))).join();
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700209 map.entrySet().thenAccept(entrySet -> {
210 entrySet.forEach(entry -> {
211 assertTrue(allKeys.contains(entry.getKey()));
212 assertTrue(Arrays.equals(entry.getValue().value(),
213 allValues.get(allKeys.indexOf(entry.getKey()))));
214 });
215 }).join();
216 map.clear().join();
217 map.isEmpty().thenAccept(result -> assertTrue(result)).join();
218
219 //test conditional put
Jordan Haltermanf6272442017-04-20 02:18:08 -0700220 allKeys.forEach(key -> map.putIfAbsent(key, allValues.get(allKeys.indexOf(key)))
221 .thenAccept(result -> assertNull(result)).join());
222 allKeys.forEach(key -> map.putIfAbsent(key, null).thenAccept(result ->
223 assertArrayEquals(result.value(), allValues.get(allKeys.indexOf(key)))
224 ).join());
225
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700226 // test alternate removes that specify value or version
Jordan Haltermanf6272442017-04-20 02:18:08 -0700227 allKeys.forEach(key -> map.remove(key, spareValue).thenAccept(result -> assertFalse(result)).join());
228 allKeys.forEach(key -> map.remove(key, allValues.get(allKeys.indexOf(key)))
229 .thenAccept(result -> assertTrue(result)).join());
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700230 map.isEmpty().thenAccept(result -> assertTrue(result)).join();
231 List<Long> versions = Lists.newArrayList();
232
233 //repopulating set for version based removal
Jordan Haltermanf6272442017-04-20 02:18:08 -0700234 allKeys.forEach(key -> map.putAndGet(key, allValues.get(allKeys.indexOf(key)))
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700235 .thenAccept(result -> versions.add(result.version())).join());
Jordan Haltermanf6272442017-04-20 02:18:08 -0700236 allKeys.forEach(key -> map.remove(key, versions.get(0)).thenAccept(result -> {
237 assertTrue(result);
238 versions.remove(0);
239 }).join());
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700240 map.isEmpty().thenAccept(result -> assertTrue(result)).join();
Jordan Haltermanf6272442017-04-20 02:18:08 -0700241
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700242 //Testing all replace both simple (k, v), and complex that consider
243 // previous mapping or version.
Jordan Haltermanf6272442017-04-20 02:18:08 -0700244 allKeys.forEach(key -> map.put(key, allValues.get(allKeys.indexOf(key)))
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700245 .thenAccept(result -> assertNull(result)).join());
Jordan Haltermanf6272442017-04-20 02:18:08 -0700246 allKeys.forEach(key -> map.replace(key, allValues.get(3 - allKeys.indexOf(key)))
247 .thenAccept(result -> assertArrayEquals(allValues.get(allKeys.indexOf(key)), result.value()))
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700248 .join());
Jordan Haltermanf6272442017-04-20 02:18:08 -0700249 allKeys.forEach(key -> map.replace(key, spareValue, allValues.get(allKeys.indexOf(key)))
250 .thenAccept(result -> assertFalse(result)).join());
251 allKeys.forEach(key -> map.replace(key, allValues.get(3 - allKeys.indexOf(key)),
252 allValues.get(allKeys.indexOf(key))).thenAccept(result -> assertTrue(result)).join());
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700253 map.clear().join();
254 map.isEmpty().thenAccept(result -> assertTrue(result)).join();
255 versions.clear();
Jordan Haltermanf6272442017-04-20 02:18:08 -0700256
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700257 //populate for version based replacement
Jordan Haltermanf6272442017-04-20 02:18:08 -0700258 allKeys.forEach(key -> map.putAndGet(key, allValues.get(3 - allKeys.indexOf(key)))
259 .thenAccept(result -> versions.add(result.version())).join());
260 allKeys.forEach(key -> map.replace(key, 0, allValues.get(allKeys.indexOf(key)))
261 .thenAccept(result -> assertFalse(result)).join());
262 allKeys.forEach(key -> map.replace(key, versions.get(0), allValues.get(allKeys.indexOf(key)))
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700263 .thenAccept(result -> {
264 assertTrue(result);
265 versions.remove(0);
266 }).join());
267 }
268
269 @Test
270 public void mapListenerTests() throws Throwable {
271 final byte[] value1 = Tools.getBytesUtf8("value1");
272 final byte[] value2 = Tools.getBytesUtf8("value2");
273 final byte[] value3 = Tools.getBytesUtf8("value3");
274
275 AtomixConsistentTreeMap map = createResource("treeMapListenerTestMap");
276 TestMapEventListener listener = new TestMapEventListener();
277
278 // add listener; insert new value into map and verify an INSERT event
279 // is received.
280 map.addListener(listener).thenCompose(v -> map.put("foo", value1))
281 .join();
282 MapEvent<String, byte[]> event = listener.event();
283 assertNotNull(event);
284 assertEquals(MapEvent.Type.INSERT, event.type());
285 assertTrue(Arrays.equals(value1, event.newValue().value()));
286
287 // remove listener and verify listener is not notified.
288 map.removeListener(listener).thenCompose(v -> map.put("foo", value2))
289 .join();
290 assertFalse(listener.eventReceived());
291
292 // add the listener back and verify UPDATE events are received
293 // correctly
294 map.addListener(listener).thenCompose(v -> map.put("foo", value3))
295 .join();
296 event = listener.event();
297 assertNotNull(event);
298 assertEquals(MapEvent.Type.UPDATE, event.type());
299 assertTrue(Arrays.equals(value3, event.newValue().value()));
300
301 // perform a non-state changing operation and verify no events are
302 // received.
303 map.putIfAbsent("foo", value1).join();
304 assertFalse(listener.eventReceived());
305
306 // verify REMOVE events are received correctly.
307 map.remove("foo").join();
308 event = listener.event();
309 assertNotNull(event);
310 assertEquals(MapEvent.Type.REMOVE, event.type());
311 assertTrue(Arrays.equals(value3, event.oldValue().value()));
312
313 // verify compute methods also generate events.
314 map.computeIf("foo", v -> v == null, (k, v) -> value1).join();
315 event = listener.event();
316 assertNotNull(event);
317 assertEquals(MapEvent.Type.INSERT, event.type());
318 assertTrue(Arrays.equals(value1, event.newValue().value()));
319
320 map.compute("foo", (k, v) -> value2).join();
321 event = listener.event();
322 assertNotNull(event);
323 assertEquals(MapEvent.Type.UPDATE, event.type());
324 assertTrue(Arrays.equals(value2, event.newValue().value()));
325
326 map.computeIf(
327 "foo", v -> Arrays.equals(v, value2), (k, v) -> null).join();
328 event = listener.event();
329 assertNotNull(event);
330 assertEquals(MapEvent.Type.REMOVE, event.type());
331 assertTrue(Arrays.equals(value2, event.oldValue().value()));
332
333 map.removeListener(listener).join();
334 }
335
336 /**
337 * Tests functionality specified in the {@link AtomixConsistentTreeMap}
338 * interface, beyond the functionality provided in
339 * {@link org.onosproject.store.service.AsyncConsistentMap}.
340 */
341 @Test
342 public void treeMapFunctionsTest() {
343 AtomixConsistentTreeMap map = createResource("treeMapFunctionTestMap");
344 //Tests on empty map
345 map.firstKey().thenAccept(result -> assertNull(result)).join();
346 map.lastKey().thenAccept(result -> assertNull(result)).join();
347 map.ceilingEntry(keyOne).thenAccept(result -> assertNull(result))
348 .join();
349 map.floorEntry(keyOne).thenAccept(result -> assertNull(result)).join();
350 map.higherEntry(keyOne).thenAccept(result -> assertNull(result))
351 .join();
352 map.lowerEntry(keyOne).thenAccept(result -> assertNull(result)).join();
353 map.firstEntry().thenAccept(result -> assertNull(result)).join();
354 map.lastEntry().thenAccept(result -> assertNull(result)).join();
355 map.pollFirstEntry().thenAccept(result -> assertNull(result)).join();
356 map.pollLastEntry().thenAccept(result -> assertNull(result)).join();
357 map.lowerKey(keyOne).thenAccept(result -> assertNull(result)).join();
358 map.floorKey(keyOne).thenAccept(result -> assertNull(result)).join();
359 map.ceilingKey(keyOne).thenAccept(result -> assertNull(result))
360 .join();
361 map.higherKey(keyOne).thenAccept(result -> assertNull(result)).join();
362 map.delete().join();
363
364 allKeys.forEach(key -> map.put(
365 key, allValues.get(allKeys.indexOf(key)))
366 .thenAccept(result -> assertNull(result)).join());
367 //Note ordering keys are in their proper ordering in ascending order
368 //both in naming and in the allKeys list.
369
370 map.firstKey().thenAccept(result -> assertEquals(keyOne, result))
371 .join();
372 map.lastKey().thenAccept(result -> assertEquals(keyFour, result))
373 .join();
374 map.ceilingEntry(keyOne)
375 .thenAccept(result -> {
376 assertEquals(keyOne, result.getKey());
377 assertArrayEquals(valueOne, result.getValue().value());
378 })
379 .join();
380 //adding an additional letter to make keyOne an unacceptable response
381 map.ceilingEntry(keyOne + "a")
382 .thenAccept(result -> {
383 assertEquals(keyTwo, result.getKey());
384 assertArrayEquals(valueTwo, result.getValue().value());
385 })
386 .join();
387 map.ceilingEntry(keyFour + "a")
388 .thenAccept(result -> {
389 assertNull(result);
390 })
391 .join();
392 map.floorEntry(keyTwo).thenAccept(result -> {
393 assertEquals(keyTwo, result.getKey());
394 assertArrayEquals(valueTwo, result.getValue().value());
395 })
396 .join();
397 //shorten the key so it itself is not an acceptable reply
398 map.floorEntry(keyTwo.substring(0, 2)).thenAccept(result -> {
399 assertEquals(keyOne, result.getKey());
400 assertArrayEquals(valueOne, result.getValue().value());
401 })
402 .join();
403 // shorten least key so no acceptable response exists
404 map.floorEntry(keyOne.substring(0, 1)).thenAccept(
405 result -> assertNull(result))
406 .join();
407
408 map.higherEntry(keyTwo).thenAccept(result -> {
409 assertEquals(keyThree, result.getKey());
410 assertArrayEquals(valueThree, result.getValue().value());
411 })
412 .join();
413 map.higherEntry(keyFour).thenAccept(result -> assertNull(result))
414 .join();
415
416 map.lowerEntry(keyFour).thenAccept(result -> {
417 assertEquals(keyThree, result.getKey());
418 assertArrayEquals(valueThree, result.getValue().value());
419 })
420 .join();
421 map.lowerEntry(keyOne).thenAccept(result -> assertNull(result))
422 .join();
423 map.firstEntry().thenAccept(result -> {
424 assertEquals(keyOne, result.getKey());
425 assertArrayEquals(valueOne, result.getValue().value());
426 })
427 .join();
428 map.lastEntry().thenAccept(result -> {
429 assertEquals(keyFour, result.getKey());
430 assertArrayEquals(valueFour, result.getValue().value());
431 })
432 .join();
433 map.pollFirstEntry().thenAccept(result -> {
434 assertEquals(keyOne, result.getKey());
435 assertArrayEquals(valueOne, result.getValue().value());
436 });
437 map.containsKey(keyOne).thenAccept(result -> assertFalse(result))
438 .join();
439 map.size().thenAccept(result -> assertEquals(3, (int) result)).join();
440 map.pollLastEntry().thenAccept(result -> {
441 assertEquals(keyFour, result.getKey());
442 assertArrayEquals(valueFour, result.getValue().value());
443 });
444 map.containsKey(keyFour).thenAccept(result -> assertFalse(result))
445 .join();
446 map.size().thenAccept(result -> assertEquals(2, (int) result)).join();
447
448 //repopulate the missing entries
449 allKeys.forEach(key -> map.put(
450 key, allValues.get(allKeys.indexOf(key)))
451 .thenAccept(result -> {
452 if (key.equals(keyOne) || key.equals(keyFour)) {
453 assertNull(result);
454 } else {
455 assertArrayEquals(allValues.get(allKeys.indexOf(key)),
456 result.value());
457 }
458 })
459 .join());
460 map.lowerKey(keyOne).thenAccept(result -> assertNull(result)).join();
461 map.lowerKey(keyThree).thenAccept(
462 result -> assertEquals(keyTwo, result))
463 .join();
464 map.floorKey(keyThree).thenAccept(
465 result -> assertEquals(keyThree, result))
466 .join();
467 //shortening the key so there is no acceptable response
468 map.floorKey(keyOne.substring(0, 1)).thenAccept(
469 result -> assertNull(result))
470 .join();
471 map.ceilingKey(keyTwo).thenAccept(
472 result -> assertEquals(keyTwo, result))
473 .join();
474 //adding to highest key so there is no acceptable response
475 map.ceilingKey(keyFour + "a")
476 .thenAccept(reslt -> assertNull(reslt))
477 .join();
478 map.higherKey(keyThree).thenAccept(
479 result -> assertEquals(keyFour, result))
480 .join();
481 map.higherKey(keyFour).thenAccept(
482 result -> assertNull(result))
483 .join();
484 map.delete().join();
485
486 }
487
488 private AtomixConsistentTreeMap createResource(String mapName) {
489 try {
490 AtomixConsistentTreeMap map = createAtomixClient().
491 getResource(mapName, AtomixConsistentTreeMap.class)
492 .join();
493 return map;
494 } catch (Throwable e) {
495 throw new RuntimeException(e.toString());
496 }
497 }
498 private static class TestMapEventListener
499 implements MapEventListener<String, byte[]> {
500
501 private final BlockingQueue<MapEvent<String, byte[]>> queue =
502 new ArrayBlockingQueue<>(1);
503
504 @Override
505 public void event(MapEvent<String, byte[]> event) {
506 try {
507 queue.put(event);
508 } catch (InterruptedException e) {
509 Throwables.propagate(e);
510 }
511 }
512
513 public boolean eventReceived() {
514 return !queue.isEmpty();
515 }
516
517 public MapEvent<String, byte[]> event() throws InterruptedException {
518 return queue.take();
519 }
520 }
521
522 /**
523 * Returns two arrays contain the same set of elements,
524 * regardless of order.
525 * @param o1 first collection
526 * @param o2 second collection
527 * @return true if they contain the same elements
528 */
529 private boolean byteArrayCollectionIsEqual(
530 Collection<? extends byte[]> o1, Collection<? extends byte[]> o2) {
531 if (o1 == null || o2 == null || o1.size() != o2.size()) {
532 return false;
533 }
534 for (byte[] array1 : o1) {
535 boolean matched = false;
536 for (byte[] array2 : o2) {
537 if (Arrays.equals(array1, array2)) {
538 matched = true;
539 break;
540 }
541 }
542 if (!matched) {
543 return false;
544 }
545 }
546 return true;
547 }
548
549 /**
550 * Compares two collections of strings returns true if they contain the
551 * same strings, false otherwise.
552 * @param s1 string collection one
553 * @param s2 string collection two
554 * @return true if the two sets contain the same strings
555 */
556 private boolean stringArrayCollectionIsEqual(
557 Collection<? extends String> s1, Collection<? extends String> s2) {
558 if (s1 == null || s2 == null || s1.size() != s2.size()) {
559 return false;
560 }
561 for (String string1 : s1) {
562 boolean matched = false;
563 for (String string2 : s2) {
564 if (string1.equals(string2)) {
565 matched = true;
566 break;
567 }
568 }
569 if (!matched) {
570 return false;
571 }
572 }
573 return true;
574 }
575
576 /**
577 * Inner entry type for testing.
578 * @param <K>
579 * @param <V>
580 */
581 private class InnerEntry<K, V> implements Map.Entry<K, V> {
582 private K key;
583 private V value;
584 public InnerEntry(K key, V value) {
585 this.key = key;
586 this.value = value;
587 }
588
589 @Override
590 public K getKey() {
591 return key;
592 }
593
594 @Override
595 public V getValue() {
596 return value;
597 }
598
599 @Override
600 public V setValue(V value) {
601 V temp = this.value;
602 this.value = value;
603 return temp;
604 }
605
606 @Override
607 public boolean equals(Object o) {
608 if (!(o instanceof InnerEntry)) {
609 return false;
610 }
611 InnerEntry other = (InnerEntry) o;
612 boolean keysEqual = false;
613 boolean valuesEqual = false;
614 if (this.key instanceof byte[]) {
615 if (other.getKey() instanceof byte[]) {
616 keysEqual = Arrays.equals((byte[]) this.key,
617 (byte[]) other.getKey());
618 } else {
619 return false;
620 }
621 } else {
622 keysEqual = this.getKey().equals(other.getKey());
623 }
624
625 if (keysEqual) {
626 if (this.value instanceof byte[]) {
627 if (other.getValue() instanceof byte[]) {
628 return Arrays.equals((byte[]) this.value,
629 (byte[]) other.getValue());
630 } else {
631 return false;
632 }
633 } else {
634 return this.key.equals(other.getKey());
635 }
636 }
637 return false;
638 }
639
640 @Override
641 public int hashCode() {
642 return 0;
643 }
644 }
Ray Milkey88cc3432017-03-30 17:19:08 -0700645}