[ONOS-6397] Fix incorrect filtering objective condition from Intent copmiler.

LinkCollectionObjectiveCompiler should generate filtering objective
according to different situation.

This implementation use criterion from in/egress FilteredConnectedPoint and encapsulation tag for the
filtering objective.

Change-Id: Ib2ccd6fb00d055a96f2762ce261780ebc544a77b
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/LinkCollectionIntentObjectiveCompiler.java b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/LinkCollectionIntentObjectiveCompiler.java
index 2e46669..ce5432f 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/LinkCollectionIntentObjectiveCompiler.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/LinkCollectionIntentObjectiveCompiler.java
@@ -31,6 +31,8 @@
 import org.onosproject.core.CoreService;
 import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.DeviceId;
+import org.onosproject.net.EncapsulationType;
+import org.onosproject.net.FilteredConnectPoint;
 import org.onosproject.net.PortNumber;
 import org.onosproject.net.domain.DomainService;
 import org.onosproject.net.flow.DefaultTrafficTreatment;
@@ -54,15 +56,18 @@
 import org.onosproject.net.intent.constraint.EncapsulationConstraint;
 import org.onosproject.net.resource.ResourceService;
 import org.onosproject.net.resource.impl.LabelAllocator;
+import org.slf4j.Logger;
 
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 import static org.onosproject.net.domain.DomainId.LOCAL;
 import static org.onosproject.net.flow.instructions.Instruction.Type.OUTPUT;
+import static org.slf4j.LoggerFactory.getLogger;
 
 /**
  * Compiler to produce flow objectives from link collections.
@@ -71,6 +76,7 @@
 public class LinkCollectionIntentObjectiveCompiler
         extends LinkCollectionCompiler<Objective>
         implements IntentCompiler<LinkCollectionIntent> {
+    private final Logger log = getLogger(getClass());
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected IntentConfigurableRegistrator registrator;
@@ -98,7 +104,6 @@
         }
     }
 
-
     @Deactivate
     public void deactivate() {
         registrator.unregisterCompiler(LinkCollectionIntent.class, true);
@@ -172,12 +177,12 @@
          */
         Optional<EncapsulationConstraint> encapConstraint = this.getIntentEncapConstraint(intent);
 
-        inPorts.forEach(inport -> {
+        inPorts.forEach(inPort -> {
 
             ForwardingInstructions instructions = this.createForwardingInstruction(
                     encapConstraint,
                     intent,
-                    inport,
+                    inPort,
                     outPorts,
                     deviceId,
                     labels
@@ -199,11 +204,16 @@
                 }
             }
 
-            EthCriterion ethDst = (EthCriterion) instructions.selector()
-                    .getCriterion(Criterion.Type.ETH_DST);
+            EthCriterion ethDst = (EthCriterion) intent.selector().getCriterion(Criterion.Type.ETH_DST);
             boolean broadcastObjective = ethDst != null &&
                     (ethDst.mac().isBroadcast() || ethDst.mac().isMulticast());
 
+            FilteringObjective filteringObjective = buildFilteringObjective(intent,
+                                                                            instructions.selector(),
+                                                                            deviceId, inPort);
+            if (filteringObjective != null) {
+                objectives.add(filteringObjective);
+            }
             if (treatmentsWithDifferentPort.size() < 2 && !broadcastObjective) {
                 objectives.addAll(createSimpleNextObjective(instructions, intent));
             } else {
@@ -220,7 +230,6 @@
                                                      Set<TrafficTreatment> treatmentsWithDifferentPort,
                                                      LinkCollectionIntent intent) {
         List<Objective> objectives = Lists.newArrayList();
-        FilteringObjective filteringObjective;
         ForwardingObjective forwardingObjective;
         NextObjective nextObjective;
 
@@ -240,9 +249,6 @@
         treatmentsWithDifferentPort.forEach(nxBuilder::addTreatment);
         nextObjective = nxBuilder.add();
 
-        filteringObjective = buildFilteringObjective(instructions.selector(), intent.priority());
-
-        objectives.add(filteringObjective);
         objectives.add(forwardingObjective);
         objectives.add(nextObjective);
 
@@ -252,7 +258,6 @@
     private List<Objective> createSimpleNextObjective(ForwardingInstructions instructions,
                                                       LinkCollectionIntent intent) {
         List<Objective> objectives = Lists.newArrayList();
-        FilteringObjective filteringObjective;
         ForwardingObjective forwardingObjective;
         NextObjective nextObjective;
 
@@ -271,16 +276,14 @@
                 .withPriority(intent.priority())
                 .add();
 
-        filteringObjective = buildFilteringObjective(instructions.selector(), intent.priority());
-
-        objectives.add(filteringObjective);
         objectives.add(forwardingObjective);
         objectives.add(nextObjective);
 
         return objectives;
     }
 
-    private ForwardingObjective buildForwardingObjective(TrafficSelector selector, Integer nextId, int priority) {
+    private ForwardingObjective buildForwardingObjective(TrafficSelector selector,
+                                                         Integer nextId, int priority) {
         return DefaultForwardingObjective.builder()
                 .withMeta(selector)
                 .withSelector(selector)
@@ -292,22 +295,95 @@
                 .add();
     }
 
-    private FilteringObjective buildFilteringObjective(TrafficSelector selector, int priority) {
+    private FilteringObjective buildFilteringObjective(LinkCollectionIntent intent,
+                                                       TrafficSelector selector,
+                                                       DeviceId deviceId,
+                                                       PortNumber inPort) {
         FilteringObjective.Builder builder = DefaultFilteringObjective.builder();
         builder.fromApp(appId)
                 .permit()
                 .makePermanent()
-                .withPriority(priority);
-
-        Criterion inPortCriterion =
-                selector.getCriterion(Criterion.Type.IN_PORT);
-
+                .withPriority(intent.priority());
+        Criterion inPortCriterion = selector.getCriterion(Criterion.Type.IN_PORT);
         if (inPortCriterion != null) {
             builder.withKey(inPortCriterion);
         }
 
-        selector.criteria().forEach(builder::addCondition);
+        FilteredConnectPoint ingressPoint = intent.filteredIngressPoints().stream()
+                .filter(fcp -> fcp.connectPoint().equals(new ConnectPoint(deviceId, inPort)))
+                .filter(fcp -> selector.criteria().containsAll(fcp.trafficSelector().criteria()))
+                .findFirst()
+                .orElse(null);
+
+        AtomicBoolean emptyCondition = new AtomicBoolean(true);
+        if (ingressPoint != null) {
+            // ingress point, use criterion of it
+            ingressPoint.trafficSelector().criteria().forEach(criterion -> {
+                builder.addCondition(criterion);
+                emptyCondition.set(false);
+            });
+            if (emptyCondition.get()) {
+                return null;
+            }
+            return builder.add();
+        }
+        Optional<EncapsulationConstraint> encapConstraint = this.getIntentEncapConstraint(intent);
+        if (encapConstraint.isPresent() &&
+                !encapConstraint.get().encapType().equals(EncapsulationType.NONE)) {
+            // encapsulation enabled, use encapsulation label and tag.
+            EncapsulationConstraint encap = encapConstraint.get();
+            switch (encap.encapType()) {
+                case VLAN:
+                    builder.addCondition(selector.getCriterion(Criterion.Type.VLAN_VID));
+                    emptyCondition.set(false);
+                    break;
+                case MPLS:
+                    builder.addCondition(selector.getCriterion(Criterion.Type.MPLS_LABEL));
+                    emptyCondition.set(false);
+                    break;
+                default:
+                    log.warn("No filtering rule found because of unknown encapsulation type.");
+                    break;
+            }
+        } else {
+            // encapsulation not enabled, check if the treatment applied to the ingress or not
+            if (intent.applyTreatmentOnEgress()) {
+                // filtering criterion will be changed on egress point, use
+                // criterion of ingress point
+                ingressPoint = intent.filteredIngressPoints().stream()
+                        .findFirst()
+                        .orElse(null);
+                if (ingressPoint == null) {
+                    log.warn("No filtering rule found because no ingress point in the Intent");
+                } else {
+                    ingressPoint.trafficSelector().criteria().stream()
+                            .filter(criterion -> !criterion.type().equals(Criterion.Type.IN_PORT))
+                            .forEach(criterion -> {
+                                builder.addCondition(criterion);
+                                emptyCondition.set(false);
+                            });
+                }
+            } else {
+                // filtering criterion will be changed on ingress point, use
+                // criterion of egress point
+                FilteredConnectPoint egressPoint = intent.filteredEgressPoints().stream()
+                        .findFirst()
+                        .orElse(null);
+                if (egressPoint == null) {
+                    log.warn("No filtering rule found because no egress point in the Intent");
+                } else {
+                    egressPoint.trafficSelector().criteria().stream()
+                            .filter(criterion -> !criterion.type().equals(Criterion.Type.IN_PORT))
+                            .forEach(criterion -> {
+                                builder.addCondition(criterion);
+                                emptyCondition.set(false);
+                            });
+                }
+            }
+        }
+        if (emptyCondition.get()) {
+            return null;
+        }
         return builder.add();
     }
-
 }
diff --git a/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/AbstractLinkCollectionTest.java b/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/AbstractLinkCollectionTest.java
index f0f1d29..f32c8a3 100644
--- a/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/AbstractLinkCollectionTest.java
+++ b/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/AbstractLinkCollectionTest.java
@@ -134,6 +134,7 @@
 
     final TrafficSelector selector = emptySelector();
     final TrafficSelector vlan69Selector = vlanSelector("69");
+    final TrafficSelector vlan1Selector = vlanSelector("1");
     final TrafficSelector vlan100Selector = vlanSelector("100");
     final TrafficSelector vlan200Selector = vlanSelector("200");
     final TrafficSelector vlan300Selector = vlanSelector("300");
diff --git a/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/LinkCollectionIntentObjectiveCompilerTest.java b/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/LinkCollectionIntentObjectiveCompilerTest.java
index 88b2118..7a5ac87 100644
--- a/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/LinkCollectionIntentObjectiveCompilerTest.java
+++ b/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/LinkCollectionIntentObjectiveCompilerTest.java
@@ -15,16 +15,19 @@
  */
 package org.onosproject.net.intent.impl.compiler;
 
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Lists;
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.onlab.packet.MacAddress;
 import org.onlab.packet.VlanId;
 import org.onosproject.cfg.ComponentConfigAdapter;
+import org.onosproject.core.ApplicationId;
 import org.onosproject.core.CoreService;
 import org.onosproject.net.DefaultLink;
 import org.onosproject.net.DeviceId;
+import org.onosproject.net.EncapsulationType;
 import org.onosproject.net.FilteredConnectPoint;
 import org.onosproject.net.Link;
 import org.onosproject.net.PortNumber;
@@ -44,23 +47,30 @@
 import org.onosproject.net.intent.Intent;
 import org.onosproject.net.intent.IntentExtensionService;
 import org.onosproject.net.intent.LinkCollectionIntent;
+import org.onosproject.net.intent.constraint.EncapsulationConstraint;
 import org.onosproject.net.resource.MockResourceService;
 import org.onosproject.net.resource.ResourceService;
 
+import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import java.util.Set;
 
 import static org.easymock.EasyMock.*;
-import static org.hamcrest.CoreMatchers.hasItem;
 import static org.hamcrest.CoreMatchers.instanceOf;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.*;
 import static org.onosproject.net.Link.Type.DIRECT;
 import static org.onosproject.net.NetTestTools.PID;
 import static org.onosproject.net.domain.DomainId.LOCAL;
+import static org.onosproject.net.flowobjective.ForwardingObjective.Flag.SPECIFIC;
+import static org.onosproject.net.flowobjective.NextObjective.Type.BROADCAST;
+import static org.onosproject.net.flowobjective.NextObjective.Type.SIMPLE;
+import static org.onosproject.net.flowobjective.Objective.Operation.ADD;
 
 public class LinkCollectionIntentObjectiveCompilerTest extends AbstractLinkCollectionTest {
+    private static final VlanId VLAN_1 = VlanId.vlanId("1");
+    private static final VlanId VLAN_100 = VlanId.vlanId("100");
 
     private LinkCollectionIntentObjectiveCompiler compiler;
     private FlowObjectiveServiceAdapter flowObjectiveService;
@@ -105,7 +115,13 @@
         LinkCollectionCompiler.copyTtl = false;
 
         replay(coreService, domainService, intentExtensionService);
+        compiler.activate();
+    }
 
+    @After
+    public void tearDown() {
+        super.tearDown();
+        compiler.deactivate();
     }
 
     /**
@@ -114,8 +130,6 @@
      */
     @Test
     public void testCompile() {
-        compiler.activate();
-
         LinkCollectionIntent intent = LinkCollectionIntent.builder()
                 .appId(appId)
                 .selector(selector)
@@ -131,14 +145,13 @@
 
         FlowObjectiveIntent foIntent = (FlowObjectiveIntent) result.get(0);
         List<Objective> objectives = foIntent.objectives();
-        assertThat(objectives, hasSize(9));
+        assertThat(objectives, hasSize(6));
 
         /*
          * First set of objective
          */
-        filteringObjective = (FilteringObjective) objectives.get(0);
-        forwardingObjective = (ForwardingObjective) objectives.get(1);
-        nextObjective = (NextObjective) objectives.get(2);
+        forwardingObjective = (ForwardingObjective) objectives.get(0);
+        nextObjective = (NextObjective) objectives.get(1);
 
         // expect selector and treatment
         TrafficSelector expectSelector = DefaultTrafficSelector.builder()
@@ -147,102 +160,44 @@
         TrafficTreatment expectTreatment = DefaultTrafficTreatment.builder()
                 .setOutput(PortNumber.portNumber(1))
                 .build();
-        PortCriterion inPortCriterion =
-                (PortCriterion) expectSelector.getCriterion(Criterion.Type.IN_PORT);
-
-        // test case for first filtering objective
-        assertThat(filteringObjective.key(), is(inPortCriterion));
-        assertThat(filteringObjective.priority(), is(intent.priority()));
-        assertThat(filteringObjective.meta(), nullValue());
-        assertThat(filteringObjective.appId(), is(appId));
-        assertThat(filteringObjective.permanent(), is(true));
-        assertThat(filteringObjective.conditions(), is(Lists.newArrayList(expectSelector.criteria())));
 
         // test case for first next objective
-        assertThat(nextObjective.type(), is(NextObjective.Type.SIMPLE));
-        assertThat(nextObjective.next(), hasSize(1));
-        assertThat(nextObjective.next().iterator().next(), is(expectTreatment));
-        assertThat(nextObjective.meta(), is(expectSelector));
-        assertThat(nextObjective.op(), is(Objective.Operation.ADD));
+        checkNext(nextObjective, SIMPLE, expectTreatment, expectSelector, ADD);
 
         // test case for first forwarding objective
-        assertThat(forwardingObjective.op(), is(Objective.Operation.ADD));
-        assertThat(forwardingObjective.selector(), is(expectSelector));
-        assertThat(forwardingObjective.nextId(), is(nextObjective.id()));
-        assertThat(forwardingObjective.flag(), is(ForwardingObjective.Flag.SPECIFIC));
+        checkForward(forwardingObjective, ADD, expectSelector, nextObjective.id(), SPECIFIC);
 
         /*
          * Second set of objective
          */
-        filteringObjective = (FilteringObjective) objectives.get(3);
-        forwardingObjective = (ForwardingObjective) objectives.get(4);
-        nextObjective = (NextObjective) objectives.get(5);
+        forwardingObjective = (ForwardingObjective) objectives.get(2);
+        nextObjective = (NextObjective) objectives.get(3);
 
 
         expectSelector = DefaultTrafficSelector.builder()
                 .matchInPort(PortNumber.portNumber(0))
                 .build();
 
-        inPortCriterion =
-                (PortCriterion) expectSelector.getCriterion(Criterion.Type.IN_PORT);
-
-        // test case for first filtering objective
-        assertThat(filteringObjective.key(), is(inPortCriterion));
-        assertThat(filteringObjective.priority(), is(intent.priority()));
-        assertThat(filteringObjective.meta(), nullValue());
-        assertThat(filteringObjective.appId(), is(appId));
-        assertThat(filteringObjective.permanent(), is(true));
-        assertThat(filteringObjective.conditions(), is(Lists.newArrayList(expectSelector.criteria())));
-
         // test case for second next objective
-        assertThat(nextObjective.type(), is(NextObjective.Type.SIMPLE));
-        assertThat(nextObjective.next(), hasSize(1));
-        assertThat(nextObjective.next().iterator().next(), is(expectTreatment));
-        assertThat(nextObjective.meta(), is(expectSelector));
-        assertThat(nextObjective.op(), is(Objective.Operation.ADD));
+        checkNext(nextObjective, SIMPLE, expectTreatment, expectSelector, ADD);
 
         // test case for second forwarding objective
-        assertThat(forwardingObjective.op(), is(Objective.Operation.ADD));
-        assertThat(forwardingObjective.selector(), is(expectSelector));
-        assertThat(forwardingObjective.nextId(), is(nextObjective.id()));
-        assertThat(forwardingObjective.flag(), is(ForwardingObjective.Flag.SPECIFIC));
+        checkForward(forwardingObjective, ADD, expectSelector, nextObjective.id(), SPECIFIC);
 
         /*
          * 3rd set of objective
          */
-        filteringObjective = (FilteringObjective) objectives.get(6);
-        forwardingObjective = (ForwardingObjective) objectives.get(7);
-        nextObjective = (NextObjective) objectives.get(8);
-
+        forwardingObjective = (ForwardingObjective) objectives.get(4);
+        nextObjective = (NextObjective) objectives.get(5);
         expectSelector = DefaultTrafficSelector.builder()
                 .matchInPort(PortNumber.portNumber(1))
                 .build();
 
-        inPortCriterion =
-                (PortCriterion) expectSelector.getCriterion(Criterion.Type.IN_PORT);
-
-        // test case for first filtering objective
-        assertThat(filteringObjective.key(), is(inPortCriterion));
-        assertThat(filteringObjective.priority(), is(intent.priority()));
-        assertThat(filteringObjective.meta(), nullValue());
-        assertThat(filteringObjective.appId(), is(appId));
-        assertThat(filteringObjective.permanent(), is(true));
-        assertThat(filteringObjective.conditions(), is(Lists.newArrayList(expectSelector.criteria())));
-
         // test case for 3rd next objective
-        assertThat(nextObjective.type(), is(NextObjective.Type.SIMPLE));
-        assertThat(nextObjective.next(), hasSize(1));
-        assertThat(nextObjective.next().iterator().next(), is(expectTreatment));
-        assertThat(nextObjective.meta(), is(expectSelector));
-        assertThat(nextObjective.op(), is(Objective.Operation.ADD));
+        checkNext(nextObjective, SIMPLE, expectTreatment, expectSelector, ADD);
 
         // test case for 3rd forwarding objective
-        assertThat(forwardingObjective.op(), is(Objective.Operation.ADD));
-        assertThat(forwardingObjective.selector(), is(expectSelector));
-        assertThat(forwardingObjective.nextId(), is(nextObjective.id()));
-        assertThat(forwardingObjective.flag(), is(ForwardingObjective.Flag.SPECIFIC));
-
-        compiler.deactivate();
+        checkForward(forwardingObjective, ADD, expectSelector, nextObjective.id(), SPECIFIC);
     }
 
     /**
@@ -258,7 +213,6 @@
      */
     @Test
     public void testFilteredConnectPointForSp() {
-        compiler.activate();
         Set<Link> testLinks = ImmutableSet.of(
                 DefaultLink.builder().providerId(PID).src(of1p2).dst(of2p1).type(DIRECT).build(),
                 DefaultLink.builder().providerId(PID).src(of2p2).dst(of3p1).type(DIRECT).build(),
@@ -307,36 +261,27 @@
         // expect selector and treatment
         TrafficSelector expectSelector = DefaultTrafficSelector.builder()
                 .matchInPort(PortNumber.portNumber(1))
-                .matchVlanId(VlanId.vlanId("100"))
+                .matchVlanId(VLAN_100)
                 .matchEthDst(MacAddress.BROADCAST)
                 .build();
-        TrafficTreatment expectTreatment = DefaultTrafficTreatment.builder()
-                .setOutput(PortNumber.portNumber(2))
-                .build();
+        List<TrafficTreatment> expectTreatments = ImmutableList.of(
+                DefaultTrafficTreatment.builder()
+                        .setOutput(PortNumber.portNumber(2))
+                        .build()
+        );
 
         PortCriterion inPortCriterion =
                 (PortCriterion) expectSelector.getCriterion(Criterion.Type.IN_PORT);
 
         // test case for first filtering objective
-        assertThat(filteringObjective.key(), is(inPortCriterion));
-        assertThat(filteringObjective.priority(), is(intent.priority()));
-        assertThat(filteringObjective.meta(), nullValue());
-        assertThat(filteringObjective.appId(), is(appId));
-        assertThat(filteringObjective.permanent(), is(true));
-        assertThat(filteringObjective.conditions(), is(Lists.newArrayList(expectSelector.criteria())));
+        checkFiltering(filteringObjective, inPortCriterion, intent.priority(),
+                       null, appId, true, vlan100Selector.criteria());
 
         // test case for first next objective
-        assertThat(nextObjective.type(), is(NextObjective.Type.BROADCAST));
-        assertThat(nextObjective.next(), hasSize(1));
-        assertThat(nextObjective.next().iterator().next(), is(expectTreatment));
-        assertThat(nextObjective.meta(), is(expectSelector));
-        assertThat(nextObjective.op(), is(Objective.Operation.ADD));
+        checkNext(nextObjective, BROADCAST, expectTreatments, expectSelector, ADD);
 
         // test case for first forwarding objective
-        assertThat(forwardingObjective.op(), is(Objective.Operation.ADD));
-        assertThat(forwardingObjective.selector(), is(expectSelector));
-        assertThat(forwardingObjective.nextId(), is(nextObjective.id()));
-        assertThat(forwardingObjective.flag(), is(ForwardingObjective.Flag.SPECIFIC));
+        checkForward(forwardingObjective, ADD, expectSelector, nextObjective.id(), SPECIFIC);
 
         /*
          * Second set of objective
@@ -349,25 +294,14 @@
                 (PortCriterion) expectSelector.getCriterion(Criterion.Type.IN_PORT);
 
         // test case for first filtering objective
-        assertThat(filteringObjective.key(), is(inPortCriterion));
-        assertThat(filteringObjective.priority(), is(intent.priority()));
-        assertThat(filteringObjective.meta(), nullValue());
-        assertThat(filteringObjective.appId(), is(appId));
-        assertThat(filteringObjective.permanent(), is(true));
-        assertThat(filteringObjective.conditions(), is(Lists.newArrayList(expectSelector.criteria())));
+        checkFiltering(filteringObjective, inPortCriterion, intent.priority(),
+                       null, appId, true, vlan100Selector.criteria());
 
         // test case for second next objective
-        assertThat(nextObjective.type(), is(NextObjective.Type.BROADCAST));
-        assertThat(nextObjective.next(), hasSize(1));
-        assertThat(nextObjective.next().iterator().next(), is(expectTreatment));
-        assertThat(nextObjective.meta(), is(expectSelector));
-        assertThat(nextObjective.op(), is(Objective.Operation.ADD));
+        checkNext(nextObjective, BROADCAST, expectTreatments, expectSelector, ADD);
 
         // test case for second forwarding objective
-        assertThat(forwardingObjective.op(), is(Objective.Operation.ADD));
-        assertThat(forwardingObjective.selector(), is(expectSelector));
-        assertThat(forwardingObjective.nextId(), is(nextObjective.id()));
-        assertThat(forwardingObjective.flag(), is(ForwardingObjective.Flag.SPECIFIC));
+        checkForward(forwardingObjective, ADD, expectSelector, nextObjective.id(), SPECIFIC);
 
         /*
          * 3rd set of objective
@@ -380,25 +314,14 @@
                 (PortCriterion) expectSelector.getCriterion(Criterion.Type.IN_PORT);
 
         // test case for first filtering objective
-        assertThat(filteringObjective.key(), is(inPortCriterion));
-        assertThat(filteringObjective.priority(), is(intent.priority()));
-        assertThat(filteringObjective.meta(), nullValue());
-        assertThat(filteringObjective.appId(), is(appId));
-        assertThat(filteringObjective.permanent(), is(true));
-        assertThat(filteringObjective.conditions(), is(Lists.newArrayList(expectSelector.criteria())));
+        checkFiltering(filteringObjective, inPortCriterion, intent.priority(),
+                       null, appId, true, vlan100Selector.criteria());
 
         // test case for 3rd next objective
-        assertThat(nextObjective.type(), is(NextObjective.Type.BROADCAST));
-        assertThat(nextObjective.next(), hasSize(1));
-        assertThat(nextObjective.next().iterator().next(), is(expectTreatment));
-        assertThat(nextObjective.meta(), is(expectSelector));
-        assertThat(nextObjective.op(), is(Objective.Operation.ADD));
+        checkNext(nextObjective, BROADCAST, expectTreatments, expectSelector, ADD);
 
         // test case for 3rd forwarding objective
-        assertThat(forwardingObjective.op(), is(Objective.Operation.ADD));
-        assertThat(forwardingObjective.selector(), is(expectSelector));
-        assertThat(forwardingObjective.nextId(), is(nextObjective.id()));
-        assertThat(forwardingObjective.flag(), is(ForwardingObjective.Flag.SPECIFIC));
+        checkForward(forwardingObjective, ADD, expectSelector, nextObjective.id(), SPECIFIC);
 
         /*
          * 4th set of objective
@@ -411,38 +334,22 @@
                 (PortCriterion) expectSelector.getCriterion(Criterion.Type.IN_PORT);
 
         // test case for first filtering objective
-        assertThat(filteringObjective.key(), is(inPortCriterion));
-        assertThat(filteringObjective.priority(), is(intent.priority()));
-        assertThat(filteringObjective.meta(), nullValue());
-        assertThat(filteringObjective.appId(), is(appId));
-        assertThat(filteringObjective.permanent(), is(true));
-        assertThat(filteringObjective.conditions(), is(Lists.newArrayList(expectSelector.criteria())));
+        checkFiltering(filteringObjective, inPortCriterion, intent.priority(),
+                       null, appId, true, vlan100Selector.criteria());
 
         // test case for 3rd next objective
-        assertThat(nextObjective.type(), is(NextObjective.Type.BROADCAST));
-
-        // have 2 treatments in this objective
-        assertThat(nextObjective.next(), hasSize(2));
-        expectTreatment = DefaultTrafficTreatment.builder()
+        expectTreatments = ImmutableList.of(
+                DefaultTrafficTreatment.builder()
                 .setOutput(PortNumber.portNumber(2))
-                .build();
-        assertThat(nextObjective.next(), hasItem(expectTreatment));
-
-        expectTreatment = DefaultTrafficTreatment.builder()
+                .build(),
+        DefaultTrafficTreatment.builder()
                 .setOutput(PortNumber.portNumber(3))
-                .build();
-        assertThat(nextObjective.next(), hasItem(expectTreatment));
-
-        assertThat(nextObjective.meta(), is(expectSelector));
-        assertThat(nextObjective.op(), is(Objective.Operation.ADD));
+                .build()
+        );
+        checkNext(nextObjective, BROADCAST, expectTreatments, expectSelector, ADD);
 
         // test case for 3rd forwarding objective
-        assertThat(forwardingObjective.op(), is(Objective.Operation.ADD));
-        assertThat(forwardingObjective.selector(), is(expectSelector));
-        assertThat(forwardingObjective.nextId(), is(nextObjective.id()));
-        assertThat(forwardingObjective.flag(), is(ForwardingObjective.Flag.SPECIFIC));
-
-        compiler.deactivate();
+        checkForward(forwardingObjective, ADD, expectSelector, nextObjective.id(), SPECIFIC);
     }
 
     /**
@@ -456,7 +363,6 @@
      */
     @Test
     public void testFilteredConnectPointForMp() {
-        compiler.activate();
         Set<Link> testLinks = ImmutableSet.of(
                 DefaultLink.builder().providerId(PID).src(of1p2).dst(of2p1).type(DIRECT).build(),
                 DefaultLink.builder().providerId(PID).src(of3p2).dst(of2p3).type(DIRECT).build(),
@@ -472,8 +378,6 @@
                 new FilteredConnectPoint(of4p2, vlan100Selector)
         );
 
-
-
         LinkCollectionIntent intent = LinkCollectionIntent.builder()
                 .appId(appId)
                 .selector(ethDstSelector)
@@ -494,7 +398,7 @@
         TrafficSelector expectSelector = DefaultTrafficSelector
                 .builder(ethDstSelector)
                 .matchInPort(PortNumber.portNumber(1))
-                .matchVlanId(VlanId.vlanId("100"))
+                .matchVlanId(VLAN_100)
                 .build();
 
         TrafficTreatment expectTreatment = DefaultTrafficTreatment.builder()
@@ -512,25 +416,14 @@
                 (PortCriterion) expectSelector.getCriterion(Criterion.Type.IN_PORT);
 
         // test case for first filtering objective
-        assertThat(filteringObjective.key(), is(inPortCriterion));
-        assertThat(filteringObjective.priority(), is(intent.priority()));
-        assertThat(filteringObjective.meta(), nullValue());
-        assertThat(filteringObjective.appId(), is(appId));
-        assertThat(filteringObjective.permanent(), is(true));
-        assertThat(filteringObjective.conditions(), is(Lists.newArrayList(expectSelector.criteria())));
+        checkFiltering(filteringObjective, inPortCriterion, intent.priority(),
+                       null, appId, true, vlan100Selector.criteria());
 
         // test case for first next objective
-        assertThat(nextObjective.type(), is(NextObjective.Type.SIMPLE));
-        assertThat(nextObjective.next(), hasSize(1));
-        assertThat(nextObjective.next().iterator().next(), is(expectTreatment));
-        assertThat(nextObjective.meta(), is(expectSelector));
-        assertThat(nextObjective.op(), is(Objective.Operation.ADD));
+        checkNext(nextObjective, SIMPLE, expectTreatment, expectSelector, ADD);
 
         // test case for first forwarding objective
-        assertThat(forwardingObjective.op(), is(Objective.Operation.ADD));
-        assertThat(forwardingObjective.selector(), is(expectSelector));
-        assertThat(forwardingObjective.nextId(), is(nextObjective.id()));
-        assertThat(forwardingObjective.flag(), is(ForwardingObjective.Flag.SPECIFIC));
+        checkForward(forwardingObjective, ADD, expectSelector, nextObjective.id(), SPECIFIC);
 
         /*
          * Second set of objective
@@ -540,25 +433,14 @@
         nextObjective = (NextObjective) objectives.get(5);
 
         // test case for first filtering objective
-        assertThat(filteringObjective.key(), is(inPortCriterion));
-        assertThat(filteringObjective.priority(), is(intent.priority()));
-        assertThat(filteringObjective.meta(), nullValue());
-        assertThat(filteringObjective.appId(), is(appId));
-        assertThat(filteringObjective.permanent(), is(true));
-        assertThat(filteringObjective.conditions(), is(Lists.newArrayList(expectSelector.criteria())));
+        checkFiltering(filteringObjective, inPortCriterion, intent.priority(),
+                       null, appId, true, vlan100Selector.criteria());
 
         // test case for first next objective
-        assertThat(nextObjective.type(), is(NextObjective.Type.SIMPLE));
-        assertThat(nextObjective.next(), hasSize(1));
-        assertThat(nextObjective.next().iterator().next(), is(expectTreatment));
-        assertThat(nextObjective.meta(), is(expectSelector));
-        assertThat(nextObjective.op(), is(Objective.Operation.ADD));
+        checkNext(nextObjective, SIMPLE, expectTreatment, expectSelector, ADD);
 
         // test case for first forwarding objective
-        assertThat(forwardingObjective.op(), is(Objective.Operation.ADD));
-        assertThat(forwardingObjective.selector(), is(expectSelector));
-        assertThat(forwardingObjective.nextId(), is(nextObjective.id()));
-        assertThat(forwardingObjective.flag(), is(ForwardingObjective.Flag.SPECIFIC));
+        checkForward(forwardingObjective, ADD, expectSelector, nextObjective.id(), SPECIFIC);
 
         /*
          * 3rd set of objective
@@ -568,25 +450,14 @@
         nextObjective = (NextObjective) objectives.get(8);
 
         // test case for first filtering objective
-        assertThat(filteringObjective.key(), is(inPortCriterion));
-        assertThat(filteringObjective.priority(), is(intent.priority()));
-        assertThat(filteringObjective.meta(), nullValue());
-        assertThat(filteringObjective.appId(), is(appId));
-        assertThat(filteringObjective.permanent(), is(true));
-        assertThat(filteringObjective.conditions(), is(Lists.newArrayList(expectSelector.criteria())));
+        checkFiltering(filteringObjective, inPortCriterion, intent.priority(),
+                       null, appId, true, vlan100Selector.criteria());
 
         // test case for first next objective
-        assertThat(nextObjective.type(), is(NextObjective.Type.SIMPLE));
-        assertThat(nextObjective.next(), hasSize(1));
-        assertThat(nextObjective.next().iterator().next(), is(expectTreatment));
-        assertThat(nextObjective.meta(), is(expectSelector));
-        assertThat(nextObjective.op(), is(Objective.Operation.ADD));
+        checkNext(nextObjective, SIMPLE, expectTreatment, expectSelector, ADD);
 
         // test case for first forwarding objective
-        assertThat(forwardingObjective.op(), is(Objective.Operation.ADD));
-        assertThat(forwardingObjective.selector(), is(expectSelector));
-        assertThat(forwardingObjective.nextId(), is(nextObjective.id()));
-        assertThat(forwardingObjective.flag(), is(ForwardingObjective.Flag.SPECIFIC));
+        checkForward(forwardingObjective, ADD, expectSelector, nextObjective.id(), SPECIFIC);
 
         /*
          * 4th set of objective
@@ -596,25 +467,14 @@
         nextObjective = (NextObjective) objectives.get(11);
 
         // test case for first filtering objective
-        assertThat(filteringObjective.key(), is(inPortCriterion));
-        assertThat(filteringObjective.priority(), is(intent.priority()));
-        assertThat(filteringObjective.meta(), nullValue());
-        assertThat(filteringObjective.appId(), is(appId));
-        assertThat(filteringObjective.permanent(), is(true));
-        assertThat(filteringObjective.conditions(), is(Lists.newArrayList(expectSelector.criteria())));
+        checkFiltering(filteringObjective, inPortCriterion, intent.priority(),
+                       null, appId, true, vlan100Selector.criteria());
 
         // test case for first next objective
-        assertThat(nextObjective.type(), is(NextObjective.Type.SIMPLE));
-        assertThat(nextObjective.next(), hasSize(1));
-        assertThat(nextObjective.next().iterator().next(), is(expectTreatment));
-        assertThat(nextObjective.meta(), is(expectSelector));
-        assertThat(nextObjective.op(), is(Objective.Operation.ADD));
+        checkNext(nextObjective, SIMPLE, expectTreatment, expectSelector, ADD);
 
         // test case for first forwarding objective
-        assertThat(forwardingObjective.op(), is(Objective.Operation.ADD));
-        assertThat(forwardingObjective.selector(), is(expectSelector));
-        assertThat(forwardingObjective.nextId(), is(nextObjective.id()));
-        assertThat(forwardingObjective.flag(), is(ForwardingObjective.Flag.SPECIFIC));
+        checkForward(forwardingObjective, ADD, expectSelector, nextObjective.id(), SPECIFIC);
 
         /*
          * 5th set of objective
@@ -624,7 +484,7 @@
         nextObjective = (NextObjective) objectives.get(14);
 
         expectSelector = DefaultTrafficSelector.builder(ethDstSelector)
-                .matchVlanId(VlanId.vlanId("100"))
+                .matchVlanId(VLAN_100)
                 .matchInPort(PortNumber.portNumber(3))
                 .build();
 
@@ -632,26 +492,14 @@
                 (PortCriterion) expectSelector.getCriterion(Criterion.Type.IN_PORT);
 
         // test case for first filtering objective
-        assertThat(filteringObjective.key(), is(inPortCriterion));
-        assertThat(filteringObjective.priority(), is(intent.priority()));
-        assertThat(filteringObjective.meta(), nullValue());
-        assertThat(filteringObjective.appId(), is(appId));
-        assertThat(filteringObjective.permanent(), is(true));
-        assertThat(filteringObjective.conditions(), is(Lists.newArrayList(expectSelector.criteria())));
+        checkFiltering(filteringObjective, inPortCriterion, intent.priority(),
+                       null, appId, true, vlan100Selector.criteria());
 
         // test case for first next objective
-        assertThat(nextObjective.type(), is(NextObjective.Type.SIMPLE));
-        assertThat(nextObjective.next(), hasSize(1));
-        assertThat(nextObjective.next().iterator().next(), is(expectTreatment));
-        assertThat(nextObjective.meta(), is(expectSelector));
-        assertThat(nextObjective.op(), is(Objective.Operation.ADD));
+        checkNext(nextObjective, SIMPLE, expectTreatment, expectSelector, ADD);
 
         // test case for first forwarding objective
-        assertThat(forwardingObjective.op(), is(Objective.Operation.ADD));
-        assertThat(forwardingObjective.selector(), is(expectSelector));
-        assertThat(forwardingObjective.nextId(), is(nextObjective.id()));
-        assertThat(forwardingObjective.flag(), is(ForwardingObjective.Flag.SPECIFIC));
-        compiler.deactivate();
+        checkForward(forwardingObjective, ADD, expectSelector, nextObjective.id(), SPECIFIC);
     }
 
     /**
@@ -661,7 +509,6 @@
      */
     @Test
     public void singleHopTestForMp() {
-        compiler.activate();
         Set<Link> testLinks = ImmutableSet.of();
 
         Set<FilteredConnectPoint> ingress = ImmutableSet.of(
@@ -694,7 +541,7 @@
         TrafficSelector expectSelector = DefaultTrafficSelector
                 .builder(ethDstSelector)
                 .matchInPort(PortNumber.portNumber(1))
-                .matchVlanId(VlanId.vlanId("100"))
+                .matchVlanId(VLAN_100)
                 .build();
 
         TrafficTreatment expectTreatment = DefaultTrafficTreatment.builder()
@@ -712,25 +559,14 @@
                 (PortCriterion) expectSelector.getCriterion(Criterion.Type.IN_PORT);
 
         // test case for first filtering objective
-        assertThat(filteringObjective.key(), is(inPortCriterion));
-        assertThat(filteringObjective.priority(), is(intent.priority()));
-        assertThat(filteringObjective.meta(), nullValue());
-        assertThat(filteringObjective.appId(), is(appId));
-        assertThat(filteringObjective.permanent(), is(true));
-        assertThat(filteringObjective.conditions(), is(Lists.newArrayList(expectSelector.criteria())));
+        checkFiltering(filteringObjective, inPortCriterion, intent.priority(),
+                       null, appId, true, vlan100Selector.criteria());
 
         // test case for first next objective
-        assertThat(nextObjective.type(), is(NextObjective.Type.SIMPLE));
-        assertThat(nextObjective.next(), hasSize(1));
-        assertThat(nextObjective.next().iterator().next(), is(expectTreatment));
-        assertThat(nextObjective.meta(), is(expectSelector));
-        assertThat(nextObjective.op(), is(Objective.Operation.ADD));
+        checkNext(nextObjective, SIMPLE, expectTreatment, expectSelector, ADD);
 
         // test case for first forwarding objective
-        assertThat(forwardingObjective.op(), is(Objective.Operation.ADD));
-        assertThat(forwardingObjective.selector(), is(expectSelector));
-        assertThat(forwardingObjective.nextId(), is(nextObjective.id()));
-        assertThat(forwardingObjective.flag(), is(ForwardingObjective.Flag.SPECIFIC));
+        checkForward(forwardingObjective, ADD, expectSelector, nextObjective.id(), SPECIFIC);
 
         /*
          * Second set of objective
@@ -741,33 +577,21 @@
 
         expectSelector = DefaultTrafficSelector.builder(ethDstSelector)
                 .matchInPort(PortNumber.portNumber(2))
-                .matchVlanId(VlanId.vlanId("100"))
+                .matchVlanId(VLAN_100)
                 .build();
 
         inPortCriterion =
                 (PortCriterion) expectSelector.getCriterion(Criterion.Type.IN_PORT);
 
         // test case for first filtering objective
-        assertThat(filteringObjective.key(), is(inPortCriterion));
-        assertThat(filteringObjective.priority(), is(intent.priority()));
-        assertThat(filteringObjective.meta(), nullValue());
-        assertThat(filteringObjective.appId(), is(appId));
-        assertThat(filteringObjective.permanent(), is(true));
-        assertThat(filteringObjective.conditions(), is(Lists.newArrayList(expectSelector.criteria())));
+        checkFiltering(filteringObjective, inPortCriterion, intent.priority(),
+                       null, appId, true, vlan100Selector.criteria());
 
         // test case for first next objective
-        assertThat(nextObjective.type(), is(NextObjective.Type.SIMPLE));
-        assertThat(nextObjective.next(), hasSize(1));
-        assertThat(nextObjective.next().iterator().next(), is(expectTreatment));
-        assertThat(nextObjective.meta(), is(expectSelector));
-        assertThat(nextObjective.op(), is(Objective.Operation.ADD));
+        checkNext(nextObjective, SIMPLE, expectTreatment, expectSelector, ADD);
 
         // test case for first forwarding objective
-        assertThat(forwardingObjective.op(), is(Objective.Operation.ADD));
-        assertThat(forwardingObjective.selector(), is(expectSelector));
-        assertThat(forwardingObjective.nextId(), is(nextObjective.id()));
-        assertThat(forwardingObjective.flag(), is(ForwardingObjective.Flag.SPECIFIC));
-        compiler.deactivate();
+        checkForward(forwardingObjective, ADD, expectSelector, nextObjective.id(), SPECIFIC);
     }
 
     /**
@@ -777,7 +601,6 @@
      */
     @Test
     public void singleHopTestForSp() {
-        compiler.activate();
         Set<Link> testLinks = ImmutableSet.of();
 
         Set<FilteredConnectPoint> ingress = ImmutableSet.of(
@@ -812,12 +635,17 @@
         TrafficSelector expectSelector = DefaultTrafficSelector
                 .builder(ethDstSelector)
                 .matchInPort(PortNumber.portNumber(1))
-                .matchVlanId(VlanId.vlanId("100"))
+                .matchVlanId(VLAN_100)
                 .build();
 
-        TrafficTreatment expectTreatment = DefaultTrafficTreatment.builder()
-                .setOutput(PortNumber.portNumber(3))
-                .build();
+        List<TrafficTreatment> expectTreatments = ImmutableList.of(
+                DefaultTrafficTreatment.builder()
+                        .setOutput(PortNumber.portNumber(2))
+                        .build(),
+                DefaultTrafficTreatment.builder()
+                        .setOutput(PortNumber.portNumber(3))
+                        .build()
+        );
 
         /*
          * First set of objective
@@ -830,33 +658,382 @@
                 (PortCriterion) expectSelector.getCriterion(Criterion.Type.IN_PORT);
 
         // test case for first filtering objective
-        assertThat(filteringObjective.key(), is(inPortCriterion));
-        assertThat(filteringObjective.priority(), is(intent.priority()));
-        assertThat(filteringObjective.meta(), nullValue());
-        assertThat(filteringObjective.appId(), is(appId));
-        assertThat(filteringObjective.permanent(), is(true));
-        assertThat(filteringObjective.conditions(), is(Lists.newArrayList(expectSelector.criteria())));
+        checkFiltering(filteringObjective, inPortCriterion, intent.priority(),
+                       null, appId, true, vlan100Selector.criteria());
 
         // test case for first next objective
-        assertThat(nextObjective.type(), is(NextObjective.Type.BROADCAST));
-        assertThat(nextObjective.next(), hasSize(2));
-        assertThat(nextObjective.next(), hasItem(expectTreatment));
-        expectTreatment = DefaultTrafficTreatment.builder()
-                .setOutput(PortNumber.portNumber(3))
-                .build();
-        assertThat(nextObjective.next(), hasItem(expectTreatment));
-        assertThat(nextObjective.meta(), is(expectSelector));
-        assertThat(nextObjective.op(), is(Objective.Operation.ADD));
+        checkNext(nextObjective, BROADCAST, expectTreatments, expectSelector, ADD);
 
         // test case for first forwarding objective
-        assertThat(forwardingObjective.op(), is(Objective.Operation.ADD));
-        assertThat(forwardingObjective.selector(), is(expectSelector));
-        assertThat(forwardingObjective.nextId(), is(nextObjective.id()));
-        assertThat(forwardingObjective.flag(), is(ForwardingObjective.Flag.SPECIFIC));
-
-        compiler.deactivate();
-
+        checkForward(forwardingObjective, ADD, expectSelector, nextObjective.id(), SPECIFIC);
     }
 
+    /**
+     * Single point to multi point case. Scenario is the follow:
+     *
+     * -1 of1 2-1 of2 2--1 of3 2-
+     *             3
+     *             `-1 of4 2-
+     *
+     * We test the proper compilation constraint of sp2mp
+     * with encapsulation, trivial selector, empty treatment and points.
+     */
+    @Test
+    public void testFilteredConnectPointForSpWithEncap() throws Exception {
+        LinkCollectionCompiler.labelAllocator.setLabelSelection(LABEL_SELECTION);
+        Set<Link> testLinks = ImmutableSet.of(
+                DefaultLink.builder().providerId(PID).src(of1p2).dst(of2p1).type(DIRECT).build(),
+                DefaultLink.builder().providerId(PID).src(of2p2).dst(of3p1).type(DIRECT).build(),
+                DefaultLink.builder().providerId(PID).src(of2p3).dst(of4p1).type(DIRECT).build()
+        );
 
+        Set<FilteredConnectPoint> ingress = ImmutableSet.of(
+                new FilteredConnectPoint(of1p1, vlan100Selector)
+        );
+
+        Set<FilteredConnectPoint> egress = ImmutableSet.of(
+                new FilteredConnectPoint(of3p2, vlan100Selector),
+                new FilteredConnectPoint(of4p2, vlan100Selector)
+        );
+
+        TrafficSelector broadcastSelector = DefaultTrafficSelector.builder()
+                .matchEthDst(MacAddress.BROADCAST)
+                .build();
+
+        EncapsulationConstraint constraint = new EncapsulationConstraint(EncapsulationType.VLAN);
+        LinkCollectionIntent intent = LinkCollectionIntent.builder()
+                .appId(appId)
+                .selector(broadcastSelector)
+                .treatment(treatment)
+                .links(testLinks)
+                .filteredIngressPoints(ingress)
+                .filteredEgressPoints(egress)
+                .applyTreatmentOnEgress(true)
+                .resourceGroup(resourceGroup1)
+                .constraints(ImmutableList.of(constraint))
+                .build();
+
+        List<Intent> result = compiler.compile(intent, Collections.emptyList());
+        assertThat(result, hasSize(1));
+        assertThat(result.get(0), instanceOf(FlowObjectiveIntent.class));
+
+        FlowObjectiveIntent foIntent = (FlowObjectiveIntent) result.get(0);
+        List<Objective> objectives = foIntent.objectives();
+        assertThat(objectives, hasSize(12));
+
+        /*
+         * First set of objective
+         */
+        filteringObjective = (FilteringObjective) objectives.get(0);
+        forwardingObjective = (ForwardingObjective) objectives.get(1);
+        nextObjective = (NextObjective) objectives.get(2);
+
+        // expect selector and treatment
+        TrafficSelector expectSelector = DefaultTrafficSelector.builder()
+                .matchInPort(PortNumber.portNumber(1))
+                .matchVlanId(VLAN_100)
+                .matchEthDst(MacAddress.BROADCAST)
+                .build();
+        List<TrafficTreatment> expectTreatments = ImmutableList.of(
+                DefaultTrafficTreatment.builder()
+                        .setVlanId(VLAN_1)
+                        .setOutput(PortNumber.portNumber(2))
+                        .build()
+        );
+        TrafficSelector filteringSelector = vlan100Selector;
+        PortCriterion inPortCriterion =
+                (PortCriterion) expectSelector.getCriterion(Criterion.Type.IN_PORT);
+
+        // test case for first filtering objective
+        checkFiltering(filteringObjective, inPortCriterion, intent.priority(),
+                       null, appId, true, filteringSelector.criteria());
+
+        // test case for first next objective
+        checkNext(nextObjective, BROADCAST, expectTreatments, expectSelector, ADD);
+
+        // test case for first forwarding objective
+        checkForward(forwardingObjective, ADD, expectSelector, nextObjective.id(), SPECIFIC);
+
+        /*
+         * Second set of objective
+         */
+        filteringObjective = (FilteringObjective) objectives.get(3);
+        forwardingObjective = (ForwardingObjective) objectives.get(4);
+        nextObjective = (NextObjective) objectives.get(5);
+        expectSelector = DefaultTrafficSelector.builder()
+                .matchInPort(PortNumber.portNumber(1))
+                .matchVlanId(VLAN_1)
+                .build();
+        expectTreatments = ImmutableList.of(
+                DefaultTrafficTreatment.builder()
+                        .setVlanId(VLAN_100)
+                        .setOutput(PortNumber.portNumber(2))
+                        .build()
+        );
+        filteringSelector = vlan1Selector;
+        inPortCriterion =
+                (PortCriterion) expectSelector.getCriterion(Criterion.Type.IN_PORT);
+
+        // test case for first filtering objective
+        checkFiltering(filteringObjective, inPortCriterion, intent.priority(),
+                       null, appId, true, filteringSelector.criteria());
+
+        // test case for second next objective
+        checkNext(nextObjective, BROADCAST, expectTreatments, expectSelector, ADD);
+
+        // test case for second forwarding objective
+        checkForward(forwardingObjective, ADD, expectSelector, nextObjective.id(), SPECIFIC);
+
+        /*
+         * 3rd set of objective
+         */
+        filteringObjective = (FilteringObjective) objectives.get(6);
+        forwardingObjective = (ForwardingObjective) objectives.get(7);
+        nextObjective = (NextObjective) objectives.get(8);
+        inPortCriterion =
+                (PortCriterion) expectSelector.getCriterion(Criterion.Type.IN_PORT);
+
+        // test case for first filtering objective
+        checkFiltering(filteringObjective, inPortCriterion, intent.priority(),
+                       null, appId, true, filteringSelector.criteria());
+
+        // test case for 3rd next objective
+        checkNext(nextObjective, BROADCAST, expectTreatments, expectSelector, ADD);
+
+        // test case for 3rd forwarding objective
+        checkForward(forwardingObjective, ADD, expectSelector, nextObjective.id(), SPECIFIC);
+
+        /*
+         * 4th set of objective
+         */
+        filteringObjective = (FilteringObjective) objectives.get(9);
+        forwardingObjective = (ForwardingObjective) objectives.get(10);
+        nextObjective = (NextObjective) objectives.get(11);
+
+        inPortCriterion =
+                (PortCriterion) expectSelector.getCriterion(Criterion.Type.IN_PORT);
+
+        // test case for first filtering objective
+        checkFiltering(filteringObjective, inPortCriterion, intent.priority(),
+                       null, appId, true, filteringSelector.criteria());
+
+        // test case for 3rd next objective
+        expectTreatments = ImmutableList.of(
+                DefaultTrafficTreatment.builder()
+                        .setVlanId(VLAN_1)
+                        .setOutput(PortNumber.portNumber(2))
+                        .build(),
+                DefaultTrafficTreatment.builder()
+                        .setVlanId(VLAN_1)
+                        .setOutput(PortNumber.portNumber(3))
+                        .build()
+        );
+        checkNext(nextObjective, BROADCAST, expectTreatments, expectSelector, ADD);
+
+        // test case for 3rd forwarding objective
+        checkForward(forwardingObjective, ADD, expectSelector, nextObjective.id(), SPECIFIC);
+    }
+
+    /**
+     * Multi point to single point intent with filtered connect point.
+     * Scenario is the follow:
+     *
+     * -1 of1 2-1 of2 2-1 of4 2-
+     *             3
+     * -1 of3 2---/
+     * We test the proper compilation constraint of mp2sp
+     * with encapsulation, trivial selector, empty treatment and points.
+     */
+    @Test
+    public void testFilteredConnectPointForMpWithEncap() throws Exception {
+        LinkCollectionCompiler.labelAllocator.setLabelSelection(LABEL_SELECTION);
+        Set<Link> testLinks = ImmutableSet.of(
+                DefaultLink.builder().providerId(PID).src(of1p2).dst(of2p1).type(DIRECT).build(),
+                DefaultLink.builder().providerId(PID).src(of3p2).dst(of2p3).type(DIRECT).build(),
+                DefaultLink.builder().providerId(PID).src(of2p2).dst(of4p1).type(DIRECT).build()
+        );
+        Set<FilteredConnectPoint> ingress = ImmutableSet.of(
+                new FilteredConnectPoint(of3p1, vlan100Selector),
+                new FilteredConnectPoint(of1p1, vlan100Selector)
+        );
+        Set<FilteredConnectPoint> egress = ImmutableSet.of(
+                new FilteredConnectPoint(of4p2, vlan100Selector)
+        );
+        EncapsulationConstraint constraint = new EncapsulationConstraint(EncapsulationType.VLAN);
+        LinkCollectionIntent intent = LinkCollectionIntent.builder()
+                .appId(appId)
+                .selector(ethDstSelector)
+                .treatment(treatment)
+                .links(testLinks)
+                .filteredIngressPoints(ingress)
+                .filteredEgressPoints(egress)
+                .constraints(ImmutableList.of(constraint))
+                .build();
+        List<Intent> result = compiler.compile(intent, Collections.emptyList());
+        assertThat(result, hasSize(1));
+        assertThat(result.get(0), instanceOf(FlowObjectiveIntent.class));
+        FlowObjectiveIntent foIntent = (FlowObjectiveIntent) result.get(0);
+        List<Objective> objectives = foIntent.objectives();
+        assertThat(objectives, hasSize(15));
+        TrafficSelector expectSelector = DefaultTrafficSelector
+                .builder(ethDstSelector)
+                .matchInPort(PortNumber.portNumber(1))
+                .matchVlanId(VLAN_100)
+                .build();
+        TrafficSelector filteringSelector = vlan100Selector;
+        TrafficTreatment expectTreatment = DefaultTrafficTreatment.builder()
+                .setVlanId(VLAN_1)
+                .setOutput(PortNumber.portNumber(2))
+                .build();
+        /*
+         * First set of objective
+         */
+        filteringObjective = (FilteringObjective) objectives.get(0);
+        forwardingObjective = (ForwardingObjective) objectives.get(1);
+        nextObjective = (NextObjective) objectives.get(2);
+        PortCriterion inPortCriterion =
+                (PortCriterion) expectSelector.getCriterion(Criterion.Type.IN_PORT);
+        // test case for first filtering objective
+        checkFiltering(filteringObjective, inPortCriterion, intent.priority(),
+                       null, appId, true, filteringSelector.criteria());
+        // test case for first next objective
+        checkNext(nextObjective, SIMPLE, expectTreatment, expectSelector, ADD);
+        // test case for first forwarding objective
+        checkForward(forwardingObjective, ADD, expectSelector, nextObjective.id(), SPECIFIC);
+        /*
+         * Second set of objective
+         */
+        filteringObjective = (FilteringObjective) objectives.get(3);
+        forwardingObjective = (ForwardingObjective) objectives.get(4);
+        nextObjective = (NextObjective) objectives.get(5);
+        expectSelector = DefaultTrafficSelector
+                .builder()
+                .matchInPort(PortNumber.portNumber(1))
+                .matchVlanId(VLAN_1)
+                .build();
+        filteringSelector = vlan1Selector;
+        expectTreatment = DefaultTrafficTreatment
+                .builder()
+                .setVlanId(VLAN_100)
+                .setOutput(PortNumber.portNumber(2))
+                .build();
+        // test case for second filtering objective
+        checkFiltering(filteringObjective, inPortCriterion, intent.priority(),
+                       null, appId, true, filteringSelector.criteria());
+        // test case for second next objective
+        checkNext(nextObjective, SIMPLE, expectTreatment, expectSelector, ADD);
+        // test case for second forwarding objective
+        checkForward(forwardingObjective, ADD, expectSelector, nextObjective.id(), SPECIFIC);
+        /*
+         * 3rd set of objective
+         */
+        filteringObjective = (FilteringObjective) objectives.get(6);
+        forwardingObjective = (ForwardingObjective) objectives.get(7);
+        nextObjective = (NextObjective) objectives.get(8);
+        filteringSelector = vlan100Selector;
+        expectTreatment = DefaultTrafficTreatment
+                .builder()
+                .setVlanId(VLAN_1)
+                .setOutput(PortNumber.portNumber(2))
+                .build();
+        expectSelector = DefaultTrafficSelector
+                .builder(ethDstSelector)
+                .matchInPort(PortNumber.portNumber(1))
+                .matchVlanId(VLAN_100)
+                .build();
+        // test case for 3rd filtering objective
+        checkFiltering(filteringObjective, inPortCriterion, intent.priority(),
+                       null, appId, true, filteringSelector.criteria());
+        // test case for 3rd next objective
+        checkNext(nextObjective, SIMPLE, expectTreatment, expectSelector, ADD);
+        // test case for 3rd forwarding objective
+        checkForward(forwardingObjective, ADD, expectSelector, nextObjective.id(), SPECIFIC);
+        /*
+         * 4th set of objective
+         */
+        filteringObjective = (FilteringObjective) objectives.get(9);
+        forwardingObjective = (ForwardingObjective) objectives.get(10);
+        nextObjective = (NextObjective) objectives.get(11);
+        filteringSelector = vlan1Selector;
+        expectSelector = DefaultTrafficSelector
+                .builder()
+                .matchInPort(PortNumber.portNumber(1))
+                .matchVlanId(VLAN_1)
+                .build();
+        // test case for 4th filtering objective
+        checkFiltering(filteringObjective, inPortCriterion, intent.priority(),
+                       null, appId, true, filteringSelector.criteria());
+        // test case for 4th next objective
+        checkNext(nextObjective, SIMPLE, expectTreatment, expectSelector, ADD);
+        // test case for 4th forwarding objective
+        checkForward(forwardingObjective, ADD, expectSelector, nextObjective.id(), SPECIFIC);
+
+        /*
+         * 5th set of objective
+         */
+        filteringObjective = (FilteringObjective) objectives.get(12);
+        forwardingObjective = (ForwardingObjective) objectives.get(13);
+        nextObjective = (NextObjective) objectives.get(14);
+        expectSelector = DefaultTrafficSelector.builder()
+                .matchVlanId(VlanId.vlanId("1"))
+                .matchInPort(PortNumber.portNumber(3))
+                .build();
+        inPortCriterion =
+                (PortCriterion) expectSelector.getCriterion(Criterion.Type.IN_PORT);
+        // test case for 5th filtering objective
+        checkFiltering(filteringObjective, inPortCriterion, intent.priority(),
+                       null, appId, true, filteringSelector.criteria());
+        // test case for 5th next objective
+        checkNext(nextObjective, SIMPLE, expectTreatment, expectSelector, ADD);
+        // test case for 5th forwarding objective
+        checkForward(forwardingObjective, ADD, expectSelector,
+                     nextObjective.id(), SPECIFIC);
+    }
+
+    private void checkFiltering(FilteringObjective filteringObjective,
+                           Criterion key,
+                           int priority,
+                           TrafficSelector meta,
+                           ApplicationId appId,
+                           boolean permanent,
+                           Collection<Criterion> conditions) {
+        conditions = ImmutableList.copyOf(conditions);
+        assertThat(filteringObjective.key(), is(key));
+        assertThat(filteringObjective.priority(), is(priority));
+        assertThat(filteringObjective.meta(), is(meta));
+        assertThat(filteringObjective.appId(), is(appId));
+        assertThat(filteringObjective.permanent(), is(permanent));
+        assertThat(filteringObjective.conditions(), is(conditions));
+    }
+
+    private void checkNext(NextObjective nextObjective,
+                           NextObjective.Type type,
+                           TrafficTreatment next,
+                           TrafficSelector meta,
+                           Objective.Operation op) {
+        checkNext(nextObjective, type, ImmutableList.of(next), meta, op);
+    }
+
+    private void checkNext(NextObjective nextObjective,
+                           NextObjective.Type type,
+                           Collection<TrafficTreatment> next,
+                           TrafficSelector meta,
+                           Objective.Operation op) {
+        assertThat(nextObjective.type(), is(type));
+        assertThat(nextObjective.next().size(), is(next.size()));
+        assertThat(nextObjective.next().containsAll(next), is(true));
+        assertThat(nextObjective.meta(), is(meta));
+        assertThat(nextObjective.op(), is(op));
+    }
+
+    private void checkForward(ForwardingObjective forwardingObjective,
+                              Objective.Operation op,
+                              TrafficSelector selector,
+                              int nextId,
+                              ForwardingObjective.Flag flag) {
+        assertThat(forwardingObjective.op(), is(op));
+        assertThat(forwardingObjective.selector(), is(selector));
+        assertThat(forwardingObjective.nextId(), is(nextId));
+        assertThat(forwardingObjective.flag(), is(flag));
+    }
 }