Jonathan Hart

Unit tests for EventuallyConsistentMapImpl.

Most functionality is tested here, except for the anti-entropy code.

ONOS-859.

Change-Id: Ib9e83518f8a91d599364106bc0f7d869e62f5133
...@@ -15,12 +15,13 @@ ...@@ -15,12 +15,13 @@
15 */ 15 */
16 package org.onosproject.store.cluster.messaging; 16 package org.onosproject.store.cluster.messaging;
17 17
18 -import java.io.IOException; 18 +import com.google.common.base.MoreObjects;
19 -
20 -import org.onosproject.cluster.NodeId;
21 import org.onlab.util.ByteArraySizeHashPrinter; 19 import org.onlab.util.ByteArraySizeHashPrinter;
20 +import org.onosproject.cluster.NodeId;
22 21
23 -import com.google.common.base.MoreObjects; 22 +import java.io.IOException;
23 +import java.util.Arrays;
24 +import java.util.Objects;
24 25
25 // TODO: Should payload type be ByteBuffer? 26 // TODO: Should payload type be ByteBuffer?
26 /** 27 /**
...@@ -79,7 +80,7 @@ public class ClusterMessage { ...@@ -79,7 +80,7 @@ public class ClusterMessage {
79 * @throws IOException when I/O exception of some sort has occurred 80 * @throws IOException when I/O exception of some sort has occurred
80 */ 81 */
81 public void respond(byte[] data) throws IOException { 82 public void respond(byte[] data) throws IOException {
82 - throw new IllegalStateException("One can only repond to message recived from others."); 83 + throw new IllegalStateException("One can only respond to message received from others.");
83 } 84 }
84 85
85 @Override 86 @Override
...@@ -90,4 +91,22 @@ public class ClusterMessage { ...@@ -90,4 +91,22 @@ public class ClusterMessage {
90 .add("payload", ByteArraySizeHashPrinter.of(payload)) 91 .add("payload", ByteArraySizeHashPrinter.of(payload))
91 .toString(); 92 .toString();
92 } 93 }
94 +
95 + @Override
96 + public boolean equals(Object o) {
97 + if (!(o instanceof ClusterMessage)) {
98 + return false;
99 + }
100 +
101 + ClusterMessage that = (ClusterMessage) o;
102 +
103 + return Objects.equals(this.sender, that.sender) &&
104 + Objects.equals(this.subject, that.subject) &&
105 + Arrays.equals(this.payload, that.payload);
106 + }
107 +
108 + @Override
109 + public int hashCode() {
110 + return Objects.hash(sender, subject, payload);
111 + }
93 } 112 }
......
...@@ -15,6 +15,10 @@ ...@@ -15,6 +15,10 @@
15 */ 15 */
16 package org.onosproject.store.impl; 16 package org.onosproject.store.impl;
17 17
18 +import com.google.common.base.MoreObjects;
19 +
20 +import java.util.Objects;
21 +
18 /** 22 /**
19 * Event object signalling that the map was modified. 23 * Event object signalling that the map was modified.
20 */ 24 */
...@@ -68,4 +72,30 @@ public class EventuallyConsistentMapEvent<K, V> { ...@@ -68,4 +72,30 @@ public class EventuallyConsistentMapEvent<K, V> {
68 public V value() { 72 public V value() {
69 return value; 73 return value;
70 } 74 }
75 +
76 + @Override
77 + public boolean equals(Object o) {
78 + if (!(o instanceof EventuallyConsistentMapEvent)) {
79 + return false;
80 + }
81 +
82 + EventuallyConsistentMapEvent that = (EventuallyConsistentMapEvent) o;
83 + return Objects.equals(this.type, that.type) &&
84 + Objects.equals(this.key, that.key) &&
85 + Objects.equals(this.value, that.value);
86 + }
87 +
88 + @Override
89 + public int hashCode() {
90 + return Objects.hash(type, key, value);
91 + }
92 +
93 + @Override
94 + public String toString() {
95 + return MoreObjects.toStringHelper(getClass())
96 + .add("type", type)
97 + .add("key", key)
98 + .add("value", value)
99 + .toString();
100 + }
71 } 101 }
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
16 package org.onosproject.store.impl; 16 package org.onosproject.store.impl;
17 17
18 import com.google.common.base.MoreObjects; 18 import com.google.common.base.MoreObjects;
19 +import com.google.common.collect.ImmutableList;
19 import org.apache.commons.lang3.RandomUtils; 20 import org.apache.commons.lang3.RandomUtils;
20 import org.onlab.util.KryoNamespace; 21 import org.onlab.util.KryoNamespace;
21 import org.onosproject.cluster.ClusterService; 22 import org.onosproject.cluster.ClusterService;
...@@ -33,11 +34,11 @@ import org.slf4j.LoggerFactory; ...@@ -33,11 +34,11 @@ import org.slf4j.LoggerFactory;
33 import java.io.IOException; 34 import java.io.IOException;
34 import java.util.ArrayList; 35 import java.util.ArrayList;
35 import java.util.Collection; 36 import java.util.Collection;
36 -import java.util.Collections;
37 import java.util.HashMap; 37 import java.util.HashMap;
38 import java.util.LinkedList; 38 import java.util.LinkedList;
39 import java.util.List; 39 import java.util.List;
40 import java.util.Map; 40 import java.util.Map;
41 +import java.util.Objects;
41 import java.util.Set; 42 import java.util.Set;
42 import java.util.concurrent.ConcurrentHashMap; 43 import java.util.concurrent.ConcurrentHashMap;
43 import java.util.concurrent.CopyOnWriteArraySet; 44 import java.util.concurrent.CopyOnWriteArraySet;
...@@ -290,13 +291,15 @@ public class EventuallyConsistentMapImpl<K, V> ...@@ -290,13 +291,15 @@ public class EventuallyConsistentMapImpl<K, V>
290 } 291 }
291 } 292 }
292 293
293 - notifyPeers(new InternalPutEvent<>(updates)); 294 + if (!updates.isEmpty()) {
295 + notifyPeers(new InternalPutEvent<>(updates));
294 296
295 - for (PutEntry<K, V> entry : updates) { 297 + for (PutEntry<K, V> entry : updates) {
296 - EventuallyConsistentMapEvent<K, V> externalEvent = 298 + EventuallyConsistentMapEvent<K, V> externalEvent = new EventuallyConsistentMapEvent<>(
297 - new EventuallyConsistentMapEvent<>( 299 + EventuallyConsistentMapEvent.Type.PUT, entry.key(),
298 - EventuallyConsistentMapEvent.Type.PUT, entry.key(), entry.value()); 300 + entry.value());
299 - notifyListeners(externalEvent); 301 + notifyListeners(externalEvent);
302 + }
300 } 303 }
301 } 304 }
302 305
...@@ -314,13 +317,16 @@ public class EventuallyConsistentMapImpl<K, V> ...@@ -314,13 +317,16 @@ public class EventuallyConsistentMapImpl<K, V>
314 } 317 }
315 } 318 }
316 319
317 - notifyPeers(new InternalRemoveEvent<>(removed)); 320 + if (!removed.isEmpty()) {
321 + notifyPeers(new InternalRemoveEvent<>(removed));
318 322
319 - for (RemoveEntry<K> entry : removed) { 323 + for (RemoveEntry<K> entry : removed) {
320 - EventuallyConsistentMapEvent<K, V> externalEvent = 324 + EventuallyConsistentMapEvent<K, V> externalEvent
321 - new EventuallyConsistentMapEvent<>( 325 + = new EventuallyConsistentMapEvent<>(
322 - EventuallyConsistentMapEvent.Type.REMOVE, entry.key(), null); 326 + EventuallyConsistentMapEvent.Type.REMOVE, entry.key(),
323 - notifyListeners(externalEvent); 327 + null);
328 + notifyListeners(externalEvent);
329 + }
324 } 330 }
325 } 331 }
326 332
...@@ -370,8 +376,11 @@ public class EventuallyConsistentMapImpl<K, V> ...@@ -370,8 +376,11 @@ public class EventuallyConsistentMapImpl<K, V>
370 executor.shutdown(); 376 executor.shutdown();
371 backgroundExecutor.shutdown(); 377 backgroundExecutor.shutdown();
372 378
379 + listeners.clear();
380 +
373 clusterCommunicator.removeSubscriber(updateMessageSubject); 381 clusterCommunicator.removeSubscriber(updateMessageSubject);
374 clusterCommunicator.removeSubscriber(removeMessageSubject); 382 clusterCommunicator.removeSubscriber(removeMessageSubject);
383 + clusterCommunicator.removeSubscriber(antiEntropyAdvertisementSubject);
375 } 384 }
376 385
377 private void notifyListeners(EventuallyConsistentMapEvent<K, V> event) { 386 private void notifyListeners(EventuallyConsistentMapEvent<K, V> event) {
...@@ -430,6 +439,23 @@ public class EventuallyConsistentMapImpl<K, V> ...@@ -430,6 +439,23 @@ public class EventuallyConsistentMapImpl<K, V>
430 public V setValue(V value) { 439 public V setValue(V value) {
431 throw new UnsupportedOperationException(); 440 throw new UnsupportedOperationException();
432 } 441 }
442 +
443 + @Override
444 + public boolean equals(Object o) {
445 + if (!(o instanceof Map.Entry)) {
446 + return false;
447 + }
448 +
449 + Map.Entry that = (Map.Entry) o;
450 +
451 + return Objects.equals(this.key, that.getKey()) &&
452 + Objects.equals(this.value, that.getValue());
453 + }
454 +
455 + @Override
456 + public int hashCode() {
457 + return Objects.hash(key, value);
458 + }
433 } 459 }
434 460
435 private final class SendAdvertisementTask implements Runnable { 461 private final class SendAdvertisementTask implements Runnable {
...@@ -728,12 +754,11 @@ public class EventuallyConsistentMapImpl<K, V> ...@@ -728,12 +754,11 @@ public class EventuallyConsistentMapImpl<K, V>
728 } 754 }
729 } 755 }
730 756
731 - private static final class InternalPutEvent<K, V> { 757 + static final class InternalPutEvent<K, V> {
732 private final List<PutEntry<K, V>> entries; 758 private final List<PutEntry<K, V>> entries;
733 759
734 public InternalPutEvent(K key, V value, Timestamp timestamp) { 760 public InternalPutEvent(K key, V value, Timestamp timestamp) {
735 - entries = Collections 761 + entries = ImmutableList.of(new PutEntry<>(key, value, timestamp));
736 - .singletonList(new PutEntry<>(key, value, timestamp));
737 } 762 }
738 763
739 public InternalPutEvent(List<PutEntry<K, V>> entries) { 764 public InternalPutEvent(List<PutEntry<K, V>> entries) {
...@@ -751,7 +776,7 @@ public class EventuallyConsistentMapImpl<K, V> ...@@ -751,7 +776,7 @@ public class EventuallyConsistentMapImpl<K, V>
751 } 776 }
752 } 777 }
753 778
754 - private static final class PutEntry<K, V> { 779 + static final class PutEntry<K, V> {
755 private final K key; 780 private final K key;
756 private final V value; 781 private final V value;
757 private final Timestamp timestamp; 782 private final Timestamp timestamp;
...@@ -791,12 +816,11 @@ public class EventuallyConsistentMapImpl<K, V> ...@@ -791,12 +816,11 @@ public class EventuallyConsistentMapImpl<K, V>
791 } 816 }
792 } 817 }
793 818
794 - private static final class InternalRemoveEvent<K> { 819 + static final class InternalRemoveEvent<K> {
795 private final List<RemoveEntry<K>> entries; 820 private final List<RemoveEntry<K>> entries;
796 821
797 public InternalRemoveEvent(K key, Timestamp timestamp) { 822 public InternalRemoveEvent(K key, Timestamp timestamp) {
798 - entries = Collections.singletonList( 823 + entries = ImmutableList.of(new RemoveEntry<>(key, timestamp));
799 - new RemoveEntry<>(key, timestamp));
800 } 824 }
801 825
802 public InternalRemoveEvent(List<RemoveEntry<K>> entries) { 826 public InternalRemoveEvent(List<RemoveEntry<K>> entries) {
...@@ -814,7 +838,7 @@ public class EventuallyConsistentMapImpl<K, V> ...@@ -814,7 +838,7 @@ public class EventuallyConsistentMapImpl<K, V>
814 } 838 }
815 } 839 }
816 840
817 - private static final class RemoveEntry<K> { 841 + static final class RemoveEntry<K> {
818 private final K key; 842 private final K key;
819 private final Timestamp timestamp; 843 private final Timestamp timestamp;
820 844
......