flowmanager tests

Change-Id: I27ff62e4483254e565153294eddc20b525f5db01
diff --git a/core/net/src/main/java/org/onlab/onos/net/flow/impl/FlowRuleManager.java b/core/net/src/main/java/org/onlab/onos/net/flow/impl/FlowRuleManager.java
index 337f437..8513a2e 100644
--- a/core/net/src/main/java/org/onlab/onos/net/flow/impl/FlowRuleManager.java
+++ b/core/net/src/main/java/org/onlab/onos/net/flow/impl/FlowRuleManager.java
@@ -1,6 +1,11 @@
 package org.onlab.onos.net.flow.impl;
 
-import com.google.common.collect.Lists;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.util.Iterator;
+import java.util.List;
+
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Deactivate;
@@ -26,11 +31,7 @@
 import org.onlab.onos.net.provider.AbstractProviderService;
 import org.slf4j.Logger;
 
-import java.util.Iterator;
-import java.util.List;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static org.slf4j.LoggerFactory.getLogger;
+import com.google.common.collect.Lists;
 
 /**
  * Provides implementation of the flow NB & SB APIs.
@@ -47,7 +48,7 @@
     private final AbstractListenerRegistry<FlowRuleEvent, FlowRuleListener>
     listenerRegistry = new AbstractListenerRegistry<>();
 
-    private FlowRuleStoreDelegate delegate = new InternalStoreDelegate();
+    private final FlowRuleStoreDelegate delegate = new InternalStoreDelegate();
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected FlowRuleStore store;
@@ -107,6 +108,7 @@
         Iterable<FlowRule> rules =  getFlowRulesById(id);
         FlowRuleProvider frp;
         Device device;
+
         for (FlowRule f : rules) {
             store.deleteFlowRule(f);
             device = deviceService.getDevice(f.deviceId());
@@ -181,10 +183,11 @@
             checkValidity();
             Device device = deviceService.getDevice(flowRule.deviceId());
             FlowRuleProvider frp = getProvider(device.providerId());
+            FlowRuleEvent event = null;
             switch (flowRule.state()) {
             case PENDING_REMOVE:
             case REMOVED:
-                store.removeFlowRule(flowRule);
+                event = store.removeFlowRule(flowRule);
                 frp.removeFlowRule(flowRule);
                 break;
             case ADDED:
@@ -195,6 +198,10 @@
                 log.debug("Flow {} has not been installed.", flowRule);
             }
 
+            if (event != null) {
+                log.debug("Flow {} removed", flowRule);
+                post(event);
+            }
 
         }
 
@@ -245,7 +252,7 @@
                 }
             }
             for (FlowRule rule : storedRules) {
-
+                log.info("missing rule is {}", rule);
                 // there are rules in the store that aren't on the switch
                 flowMissing(rule);
 
diff --git a/core/net/src/test/java/org/onlab/onos/net/flow/impl/FlowRuleManagerTest.java b/core/net/src/test/java/org/onlab/onos/net/flow/impl/FlowRuleManagerTest.java
index 4e634c9..54abb84 100644
--- a/core/net/src/test/java/org/onlab/onos/net/flow/impl/FlowRuleManagerTest.java
+++ b/core/net/src/test/java/org/onlab/onos/net/flow/impl/FlowRuleManagerTest.java
@@ -116,6 +116,7 @@
         }
 
         int i = 0;
+        System.err.println("events :" + listener.events);
         for (FlowRuleEvent e : listener.events) {
             assertTrue("unexpected event", e.type().equals(events[i]));
             i++;
@@ -207,6 +208,12 @@
 
         providerService.flowRemoved(rem1);
         validateEvents();
+
+        FlowRule f3 = flowRule(flowRule(3, 3), FlowRuleState.ADDED);
+        providerService.flowAdded(f3);
+        validateEvents(RULE_ADDED);
+        providerService.flowRemoved(f3);
+        validateEvents();
     }
 
     @Test
@@ -215,6 +222,7 @@
         FlowRule f2 = flowRule(2, 2);
         FlowRule f3 = flowRule(3, 3);
 
+
         FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
         FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
         mgr.applyFlowRules(f1, f2, f3);
@@ -224,7 +232,71 @@
         assertTrue("Entries should be added.",
                 validateState(FlowRuleState.PENDING_ADD, FlowRuleState.ADDED,
                         FlowRuleState.ADDED));
-        //TODO: add tests for flowmissing and extraneous flows
+
+        validateEvents(RULE_UPDATED, RULE_UPDATED);
+    }
+
+    @Test
+    public void extraneousFlow() {
+        FlowRule f1 = flowRule(1, 1);
+        FlowRule f2 = flowRule(2, 2);
+        FlowRule f3 = flowRule(3, 3);
+
+        FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
+        FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
+        FlowRule updatedF3 = flowRule(f3, FlowRuleState.ADDED);
+        mgr.applyFlowRules(f1, f2);
+
+        providerService.pushFlowMetrics(DID, Lists.newArrayList(updatedF1, updatedF2, updatedF3));
+
+        validateEvents(RULE_UPDATED, RULE_UPDATED);
+
+    }
+
+    /*
+     * Tests whether a rule that was marked for removal but no flowRemoved was received
+     * is indeed removed at the next stats update.
+     */
+    @Test
+    public void flowMissingRemove() {
+        FlowRule f1 = flowRule(1, 1);
+        FlowRule f2 = flowRule(2, 2);
+        FlowRule f3 = flowRule(3, 3);
+
+        FlowRule updatedF1 = flowRule(f1, FlowRuleState.ADDED);
+        FlowRule updatedF2 = flowRule(f2, FlowRuleState.ADDED);
+        mgr.applyFlowRules(f1, f2, f3);
+
+        mgr.removeFlowRules(f3);
+
+        providerService.pushFlowMetrics(DID, Lists.newArrayList(updatedF1, updatedF2));
+
+        validateEvents(RULE_UPDATED, RULE_UPDATED, RULE_REMOVED);
+
+    }
+
+    @Test
+    public void getByAppId() {
+        FlowRule f1 = flowRule(1, 1);
+        FlowRule f2 = flowRule(2, 2);
+        mgr.applyFlowRules(f1, f2);
+
+        assertTrue("should have two rules",
+                Lists.newLinkedList(mgr.getFlowRulesById(appId)).size() == 2);
+    }
+
+    @Test
+    public void removeByAppId() {
+        FlowRule f1 = flowRule(1, 1);
+        FlowRule f2 = flowRule(2, 2);
+        mgr.applyFlowRules(f1, f2);
+
+
+        mgr.removeFlowRulesById(appId);
+
+        //only check that we are in pending remove. Events and actual remove state will
+        // be set by flowRemoved call.
+        validateState(FlowRuleState.PENDING_REMOVE, FlowRuleState.PENDING_REMOVE);
     }
 
     private static class TestListener implements FlowRuleListener {