Unit tests for the distributed group store.
Change-Id: Ie8f00b9bbc1ba46a6f80e70f63d1fd853d64154b
diff --git a/core/api/src/test/java/org/onosproject/store/cluster/messaging/ClusterCommunicationServiceAdapter.java b/core/api/src/test/java/org/onosproject/store/cluster/messaging/ClusterCommunicationServiceAdapter.java
new file mode 100644
index 0000000..04f890c
--- /dev/null
+++ b/core/api/src/test/java/org/onosproject/store/cluster/messaging/ClusterCommunicationServiceAdapter.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.store.cluster.messaging;
+
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+import org.onosproject.cluster.NodeId;
+
+/**
+ * Testing adapter for the cluster communication service.
+ */
+public class ClusterCommunicationServiceAdapter
+ implements ClusterCommunicationService {
+
+ @Override
+ public void addSubscriber(MessageSubject subject,
+ ClusterMessageHandler subscriber,
+ ExecutorService executor) {
+ }
+
+ @Override
+ public void removeSubscriber(MessageSubject subject) {}
+
+ @Override
+ public <M> void broadcast(M message, MessageSubject subject,
+ Function<M, byte[]> encoder) {
+ }
+
+ @Override
+ public <M> void broadcastIncludeSelf(M message,
+ MessageSubject subject, Function<M, byte[]> encoder) {
+ }
+
+ @Override
+ public <M> CompletableFuture<Void> unicast(M message, MessageSubject subject,
+ Function<M, byte[]> encoder, NodeId toNodeId) {
+ return null;
+ }
+
+ @Override
+ public <M> void multicast(M message, MessageSubject subject,
+ Function<M, byte[]> encoder, Set<NodeId> nodes) {
+ }
+
+ @Override
+ public <M, R> CompletableFuture<R> sendAndReceive(M message,
+ MessageSubject subject, Function<M, byte[]> encoder,
+ Function<byte[], R> decoder, NodeId toNodeId) {
+ return null;
+ }
+
+ @Override
+ public <M, R> void addSubscriber(MessageSubject subject,
+ Function<byte[], M> decoder, Function<M, R> handler,
+ Function<R, byte[]> encoder, Executor executor) {
+ }
+
+ @Override
+ public <M, R> void addSubscriber(MessageSubject subject,
+ Function<byte[], M> decoder, Function<M, CompletableFuture<R>> handler,
+ Function<R, byte[]> encoder) {
+ }
+
+ @Override
+ public <M> void addSubscriber(MessageSubject subject,
+ Function<byte[], M> decoder, Consumer<M> handler,
+ Executor executor) {
+
+ }
+}
diff --git a/core/api/src/test/java/org/onosproject/store/service/TestEventuallyConsistentMap.java b/core/api/src/test/java/org/onosproject/store/service/TestEventuallyConsistentMap.java
index 5ee44c4..4f612de 100644
--- a/core/api/src/test/java/org/onosproject/store/service/TestEventuallyConsistentMap.java
+++ b/core/api/src/test/java/org/onosproject/store/service/TestEventuallyConsistentMap.java
@@ -91,7 +91,9 @@
EventuallyConsistentMapEvent<K, V> addEvent =
new EventuallyConsistentMapEvent<>(mapName, PUT, key, value);
notifyListeners(addEvent);
- peerUpdateFunction.apply(key, value);
+ if (peerUpdateFunction != null) {
+ peerUpdateFunction.apply(key, value);
+ }
}
@Override
diff --git a/core/store/dist/src/main/java/org/onosproject/store/group/impl/DistributedGroupStore.java b/core/store/dist/src/main/java/org/onosproject/store/group/impl/DistributedGroupStore.java
index a0cb189..cd42b17 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/group/impl/DistributedGroupStore.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/group/impl/DistributedGroupStore.java
@@ -1014,7 +1014,7 @@
/**
* Flattened map key to be used to store group entries.
*/
- private class GroupStoreMapKey {
+ protected static class GroupStoreMapKey {
private final DeviceId deviceId;
public GroupStoreMapKey(DeviceId deviceId) {
@@ -1047,7 +1047,7 @@
}
}
- private class GroupStoreKeyMapKey extends GroupStoreMapKey {
+ protected static class GroupStoreKeyMapKey extends GroupStoreMapKey {
private final GroupKey appCookie;
public GroupStoreKeyMapKey(DeviceId deviceId,
GroupKey appCookie) {
@@ -1078,7 +1078,7 @@
}
}
- private class GroupStoreIdMapKey extends GroupStoreMapKey {
+ protected static class GroupStoreIdMapKey extends GroupStoreMapKey {
private final GroupId groupId;
public GroupStoreIdMapKey(DeviceId deviceId,
GroupId groupId) {
diff --git a/core/store/dist/src/test/java/org/onosproject/store/ecmap/EventuallyConsistentMapImplTest.java b/core/store/dist/src/test/java/org/onosproject/store/ecmap/EventuallyConsistentMapImplTest.java
index b5696a2..ccf6ee7 100644
--- a/core/store/dist/src/test/java/org/onosproject/store/ecmap/EventuallyConsistentMapImplTest.java
+++ b/core/store/dist/src/test/java/org/onosproject/store/ecmap/EventuallyConsistentMapImplTest.java
@@ -15,10 +15,22 @@
*/
package org.onosproject.store.ecmap;
-import com.google.common.collect.ComparisonChain;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.util.concurrent.MoreExecutors;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.Consumer;
+import java.util.function.Function;
import org.junit.After;
import org.junit.Before;
@@ -32,38 +44,35 @@
import org.onosproject.event.AbstractEvent;
import org.onosproject.store.Timestamp;
import org.onosproject.store.cluster.messaging.ClusterCommunicationService;
-import org.onosproject.store.cluster.messaging.ClusterMessageHandler;
+import org.onosproject.store.cluster.messaging.ClusterCommunicationServiceAdapter;
import org.onosproject.store.cluster.messaging.MessageSubject;
import org.onosproject.store.impl.LogicalTimestamp;
-import org.onosproject.store.service.WallClockTimestamp;
import org.onosproject.store.serializers.KryoNamespaces;
import org.onosproject.store.serializers.KryoSerializer;
import org.onosproject.store.service.EventuallyConsistentMap;
import org.onosproject.store.service.EventuallyConsistentMapEvent;
import org.onosproject.store.service.EventuallyConsistentMapListener;
+import org.onosproject.store.service.WallClockTimestamp;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.Set;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.Executor;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.function.Consumer;
-import java.util.function.Function;
+import com.google.common.collect.ComparisonChain;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.util.concurrent.MoreExecutors;
import static com.google.common.base.Preconditions.checkArgument;
import static junit.framework.TestCase.assertFalse;
-import static org.easymock.EasyMock.*;
-import static org.junit.Assert.*;
+import static org.easymock.EasyMock.anyObject;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.eq;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.reset;
+import static org.easymock.EasyMock.verify;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
/**
* Unit tests for EventuallyConsistentMapImpl.
@@ -697,7 +706,7 @@
* Sets up a mock ClusterCommunicationService to expect a specific cluster
* message to be broadcast to the cluster.
*
- * @param m message we expect to be sent
+ * @param message message we expect to be sent
* @param clusterCommunicator a mock ClusterCommunicationService to set up
*/
//FIXME rename
@@ -776,56 +785,7 @@
* events coming in from other instances.
*/
private final class TestClusterCommunicationService
- implements ClusterCommunicationService {
-
- @Override
- public void addSubscriber(MessageSubject subject,
- ClusterMessageHandler subscriber,
- ExecutorService executor) {
- }
-
- @Override
- public void removeSubscriber(MessageSubject subject) {}
-
- @Override
- public <M> void broadcast(M message, MessageSubject subject,
- Function<M, byte[]> encoder) {
- }
-
- @Override
- public <M> void broadcastIncludeSelf(M message,
- MessageSubject subject, Function<M, byte[]> encoder) {
- }
-
- @Override
- public <M> CompletableFuture<Void> unicast(M message, MessageSubject subject,
- Function<M, byte[]> encoder, NodeId toNodeId) {
- return null;
- }
-
- @Override
- public <M> void multicast(M message, MessageSubject subject,
- Function<M, byte[]> encoder, Set<NodeId> nodes) {
- }
-
- @Override
- public <M, R> CompletableFuture<R> sendAndReceive(M message,
- MessageSubject subject, Function<M, byte[]> encoder,
- Function<byte[], R> decoder, NodeId toNodeId) {
- return null;
- }
-
- @Override
- public <M, R> void addSubscriber(MessageSubject subject,
- Function<byte[], M> decoder, Function<M, R> handler,
- Function<R, byte[]> encoder, Executor executor) {
- }
-
- @Override
- public <M, R> void addSubscriber(MessageSubject subject,
- Function<byte[], M> decoder, Function<M, CompletableFuture<R>> handler,
- Function<R, byte[]> encoder) {
- }
+ extends ClusterCommunicationServiceAdapter {
@Override
public <M> void addSubscriber(MessageSubject subject,
diff --git a/core/store/dist/src/test/java/org/onosproject/store/group/impl/DistributedGroupStoreTest.java b/core/store/dist/src/test/java/org/onosproject/store/group/impl/DistributedGroupStoreTest.java
new file mode 100644
index 0000000..560fdb3
--- /dev/null
+++ b/core/store/dist/src/test/java/org/onosproject/store/group/impl/DistributedGroupStoreTest.java
@@ -0,0 +1,420 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.store.group.impl;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.junit.TestUtils;
+import org.onosproject.core.DefaultGroupId;
+import org.onosproject.core.GroupId;
+import org.onosproject.mastership.MastershipServiceAdapter;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.MastershipRole;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.group.DefaultGroup;
+import org.onosproject.net.group.DefaultGroupBucket;
+import org.onosproject.net.group.DefaultGroupDescription;
+import org.onosproject.net.group.DefaultGroupKey;
+import org.onosproject.net.group.Group;
+import org.onosproject.net.group.GroupBucket;
+import org.onosproject.net.group.GroupBuckets;
+import org.onosproject.net.group.GroupDescription;
+import org.onosproject.net.group.GroupEvent;
+import org.onosproject.net.group.GroupKey;
+import org.onosproject.net.group.GroupOperation;
+import org.onosproject.net.group.GroupStore;
+import org.onosproject.net.group.GroupStoreDelegate;
+import org.onosproject.store.cluster.messaging.ClusterCommunicationServiceAdapter;
+import org.onosproject.store.service.EventuallyConsistentMap;
+import org.onosproject.store.service.TestStorageService;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.common.testing.EqualsTester;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.hasSize;
+import static org.hamcrest.Matchers.instanceOf;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.hamcrest.Matchers.nullValue;
+import static org.onosproject.net.NetTestTools.APP_ID;
+import static org.onosproject.net.NetTestTools.did;
+
+/**
+ * Distributed group store test.
+ */
+public class DistributedGroupStoreTest {
+
+ DeviceId deviceId1 = did("dev1");
+ DeviceId deviceId2 = did("dev2");
+ GroupId groupId1 = new DefaultGroupId(1);
+ GroupId groupId2 = new DefaultGroupId(2);
+ GroupKey groupKey1 = new DefaultGroupKey("abc".getBytes());
+ GroupKey groupKey2 = new DefaultGroupKey("def".getBytes());
+
+ TrafficTreatment treatment =
+ DefaultTrafficTreatment.emptyTreatment();
+ GroupBucket selectGroupBucket =
+ DefaultGroupBucket.createSelectGroupBucket(treatment);
+ GroupBucket failoverGroupBucket =
+ DefaultGroupBucket.createFailoverGroupBucket(treatment,
+ PortNumber.IN_PORT, groupId1);
+
+ GroupBuckets buckets = new GroupBuckets(ImmutableList.of(selectGroupBucket));
+ GroupDescription groupDescription1 = new DefaultGroupDescription(
+ deviceId1,
+ GroupDescription.Type.INDIRECT,
+ buckets,
+ groupKey1,
+ groupId1.id(),
+ APP_ID);
+ GroupDescription groupDescription2 = new DefaultGroupDescription(
+ deviceId2,
+ GroupDescription.Type.INDIRECT,
+ buckets,
+ groupKey2,
+ groupId2.id(),
+ APP_ID);
+
+ DistributedGroupStore groupStoreImpl;
+ GroupStore groupStore;
+ EventuallyConsistentMap auditPendingReqQueue;
+
+ static class MasterOfAll extends MastershipServiceAdapter {
+ @Override
+ public MastershipRole getLocalRole(DeviceId deviceId) {
+ return MastershipRole.MASTER;
+ }
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ groupStoreImpl = new DistributedGroupStore();
+ groupStoreImpl.storageService = new TestStorageService();
+ groupStoreImpl.clusterCommunicator = new ClusterCommunicationServiceAdapter();
+ groupStoreImpl.mastershipService = new MasterOfAll();
+ groupStoreImpl.activate();
+ groupStore = groupStoreImpl;
+ auditPendingReqQueue =
+ TestUtils.getField(groupStoreImpl, "auditPendingReqQueue");
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ groupStoreImpl.deactivate();
+ }
+
+ /**
+ * Tests the initial state of the store.
+ */
+ @Test
+ public void testEmptyStore() {
+ assertThat(groupStore.getGroupCount(deviceId1), is(0));
+ assertThat(groupStore.getGroup(deviceId1, groupId1), nullValue());
+ assertThat(groupStore.getGroup(deviceId1, groupKey1), nullValue());
+ }
+
+ /**
+ * Tests adding a pending group.
+ */
+ @Test
+ public void testAddPendingGroup() throws Exception {
+ // Make sure the pending list starts out empty
+ assertThat(auditPendingReqQueue.size(), is(0));
+
+ // Add a new pending group. Make sure that the store remains empty
+ groupStore.storeGroupDescription(groupDescription1);
+ assertThat(groupStore.getGroupCount(deviceId1), is(0));
+ assertThat(groupStore.getGroup(deviceId1, groupId1), nullValue());
+ assertThat(groupStore.getGroup(deviceId1, groupKey1), nullValue());
+
+ // Make sure the group is pending
+ assertThat(auditPendingReqQueue.size(), is(1));
+
+ groupStore.deviceInitialAuditCompleted(deviceId1, true);
+
+ // Make sure the group isn't pending anymore
+ assertThat(auditPendingReqQueue.size(), is(0));
+ }
+
+
+ /**
+ * Tests adding and removing a group.
+ */
+ @Test
+ public void testAddRemoveGroup() throws Exception {
+ groupStore.deviceInitialAuditCompleted(deviceId1, true);
+ assertThat(groupStore.deviceInitialAuditStatus(deviceId1), is(true));
+
+ // Make sure the pending list starts out empty
+ assertThat(auditPendingReqQueue.size(), is(0));
+
+ groupStore.storeGroupDescription(groupDescription1);
+ assertThat(groupStore.getGroupCount(deviceId1), is(1));
+ assertThat(groupStore.getGroup(deviceId1, groupId1), notNullValue());
+ assertThat(groupStore.getGroup(deviceId1, groupKey1), notNullValue());
+
+ // Make sure that nothing is pending
+ assertThat(auditPendingReqQueue.size(), is(0));
+
+ Group groupById = groupStore.getGroup(deviceId1, groupId1);
+ Group groupByKey = groupStore.getGroup(deviceId1, groupKey1);
+ assertThat(groupById, notNullValue());
+ assertThat(groupByKey, notNullValue());
+ assertThat(groupById, is(groupByKey));
+ assertThat(groupById.deviceId(), is(did("dev1")));
+
+ groupStore.removeGroupEntry(groupById);
+
+ assertThat(groupStore.getGroupCount(deviceId1), is(0));
+ assertThat(groupStore.getGroup(deviceId1, groupId1), nullValue());
+ assertThat(groupStore.getGroup(deviceId1, groupKey1), nullValue());
+
+ // Make sure that nothing is pending
+ assertThat(auditPendingReqQueue.size(), is(0));
+ }
+
+ /**
+ * Tests adding and removing a group.
+ */
+ @Test
+ public void testRemoveGroupDescription() throws Exception {
+ groupStore.deviceInitialAuditCompleted(deviceId1, true);
+
+ groupStore.storeGroupDescription(groupDescription1);
+
+ groupStore.deleteGroupDescription(deviceId1, groupKey1);
+
+ // Group should still be there, marked for removal
+ assertThat(groupStore.getGroupCount(deviceId1), is(1));
+ Group queriedGroup = groupStore.getGroup(deviceId1, groupId1);
+ assertThat(queriedGroup.state(), is(Group.GroupState.PENDING_DELETE));
+
+ }
+
+ /**
+ * Tests pushing group metrics.
+ */
+ @Test
+ public void testPushGroupMetrics() {
+ groupStore.deviceInitialAuditCompleted(deviceId1, true);
+ groupStore.deviceInitialAuditCompleted(deviceId2, true);
+
+ GroupDescription groupDescription3 = new DefaultGroupDescription(
+ deviceId1,
+ GroupDescription.Type.SELECT,
+ buckets,
+ new DefaultGroupKey("aaa".getBytes()),
+ null,
+ APP_ID);
+
+ groupStore.storeGroupDescription(groupDescription1);
+ groupStore.storeGroupDescription(groupDescription2);
+ groupStore.storeGroupDescription(groupDescription3);
+ Group group1 = groupStore.getGroup(deviceId1, groupId1);
+
+ assertThat(group1, instanceOf(DefaultGroup.class));
+ DefaultGroup defaultGroup1 = (DefaultGroup) group1;
+ defaultGroup1.setPackets(55L);
+ defaultGroup1.setBytes(66L);
+ groupStore.pushGroupMetrics(deviceId1, ImmutableList.of(group1));
+
+ // Make sure the group was updated.
+
+ Group requeryGroup1 = groupStore.getGroup(deviceId1, groupId1);
+ assertThat(requeryGroup1.packets(), is(55L));
+ assertThat(requeryGroup1.bytes(), is(66L));
+
+ }
+
+ class TestDelegate implements GroupStoreDelegate {
+ private List<GroupEvent> eventsSeen = new LinkedList<>();
+ @Override
+ public void notify(GroupEvent event) {
+ eventsSeen.add(event);
+ }
+
+ public List<GroupEvent> eventsSeen() {
+ return eventsSeen;
+ }
+
+ public void resetEvents() {
+ eventsSeen.clear();
+ }
+ }
+
+ /**
+ * Tests group operation failed interface.
+ */
+ @Test
+ public void testGroupOperationFailed() {
+ TestDelegate delegate = new TestDelegate();
+ groupStore.setDelegate(delegate);
+ groupStore.deviceInitialAuditCompleted(deviceId1, true);
+ groupStore.deviceInitialAuditCompleted(deviceId2, true);
+
+ groupStore.storeGroupDescription(groupDescription1);
+ groupStore.storeGroupDescription(groupDescription2);
+
+ List<GroupEvent> eventsAfterAdds = delegate.eventsSeen();
+ assertThat(eventsAfterAdds, hasSize(2));
+ eventsAfterAdds.stream().forEach(event -> assertThat(event.type(), is(GroupEvent.Type.GROUP_ADD_REQUESTED)));
+ delegate.resetEvents();
+
+ GroupOperation opAdd =
+ GroupOperation.createAddGroupOperation(groupId1,
+ GroupDescription.Type.INDIRECT,
+ buckets);
+ groupStore.groupOperationFailed(deviceId1, opAdd);
+
+ List<GroupEvent> eventsAfterAddFailed = delegate.eventsSeen();
+ assertThat(eventsAfterAddFailed, hasSize(2));
+ assertThat(eventsAfterAddFailed.get(0).type(),
+ is(GroupEvent.Type.GROUP_ADD_FAILED));
+ assertThat(eventsAfterAddFailed.get(1).type(),
+ is(GroupEvent.Type.GROUP_REMOVED));
+ delegate.resetEvents();
+
+ GroupOperation opModify =
+ GroupOperation.createModifyGroupOperation(groupId2,
+ GroupDescription.Type.INDIRECT,
+ buckets);
+ groupStore.groupOperationFailed(deviceId2, opModify);
+ List<GroupEvent> eventsAfterModifyFailed = delegate.eventsSeen();
+ assertThat(eventsAfterModifyFailed, hasSize(1));
+ assertThat(eventsAfterModifyFailed.get(0).type(),
+ is(GroupEvent.Type.GROUP_UPDATE_FAILED));
+ delegate.resetEvents();
+
+ GroupOperation opDelete =
+ GroupOperation.createDeleteGroupOperation(groupId2,
+ GroupDescription.Type.INDIRECT);
+ groupStore.groupOperationFailed(deviceId2, opDelete);
+ List<GroupEvent> eventsAfterDeleteFailed = delegate.eventsSeen();
+ assertThat(eventsAfterDeleteFailed, hasSize(1));
+ assertThat(eventsAfterDeleteFailed.get(0).type(),
+ is(GroupEvent.Type.GROUP_REMOVE_FAILED));
+ delegate.resetEvents();
+ }
+
+ /**
+ * Tests extraneous group operations.
+ */
+ @Test
+ public void testExtraneousOperations() {
+ ArrayList<Group> extraneous;
+ groupStore.deviceInitialAuditCompleted(deviceId1, true);
+
+ groupStore.storeGroupDescription(groupDescription1);
+ Group group1 = groupStore.getGroup(deviceId1, groupId1);
+
+ extraneous = Lists.newArrayList(groupStore.getExtraneousGroups(deviceId1));
+ assertThat(extraneous, hasSize(0));
+
+ groupStore.addOrUpdateExtraneousGroupEntry(group1);
+ extraneous = Lists.newArrayList(groupStore.getExtraneousGroups(deviceId1));
+ assertThat(extraneous, hasSize(1));
+
+ groupStore.removeExtraneousGroupEntry(group1);
+ extraneous = Lists.newArrayList(groupStore.getExtraneousGroups(deviceId1));
+ assertThat(extraneous, hasSize(0));
+ }
+
+ /**
+ * Tests updating of group descriptions.
+ */
+ @Test
+ public void testUpdateGroupDescription() {
+
+ GroupBuckets buckets =
+ new GroupBuckets(ImmutableList.of(failoverGroupBucket));
+
+ groupStore.deviceInitialAuditCompleted(deviceId1, true);
+ groupStore.storeGroupDescription(groupDescription1);
+
+ GroupKey newKey = new DefaultGroupKey("123".getBytes());
+ groupStore.updateGroupDescription(deviceId1,
+ groupKey1,
+ GroupStore.UpdateType.ADD,
+ buckets,
+ newKey);
+ Group group1 = groupStore.getGroup(deviceId1, groupId1);
+ assertThat(group1.appCookie(), is(newKey));
+ assertThat(group1.buckets().buckets(), hasSize(2));
+ }
+
+ @Test
+ public void testEqualsGroupStoreIdMapKey() {
+ DistributedGroupStore.GroupStoreIdMapKey key1 =
+ new DistributedGroupStore.GroupStoreIdMapKey(deviceId1, groupId1);
+ DistributedGroupStore.GroupStoreIdMapKey sameAsKey1 =
+ new DistributedGroupStore.GroupStoreIdMapKey(deviceId1, groupId1);
+ DistributedGroupStore.GroupStoreIdMapKey key2 =
+ new DistributedGroupStore.GroupStoreIdMapKey(deviceId2, groupId1);
+ DistributedGroupStore.GroupStoreIdMapKey key3 =
+ new DistributedGroupStore.GroupStoreIdMapKey(deviceId1, groupId2);
+
+ new EqualsTester()
+ .addEqualityGroup(key1, sameAsKey1)
+ .addEqualityGroup(key2)
+ .addEqualityGroup(key3)
+ .testEquals();
+ }
+
+ @Test
+ public void testEqualsGroupStoreKeyMapKey() {
+ DistributedGroupStore.GroupStoreKeyMapKey key1 =
+ new DistributedGroupStore.GroupStoreKeyMapKey(deviceId1, groupKey1);
+ DistributedGroupStore.GroupStoreKeyMapKey sameAsKey1 =
+ new DistributedGroupStore.GroupStoreKeyMapKey(deviceId1, groupKey1);
+ DistributedGroupStore.GroupStoreKeyMapKey key2 =
+ new DistributedGroupStore.GroupStoreKeyMapKey(deviceId2, groupKey1);
+ DistributedGroupStore.GroupStoreKeyMapKey key3 =
+ new DistributedGroupStore.GroupStoreKeyMapKey(deviceId1, groupKey2);
+
+ new EqualsTester()
+ .addEqualityGroup(key1, sameAsKey1)
+ .addEqualityGroup(key2)
+ .addEqualityGroup(key3)
+ .testEquals();
+ }
+
+ @Test
+ public void testEqualsGroupStoreMapKey() {
+ DistributedGroupStore.GroupStoreMapKey key1 =
+ new DistributedGroupStore.GroupStoreMapKey(deviceId1);
+ DistributedGroupStore.GroupStoreMapKey sameAsKey1 =
+ new DistributedGroupStore.GroupStoreMapKey(deviceId1);
+ DistributedGroupStore.GroupStoreMapKey key2 =
+ new DistributedGroupStore.GroupStoreMapKey(deviceId2);
+ DistributedGroupStore.GroupStoreMapKey key3 =
+ new DistributedGroupStore.GroupStoreMapKey(did("dev3"));
+
+ new EqualsTester()
+ .addEqualityGroup(key1, sameAsKey1)
+ .addEqualityGroup(key2)
+ .addEqualityGroup(key3)
+ .testEquals();
+ }
+}