T3 Dual homing tests

Change-Id: I2690be3b3ec507a25cc721a0d2860f448d6a99c1
(cherry picked from commit 71a2076a4dfdd99b3ddea8d053f2fa83b714d623)
diff --git a/src/test/java/org/onosproject/t3/impl/T3TestObjects.java b/src/test/java/org/onosproject/t3/impl/T3TestObjects.java
index aeffbb2..8501400 100644
--- a/src/test/java/org/onosproject/t3/impl/T3TestObjects.java
+++ b/src/test/java/org/onosproject/t3/impl/T3TestObjects.java
@@ -26,6 +26,7 @@
 import org.onosproject.core.DefaultApplicationId;
 import org.onosproject.core.GroupId;
 import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DefaultAnnotations;
 import org.onosproject.net.DefaultHost;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.Host;
@@ -61,6 +62,9 @@
     private static final String HOST_TWO_VLAN = "None";
     private static final String HOST_ONE = HOST_ONE_MAC + "/" + HOST_ONE_VLAN;
     private static final String HOST_TWO = HOST_TWO_MAC + "/" + HOST_TWO_VLAN;
+    private static final String HOST_DUAL_HOMED_MAC = "00:00:00:00:00:03";
+    private static final String HOST_DUAL_HOMED_VLAN = "None";
+    private static final String HOST_DUAL_HOMED = HOST_DUAL_HOMED_MAC + "/" + HOST_DUAL_HOMED_VLAN;
 
     //offline device
     static final DeviceId OFFLINE_DEVICE = DeviceId.deviceId("offlineDevice");
@@ -623,6 +627,74 @@
 
     static final ConnectPoint NO_BUCKET_CP = ConnectPoint.deviceConnectPoint(NO_BUCKET_DEVICE + "/" + 1);
 
+    //Dual Homing
+
+    static final DeviceId DUAL_HOME_DEVICE_1 = DeviceId.deviceId("DualHomeDevice1");
+
+    static final DeviceId DUAL_HOME_DEVICE_2 = DeviceId.deviceId("DualHomeDevice2");
+
+    static final DeviceId DUAL_HOME_DEVICE_3 = DeviceId.deviceId("DualHomeDevice3");
+
+    static final ConnectPoint DUAL_HOME_CP_1_1 = ConnectPoint.deviceConnectPoint(DUAL_HOME_DEVICE_1 + "/" + 1);
+    static final ConnectPoint DUAL_HOME_CP_1_2 = ConnectPoint.deviceConnectPoint(DUAL_HOME_DEVICE_1 + "/" + 2);
+    static final ConnectPoint DUAL_HOME_CP_1_3 = ConnectPoint.deviceConnectPoint(DUAL_HOME_DEVICE_1 + "/" + 3);
+
+    static final ConnectPoint DUAL_HOME_CP_2_1 = ConnectPoint.deviceConnectPoint(DUAL_HOME_DEVICE_2 + "/" + 1);
+    static final ConnectPoint DUAL_HOME_CP_2_2 = ConnectPoint.deviceConnectPoint(DUAL_HOME_DEVICE_2 + "/" + 2);
+
+    static final ConnectPoint DUAL_HOME_CP_3_1 = ConnectPoint.deviceConnectPoint(DUAL_HOME_DEVICE_3 + "/" + 1);
+    static final ConnectPoint DUAL_HOME_CP_3_2 = ConnectPoint.deviceConnectPoint(DUAL_HOME_DEVICE_3 + "/" + 2);
+
+
+    private static final TrafficSelector  DUAL_HOME_INPUT_FLOW_SELECTOR = DefaultTrafficSelector.builder()
+            .matchInPort(PortNumber.portNumber(1))
+            .build();
+
+    private static final GroupId DUAL_HOME_GROUP_ID = GroupId.valueOf(1);
+
+    private static final TrafficTreatment DUAL_HOME_GROUP_TREATMENT = DefaultTrafficTreatment.builder()
+            .group(DUAL_HOME_GROUP_ID)
+            .build();
+    private static final FlowRule DUAL_HOME_INPUT_FLOW = DefaultFlowEntry.builder().forDevice(DUAL_HOME_DEVICE_1)
+            .forTable(0)
+            .withPriority(100)
+            .withSelector(DUAL_HOME_INPUT_FLOW_SELECTOR)
+            .withTreatment(DUAL_HOME_GROUP_TREATMENT)
+            .fromApp(new DefaultApplicationId(0, "TestApp"))
+            .makePermanent()
+            .build();
+    static final FlowEntry DUAL_HOME_FLOW_ENTRY = new DefaultFlowEntry(DUAL_HOME_INPUT_FLOW);
+
+    private static final TrafficTreatment DUAL_HOME_OUTPUT_1_FLOW_TREATMENT = DefaultTrafficTreatment.builder()
+            .setOutput(PortNumber.portNumber(2)).build();
+    private static final TrafficTreatment DUAL_HOME_OUTPUT_2_FLOW_TREATMENT = DefaultTrafficTreatment.builder()
+            .setOutput(PortNumber.portNumber(3)).build();
+
+    private static final GroupBucket BUCKET_1_DUAL_HOMED =
+            DefaultGroupBucket.createSelectGroupBucket(DUAL_HOME_OUTPUT_1_FLOW_TREATMENT);
+
+    private static final GroupBucket BUCKET_2_DUAL_HOMED =
+            DefaultGroupBucket.createSelectGroupBucket(DUAL_HOME_OUTPUT_2_FLOW_TREATMENT);
+
+    private static final GroupBuckets BUCKETS_MULTIPLE_DUAL = new GroupBuckets(ImmutableList.of(BUCKET_1_DUAL_HOMED,
+            BUCKET_2_DUAL_HOMED));
+
+    static final Group DUAL_HOME_GROUP = new DefaultGroup(DUAL_HOME_GROUP_ID, DUAL_HOME_DEVICE_1,
+            Group.Type.SELECT, BUCKETS_MULTIPLE_DUAL);
+
+    private static final TrafficTreatment DUAL_HOME_TREATMENT = DefaultTrafficTreatment.builder()
+            .setOutput(PortNumber.portNumber("2"))
+            .build();
+    private static final FlowRule DUAL_HOME_OUT_FLOW = DefaultFlowEntry.builder().forDevice(DUAL_HOME_DEVICE_2)
+            .forTable(0)
+            .withPriority(100)
+            .withSelector(DUAL_HOME_INPUT_FLOW_SELECTOR)
+            .withTreatment(DUAL_HOME_TREATMENT)
+            .fromApp(new DefaultApplicationId(0, "TestApp"))
+            .makePermanent()
+            .build();
+    static final FlowEntry DUAL_HOME_OUT_FLOW_ENTRY = new DefaultFlowEntry(DUAL_HOME_OUT_FLOW);
+
     //helper elements
 
     static final String MASTER_1 = "Master1";
@@ -635,6 +707,12 @@
             VlanId.NONE, new HostLocation(TOPO_FLOW_3_DEVICE, PortNumber.portNumber(2), 0),
             ImmutableSet.of(IpAddress.valueOf("127.0.0.3")));
 
+    static final Host DUAL_HOME_H = new DefaultHost(ProviderId.NONE, HostId.hostId(HOST_DUAL_HOMED),
+            MacAddress.valueOf(HOST_DUAL_HOMED_MAC),
+            VlanId.NONE, ImmutableSet.of(new HostLocation(DUAL_HOME_DEVICE_2, PortNumber.portNumber(2), 0),
+            new HostLocation(DUAL_HOME_DEVICE_3, PortNumber.portNumber(2), 0)),
+            ImmutableSet.of(IpAddress.valueOf("127.0.0.4")), true, DefaultAnnotations.builder().build());
+
     static final TrafficSelector PACKET_OK = DefaultTrafficSelector.builder()
             .matchInPort(PortNumber.portNumber(1))
             .matchEthType(EthType.EtherType.IPV4.ethType().toShort())
@@ -667,6 +745,13 @@
             .matchIPDst(IpPrefix.valueOf("224.0.0.1/32"))
             .build();
 
+    static final TrafficSelector PACKET_DUAL_HOME = DefaultTrafficSelector.builder()
+            .matchInPort(PortNumber.portNumber(1))
+            .matchEthType(EthType.EtherType.IPV4.ethType().toShort())
+            .matchIPSrc(IpPrefix.valueOf("127.0.0.1/32"))
+            .matchIPDst(IpPrefix.valueOf("127.0.0.4/32"))
+            .build();
+
     static final TrafficSelector PACKET_FAIL = DefaultTrafficSelector.builder()
             .matchInPort(PortNumber.portNumber(1))
             .matchIPSrc(IpPrefix.valueOf("127.0.0.1/32"))
diff --git a/src/test/java/org/onosproject/t3/impl/TroubleshootManagerTest.java b/src/test/java/org/onosproject/t3/impl/TroubleshootManagerTest.java
index fa19d22..bbf9fd5 100644
--- a/src/test/java/org/onosproject/t3/impl/TroubleshootManagerTest.java
+++ b/src/test/java/org/onosproject/t3/impl/TroubleshootManagerTest.java
@@ -364,6 +364,23 @@
 
     }
 
+    /**
+     * Tests dual homing of a host.
+     */
+    @Test
+    public void dualhomedTest() throws Exception {
+        StaticPacketTrace traceSuccess = mngr.trace(PACKET_DUAL_HOME, DUAL_HOME_CP_1_1);
+
+        assertNotNull("trace should not be null", traceSuccess);
+        assertTrue("Should have 2 output paths", traceSuccess.getCompletePaths().size() == 2);
+        assertTrue("Should contain proper path", traceSuccess.getCompletePaths()
+                .contains(ImmutableList.of(DUAL_HOME_CP_1_1, DUAL_HOME_CP_1_2, DUAL_HOME_CP_2_1, DUAL_HOME_CP_2_2)));
+        assertTrue("Should contain proper path", traceSuccess.getCompletePaths()
+                .contains(ImmutableList.of(DUAL_HOME_CP_1_1, DUAL_HOME_CP_1_3, DUAL_HOME_CP_3_1, DUAL_HOME_CP_3_2)));
+
+    }
+
+
     private StaticPacketTrace testSuccess(TrafficSelector packet, ConnectPoint in, DeviceId deviceId, ConnectPoint out,
                                           int paths, int outputs) {
         StaticPacketTrace traceSuccess = mngr.trace(packet, in);
@@ -432,6 +449,10 @@
                 return ImmutableList.of(MULTICAST_GROUP_FLOW_ENTRY);
             } else if (deviceId.equals(NO_BUCKET_DEVICE)) {
                 return ImmutableList.of(NO_BUCKET_ENTRY);
+            } else if (deviceId.equals(DUAL_HOME_DEVICE_1)) {
+                return ImmutableList.of(DUAL_HOME_FLOW_ENTRY);
+            } else if (deviceId.equals(DUAL_HOME_DEVICE_2) || deviceId.equals(DUAL_HOME_DEVICE_3)) {
+                return ImmutableList.of(DUAL_HOME_OUT_FLOW_ENTRY);
             }
             return ImmutableList.of();
         }
@@ -462,6 +483,8 @@
                 return ImmutableList.of(MULTICAST_GROUP);
             } else if (deviceId.equals(NO_BUCKET_DEVICE)) {
                 return ImmutableList.of(NO_BUCKET_GROUP);
+            } else if (deviceId.equals(DUAL_HOME_DEVICE_1)) {
+                return ImmutableList.of(DUAL_HOME_GROUP);
             }
             return ImmutableList.of();
         }
@@ -485,6 +508,9 @@
                     connectPoint.equals(DUAL_LINK_3_CP_3_OUT)) {
                 return ImmutableSet.of(H1);
             }
+            if (connectPoint.equals(DUAL_HOME_CP_2_2) || connectPoint.equals(DUAL_HOME_CP_3_2)) {
+                return ImmutableSet.of(DUAL_HOME_H);
+            }
             return ImmutableSet.of();
         }
 
@@ -494,6 +520,8 @@
                 return ImmutableSet.of(H1);
             } else if (mac.equals(H2.mac())) {
                 return ImmutableSet.of(H2);
+            } else if (mac.equals(DUAL_HOME_H.mac())) {
+                return ImmutableSet.of(DUAL_HOME_H);
             }
             return ImmutableSet.of();
         }
@@ -504,6 +532,8 @@
                 return ImmutableSet.of(H1);
             } else if ((H2.ipAddresses().contains(ip))) {
                 return ImmutableSet.of(H2);
+            } else if ((DUAL_HOME_H.ipAddresses().contains(ip))) {
+                return ImmutableSet.of(DUAL_HOME_H);
             }
             return ImmutableSet.of();
         }
@@ -569,6 +599,20 @@
                         .src(DUAL_LINK_2_CP_3_OUT)
                         .dst(DUAL_LINK_3_CP_2_IN)
                         .build());
+            } else if (connectPoint.equals(DUAL_HOME_CP_1_2)) {
+                return ImmutableSet.of(DefaultLink.builder()
+                        .providerId(ProviderId.NONE)
+                        .type(Link.Type.DIRECT)
+                        .src(DUAL_HOME_CP_1_2)
+                        .dst(DUAL_HOME_CP_2_1)
+                        .build());
+            } else if (connectPoint.equals(DUAL_HOME_CP_1_3)) {
+                return ImmutableSet.of(DefaultLink.builder()
+                        .providerId(ProviderId.NONE)
+                        .type(Link.Type.DIRECT)
+                        .src(DUAL_HOME_CP_1_3)
+                        .dst(DUAL_HOME_CP_3_1)
+                        .build());
             }
             return ImmutableSet.of();
         }