blob: 57bf60cf583cc9ef30233125b6c3463453329e3f [file] [log] [blame]
Aaron Kruglikov3e29f662016-07-13 10:18:10 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
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
Jordan Halterman2bf177c2017-06-29 01:49:08 -070018import com.google.common.collect.Lists;
19import io.atomix.protocols.raft.proxy.RaftProxy;
20import io.atomix.protocols.raft.service.RaftService;
21import org.junit.Test;
22import org.onlab.util.Tools;
23import org.onosproject.store.service.MapEvent;
24import org.onosproject.store.service.MapEventListener;
25
Ray Milkey6a51cb92018-03-06 09:03:03 -080026import java.util.Arrays;
27import java.util.Collection;
28import java.util.List;
29import java.util.concurrent.ArrayBlockingQueue;
30import java.util.concurrent.BlockingQueue;
31import java.util.stream.Collectors;
32
Aaron Kruglikov3e29f662016-07-13 10:18:10 -070033import static org.junit.Assert.assertArrayEquals;
34import static org.junit.Assert.assertEquals;
35import static org.junit.Assert.assertFalse;
Jordan Haltermanf6272442017-04-20 02:18:08 -070036import static org.junit.Assert.assertNotEquals;
Aaron Kruglikov3e29f662016-07-13 10:18:10 -070037import static org.junit.Assert.assertNotNull;
38import static org.junit.Assert.assertNull;
39import static org.junit.Assert.assertTrue;
40
41/**
42 * Unit tests for {@link AtomixConsistentTreeMap}.
43 */
Jordan Halterman2bf177c2017-06-29 01:49:08 -070044public class AtomixConsistentTreeMapTest extends AtomixTestBase<AtomixConsistentTreeMap> {
Aaron Kruglikov3e29f662016-07-13 10:18:10 -070045 private final String keyFour = "hello";
46 private final String keyThree = "goodbye";
47 private final String keyTwo = "foo";
48 private final String keyOne = "bar";
49 private final byte[] valueOne = Tools.getBytesUtf8(keyOne);
50 private final byte[] valueTwo = Tools.getBytesUtf8(keyTwo);
51 private final byte[] valueThree = Tools.getBytesUtf8(keyThree);
52 private final byte[] valueFour = Tools.getBytesUtf8(keyFour);
53 private final byte[] spareValue = Tools.getBytesUtf8("spareValue");
54 private final List<String> allKeys = Lists.newArrayList(keyOne, keyTwo,
55 keyThree, keyFour);
56 private final List<byte[]> allValues = Lists.newArrayList(valueOne,
57 valueTwo,
58 valueThree,
59 valueFour);
Aaron Kruglikov3e29f662016-07-13 10:18:10 -070060
Jordan Halterman2bf177c2017-06-29 01:49:08 -070061 @Override
62 protected RaftService createService() {
63 return new AtomixConsistentTreeMapService();
Aaron Kruglikov3e29f662016-07-13 10:18:10 -070064 }
65
66 @Override
Jordan Halterman2bf177c2017-06-29 01:49:08 -070067 protected AtomixConsistentTreeMap createPrimitive(RaftProxy proxy) {
68 return new AtomixConsistentTreeMap(proxy);
Aaron Kruglikov3e29f662016-07-13 10:18:10 -070069 }
70
71 /**
72 * Tests of the functionality associated with the
73 * {@link org.onosproject.store.service.AsyncConsistentMap} interface
74 * except transactions and listeners.
75 */
76 @Test
77 public void testBasicMapOperations() throws Throwable {
78 //Throughout the test there are isEmpty queries, these are intended to
79 //make sure that the previous section has been cleaned up, they serve
80 //the secondary purpose of testing isEmpty but that is not their
81 //primary purpose.
82 AtomixConsistentTreeMap map = createResource("basicTestMap");
83 //test size
84 map.size().thenAccept(result -> assertEquals(0, (int) result)).join();
85 map.isEmpty().thenAccept(result -> assertTrue(result)).join();
Jordan Haltermanf6272442017-04-20 02:18:08 -070086
Aaron Kruglikov3e29f662016-07-13 10:18:10 -070087 //test contains key
88 allKeys.forEach(key -> map.containsKey(key).
89 thenAccept(result -> assertFalse(result)).join());
Jordan Haltermanf6272442017-04-20 02:18:08 -070090
Aaron Kruglikov3e29f662016-07-13 10:18:10 -070091 //test contains value
92 allValues.forEach(value -> map.containsValue(value)
93 .thenAccept(result -> assertFalse(result)).join());
Jordan Haltermanf6272442017-04-20 02:18:08 -070094
Aaron Kruglikov3e29f662016-07-13 10:18:10 -070095 //test get
96 allKeys.forEach(key -> map.get(key).
97 thenAccept(result -> assertNull(result)).join());
98
Jordan Haltermanf6272442017-04-20 02:18:08 -070099 //test getOrDefault
100 allKeys.forEach(key -> map.getOrDefault(key, null).thenAccept(result -> {
101 assertEquals(0, result.version());
102 assertNull(result.value());
103 }).join());
104
105 allKeys.forEach(key -> map.getOrDefault(key, "bar".getBytes()).thenAccept(result -> {
106 assertEquals(0, result.version());
107 assertArrayEquals("bar".getBytes(), result.value());
108 }).join());
109
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700110 //populate and redo prior three tests
Jordan Haltermanf6272442017-04-20 02:18:08 -0700111 allKeys.forEach(key -> map.put(key, allValues.get(allKeys.indexOf(key)))
112 .thenAccept(result -> assertNull(result)).join());
113
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700114 //test contains key
Jordan Haltermanf6272442017-04-20 02:18:08 -0700115 allKeys.forEach(key -> map.containsKey(key)
116 .thenAccept(result -> assertTrue(result)).join());
117
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700118 //test contains value
119 allValues.forEach(value -> map.containsValue(value)
120 .thenAccept(result -> assertTrue(result)).join());
Jordan Haltermanf6272442017-04-20 02:18:08 -0700121
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700122 //test get
Jordan Haltermanf6272442017-04-20 02:18:08 -0700123 allKeys.forEach(key -> map.get(key).thenAccept(result -> {
124 assertArrayEquals(allValues.get(allKeys.indexOf(key)), result.value());
125 }).join());
126
127 allKeys.forEach(key -> map.getOrDefault(key, null).thenAccept(result -> {
128 assertNotEquals(0, result.version());
129 assertArrayEquals(allValues.get(allKeys.indexOf(key)), result.value());
130 }).join());
131
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700132 //test all compute methods in this section
Jordan Haltermanf6272442017-04-20 02:18:08 -0700133 allKeys.forEach(key -> map.computeIfAbsent(key, v -> allValues.get(allKeys.indexOf(key)))
134 .thenAccept(result -> {
135 assertArrayEquals(allValues.get(allKeys.indexOf(key)), result.value());
136 }).join());
137
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700138 map.size().thenAccept(result -> assertEquals(4, (int) result)).join();
139 map.isEmpty().thenAccept(result -> assertFalse(result)).join();
Jordan Haltermanf6272442017-04-20 02:18:08 -0700140
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700141 allKeys.forEach(key -> map.computeIfPresent(key, (k, v) -> null).
142 thenAccept(result -> assertNull(result)).join());
Jordan Haltermanf6272442017-04-20 02:18:08 -0700143
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700144 map.isEmpty().thenAccept(result -> assertTrue(result)).join();
Jordan Haltermanf6272442017-04-20 02:18:08 -0700145
146 allKeys.forEach(key -> map.compute(key, (k, v) -> allValues.get(allKeys.indexOf(key)))
147 .thenAccept(result -> assertArrayEquals(allValues.get(allKeys.indexOf(key)), result.value())).join());
148
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700149 map.size().thenAccept(result -> assertEquals(4, (int) result)).join();
150 map.isEmpty().thenAccept(result -> assertFalse(result)).join();
Jordan Haltermanf6272442017-04-20 02:18:08 -0700151
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700152 allKeys.forEach(key -> map.computeIf(key,
Jordan Haltermanf6272442017-04-20 02:18:08 -0700153 (k) -> allKeys.indexOf(key) < 2, (k, v) -> null).thenAccept(result -> {
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700154 if (allKeys.indexOf(key) < 2) {
155 assertNull(result);
156 } else {
Jordan Haltermanf6272442017-04-20 02:18:08 -0700157 assertArrayEquals(allValues.get(allKeys.indexOf(key)), result.value());
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700158 }
Jordan Haltermanf6272442017-04-20 02:18:08 -0700159 }).join());
160
161 map.size().thenAccept(result -> assertEquals(2, (int) result)).join();
162 map.isEmpty().thenAccept(result -> assertFalse(result)).join();
163
164 //test simple put
165 allKeys.forEach(key -> map.put(key, allValues.get(allKeys.indexOf(key))).thenAccept(result -> {
166 if (allKeys.indexOf(key) < 2) {
167 assertNull(result);
168 } else {
169 assertArrayEquals(allValues.get(allKeys.indexOf(key)), result.value());
170 }
171 }).join());
172
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700173 map.size().thenAccept(result -> assertEquals(4, (int) result)).join();
174 map.isEmpty().thenAccept(result -> assertFalse(result)).join();
Jordan Haltermanf6272442017-04-20 02:18:08 -0700175
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700176 //test put and get for version retrieval
Jordan Haltermanf6272442017-04-20 02:18:08 -0700177 allKeys.forEach(key -> map.putAndGet(key, allValues.get(allKeys.indexOf(key))).thenAccept(firstResult -> {
178 map.putAndGet(key, allValues.get(allKeys.indexOf(key))).thenAccept(secondResult -> {
179 assertArrayEquals(allValues.get(allKeys.indexOf(key)), firstResult.value());
180 assertArrayEquals(allValues.get(allKeys.indexOf(key)), secondResult.value());
Jordan Haltermanf6272442017-04-20 02:18:08 -0700181 });
182 }).join());
183
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700184 //test removal
185 allKeys.forEach(key -> map.remove(key).thenAccept(
186 result -> assertArrayEquals(
187 allValues.get(allKeys.indexOf(key)), result.value()))
188 .join());
189 map.isEmpty().thenAccept(result -> assertTrue(result));
Jordan Haltermanf6272442017-04-20 02:18:08 -0700190
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700191 //repopulating, this is not mainly for testing
Jordan Haltermanf6272442017-04-20 02:18:08 -0700192 allKeys.forEach(key -> map.put(key, allValues.get(allKeys.indexOf(key))).thenAccept(result -> {
193 assertNull(result);
194 }).join());
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700195
196 //Test various collections of keys, values and entries
Jordan Haltermanf6272442017-04-20 02:18:08 -0700197 map.keySet().thenAccept(keys -> assertTrue(stringArrayCollectionIsEqual(keys, allKeys))).join();
198 map.values().thenAccept(values -> assertTrue(
199 byteArrayCollectionIsEqual(values.stream().map(v -> v.value())
200 .collect(Collectors.toSet()), allValues))).join();
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700201 map.entrySet().thenAccept(entrySet -> {
202 entrySet.forEach(entry -> {
203 assertTrue(allKeys.contains(entry.getKey()));
204 assertTrue(Arrays.equals(entry.getValue().value(),
205 allValues.get(allKeys.indexOf(entry.getKey()))));
206 });
207 }).join();
208 map.clear().join();
209 map.isEmpty().thenAccept(result -> assertTrue(result)).join();
210
211 //test conditional put
Jordan Haltermanf6272442017-04-20 02:18:08 -0700212 allKeys.forEach(key -> map.putIfAbsent(key, allValues.get(allKeys.indexOf(key)))
213 .thenAccept(result -> assertNull(result)).join());
214 allKeys.forEach(key -> map.putIfAbsent(key, null).thenAccept(result ->
215 assertArrayEquals(result.value(), allValues.get(allKeys.indexOf(key)))
216 ).join());
217
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700218 // test alternate removes that specify value or version
Jordan Haltermanf6272442017-04-20 02:18:08 -0700219 allKeys.forEach(key -> map.remove(key, spareValue).thenAccept(result -> assertFalse(result)).join());
220 allKeys.forEach(key -> map.remove(key, allValues.get(allKeys.indexOf(key)))
221 .thenAccept(result -> assertTrue(result)).join());
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700222 map.isEmpty().thenAccept(result -> assertTrue(result)).join();
223 List<Long> versions = Lists.newArrayList();
224
225 //repopulating set for version based removal
Jordan Haltermanf6272442017-04-20 02:18:08 -0700226 allKeys.forEach(key -> map.putAndGet(key, allValues.get(allKeys.indexOf(key)))
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700227 .thenAccept(result -> versions.add(result.version())).join());
Jordan Haltermanf6272442017-04-20 02:18:08 -0700228 allKeys.forEach(key -> map.remove(key, versions.get(0)).thenAccept(result -> {
229 assertTrue(result);
230 versions.remove(0);
231 }).join());
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700232 map.isEmpty().thenAccept(result -> assertTrue(result)).join();
Jordan Haltermanf6272442017-04-20 02:18:08 -0700233
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700234 //Testing all replace both simple (k, v), and complex that consider
235 // previous mapping or version.
Jordan Haltermanf6272442017-04-20 02:18:08 -0700236 allKeys.forEach(key -> map.put(key, allValues.get(allKeys.indexOf(key)))
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700237 .thenAccept(result -> assertNull(result)).join());
Jordan Haltermanf6272442017-04-20 02:18:08 -0700238 allKeys.forEach(key -> map.replace(key, allValues.get(3 - allKeys.indexOf(key)))
239 .thenAccept(result -> assertArrayEquals(allValues.get(allKeys.indexOf(key)), result.value()))
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700240 .join());
Jordan Haltermanf6272442017-04-20 02:18:08 -0700241 allKeys.forEach(key -> map.replace(key, spareValue, allValues.get(allKeys.indexOf(key)))
242 .thenAccept(result -> assertFalse(result)).join());
243 allKeys.forEach(key -> map.replace(key, allValues.get(3 - allKeys.indexOf(key)),
244 allValues.get(allKeys.indexOf(key))).thenAccept(result -> assertTrue(result)).join());
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700245 map.clear().join();
246 map.isEmpty().thenAccept(result -> assertTrue(result)).join();
247 versions.clear();
Jordan Haltermanf6272442017-04-20 02:18:08 -0700248
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700249 //populate for version based replacement
Jordan Haltermanf6272442017-04-20 02:18:08 -0700250 allKeys.forEach(key -> map.putAndGet(key, allValues.get(3 - allKeys.indexOf(key)))
251 .thenAccept(result -> versions.add(result.version())).join());
252 allKeys.forEach(key -> map.replace(key, 0, allValues.get(allKeys.indexOf(key)))
253 .thenAccept(result -> assertFalse(result)).join());
254 allKeys.forEach(key -> map.replace(key, versions.get(0), allValues.get(allKeys.indexOf(key)))
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700255 .thenAccept(result -> {
256 assertTrue(result);
257 versions.remove(0);
258 }).join());
259 }
260
261 @Test
262 public void mapListenerTests() throws Throwable {
263 final byte[] value1 = Tools.getBytesUtf8("value1");
264 final byte[] value2 = Tools.getBytesUtf8("value2");
265 final byte[] value3 = Tools.getBytesUtf8("value3");
266
267 AtomixConsistentTreeMap map = createResource("treeMapListenerTestMap");
268 TestMapEventListener listener = new TestMapEventListener();
269
270 // add listener; insert new value into map and verify an INSERT event
271 // is received.
272 map.addListener(listener).thenCompose(v -> map.put("foo", value1))
273 .join();
274 MapEvent<String, byte[]> event = listener.event();
275 assertNotNull(event);
276 assertEquals(MapEvent.Type.INSERT, event.type());
277 assertTrue(Arrays.equals(value1, event.newValue().value()));
278
279 // remove listener and verify listener is not notified.
280 map.removeListener(listener).thenCompose(v -> map.put("foo", value2))
281 .join();
282 assertFalse(listener.eventReceived());
283
284 // add the listener back and verify UPDATE events are received
285 // correctly
286 map.addListener(listener).thenCompose(v -> map.put("foo", value3))
287 .join();
288 event = listener.event();
289 assertNotNull(event);
290 assertEquals(MapEvent.Type.UPDATE, event.type());
291 assertTrue(Arrays.equals(value3, event.newValue().value()));
292
293 // perform a non-state changing operation and verify no events are
294 // received.
295 map.putIfAbsent("foo", value1).join();
296 assertFalse(listener.eventReceived());
297
298 // verify REMOVE events are received correctly.
299 map.remove("foo").join();
300 event = listener.event();
301 assertNotNull(event);
302 assertEquals(MapEvent.Type.REMOVE, event.type());
303 assertTrue(Arrays.equals(value3, event.oldValue().value()));
304
305 // verify compute methods also generate events.
306 map.computeIf("foo", v -> v == null, (k, v) -> value1).join();
307 event = listener.event();
308 assertNotNull(event);
309 assertEquals(MapEvent.Type.INSERT, event.type());
310 assertTrue(Arrays.equals(value1, event.newValue().value()));
311
312 map.compute("foo", (k, v) -> value2).join();
313 event = listener.event();
314 assertNotNull(event);
315 assertEquals(MapEvent.Type.UPDATE, event.type());
316 assertTrue(Arrays.equals(value2, event.newValue().value()));
317
318 map.computeIf(
319 "foo", v -> Arrays.equals(v, value2), (k, v) -> null).join();
320 event = listener.event();
321 assertNotNull(event);
322 assertEquals(MapEvent.Type.REMOVE, event.type());
323 assertTrue(Arrays.equals(value2, event.oldValue().value()));
324
325 map.removeListener(listener).join();
326 }
327
328 /**
329 * Tests functionality specified in the {@link AtomixConsistentTreeMap}
330 * interface, beyond the functionality provided in
331 * {@link org.onosproject.store.service.AsyncConsistentMap}.
332 */
333 @Test
334 public void treeMapFunctionsTest() {
335 AtomixConsistentTreeMap map = createResource("treeMapFunctionTestMap");
336 //Tests on empty map
337 map.firstKey().thenAccept(result -> assertNull(result)).join();
338 map.lastKey().thenAccept(result -> assertNull(result)).join();
339 map.ceilingEntry(keyOne).thenAccept(result -> assertNull(result))
340 .join();
341 map.floorEntry(keyOne).thenAccept(result -> assertNull(result)).join();
342 map.higherEntry(keyOne).thenAccept(result -> assertNull(result))
343 .join();
344 map.lowerEntry(keyOne).thenAccept(result -> assertNull(result)).join();
345 map.firstEntry().thenAccept(result -> assertNull(result)).join();
346 map.lastEntry().thenAccept(result -> assertNull(result)).join();
347 map.pollFirstEntry().thenAccept(result -> assertNull(result)).join();
348 map.pollLastEntry().thenAccept(result -> assertNull(result)).join();
349 map.lowerKey(keyOne).thenAccept(result -> assertNull(result)).join();
350 map.floorKey(keyOne).thenAccept(result -> assertNull(result)).join();
351 map.ceilingKey(keyOne).thenAccept(result -> assertNull(result))
352 .join();
353 map.higherKey(keyOne).thenAccept(result -> assertNull(result)).join();
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700354
355 // TODO: delete() is not supported
356 //map.delete().join();
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700357
358 allKeys.forEach(key -> map.put(
359 key, allValues.get(allKeys.indexOf(key)))
360 .thenAccept(result -> assertNull(result)).join());
361 //Note ordering keys are in their proper ordering in ascending order
362 //both in naming and in the allKeys list.
363
364 map.firstKey().thenAccept(result -> assertEquals(keyOne, result))
365 .join();
366 map.lastKey().thenAccept(result -> assertEquals(keyFour, result))
367 .join();
368 map.ceilingEntry(keyOne)
369 .thenAccept(result -> {
370 assertEquals(keyOne, result.getKey());
371 assertArrayEquals(valueOne, result.getValue().value());
372 })
373 .join();
374 //adding an additional letter to make keyOne an unacceptable response
375 map.ceilingEntry(keyOne + "a")
376 .thenAccept(result -> {
377 assertEquals(keyTwo, result.getKey());
378 assertArrayEquals(valueTwo, result.getValue().value());
379 })
380 .join();
381 map.ceilingEntry(keyFour + "a")
382 .thenAccept(result -> {
383 assertNull(result);
384 })
385 .join();
386 map.floorEntry(keyTwo).thenAccept(result -> {
387 assertEquals(keyTwo, result.getKey());
388 assertArrayEquals(valueTwo, result.getValue().value());
389 })
390 .join();
391 //shorten the key so it itself is not an acceptable reply
392 map.floorEntry(keyTwo.substring(0, 2)).thenAccept(result -> {
393 assertEquals(keyOne, result.getKey());
394 assertArrayEquals(valueOne, result.getValue().value());
395 })
396 .join();
397 // shorten least key so no acceptable response exists
398 map.floorEntry(keyOne.substring(0, 1)).thenAccept(
399 result -> assertNull(result))
400 .join();
401
402 map.higherEntry(keyTwo).thenAccept(result -> {
403 assertEquals(keyThree, result.getKey());
404 assertArrayEquals(valueThree, result.getValue().value());
405 })
406 .join();
407 map.higherEntry(keyFour).thenAccept(result -> assertNull(result))
408 .join();
409
410 map.lowerEntry(keyFour).thenAccept(result -> {
411 assertEquals(keyThree, result.getKey());
412 assertArrayEquals(valueThree, result.getValue().value());
413 })
414 .join();
415 map.lowerEntry(keyOne).thenAccept(result -> assertNull(result))
416 .join();
417 map.firstEntry().thenAccept(result -> {
418 assertEquals(keyOne, result.getKey());
419 assertArrayEquals(valueOne, result.getValue().value());
420 })
421 .join();
422 map.lastEntry().thenAccept(result -> {
423 assertEquals(keyFour, result.getKey());
424 assertArrayEquals(valueFour, result.getValue().value());
425 })
426 .join();
427 map.pollFirstEntry().thenAccept(result -> {
428 assertEquals(keyOne, result.getKey());
429 assertArrayEquals(valueOne, result.getValue().value());
430 });
431 map.containsKey(keyOne).thenAccept(result -> assertFalse(result))
432 .join();
433 map.size().thenAccept(result -> assertEquals(3, (int) result)).join();
434 map.pollLastEntry().thenAccept(result -> {
435 assertEquals(keyFour, result.getKey());
436 assertArrayEquals(valueFour, result.getValue().value());
437 });
438 map.containsKey(keyFour).thenAccept(result -> assertFalse(result))
439 .join();
440 map.size().thenAccept(result -> assertEquals(2, (int) result)).join();
441
442 //repopulate the missing entries
443 allKeys.forEach(key -> map.put(
444 key, allValues.get(allKeys.indexOf(key)))
445 .thenAccept(result -> {
446 if (key.equals(keyOne) || key.equals(keyFour)) {
447 assertNull(result);
448 } else {
449 assertArrayEquals(allValues.get(allKeys.indexOf(key)),
450 result.value());
451 }
452 })
453 .join());
454 map.lowerKey(keyOne).thenAccept(result -> assertNull(result)).join();
455 map.lowerKey(keyThree).thenAccept(
456 result -> assertEquals(keyTwo, result))
457 .join();
458 map.floorKey(keyThree).thenAccept(
459 result -> assertEquals(keyThree, result))
460 .join();
461 //shortening the key so there is no acceptable response
462 map.floorKey(keyOne.substring(0, 1)).thenAccept(
463 result -> assertNull(result))
464 .join();
465 map.ceilingKey(keyTwo).thenAccept(
466 result -> assertEquals(keyTwo, result))
467 .join();
468 //adding to highest key so there is no acceptable response
469 map.ceilingKey(keyFour + "a")
470 .thenAccept(reslt -> assertNull(reslt))
471 .join();
472 map.higherKey(keyThree).thenAccept(
473 result -> assertEquals(keyFour, result))
474 .join();
475 map.higherKey(keyFour).thenAccept(
476 result -> assertNull(result))
477 .join();
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700478
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700479 // TODO: delete() is not supported
480 //map.delete().join();
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700481 }
482
483 private AtomixConsistentTreeMap createResource(String mapName) {
484 try {
Jordan Halterman2bf177c2017-06-29 01:49:08 -0700485 AtomixConsistentTreeMap map = newPrimitive(mapName);
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700486 return map;
487 } catch (Throwable e) {
488 throw new RuntimeException(e.toString());
489 }
490 }
491 private static class TestMapEventListener
492 implements MapEventListener<String, byte[]> {
493
494 private final BlockingQueue<MapEvent<String, byte[]>> queue =
495 new ArrayBlockingQueue<>(1);
496
497 @Override
498 public void event(MapEvent<String, byte[]> event) {
499 try {
500 queue.put(event);
501 } catch (InterruptedException e) {
Ray Milkey6a51cb92018-03-06 09:03:03 -0800502 Thread.interrupted();
503 throw new IllegalStateException(e);
Aaron Kruglikov3e29f662016-07-13 10:18:10 -0700504 }
505 }
506
507 public boolean eventReceived() {
508 return !queue.isEmpty();
509 }
510
511 public MapEvent<String, byte[]> event() throws InterruptedException {
512 return queue.take();
513 }
514 }
515
516 /**
517 * Returns two arrays contain the same set of elements,
518 * regardless of order.
519 * @param o1 first collection
520 * @param o2 second collection
521 * @return true if they contain the same elements
522 */
523 private boolean byteArrayCollectionIsEqual(
524 Collection<? extends byte[]> o1, Collection<? extends byte[]> o2) {
525 if (o1 == null || o2 == null || o1.size() != o2.size()) {
526 return false;
527 }
528 for (byte[] array1 : o1) {
529 boolean matched = false;
530 for (byte[] array2 : o2) {
531 if (Arrays.equals(array1, array2)) {
532 matched = true;
533 break;
534 }
535 }
536 if (!matched) {
537 return false;
538 }
539 }
540 return true;
541 }
542
543 /**
544 * Compares two collections of strings returns true if they contain the
545 * same strings, false otherwise.
546 * @param s1 string collection one
547 * @param s2 string collection two
548 * @return true if the two sets contain the same strings
549 */
550 private boolean stringArrayCollectionIsEqual(
551 Collection<? extends String> s1, Collection<? extends String> s2) {
552 if (s1 == null || s2 == null || s1.size() != s2.size()) {
553 return false;
554 }
555 for (String string1 : s1) {
556 boolean matched = false;
557 for (String string2 : s2) {
558 if (string1.equals(string2)) {
559 matched = true;
560 break;
561 }
562 }
563 if (!matched) {
564 return false;
565 }
566 }
567 return true;
568 }
Ray Milkey88cc3432017-03-30 17:19:08 -0700569}