ONOS-985: Sample integration test application for group subsystem
Change-Id: I68352f922e5c7a0800fcc4fa839955769bf925a6
diff --git a/core/net/src/main/java/org/onosproject/net/group/impl/GroupManager.java b/core/net/src/main/java/org/onosproject/net/group/impl/GroupManager.java
index 4cb21e5..1490b0b 100644
--- a/core/net/src/main/java/org/onosproject/net/group/impl/GroupManager.java
+++ b/core/net/src/main/java/org/onosproject/net/group/impl/GroupManager.java
@@ -32,6 +32,9 @@
import org.onosproject.event.AbstractListenerRegistry;
import org.onosproject.event.EventDeliveryService;
import org.onosproject.net.DeviceId;
+import org.onosproject.net.device.DeviceEvent;
+import org.onosproject.net.device.DeviceListener;
+import org.onosproject.net.device.DeviceService;
import org.onosproject.net.group.Group;
import org.onosproject.net.group.GroupBuckets;
import org.onosproject.net.group.GroupDescription;
@@ -67,17 +70,22 @@
private final AbstractListenerRegistry<GroupEvent, GroupListener>
listenerRegistry = new AbstractListenerRegistry<>();
private final GroupStoreDelegate delegate = new InternalGroupStoreDelegate();
+ private final DeviceListener deviceListener = new InternalDeviceListener();
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected GroupStore store;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected DeviceService deviceService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected EventDeliveryService eventDispatcher;
@Activate
public void activate() {
store.setDelegate(delegate);
eventDispatcher.addSink(GroupEvent.class, listenerRegistry);
+ deviceService.addListener(deviceListener);
log.info("Started");
}
@@ -232,6 +240,8 @@
GroupOperations groupOps = null;
switch (event.type()) {
case GROUP_ADD_REQUESTED:
+ log.debug("GROUP_ADD_REQUESTED for Group {} on device {}",
+ group.id(), group.deviceId());
GroupOperation groupAddOp = GroupOperation.
createAddGroupOperation(group.id(),
group.type(),
@@ -242,6 +252,8 @@
break;
case GROUP_UPDATE_REQUESTED:
+ log.debug("GROUP_UPDATE_REQUESTED for Group {} on device {}",
+ group.id(), group.deviceId());
GroupOperation groupModifyOp = GroupOperation.
createModifyGroupOperation(group.id(),
group.type(),
@@ -252,6 +264,8 @@
break;
case GROUP_REMOVE_REQUESTED:
+ log.debug("GROUP_REMOVE_REQUESTED for Group {} on device {}",
+ group.id(), group.deviceId());
GroupOperation groupDeleteOp = GroupOperation.
createDeleteGroupOperation(group.id(),
group.type());
@@ -294,10 +308,14 @@
GroupProvider gp = getProvider(group.deviceId());
switch (group.state()) {
case PENDING_DELETE:
+ log.debug("Group {} delete confirmation from device {}",
+ group, group.deviceId());
store.removeGroupEntry(group);
break;
case ADDED:
case PENDING_ADD:
+ log.debug("Group {} is in store but not on device {}",
+ group, group.deviceId());
GroupOperation groupAddOp = GroupOperation.
createAddGroupOperation(group.id(),
group.type(),
@@ -314,7 +332,8 @@
private void extraneousGroup(Group group) {
- log.debug("Group {} is on switch but not in store.", group);
+ log.debug("Group {} is on device {} but not in store.",
+ group, group.deviceId());
checkValidity();
store.addOrUpdateExtraneousGroupEntry(group);
}
@@ -322,13 +341,16 @@
private void groupAdded(Group group) {
checkValidity();
- log.trace("Group {}", group);
+ log.trace("Group {} Added or Updated in device {}",
+ group, group.deviceId());
store.addOrUpdateGroupEntry(group);
}
@Override
public void pushGroupMetrics(DeviceId deviceId,
Collection<Group> groupEntries) {
+ log.trace("Received group metrics from device {}",
+ deviceId);
boolean deviceInitialAuditStatus =
store.deviceInitialAuditStatus(deviceId);
Set<Group> southboundGroupEntries =
@@ -338,31 +360,75 @@
Set<Group> extraneousStoredEntries =
Sets.newHashSet(store.getExtraneousGroups(deviceId));
+ log.trace("Displaying all southboundGroupEntries for device {}", deviceId);
+ for (Iterator<Group> it = southboundGroupEntries.iterator(); it.hasNext();) {
+ Group group = it.next();
+ log.trace("Group {} in device {}", group, deviceId);
+ }
+
+ log.trace("Displaying all stored group entries for device {}", deviceId);
+ for (Iterator<Group> it = storedGroupEntries.iterator(); it.hasNext();) {
+ Group group = it.next();
+ log.trace("Stored Group {} for device {}", group, deviceId);
+ }
+
for (Iterator<Group> it = southboundGroupEntries.iterator(); it.hasNext();) {
Group group = it.next();
if (storedGroupEntries.remove(group)) {
// we both have the group, let's update some info then.
+ log.trace("Group AUDIT: group {} exists "
+ + "in both planes for device {}",
+ group.id(), deviceId);
groupAdded(group);
it.remove();
}
}
for (Group group : southboundGroupEntries) {
// there are groups in the switch that aren't in the store
+ log.trace("Group AUDIT: extraneous group {} exists "
+ + "in data plane for device {}",
+ group.id(), deviceId);
extraneousStoredEntries.remove(group);
extraneousGroup(group);
}
for (Group group : storedGroupEntries) {
// there are groups in the store that aren't in the switch
+ log.trace("Group AUDIT: group {} missing "
+ + "in data plane for device {}",
+ group.id(), deviceId);
groupMissing(group);
}
for (Group group : extraneousStoredEntries) {
// there are groups in the extraneous store that
// aren't in the switch
+ log.trace("Group AUDIT: clearing extransoeus group {} "
+ + "from store for device {}",
+ group.id(), deviceId);
store.removeExtraneousGroupEntry(group);
}
if (!deviceInitialAuditStatus) {
- store.deviceInitialAuditCompleted(deviceId);
+ log.debug("Group AUDIT: Setting device {} initial "
+ + "AUDIT completed", deviceId);
+ store.deviceInitialAuditCompleted(deviceId, true);
+ }
+ }
+ }
+
+ private class InternalDeviceListener implements DeviceListener {
+
+ @Override
+ public void event(DeviceEvent event) {
+ switch (event.type()) {
+ case DEVICE_REMOVED:
+ log.debug("Clearing device {} initial "
+ + "AUDIT completed status as device is going down",
+ event.subject().id());
+ store.deviceInitialAuditCompleted(event.subject().id(), false);
+ break;
+
+ default:
+ break;
}
}
}
diff --git a/core/net/src/test/java/org/onosproject/net/group/impl/GroupManagerTest.java b/core/net/src/test/java/org/onosproject/net/group/impl/GroupManagerTest.java
index 7099464..2fe5e4b 100644
--- a/core/net/src/test/java/org/onosproject/net/group/impl/GroupManagerTest.java
+++ b/core/net/src/test/java/org/onosproject/net/group/impl/GroupManagerTest.java
@@ -32,6 +32,7 @@
import org.onosproject.event.impl.TestEventDispatcher;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
+import org.onosproject.net.device.impl.DeviceManager;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.group.DefaultGroup;
@@ -81,6 +82,7 @@
public void setUp() {
mgr = new GroupManager();
groupService = mgr;
+ mgr.deviceService = new DeviceManager();
mgr.store = new SimpleGroupStore();
mgr.eventDispatcher = new TestEventDispatcher();
providerRegistry = mgr;
@@ -147,11 +149,34 @@
*/
@Test
public void testGroupService() {
+ // Test Group creation before AUDIT process
+ testGroupCreationBeforeAudit();
+
+ // Test initial group audit process
+ testInitialAuditWithPendingGroupRequests();
+
+ // Test audit with extraneous and missing groups
+ testAuditWithExtraneousMissingGroups();
+
+ // Test audit with confirmed groups
+ testAuditWithConfirmedGroups();
+
+ // Test group add bucket operations
+ testAddBuckets();
+
+ // Test group remove bucket operations
+ testRemoveBuckets();
+
+ // Test group remove operations
+ testRemoveGroup();
+ }
+
+ // Test Group creation before AUDIT process
+ private void testGroupCreationBeforeAudit() {
PortNumber[] ports1 = {PortNumber.portNumber(31),
PortNumber.portNumber(32)};
PortNumber[] ports2 = {PortNumber.portNumber(41),
PortNumber.portNumber(42)};
- // Test Group creation before AUDIT process
TestGroupKey key = new TestGroupKey("group1BeforeAudit");
List<GroupBucket> buckets = new ArrayList<GroupBucket>();
List<PortNumber> outPorts = new ArrayList<PortNumber>();
@@ -177,8 +202,14 @@
internalProvider.validate(DID, null);
assertEquals(null, groupService.getGroup(DID, key));
assertEquals(0, Iterables.size(groupService.getGroups(DID, appId)));
+ }
- // Test initial group audit process
+ // Test initial AUDIT process with pending group requests
+ private void testInitialAuditWithPendingGroupRequests() {
+ PortNumber[] ports1 = {PortNumber.portNumber(31),
+ PortNumber.portNumber(32)};
+ PortNumber[] ports2 = {PortNumber.portNumber(41),
+ PortNumber.portNumber(42)};
GroupId gId1 = new DefaultGroupId(1);
Group group1 = createSouthboundGroupEntry(gId1,
Arrays.asList(ports1),
@@ -193,50 +224,76 @@
providerService.pushGroupMetrics(DID, groupEntries);
// First group metrics would trigger the device audit completion
// post which all pending group requests are also executed.
+ TestGroupKey key = new TestGroupKey("group1BeforeAudit");
Group createdGroup = groupService.getGroup(DID, key);
int createdGroupId = createdGroup.id().id();
assertNotEquals(gId1.id(), createdGroupId);
assertNotEquals(gId2.id(), createdGroupId);
+
List<GroupOperation> expectedGroupOps = Arrays.asList(
GroupOperation.createDeleteGroupOperation(gId1,
Group.Type.SELECT),
GroupOperation.createAddGroupOperation(
createdGroup.id(),
Group.Type.SELECT,
- groupBuckets));
+ createdGroup.buckets()));
internalProvider.validate(DID, expectedGroupOps);
+ }
- group1 = createSouthboundGroupEntry(gId1,
+ // Test AUDIT process with extraneous groups and missing groups
+ private void testAuditWithExtraneousMissingGroups() {
+ PortNumber[] ports1 = {PortNumber.portNumber(31),
+ PortNumber.portNumber(32)};
+ PortNumber[] ports2 = {PortNumber.portNumber(41),
+ PortNumber.portNumber(42)};
+ GroupId gId1 = new DefaultGroupId(1);
+ Group group1 = createSouthboundGroupEntry(gId1,
Arrays.asList(ports1),
0);
- group2 = createSouthboundGroupEntry(gId2,
+ GroupId gId2 = new DefaultGroupId(2);
+ Group group2 = createSouthboundGroupEntry(gId2,
Arrays.asList(ports2),
0);
- groupEntries = Arrays.asList(group1, group2);
+ List<Group> groupEntries = Arrays.asList(group1, group2);
providerService.pushGroupMetrics(DID, groupEntries);
- expectedGroupOps = Arrays.asList(
+ TestGroupKey key = new TestGroupKey("group1BeforeAudit");
+ Group createdGroup = groupService.getGroup(DID, key);
+ List<GroupOperation> expectedGroupOps = Arrays.asList(
GroupOperation.createDeleteGroupOperation(gId1,
Group.Type.SELECT),
GroupOperation.createDeleteGroupOperation(gId2,
Group.Type.SELECT),
GroupOperation.createAddGroupOperation(createdGroup.id(),
Group.Type.SELECT,
- groupBuckets));
+ createdGroup.buckets()));
internalProvider.validate(DID, expectedGroupOps);
+ }
+ // Test AUDIT with confirmed groups
+ private void testAuditWithConfirmedGroups() {
+ TestGroupKey key = new TestGroupKey("group1BeforeAudit");
+ Group createdGroup = groupService.getGroup(DID, key);
createdGroup = new DefaultGroup(createdGroup.id(),
DID,
Group.Type.SELECT,
- groupBuckets);
- groupEntries = Arrays.asList(createdGroup);
+ createdGroup.buckets());
+ List<Group> groupEntries = Arrays.asList(createdGroup);
providerService.pushGroupMetrics(DID, groupEntries);
internalListener.validateEvent(Arrays.asList(GroupEvent.Type.GROUP_ADDED));
+ }
- // Test group add bucket operations
+ // Test group add bucket operations
+ private void testAddBuckets() {
TestGroupKey addKey = new TestGroupKey("group1AddBuckets");
+
+ TestGroupKey prevKey = new TestGroupKey("group1BeforeAudit");
+ Group createdGroup = groupService.getGroup(DID, prevKey);
+ List<GroupBucket> buckets = new ArrayList<GroupBucket>();
+ buckets.addAll(createdGroup.buckets().buckets());
+
PortNumber[] addPorts = {PortNumber.portNumber(51),
PortNumber.portNumber(52)};
- outPorts.clear();
+ List<PortNumber> outPorts = new ArrayList<PortNumber>();
outPorts.addAll(Arrays.asList(addPorts));
List<GroupBucket> addBuckets = new ArrayList<GroupBucket>();
for (PortNumber portNumber: outPorts) {
@@ -253,26 +310,34 @@
}
GroupBuckets groupAddBuckets = new GroupBuckets(addBuckets);
groupService.addBucketsToGroup(DID,
- key,
+ prevKey,
groupAddBuckets,
addKey,
appId);
GroupBuckets updatedBuckets = new GroupBuckets(buckets);
- expectedGroupOps = Arrays.asList(
+ List<GroupOperation> expectedGroupOps = Arrays.asList(
GroupOperation.createModifyGroupOperation(createdGroup.id(),
Group.Type.SELECT,
updatedBuckets));
internalProvider.validate(DID, expectedGroupOps);
Group existingGroup = groupService.getGroup(DID, addKey);
- groupEntries = Arrays.asList(existingGroup);
+ List<Group> groupEntries = Arrays.asList(existingGroup);
providerService.pushGroupMetrics(DID, groupEntries);
internalListener.validateEvent(Arrays.asList(GroupEvent.Type.GROUP_UPDATED));
+ }
- // Test group remove bucket operations
+ // Test group remove bucket operations
+ private void testRemoveBuckets() {
TestGroupKey removeKey = new TestGroupKey("group1RemoveBuckets");
+
+ TestGroupKey prevKey = new TestGroupKey("group1AddBuckets");
+ Group createdGroup = groupService.getGroup(DID, prevKey);
+ List<GroupBucket> buckets = new ArrayList<GroupBucket>();
+ buckets.addAll(createdGroup.buckets().buckets());
+
PortNumber[] removePorts = {PortNumber.portNumber(31),
PortNumber.portNumber(32)};
- outPorts.clear();
+ List<PortNumber> outPorts = new ArrayList<PortNumber>();
outPorts.addAll(Arrays.asList(removePorts));
List<GroupBucket> removeBuckets = new ArrayList<GroupBucket>();
for (PortNumber portNumber: outPorts) {
@@ -289,28 +354,32 @@
}
GroupBuckets groupRemoveBuckets = new GroupBuckets(removeBuckets);
groupService.removeBucketsFromGroup(DID,
- addKey,
+ prevKey,
groupRemoveBuckets,
removeKey,
appId);
- updatedBuckets = new GroupBuckets(buckets);
- expectedGroupOps = Arrays.asList(
+ GroupBuckets updatedBuckets = new GroupBuckets(buckets);
+ List<GroupOperation> expectedGroupOps = Arrays.asList(
GroupOperation.createModifyGroupOperation(createdGroup.id(),
Group.Type.SELECT,
updatedBuckets));
internalProvider.validate(DID, expectedGroupOps);
- existingGroup = groupService.getGroup(DID, removeKey);
- groupEntries = Arrays.asList(existingGroup);
+ Group existingGroup = groupService.getGroup(DID, removeKey);
+ List<Group> groupEntries = Arrays.asList(existingGroup);
providerService.pushGroupMetrics(DID, groupEntries);
internalListener.validateEvent(Arrays.asList(GroupEvent.Type.GROUP_UPDATED));
+ }
- // Test group remove operations
- groupService.removeGroup(DID, removeKey, appId);
- expectedGroupOps = Arrays.asList(
- GroupOperation.createDeleteGroupOperation(createdGroup.id(),
+ // Test group remove operations
+ private void testRemoveGroup() {
+ TestGroupKey currKey = new TestGroupKey("group1RemoveBuckets");
+ Group existingGroup = groupService.getGroup(DID, currKey);
+ groupService.removeGroup(DID, currKey, appId);
+ List<GroupOperation> expectedGroupOps = Arrays.asList(
+ GroupOperation.createDeleteGroupOperation(existingGroup.id(),
Group.Type.SELECT));
internalProvider.validate(DID, expectedGroupOps);
- groupEntries = Collections.emptyList();
+ List<Group> groupEntries = Collections.emptyList();
providerService.pushGroupMetrics(DID, groupEntries);
internalListener.validateEvent(Arrays.asList(GroupEvent.Type.GROUP_REMOVED));
}