/*
 * Copyright 2015-present Open Networking Laboratory
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.onosproject.net.intent.impl.compiler;

import com.google.common.collect.ImmutableList;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.Ethernet;
import org.onlab.packet.MplsLabel;
import org.onlab.packet.VlanId;
import org.onosproject.TestApplicationId;
import org.onosproject.cfg.ComponentConfigAdapter;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.core.IdGenerator;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultLink;
import org.onosproject.net.DefaultPath;
import org.onosproject.net.DeviceId;
import org.onosproject.net.EncapsulationType;
import org.onosproject.net.Link;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.flow.instructions.L2ModificationInstruction;
import org.onosproject.net.intent.FlowRuleIntent;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentExtensionService;
import org.onosproject.net.intent.MockIdGenerator;
import org.onosproject.net.intent.PathIntent;
import org.onosproject.net.intent.constraint.EncapsulationConstraint;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.net.resource.MockResourceService;

import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.lessThan;
import static org.hamcrest.number.OrderingComparison.greaterThan;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import static org.onosproject.net.DefaultEdgeLink.createEdgeLink;
import static org.onosproject.net.Link.Type.DIRECT;
import static org.onosproject.net.Link.Type.INDIRECT;
import static org.onosproject.net.NetTestTools.APP_ID;
import static org.onosproject.net.NetTestTools.PID;
import static org.onosproject.net.NetTestTools.connectPoint;

/**
 * Unit tests for PathIntentCompiler.
 */
public class PathIntentCompilerTest {

    private CoreService coreService;
    private IntentExtensionService intentExtensionService;
    private IntentConfigurableRegistrator registrator;
    private IdGenerator idGenerator = new MockIdGenerator();
    private PathIntentCompiler sut;

    private final TrafficSelector selector = DefaultTrafficSelector.builder().build();
    private final TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
    private final VlanId ingressVlan = VlanId.vlanId(((short) 101));
    private final TrafficSelector vlanSelector = DefaultTrafficSelector.builder()
            .matchVlanId(ingressVlan).build();
    private final VlanId egressVlan = VlanId.vlanId((short) 100);
    private final TrafficTreatment vlanTreatment = DefaultTrafficTreatment.builder()
            .setVlanId(egressVlan).build();

    private final ApplicationId appId = new TestApplicationId("test");
    private final ProviderId pid = new ProviderId("of", "test");

    // Edge scenario
    private final ConnectPoint d1p2 = connectPoint("s1", 2);
    private final ConnectPoint d1p3 = connectPoint("s1", 3);
    private final List<Link> edgeNet = Arrays.asList(
            createEdgeLink(d1p2, true),
            createEdgeLink(d1p3, false)
    );
    private final int edgeHops = edgeNet.size() - 1;
    private PathIntent edgeIntentNoVlan;
    private PathIntent edgeIntentIngressVlan;
    private PathIntent edgeIntentEgressVlan;
    private PathIntent edgeIntentVlan;

    // Single-hop scenario - indirect
    private final ConnectPoint d1p4 = connectPoint("s1", 4);
    private final ConnectPoint d2p2 = connectPoint("s2", 2);
    private final ConnectPoint d2p3 = connectPoint("s2", 3);
    private final ConnectPoint d3p2 = connectPoint("s3", 2);
    private final List<Link> singleHopIndirect = Arrays.asList(
            DefaultLink.builder().providerId(PID).src(d1p4).dst(d2p2).type(DIRECT).build(),
            DefaultLink.builder().providerId(PID).src(d2p3).dst(d3p2).type(INDIRECT).build()
    );
    private final int singleHopIndirectHops = singleHopIndirect.size() - 1;
    private PathIntent singleHopIndirectIntentNoVlan;
    private PathIntent singleHopIndirectIntentIngressVlan;
    private PathIntent singleHopIndirectIntentEgressVlan;
    private PathIntent singleHopIndirectIntentVlan;


    // Single-hop scenario- direct
    private final ConnectPoint d1p5 = connectPoint("s1", 5);
    private final ConnectPoint d2p4 = connectPoint("s2", 4);
    private final ConnectPoint d2p5 = connectPoint("s2", 5);
    private final ConnectPoint d3p3 = connectPoint("s3", 3);
    private final List<Link> singleHopDirect = Arrays.asList(
            DefaultLink.builder().providerId(PID).src(d1p5).dst(d2p4).type(DIRECT).build(),
            DefaultLink.builder().providerId(PID).src(d2p5).dst(d3p3).type(DIRECT).build()
    );
    private final int singleHopDirectHops = singleHopDirect.size() - 1;
    private PathIntent singleHopDirectIntentNoVlan;
    private PathIntent singleHopDirectIntentIngressVlan;
    private PathIntent singleHopDirectIntentEgressVlan;
    private PathIntent singleHopDirectIntentVlan;


    // Multi-hop scenario
    private final ConnectPoint d1p1 = connectPoint("s1", 0);
    private final ConnectPoint d2p0 = connectPoint("s2", 0);
    private final ConnectPoint d2p1 = connectPoint("s2", 1);
    private final ConnectPoint d3p1 = connectPoint("s3", 1);
    private final ConnectPoint d3p0 = connectPoint("s3", 10);
    private final ConnectPoint d1p0 = connectPoint("s1", 10);
    private static final int PRIORITY = 555;

    private final List<Link> links = Arrays.asList(
            createEdgeLink(d1p0, true),
            DefaultLink.builder().providerId(PID).src(d1p1).dst(d2p0).type(DIRECT).build(),
            DefaultLink.builder().providerId(PID).src(d2p1).dst(d3p1).type(DIRECT).build(),
            createEdgeLink(d3p0, false)
    );
    private final int hops = links.size() - 1;
    private PathIntent intent;
    private PathIntent constraintVlanIntent;
    private PathIntent constrainIngressEgressVlanIntent;
    private PathIntent constraintMplsIntent;

    /**
     * Configures mock objects used in all the test cases.
     * Creates the intents to test as well.
     */
    @Before
    public void setUp() {
        sut = new PathIntentCompiler();
        coreService = createMock(CoreService.class);
        expect(coreService.registerApplication("org.onosproject.net.intent"))
                .andReturn(appId);
        sut.coreService = coreService;
        sut.resourceService = new MockResourceService();

        Intent.bindIdGenerator(idGenerator);

        intent = PathIntent.builder()
                .appId(APP_ID)
                .selector(selector)
                .treatment(treatment)
                .priority(PRIORITY)
                .path(new DefaultPath(pid, links, hops))
                .build();

        //Intent with VLAN encap without egress VLAN
        constraintVlanIntent = PathIntent.builder()
                .appId(APP_ID)
                .selector(selector)
                .treatment(treatment)
                .priority(PRIORITY)
                .constraints(ImmutableList.of(new EncapsulationConstraint(EncapsulationType.VLAN)))
                .path(new DefaultPath(pid, links, hops))
                .build();

        //Intent with VLAN encap with ingress and egress VLAN
        constrainIngressEgressVlanIntent = PathIntent.builder()
                .appId(APP_ID)
                .selector(vlanSelector)
                .treatment(vlanTreatment)
                .priority(PRIORITY)
                .constraints(ImmutableList.of(new EncapsulationConstraint(EncapsulationType.VLAN)))
                .path(new DefaultPath(pid, links, hops))
                .build();

        constraintMplsIntent = PathIntent.builder()
                .appId(APP_ID)
                .selector(selector)
                .treatment(treatment)
                .priority(PRIORITY)
                .constraints(ImmutableList.of(new EncapsulationConstraint(EncapsulationType.MPLS)))
                .path(new DefaultPath(pid, links, hops))
                .build();

        edgeIntentNoVlan = PathIntent.builder()
                .appId(APP_ID)
                .selector(selector)
                .treatment(treatment)
                .priority(PRIORITY)
                .constraints(ImmutableList.of(new EncapsulationConstraint(EncapsulationType.VLAN)))
                .path(new DefaultPath(pid, edgeNet, edgeHops))
                .build();

        edgeIntentIngressVlan = PathIntent.builder()
                .appId(APP_ID)
                .selector(vlanSelector)
                .treatment(treatment)
                .priority(PRIORITY)
                .constraints(ImmutableList.of(new EncapsulationConstraint(EncapsulationType.VLAN)))
                .path(new DefaultPath(pid, edgeNet, edgeHops))
                .build();

        edgeIntentEgressVlan = PathIntent.builder()
                .appId(APP_ID)
                .selector(selector)
                .treatment(vlanTreatment)
                .priority(PRIORITY)
                .constraints(ImmutableList.of(new EncapsulationConstraint(EncapsulationType.VLAN)))
                .path(new DefaultPath(pid, edgeNet, edgeHops))
                .build();

        edgeIntentVlan = PathIntent.builder()
                .appId(APP_ID)
                .selector(vlanSelector)
                .treatment(vlanTreatment)
                .priority(PRIORITY)
                .constraints(ImmutableList.of(new EncapsulationConstraint(EncapsulationType.VLAN)))
                .path(new DefaultPath(pid, edgeNet, edgeHops))
                .build();

        singleHopIndirectIntentNoVlan = PathIntent.builder()
                .appId(APP_ID)
                .selector(selector)
                .treatment(treatment)
                .priority(PRIORITY)
                .constraints(ImmutableList.of(new EncapsulationConstraint(EncapsulationType.VLAN)))
                .path(new DefaultPath(pid, singleHopIndirect, singleHopIndirectHops))
                .build();

        singleHopIndirectIntentIngressVlan = PathIntent.builder()
                .appId(APP_ID)
                .selector(vlanSelector)
                .treatment(treatment)
                .priority(PRIORITY)
                .constraints(ImmutableList.of(new EncapsulationConstraint(EncapsulationType.VLAN)))
                .path(new DefaultPath(pid, singleHopIndirect, singleHopIndirectHops))
                .build();

        singleHopIndirectIntentEgressVlan = PathIntent.builder()
                .appId(APP_ID)
                .selector(selector)
                .treatment(vlanTreatment)
                .priority(PRIORITY)
                .constraints(ImmutableList.of(new EncapsulationConstraint(EncapsulationType.VLAN)))
                .path(new DefaultPath(pid, singleHopIndirect, singleHopIndirectHops))
                .build();

        singleHopIndirectIntentVlan = PathIntent.builder()
                .appId(APP_ID)
                .selector(vlanSelector)
                .treatment(vlanTreatment)
                .priority(PRIORITY)
                .constraints(ImmutableList.of(new EncapsulationConstraint(EncapsulationType.VLAN)))
                .path(new DefaultPath(pid, singleHopIndirect, singleHopIndirectHops))
                .build();

        singleHopDirectIntentNoVlan = PathIntent.builder()
                .appId(APP_ID)
                .selector(selector)
                .treatment(treatment)
                .priority(PRIORITY)
                .constraints(ImmutableList.of(new EncapsulationConstraint(EncapsulationType.VLAN)))
                .path(new DefaultPath(pid, singleHopDirect, singleHopDirectHops))
                .build();

        singleHopDirectIntentIngressVlan = PathIntent.builder()
                .appId(APP_ID)
                .selector(vlanSelector)
                .treatment(treatment)
                .priority(PRIORITY)
                .constraints(ImmutableList.of(new EncapsulationConstraint(EncapsulationType.VLAN)))
                .path(new DefaultPath(pid, singleHopDirect, singleHopDirectHops))
                .build();

        singleHopDirectIntentEgressVlan = PathIntent.builder()
                .appId(APP_ID)
                .selector(selector)
                .treatment(vlanTreatment)
                .priority(PRIORITY)
                .constraints(ImmutableList.of(new EncapsulationConstraint(EncapsulationType.VLAN)))
                .path(new DefaultPath(pid, singleHopDirect, singleHopDirectHops))
                .build();

        singleHopDirectIntentVlan = PathIntent.builder()
                .appId(APP_ID)
                .selector(vlanSelector)
                .treatment(vlanTreatment)
                .priority(PRIORITY)
                .constraints(ImmutableList.of(new EncapsulationConstraint(EncapsulationType.VLAN)))
                .path(new DefaultPath(pid, singleHopDirect, singleHopDirectHops))
                .build();

        intentExtensionService = createMock(IntentExtensionService.class);
        intentExtensionService.registerCompiler(PathIntent.class, sut);
        intentExtensionService.unregisterCompiler(PathIntent.class);

        registrator = new IntentConfigurableRegistrator();
        registrator.extensionService = intentExtensionService;
        registrator.cfgService = new ComponentConfigAdapter();
        registrator.activate();

        sut.registrator = registrator;

        replay(coreService, intentExtensionService);
    }

    /**
     * Tears down objects used in all the test cases.
     */
    @After
    public void tearDown() {
        Intent.unbindIdGenerator(idGenerator);
    }


    /**
     * Tests the compilation behavior of the path intent compiler in case of
     * VLAN {@link EncapsulationType} encapsulation constraint {@link EncapsulationConstraint}
     * and edge communication. No ingress VLAN. No egress VLAN.
     */
    @Test
    public void testVlanEncapCompileEdgeNoVlan() {
        sut.activate();

        List<Intent> compiled = sut.compile(edgeIntentNoVlan, Collections.emptyList());
        assertThat(compiled, hasSize(1));

        Collection<FlowRule> rules = ((FlowRuleIntent) compiled.get(0)).flowRules();
        assertThat(rules, hasSize(1));

        FlowRule rule = rules.stream()
                .filter(x -> x.deviceId().equals(d1p2.deviceId()))
                .findFirst()
                .get();
        verifyIdAndPriority(rule, d1p2.deviceId());

        assertThat(rule.selector(), is(DefaultTrafficSelector.builder().matchInPort(d1p2.port())
                                               .build()));
        assertThat(rule.treatment(),
                   is(DefaultTrafficTreatment.builder().setOutput(d1p3.port()).build()));

        sut.deactivate();
    }

    /**
     * Tests the compilation behavior of the path intent compiler in case of
     * VLAN {@link EncapsulationType} encapsulation constraint {@link EncapsulationConstraint}
     * and edge communication. Ingress VLAN. No egress VLAN.
     */
    @Test
    public void testVlanEncapCompileEdgeIngressVlan() {
        sut.activate();

        List<Intent> compiled = sut.compile(edgeIntentIngressVlan, Collections.emptyList());
        assertThat(compiled, hasSize(1));

        Collection<FlowRule> rules = ((FlowRuleIntent) compiled.get(0)).flowRules();
        assertThat(rules, hasSize(1));

        FlowRule rule = rules.stream()
                .filter(x -> x.deviceId().equals(d1p2.deviceId()))
                .findFirst()
                .get();
        verifyIdAndPriority(rule, d1p2.deviceId());

        assertThat(rule.selector(), is(DefaultTrafficSelector.builder().matchInPort(d1p2.port())
                                               .matchVlanId(ingressVlan).build()));
        assertThat(rule.treatment(),
                   is(DefaultTrafficTreatment.builder().setOutput(d1p3.port()).build()));

        sut.deactivate();
    }

    /**
     * Tests the compilation behavior of the path intent compiler in case of
     * VLAN {@link EncapsulationType} encapsulation constraint {@link EncapsulationConstraint}
     * and edge communication. No ingress VLAN. Egress VLAN.
     */
    @Test
    public void testVlanEncapCompileEdgeEgressVlan() {
        sut.activate();

        List<Intent> compiled = sut.compile(edgeIntentEgressVlan, Collections.emptyList());
        assertThat(compiled, hasSize(1));

        Collection<FlowRule> rules = ((FlowRuleIntent) compiled.get(0)).flowRules();
        assertThat(rules, hasSize(1));

        FlowRule rule = rules.stream()
                .filter(x -> x.deviceId().equals(d1p2.deviceId()))
                .findFirst()
                .get();
        verifyIdAndPriority(rule, d1p2.deviceId());

        assertThat(rule.selector(), is(DefaultTrafficSelector.builder().matchInPort(d1p2.port())
                                               .build()));
        assertThat(rule.treatment(), is(DefaultTrafficTreatment.builder().setVlanId(egressVlan)
                                                .setOutput(d1p3.port()).build()));

        Set<L2ModificationInstruction.ModVlanIdInstruction> vlanMod = rule.treatment().allInstructions().stream()
                .filter(treat -> treat instanceof L2ModificationInstruction.ModVlanIdInstruction)
                .map(x -> (L2ModificationInstruction.ModVlanIdInstruction) x)
                .collect(Collectors.toSet());
        assertThat(rule.treatment().allInstructions().stream()
                           .filter(treat -> treat instanceof L2ModificationInstruction.ModVlanIdInstruction)
                           .collect(Collectors.toSet()), hasSize(1));
        assertThat(vlanMod.iterator().next().vlanId(), is(egressVlan));
        assertThat(rule.treatment().allInstructions().stream()
                           .filter(treat -> treat instanceof L2ModificationInstruction.ModVlanHeaderInstruction)
                           .collect(Collectors.toSet()), hasSize(0));

        sut.deactivate();
    }

    /**
     * Tests the compilation behavior of the path intent compiler in case of
     * VLAN {@link EncapsulationType} encapsulation constraint {@link EncapsulationConstraint}
     * and edge communication. Ingress VLAN. Egress VLAN.
     */
    @Test
    public void testVlanEncapCompileEdgeVlan() {
        sut.activate();

        List<Intent> compiled = sut.compile(edgeIntentVlan, Collections.emptyList());
        assertThat(compiled, hasSize(1));

        Collection<FlowRule> rules = ((FlowRuleIntent) compiled.get(0)).flowRules();
        assertThat(rules, hasSize(1));

        FlowRule rule = rules.stream()
                .filter(x -> x.deviceId().equals(d1p2.deviceId()))
                .findFirst()
                .get();
        verifyIdAndPriority(rule, d1p2.deviceId());

        assertThat(rule.selector(), is(DefaultTrafficSelector.builder().matchInPort(d1p2.port())
                                               .matchVlanId(ingressVlan).build()));
        assertThat(rule.treatment(), is(DefaultTrafficTreatment.builder().setVlanId(egressVlan)
                                                .setOutput(d1p3.port()).build()));

        Set<L2ModificationInstruction.ModVlanIdInstruction> vlanMod = rule.treatment().allInstructions().stream()
                .filter(treat -> treat instanceof L2ModificationInstruction.ModVlanIdInstruction)
                .map(x -> (L2ModificationInstruction.ModVlanIdInstruction) x)
                .collect(Collectors.toSet());
        assertThat(rule.treatment().allInstructions().stream()
                           .filter(treat -> treat instanceof L2ModificationInstruction.ModVlanIdInstruction)
                           .collect(Collectors.toSet()), hasSize(1));
        assertThat(vlanMod.iterator().next().vlanId(), is(egressVlan));
        assertThat(rule.treatment().allInstructions().stream()
                           .filter(treat -> treat instanceof L2ModificationInstruction.ModVlanHeaderInstruction)
                           .collect(Collectors.toSet()), hasSize(0));

        sut.deactivate();
    }

    /**
     * Tests the compilation behavior of the path intent compiler in case of
     * VLAN {@link EncapsulationType} encapsulation constraint {@link EncapsulationConstraint}
     * and single-hop-indirect-link scenario. No ingress VLAN. No egress VLAN.
     */
    @Test
    public void testVlanEncapCompileSingleHopIndirectNoVlan() {
        sut.activate();

        List<Intent> compiled = sut.compile(singleHopIndirectIntentNoVlan, Collections.emptyList());
        assertThat(compiled, hasSize(1));

        Collection<FlowRule> rules = ((FlowRuleIntent) compiled.get(0)).flowRules();
        assertThat(rules, hasSize(1));


        FlowRule rule = rules.stream()
                .filter(x -> x.deviceId().equals(d2p2.deviceId()))
                .findFirst()
                .get();
        verifyIdAndPriority(rule, d2p2.deviceId());

        assertThat(rule.selector(), is(DefaultTrafficSelector.builder().matchInPort(d2p2.port())
                                               .build()));
        assertThat(rule.treatment(),
                   is(DefaultTrafficTreatment.builder().setOutput(d2p3.port()).build()));

        sut.deactivate();
    }

    /**
     * Tests the compilation behavior of the path intent compiler in case of
     * VLAN {@link EncapsulationType} encapsulation constraint {@link EncapsulationConstraint}
     * and single-hop-indirect-link scenario. Ingress VLAN. No egress VLAN.
     */
    @Test
    public void testVlanEncapCompileSingleHopIndirectIngressVlan() {
        sut.activate();

        List<Intent> compiled = sut.compile(singleHopIndirectIntentIngressVlan, Collections.emptyList());
        assertThat(compiled, hasSize(1));

        Collection<FlowRule> rules = ((FlowRuleIntent) compiled.get(0)).flowRules();
        assertThat(rules, hasSize(1));


        FlowRule rule = rules.stream()
                .filter(x -> x.deviceId().equals(d2p2.deviceId()))
                .findFirst()
                .get();
        verifyIdAndPriority(rule, d2p2.deviceId());

        assertThat(rule.selector(), is(DefaultTrafficSelector.builder().matchInPort(d2p2.port())
                                               .matchVlanId(ingressVlan).build()));
        assertThat(rule.treatment(),
                   is(DefaultTrafficTreatment.builder().setOutput(d2p3.port()).build()));

        sut.deactivate();
    }

    /**
     * Tests the compilation behavior of the path intent compiler in case of
     * VLAN {@link EncapsulationType} encapsulation constraint {@link EncapsulationConstraint}
     * and single-hop-indirect-link scenario. No ingress VLAN. Egress VLAN.
     */
    @Test
    public void testVlanEncapCompileSingleHopIndirectEgressVlan() {
        sut.activate();

        List<Intent> compiled = sut.compile(singleHopIndirectIntentEgressVlan, Collections.emptyList());
        assertThat(compiled, hasSize(1));

        Collection<FlowRule> rules = ((FlowRuleIntent) compiled.get(0)).flowRules();
        assertThat(rules, hasSize(1));


        FlowRule rule = rules.stream()
                .filter(x -> x.deviceId().equals(d2p2.deviceId()))
                .findFirst()
                .get();
        verifyIdAndPriority(rule, d2p2.deviceId());

        assertThat(rule.selector(), is(DefaultTrafficSelector.builder().matchInPort(d2p2.port())
                                               .build()));
        assertThat(rule.treatment(), is(DefaultTrafficTreatment.builder().setVlanId(egressVlan)
                              .setOutput(d2p3.port()).build()));

        Set<L2ModificationInstruction.ModVlanIdInstruction> vlanMod = rule.treatment().allInstructions().stream()
                .filter(treat -> treat instanceof L2ModificationInstruction.ModVlanIdInstruction)
                .map(x -> (L2ModificationInstruction.ModVlanIdInstruction) x)
                .collect(Collectors.toSet());
        assertThat(rule.treatment().allInstructions().stream()
                           .filter(treat -> treat instanceof L2ModificationInstruction.ModVlanIdInstruction)
                           .collect(Collectors.toSet()), hasSize(1));
        assertThat(vlanMod.iterator().next().vlanId(), is(egressVlan));
        assertThat(rule.treatment().allInstructions().stream()
                           .filter(treat -> treat instanceof L2ModificationInstruction.ModVlanHeaderInstruction)
                           .collect(Collectors.toSet()), hasSize(0));

        sut.deactivate();
    }

    /**
     * Tests the compilation behavior of the path intent compiler in case of
     * VLAN {@link EncapsulationType} encapsulation constraint {@link EncapsulationConstraint}
     * and single-hop-indirect-link scenario. Ingress VLAN. Egress VLAN.
     */
    @Test
    public void testVlanEncapCompileSingleHopIndirectVlan() {
        sut.activate();

        List<Intent> compiled = sut.compile(singleHopIndirectIntentVlan, Collections.emptyList());
        assertThat(compiled, hasSize(1));

        Collection<FlowRule> rules = ((FlowRuleIntent) compiled.get(0)).flowRules();
        assertThat(rules, hasSize(1));


        FlowRule rule = rules.stream()
                .filter(x -> x.deviceId().equals(d2p2.deviceId()))
                .findFirst()
                .get();
        verifyIdAndPriority(rule, d2p2.deviceId());

        assertThat(rule.selector(), is(DefaultTrafficSelector.builder().matchInPort(d2p2.port())
                                               .matchVlanId(ingressVlan).build()));
        assertThat(rule.treatment(), is(DefaultTrafficTreatment.builder().setVlanId(egressVlan)
                                                .setOutput(d2p3.port()).build()));

        Set<L2ModificationInstruction.ModVlanIdInstruction> vlanMod = rule.treatment().allInstructions().stream()
                .filter(treat -> treat instanceof L2ModificationInstruction.ModVlanIdInstruction)
                .map(x -> (L2ModificationInstruction.ModVlanIdInstruction) x)
                .collect(Collectors.toSet());
        assertThat(rule.treatment().allInstructions().stream()
                           .filter(treat -> treat instanceof L2ModificationInstruction.ModVlanIdInstruction)
                           .collect(Collectors.toSet()), hasSize(1));
        assertThat(vlanMod.iterator().next().vlanId(), is(egressVlan));
        assertThat(rule.treatment().allInstructions().stream()
                           .filter(treat -> treat instanceof L2ModificationInstruction.ModVlanHeaderInstruction)
                           .collect(Collectors.toSet()), hasSize(0));

        sut.deactivate();
    }

    /**
     * Tests the compilation behavior of the path intent compiler in case of
     * VLAN {@link EncapsulationType} encapsulation constraint {@link EncapsulationConstraint}
     * and single-hop-direct-link scenario. No ingress VLAN. No egress VLAN.
     */
    @Test
    public void testVlanEncapCompileSingleHopDirectNoVlan() {
        sut.activate();

        List<Intent> compiled = sut.compile(singleHopDirectIntentNoVlan, Collections.emptyList());
        assertThat(compiled, hasSize(1));

        Collection<FlowRule> rules = ((FlowRuleIntent) compiled.get(0)).flowRules();
        assertThat(rules, hasSize(1));


        FlowRule rule = rules.stream()
                .filter(x -> x.deviceId().equals(d2p4.deviceId()))
                .findFirst()
                .get();
        verifyIdAndPriority(rule, d2p4.deviceId());

        assertThat(rule.selector(), is(DefaultTrafficSelector.builder().matchInPort(d2p4.port())
                                               .build()));
        assertThat(rule.treatment(),
                   is(DefaultTrafficTreatment.builder().setOutput(d2p5.port()).build()));

        sut.deactivate();
    }

    /**
     * Tests the compilation behavior of the path intent compiler in case of
     * VLAN {@link EncapsulationType} encapsulation constraint {@link EncapsulationConstraint}
     * and single-hop-direct-link scenario. Ingress VLAN. No egress VLAN.
     */
    @Test
    public void testVlanEncapCompileSingleHopDirectIngressVlan() {
        sut.activate();

        List<Intent> compiled = sut.compile(singleHopDirectIntentIngressVlan, Collections.emptyList());
        assertThat(compiled, hasSize(1));

        Collection<FlowRule> rules = ((FlowRuleIntent) compiled.get(0)).flowRules();
        assertThat(rules, hasSize(1));


        FlowRule rule = rules.stream()
                .filter(x -> x.deviceId().equals(d2p4.deviceId()))
                .findFirst()
                .get();
        verifyIdAndPriority(rule, d2p4.deviceId());

        assertThat(rule.selector(), is(DefaultTrafficSelector.builder().matchInPort(d2p4.port())
                                               .matchVlanId(ingressVlan).build()));
        assertThat(rule.treatment(),
                   is(DefaultTrafficTreatment.builder().setOutput(d2p5.port()).build()));

        sut.deactivate();
    }

    /**
     * Tests the compilation behavior of the path intent compiler in case of
     * VLAN {@link EncapsulationType} encapsulation constraint {@link EncapsulationConstraint}
     * and single-hop-direct-link scenario. No ingress VLAN. Egress VLAN.
     */
    @Test
    public void testVlanEncapCompileSingleHopDirectEgressVlan() {
        sut.activate();

        List<Intent> compiled = sut.compile(singleHopDirectIntentEgressVlan, Collections.emptyList());
        assertThat(compiled, hasSize(1));

        Collection<FlowRule> rules = ((FlowRuleIntent) compiled.get(0)).flowRules();
        assertThat(rules, hasSize(1));


        FlowRule rule = rules.stream()
                .filter(x -> x.deviceId().equals(d2p4.deviceId()))
                .findFirst()
                .get();
        verifyIdAndPriority(rule, d2p4.deviceId());

        assertThat(rule.selector(), is(DefaultTrafficSelector.builder().matchInPort(d2p4.port())
                                               .build()));
        assertThat(rule.treatment(), is(DefaultTrafficTreatment.builder().setVlanId(egressVlan)
                                                .setOutput(d2p5.port()).build()));

        Set<L2ModificationInstruction.ModVlanIdInstruction> vlanMod = rule.treatment().allInstructions().stream()
                .filter(treat -> treat instanceof L2ModificationInstruction.ModVlanIdInstruction)
                .map(x -> (L2ModificationInstruction.ModVlanIdInstruction) x)
                .collect(Collectors.toSet());
        assertThat(rule.treatment().allInstructions().stream()
                           .filter(treat -> treat instanceof L2ModificationInstruction.ModVlanIdInstruction)
                           .collect(Collectors.toSet()), hasSize(1));
        assertThat(vlanMod.iterator().next().vlanId(), is(egressVlan));
        assertThat(rule.treatment().allInstructions().stream()
                           .filter(treat -> treat instanceof L2ModificationInstruction.ModVlanHeaderInstruction)
                           .collect(Collectors.toSet()), hasSize(0));

        sut.deactivate();
    }

    /**
     * Tests the compilation behavior of the path intent compiler in case of
     * VLAN {@link EncapsulationType} encapsulation constraint {@link EncapsulationConstraint}
     * and single-hop-direct-link scenario. Ingress VLAN. Egress VLAN.
     */
    @Test
    public void testVlanEncapCompileSingleHopDirectVlan() {
        sut.activate();

        List<Intent> compiled = sut.compile(singleHopDirectIntentVlan, Collections.emptyList());
        assertThat(compiled, hasSize(1));

        Collection<FlowRule> rules = ((FlowRuleIntent) compiled.get(0)).flowRules();
        assertThat(rules, hasSize(1));


        FlowRule rule = rules.stream()
                .filter(x -> x.deviceId().equals(d2p4.deviceId()))
                .findFirst()
                .get();
        verifyIdAndPriority(rule, d2p4.deviceId());

        assertThat(rule.selector(), is(DefaultTrafficSelector.builder().matchInPort(d2p4.port())
                                               .matchVlanId(ingressVlan).build()));
        assertThat(rule.treatment(), is(DefaultTrafficTreatment.builder().setVlanId(egressVlan)
                                                .setOutput(d2p5.port()).build()));

        Set<L2ModificationInstruction.ModVlanIdInstruction> vlanMod = rule.treatment().allInstructions().stream()
                .filter(treat -> treat instanceof L2ModificationInstruction.ModVlanIdInstruction)
                .map(x -> (L2ModificationInstruction.ModVlanIdInstruction) x)
                .collect(Collectors.toSet());
        assertThat(rule.treatment().allInstructions().stream()
                           .filter(treat -> treat instanceof L2ModificationInstruction.ModVlanIdInstruction)
                           .collect(Collectors.toSet()), hasSize(1));
        assertThat(vlanMod.iterator().next().vlanId(), is(egressVlan));
        assertThat(rule.treatment().allInstructions().stream()
                           .filter(treat -> treat instanceof L2ModificationInstruction.ModVlanHeaderInstruction)
                           .collect(Collectors.toSet()), hasSize(0));

        sut.deactivate();
    }

    /**
     * Tests the compilation behavior of the path intent compiler.
     */
    @Test
    public void testCompile() {
        sut.activate();

        List<Intent> compiled = sut.compile(intent, Collections.emptyList());
        assertThat(compiled, hasSize(1));

        Collection<FlowRule> rules = ((FlowRuleIntent) compiled.get(0)).flowRules();

        FlowRule rule1 = rules.stream()
                .filter(x -> x.deviceId().equals(d1p0.deviceId()))
                .findFirst()
                .get();
        verifyIdAndPriority(rule1, d1p0.deviceId());
        assertThat(rule1.selector(),
                is(DefaultTrafficSelector.builder(selector).matchInPort(d1p0.port()).build()));
        assertThat(rule1.treatment(),
                is(DefaultTrafficTreatment.builder().setOutput(d1p1.port()).build()));


        FlowRule rule2 = rules.stream()
                .filter(x -> x.deviceId().equals(d2p0.deviceId()))
                .findFirst()
                .get();
        verifyIdAndPriority(rule2, d2p0.deviceId());
        assertThat(rule2.selector(),
                is(DefaultTrafficSelector.builder(selector).matchInPort(d2p0.port()).build()));
        assertThat(rule2.treatment(),
                is(DefaultTrafficTreatment.builder().setOutput(d2p1.port()).build()));

        FlowRule rule3 = rules.stream()
                .filter(x -> x.deviceId().equals(d3p0.deviceId()))
                .findFirst()
                .get();
        verifyIdAndPriority(rule3, d3p1.deviceId());
        assertThat(rule3.selector(),
                is(DefaultTrafficSelector.builder(selector).matchInPort(d3p1.port()).build()));
        assertThat(rule3.treatment(),
                is(DefaultTrafficTreatment.builder(treatment).setOutput(d3p0.port()).build()));

        sut.deactivate();
    }

    /**
     * Tests the compilation behavior of the path intent compiler in case of
     * VLAN {@link EncapsulationType} encapsulation constraint {@link EncapsulationConstraint}.
     */
    @Test
    public void testVlanEncapCompile() {
        sut.activate();

        List<Intent> compiled = sut.compile(constraintVlanIntent, Collections.emptyList());
        assertThat(compiled, hasSize(1));

        Collection<FlowRule> rules = ((FlowRuleIntent) compiled.get(0)).flowRules();
        assertThat(rules, hasSize(3));

        FlowRule rule1 = rules.stream()
                .filter(x -> x.deviceId().equals(d1p0.deviceId()))
                .findFirst()
                .get();
        verifyIdAndPriority(rule1, d1p0.deviceId());
        assertThat(rule1.selector(), is(DefaultTrafficSelector.builder(selector)
                                        .matchInPort(d1p0.port()).build()));
        VlanId vlanToEncap = verifyVlanEncapTreatment(rule1.treatment(), d1p1, true, false);

        FlowRule rule2 = rules.stream()
                .filter(x -> x.deviceId().equals(d2p0.deviceId()))
                .findFirst()
                .get();
        verifyIdAndPriority(rule2, d2p0.deviceId());
        verifyVlanEncapSelector(rule2.selector(), d2p0, vlanToEncap);
        vlanToEncap = verifyVlanEncapTreatment(rule2.treatment(), d2p1, false, false);

        FlowRule rule3 = rules.stream()
                .filter(x -> x.deviceId().equals(d3p0.deviceId()))
                .findFirst()
                .get();
        verifyIdAndPriority(rule3, d3p1.deviceId());
        verifyVlanEncapSelector(rule3.selector(), d3p1, vlanToEncap);
        verifyVlanEncapTreatment(rule3.treatment(), d3p0, false, true);

        sut.deactivate();
    }

    /**
     * Tests the compilation behavior of the path intent compiler in case of
     * VLAN {@link EncapsulationType} encapsulation constraint {@link EncapsulationConstraint}.
     * This test includes a selector to match a VLAN at the ingress and a treatment to set VLAN at the egress.
     */
    @Test
    public void testEncapIngressEgressVlansCompile() {
        sut.activate();

        List<Intent> compiled = sut.compile(constrainIngressEgressVlanIntent,
                Collections.emptyList());
        assertThat(compiled, hasSize(1));

        Collection<FlowRule> rules = ((FlowRuleIntent) compiled.get(0)).flowRules();
        assertThat(rules, hasSize(3));

        FlowRule rule1 = rules.stream()
                .filter(x -> x.deviceId().equals(d1p0.deviceId()))
                .findFirst()
                .get();
        verifyIdAndPriority(rule1, d1p0.deviceId());
        verifyVlanEncapSelector(rule1.selector(), d1p0, ingressVlan);
        VlanId vlanToEncap = verifyVlanEncapTreatment(rule1.treatment(), d1p1, true, false);

        FlowRule rule2 = rules.stream()
                .filter(x -> x.deviceId().equals(d2p0.deviceId()))
                .findFirst()
                .get();
        verifyIdAndPriority(rule2, d2p0.deviceId());
        verifyVlanEncapSelector(rule2.selector(), d2p0, vlanToEncap);
        vlanToEncap = verifyVlanEncapTreatment(rule2.treatment(), d2p1, false, false);

        FlowRule rule3 = rules.stream()
                .filter(x -> x.deviceId().equals(d3p0.deviceId()))
                .findFirst()
                .get();
        verifyIdAndPriority(rule3, d3p1.deviceId());
        verifyVlanEncapSelector(rule3.selector(), d3p1, vlanToEncap);
        Set<L2ModificationInstruction.ModVlanIdInstruction> vlanMod = rule3.treatment().allInstructions().stream()
                .filter(treat -> treat instanceof L2ModificationInstruction.ModVlanIdInstruction)
                .map(x -> (L2ModificationInstruction.ModVlanIdInstruction) x)
                .collect(Collectors.toSet());
        assertThat(rule3.treatment().allInstructions().stream()
                .filter(treat -> treat instanceof L2ModificationInstruction.ModVlanIdInstruction)
                .collect(Collectors.toSet()), hasSize(1));
        assertThat(vlanMod.iterator().next().vlanId(), is(egressVlan));
        assertThat(rule3.treatment().allInstructions().stream()
                .filter(treat -> treat instanceof L2ModificationInstruction.ModVlanHeaderInstruction)
                .collect(Collectors.toSet()), hasSize(0));

        sut.deactivate();
    }

    /**
     * Tests the random selection of VLAN Ids in the PathCompiler.
     * It can fail randomly (it is unlikely)
     */
    @Test
    public void testRandomVlanSelection() {

            sut.activate();

            List<Intent> compiled = sut.compile(constraintVlanIntent, Collections.emptyList());
            assertThat(compiled, hasSize(1));

            Collection<FlowRule> rules = ((FlowRuleIntent) compiled.get(0)).flowRules();
            assertThat(rules, hasSize(3));

            FlowRule rule1 = rules.stream()
                    .filter(x -> x.deviceId().equals(d1p0.deviceId()))
                    .findFirst()
                    .get();
            verifyIdAndPriority(rule1, d1p0.deviceId());
            assertThat(rule1.selector(), is(DefaultTrafficSelector.builder(selector)
                    .matchInPort(d1p0.port()).build()));

            VlanId vlanToEncap = verifyVlanEncapTreatment(rule1.treatment(), d1p1, true, false);

            assertTrue(VlanId.NO_VID < vlanToEncap.toShort() && vlanToEncap.toShort() < VlanId.MAX_VLAN);

            /*
             * This second part is meant to test if the random selection is working properly.
             * We are compiling the same intent in order to verify if the VLAN ID is different
             * from the previous one.
             */

            List<Intent> compiled2 = sut.compile(constraintVlanIntent, Collections.emptyList());
            assertThat(compiled2, hasSize(1));

            Collection<FlowRule> rules2 = ((FlowRuleIntent) compiled2.get(0)).flowRules();
            assertThat(rules2, hasSize(3));

            FlowRule rule2 = rules2.stream()
                    .filter(x -> x.deviceId().equals(d1p0.deviceId()))
                    .findFirst()
                    .get();
            verifyIdAndPriority(rule2, d1p0.deviceId());
            assertThat(rule2.selector(), is(DefaultTrafficSelector.builder(selector)
                    .matchInPort(d1p0.port()).build()));

            VlanId vlanToEncap2 = verifyVlanEncapTreatment(rule2.treatment(), d1p1, true, false);

            assertTrue(VlanId.NO_VID < vlanToEncap2.toShort() && vlanToEncap2.toShort() < VlanId.MAX_VLAN);
            assertNotEquals(vlanToEncap, vlanToEncap2);

            sut.deactivate();


    }

    private VlanId verifyVlanEncapTreatment(TrafficTreatment trafficTreatment,
                                        ConnectPoint egress, boolean isIngress, boolean isEgress) {
        Set<Instructions.OutputInstruction> ruleOutput = trafficTreatment.allInstructions().stream()
                .filter(treat -> treat instanceof Instructions.OutputInstruction)
                .map(treat -> (Instructions.OutputInstruction) treat)
                .collect(Collectors.toSet());
        assertThat(ruleOutput, hasSize(1));
        assertThat((ruleOutput.iterator().next()).port(), is(egress.port()));
        VlanId vlanToEncap = VlanId.NONE;
        if (isIngress && !isEgress) {
            Set<L2ModificationInstruction.ModVlanIdInstruction> vlanRules = trafficTreatment.allInstructions().stream()
                    .filter(treat -> treat instanceof L2ModificationInstruction.ModVlanIdInstruction)
                    .map(x -> (L2ModificationInstruction.ModVlanIdInstruction) x)
                    .collect(Collectors.toSet());
            assertThat(vlanRules, hasSize(1));
            L2ModificationInstruction.ModVlanIdInstruction vlanRule = vlanRules.iterator().next();
            assertThat(vlanRule.vlanId().toShort(), greaterThan((short) VlanId.NO_VID));
            assertThat(vlanRule.vlanId().toShort(), lessThan((short) VlanId.MAX_VLAN));
            vlanToEncap = vlanRule.vlanId();
        } else if (!isIngress && !isEgress) {

            Set<L2ModificationInstruction.ModVlanIdInstruction> vlanRules = trafficTreatment.allInstructions().stream()
                    .filter(treat -> treat instanceof L2ModificationInstruction.ModVlanIdInstruction)
                    .map(x -> (L2ModificationInstruction.ModVlanIdInstruction) x)
                    .collect(Collectors.toSet());
            assertThat(vlanRules, hasSize(1));
            L2ModificationInstruction.ModVlanIdInstruction vlanRule = vlanRules.iterator().next();
            assertThat(vlanRule.vlanId().toShort(), greaterThan((short) VlanId.NO_VID));
            assertThat(vlanRule.vlanId().toShort(), lessThan((short) VlanId.MAX_VLAN));
            vlanToEncap = vlanRule.vlanId();

        } else {
            assertThat(trafficTreatment.allInstructions().stream()
                               .filter(treat -> treat instanceof L2ModificationInstruction.ModVlanIdInstruction)
                               .collect(Collectors.toSet()), hasSize(0));
            assertThat(trafficTreatment.allInstructions().stream()
                               .filter(treat -> treat instanceof L2ModificationInstruction.ModVlanHeaderInstruction)
                               .collect(Collectors.toSet()), hasSize(1));

        }

        return vlanToEncap;

    }

    private void verifyVlanEncapSelector(TrafficSelector trafficSelector, ConnectPoint ingress, VlanId vlanToMatch) {

        assertThat(trafficSelector, is(DefaultTrafficSelector.builder().matchInPort(ingress.port())
                   .matchVlanId(vlanToMatch).build()));
    }

    /**
     * Tests the compilation behavior of the path intent compiler in case of
     * encasulation costraint {@link EncapsulationConstraint}.
     */
    @Test
    public void testMplsEncapCompile() {
        sut.activate();

        List<Intent> compiled = sut.compile(constraintMplsIntent, Collections.emptyList());
        assertThat(compiled, hasSize(1));

        Collection<FlowRule> rules = ((FlowRuleIntent) compiled.get(0)).flowRules();
        assertThat(rules, hasSize(3));

        FlowRule rule1 = rules.stream()
                .filter(x -> x.deviceId().equals(d1p0.deviceId()))
                .findFirst()
                .get();
        verifyIdAndPriority(rule1, d1p0.deviceId());
        assertThat(rule1.selector(), is(DefaultTrafficSelector
                                                .builder(selector)
                                                .matchInPort(d1p0.port())
                                                .build()));
        MplsLabel mplsLabelToEncap = verifyMplsEncapTreatment(rule1.treatment(), d1p1, true, false);

        FlowRule rule2 = rules.stream()
                .filter(x -> x.deviceId().equals(d2p0.deviceId()))
                .findFirst()
                .get();
        verifyIdAndPriority(rule2, d2p0.deviceId());
        verifyMplsEncapSelector(rule2.selector(), d2p0, mplsLabelToEncap);
        mplsLabelToEncap = verifyMplsEncapTreatment(rule2.treatment(), d2p1, false, false);

        FlowRule rule3 = rules.stream()
                .filter(x -> x.deviceId().equals(d3p0.deviceId()))
                .findFirst()
                .get();
        verifyIdAndPriority(rule3, d3p1.deviceId());
        verifyMplsEncapSelector(rule3.selector(), d3p1, mplsLabelToEncap);
        verifyMplsEncapTreatment(rule3.treatment(), d3p0, false, true);

        sut.deactivate();
    }


    private MplsLabel verifyMplsEncapTreatment(TrafficTreatment trafficTreatment,
                                               ConnectPoint egress, boolean isIngress, boolean isEgress) {
        Set<Instructions.OutputInstruction> ruleOutput = trafficTreatment.allInstructions().stream()
                .filter(treat -> treat instanceof Instructions.OutputInstruction)
                .map(treat -> (Instructions.OutputInstruction) treat)
                .collect(Collectors.toSet());
        assertThat(ruleOutput, hasSize(1));
        assertThat((ruleOutput.iterator().next()).port(), is(egress.port()));
        MplsLabel mplsToEncap = MplsLabel.mplsLabel(0);
        if (isIngress && !isEgress) {
            Set<L2ModificationInstruction.ModMplsLabelInstruction> mplsRules = trafficTreatment
                    .allInstructions()
                    .stream()
                    .filter(treat -> treat instanceof L2ModificationInstruction.ModMplsLabelInstruction)
                    .map(x -> (L2ModificationInstruction.ModMplsLabelInstruction) x)
                    .collect(Collectors.toSet());
            assertThat(mplsRules, hasSize(1));
            L2ModificationInstruction.ModMplsLabelInstruction mplsRule = mplsRules.iterator().next();
            assertThat(mplsRule.label().toInt(), greaterThan(0));
            assertThat(mplsRule.label().toInt(), lessThan(MplsLabel.MAX_MPLS));
            mplsToEncap = mplsRule.label();
        } else if (!isIngress && !isEgress) {
            Set<L2ModificationInstruction.ModMplsLabelInstruction> mplsRules = trafficTreatment
                    .allInstructions()
                    .stream()
                    .filter(treat -> treat instanceof L2ModificationInstruction.ModMplsLabelInstruction)
                    .map(x -> (L2ModificationInstruction.ModMplsLabelInstruction) x)
                    .collect(Collectors.toSet());
            assertThat(mplsRules, hasSize(1));
            L2ModificationInstruction.ModMplsLabelInstruction mplsRule = mplsRules.iterator().next();
            assertThat(mplsRule.label().toInt(), greaterThan(0));
            assertThat(mplsRule.label().toInt(), lessThan(MplsLabel.MAX_MPLS));
            mplsToEncap = mplsRule.label();
        } else {
            assertThat(trafficTreatment.allInstructions().stream()
                               .filter(treat -> treat instanceof L2ModificationInstruction.ModMplsLabelInstruction)
                               .collect(Collectors.toSet()), hasSize(0));
            assertThat(trafficTreatment.allInstructions().stream()
                               .filter(treat -> treat instanceof L2ModificationInstruction.ModMplsHeaderInstruction)
                               .collect(Collectors.toSet()), hasSize(1));

        }
        return mplsToEncap;

    }

    private void verifyMplsEncapSelector(TrafficSelector trafficSelector, ConnectPoint ingress, MplsLabel mplsLabel) {

        assertThat(trafficSelector, is(DefaultTrafficSelector.builder()
                                               .matchInPort(ingress.port()).matchEthType(Ethernet.MPLS_UNICAST)
                                               .matchMplsLabel(mplsLabel).build()));
    }

    private void verifyIdAndPriority(FlowRule rule, DeviceId deviceId) {
        assertThat(rule.deviceId(), is(deviceId));
        assertThat(rule.priority(), is(PRIORITY));
    }
}
