ONOS-6151 Add group behavior in case of device master "null" is made inline with flow subsystem. i.e. group add is allowed when master is null, this gets added to the pending audit queue and when the device is up the pending group add request gets fullfilled

Change-Id: I6e67c03213cad5e5f8dbddbed8ffee55e3c877b3
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 df8a99c..f820feb 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
@@ -446,10 +446,10 @@
             log.debug("storeGroupDescription: Device {} local role is not MASTER",
                       groupDesc.deviceId());
             if (mastershipService.getMasterFor(groupDesc.deviceId()) == null) {
-                log.error("No Master for device {}..."
-                                  + "Can not perform add group operation",
+                log.debug("No Master for device {}..."
+                                  + "Queuing Group ADD request",
                           groupDesc.deviceId());
-                //TODO: Send Group operation failure event
+                addToPendingAudit(groupDesc);
                 return;
             }
             GroupStoreMessage groupOp = GroupStoreMessage.
@@ -481,6 +481,21 @@
         storeGroupDescriptionInternal(groupDesc);
     }
 
+    private void addToPendingAudit(GroupDescription groupDesc) {
+        Integer groupIdVal = groupDesc.givenGroupId();
+        GroupId groupId = (groupIdVal != null) ? new GroupId(groupIdVal) : dummyGroupId;
+        addToPendingKeyTable(new DefaultGroup(groupId, groupDesc));
+    }
+
+    private void addToPendingKeyTable(StoredGroupEntry group) {
+        group.setState(GroupState.WAITING_AUDIT_COMPLETE);
+        Map<GroupStoreKeyMapKey, StoredGroupEntry> pendingKeyTable =
+                getPendingGroupKeyTable();
+        pendingKeyTable.put(new GroupStoreKeyMapKey(group.deviceId(),
+                        group.appCookie()),
+                group);
+    }
+
     private Group getMatchingExtraneousGroupbyId(DeviceId deviceId, Integer groupId) {
         ConcurrentMap<GroupId, Group> extraneousMap =
                 extraneousGroupEntriesById.get(deviceId);
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
index 3e25bd6..fd9b484 100644
--- 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
@@ -15,10 +15,9 @@
  */
 package org.onosproject.store.group.impl;
 
-import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.List;
-
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.common.testing.EqualsTester;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -49,9 +48,9 @@
 import org.onosproject.store.service.ConsistentMap;
 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 java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
 
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.hasSize;
@@ -62,8 +61,11 @@
 import static org.junit.Assert.assertEquals;
 import static org.onosproject.net.NetTestTools.APP_ID;
 import static org.onosproject.net.NetTestTools.did;
-import static org.onosproject.net.group.GroupDescription.Type.*;
-import static org.onosproject.net.group.GroupStore.UpdateType.*;
+import static org.onosproject.net.group.GroupDescription.Type.ALL;
+import static org.onosproject.net.group.GroupDescription.Type.INDIRECT;
+import static org.onosproject.net.group.GroupDescription.Type.SELECT;
+import static org.onosproject.net.group.GroupStore.UpdateType.ADD;
+import static org.onosproject.net.group.GroupStore.UpdateType.SET;
 /**
  * Distributed group store test.
  */
@@ -125,6 +127,18 @@
         }
     }
 
+    static class MasterNull extends MastershipServiceAdapter {
+        @Override
+        public MastershipRole getLocalRole(DeviceId deviceId) {
+            return null;
+        }
+
+        @Override
+        public NodeId getMasterFor(DeviceId deviceId) {
+            return null;
+        }
+    }
+
     @Before
     public void setUp() throws Exception {
         groupStoreImpl = new DistributedGroupStore();
@@ -498,4 +512,33 @@
                 .addEqualityGroup(key3)
                 .testEquals();
     }
+
+    @Test
+    public void testMasterNull() 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));
+        //Simulate master null
+        groupStoreImpl.mastershipService = new MasterNull();
+        //Add a group
+        groupStore.storeGroupDescription(groupDescription1);
+        assertThat(groupStore.getGroupCount(deviceId1), is(0));
+        assertThat(groupStore.getGroup(deviceId1, groupId1), nullValue());
+        assertThat(groupStore.getGroup(deviceId1, groupKey1), nullValue());
+        //reset master
+        groupStoreImpl.mastershipService = new MasterOfAll();
+        // Master was null when the group add attempt is made.
+        // So size of the pending list should be 1 now.
+        assertThat(auditPendingReqQueue.size(), is(1));
+        groupStore.deviceInitialAuditCompleted(deviceId1, true);
+        //After the audit , the group should be removed from pending audit queue
+        assertThat(auditPendingReqQueue.size(), is(0));
+        //test whether the group is added to the store
+        assertThat(groupStore.getGroupCount(deviceId1), is(1));
+        assertThat(groupStore.getGroup(deviceId1, groupId1), notNullValue());
+        assertThat(groupStore.getGroup(deviceId1, groupKey1), notNullValue());
+    }
+
+
 }