diff --git a/apps/vpls/src/test/java/org/onosproject/vpls/VplsTest.java b/apps/vpls/src/test/java/org/onosproject/vpls/VplsTest.java
index 6dfcea5..716b331 100644
--- a/apps/vpls/src/test/java/org/onosproject/vpls/VplsTest.java
+++ b/apps/vpls/src/test/java/org/onosproject/vpls/VplsTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016-present Open Networking Laboratory
+ * Copyright 2017-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.
@@ -13,704 +13,213 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package org.onosproject.vpls;
 
-import com.google.common.collect.HashMultimap;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.ImmutableSetMultimap;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
-import com.google.common.collect.SetMultimap;
 import com.google.common.collect.Sets;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
 import org.onlab.packet.Ip4Address;
+import org.onlab.packet.IpAddress;
 import org.onlab.packet.MacAddress;
 import org.onlab.packet.VlanId;
 import org.onosproject.TestApplicationId;
-import org.onosproject.app.ApplicationService;
+import org.onosproject.cluster.LeadershipEvent;
+import org.onosproject.cluster.LeadershipEventListener;
+import org.onosproject.cluster.LeadershipServiceAdapter;
+import org.onosproject.cluster.NodeId;
 import org.onosproject.core.ApplicationId;
-import org.onosproject.core.CoreService;
+import org.onosproject.core.CoreServiceAdapter;
 import org.onosproject.core.IdGenerator;
 import org.onosproject.incubator.net.intf.Interface;
 import org.onosproject.incubator.net.intf.InterfaceListener;
 import org.onosproject.incubator.net.intf.InterfaceService;
-import org.onosproject.intentsync.IntentSynchronizationService;
 import org.onosproject.net.ConnectPoint;
 import org.onosproject.net.DefaultHost;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.EncapsulationType;
-import org.onosproject.net.FilteredConnectPoint;
 import org.onosproject.net.Host;
 import org.onosproject.net.HostId;
 import org.onosproject.net.HostLocation;
 import org.onosproject.net.PortNumber;
-import org.onosproject.net.config.NetworkConfigService;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.criteria.Criterion;
-import org.onosproject.net.flow.criteria.VlanIdCriterion;
+import org.onosproject.net.config.Config;
+import org.onosproject.net.config.ConfigApplyDelegate;
+import org.onosproject.net.config.NetworkConfigEvent;
+import org.onosproject.net.config.NetworkConfigListener;
+import org.onosproject.net.config.NetworkConfigServiceAdapter;
 import org.onosproject.net.host.HostEvent;
 import org.onosproject.net.host.HostListener;
-import org.onosproject.net.host.HostService;
 import org.onosproject.net.host.HostServiceAdapter;
 import org.onosproject.net.intent.Intent;
-import org.onosproject.net.intent.IntentService;
+import org.onosproject.net.intent.IntentData;
+import org.onosproject.net.intent.IntentEvent;
+import org.onosproject.net.intent.IntentListener;
 import org.onosproject.net.intent.IntentServiceAdapter;
-import org.onosproject.net.intent.IntentUtils;
-import org.onosproject.net.intent.Key;
-import org.onosproject.net.intent.MultiPointToSinglePointIntent;
-import org.onosproject.net.intent.SinglePointToMultiPointIntent;
+import org.onosproject.net.intent.IntentState;
 import org.onosproject.net.provider.ProviderId;
-import org.onosproject.vpls.config.VplsConfigService;
+import org.onosproject.store.StoreDelegate;
+import org.onosproject.store.service.WallClockTimestamp;
+import org.onosproject.vpls.api.Vpls;
+import org.onosproject.vpls.api.VplsData;
+import org.onosproject.vpls.config.VplsAppConfig;
+import org.onosproject.vpls.config.VplsAppConfigTest;
+import org.onosproject.vpls.config.VplsConfig;
+import org.onosproject.vpls.store.VplsStoreAdapter;
+import org.onosproject.vpls.store.VplsStoreEvent;
 
+import java.io.IOException;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.stream.Collectors;
 
-import static java.lang.String.format;
-import static org.easymock.EasyMock.anyObject;
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.expectLastCall;
-import static org.easymock.EasyMock.replay;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.onosproject.net.EncapsulationType.NONE;
-import static org.onosproject.net.EncapsulationType.VLAN;
-import static org.onosproject.net.EncapsulationType.valueOf;
-import static org.onosproject.vpls.IntentInstaller.PARTIAL_FAILURE_CONSTRAINT;
-import static org.onosproject.vpls.IntentInstaller.PREFIX_BROADCAST;
-import static org.onosproject.vpls.IntentInstaller.PREFIX_UNICAST;
-import static org.onosproject.vpls.IntentInstaller.setEncap;
-
 /**
- * Tests for the {@link Vpls} class.
+ * Class provides data for VPLS testing.
  */
-public class VplsTest {
-    private static final String APP_NAME = "org.onosproject.vpls";
-    private static final ApplicationId APPID = TestApplicationId.create(APP_NAME);
-    private static final String DASH = "-";
-    private static final int PRIORITY_OFFSET = 1000;
-    private static final String VPLS1 = "vpls1";
-    private static final String VPLS2 = "vpls2";
-    private static final String VPLS3 = "vpls3";
-    private static final String VPLS4 = "vpls4";
+public abstract class VplsTest {
+    protected static final String APP_NAME = "org.onosproject.vpls";
+    protected static final ApplicationId APPID = TestApplicationId.create(APP_NAME);
+    protected static final String DASH = "-";
+    protected static final int PRIORITY_OFFSET = 1000;
+    protected static final String VPLS1 = "vpls1";
+    protected static final String VPLS2 = "vpls2";
+    protected static final String VPLS3 = "vpls3";
+    protected static final String VPLS4 = "vpls4";
 
-    private static final PortNumber P1 = PortNumber.portNumber(1);
-    private static final PortNumber P2 = PortNumber.portNumber(2);
+    protected static final PortNumber P1 = PortNumber.portNumber(1);
+    protected static final PortNumber P2 = PortNumber.portNumber(2);
 
-    private static final DeviceId DID1 = getDeviceId(1);
-    private static final DeviceId DID2 = getDeviceId(2);
-    private static final DeviceId DID3 = getDeviceId(3);
-    private static final DeviceId DID4 = getDeviceId(4);
-    private static final DeviceId DID5 = getDeviceId(5);
-    private static final DeviceId DID6 = getDeviceId(6);
+    protected static final DeviceId DID1 = getDeviceId(1);
+    protected static final DeviceId DID2 = getDeviceId(2);
+    protected static final DeviceId DID3 = getDeviceId(3);
+    protected static final DeviceId DID4 = getDeviceId(4);
+    protected static final DeviceId DID5 = getDeviceId(5);
+    protected static final DeviceId DID6 = getDeviceId(6);
 
-    private static final ConnectPoint CP1 = new ConnectPoint(DID1, P1);
-    private static final ConnectPoint CP2 = new ConnectPoint(DID2, P1);
-    private static final ConnectPoint CP3 = new ConnectPoint(DID3, P1);
-    private static final ConnectPoint CP4 = new ConnectPoint(DID4, P1);
-    private static final ConnectPoint CP5 = new ConnectPoint(DID5, P1);
-    private static final ConnectPoint CP6 = new ConnectPoint(DID6, P1);
-    private static final ConnectPoint CP7 = new ConnectPoint(DID4, P2);
-    private static final ConnectPoint CP8 = new ConnectPoint(DID3, P2);
-    private static final ConnectPoint CP9 = new ConnectPoint(DID5, P1);
-    private static final ConnectPoint CP10 = new ConnectPoint(DID5, P2);
+    protected static final ConnectPoint CP1 = new ConnectPoint(DID1, P1);
+    protected static final ConnectPoint CP2 = new ConnectPoint(DID2, P1);
+    protected static final ConnectPoint CP3 = new ConnectPoint(DID3, P1);
+    protected static final ConnectPoint CP4 = new ConnectPoint(DID4, P1);
+    protected static final ConnectPoint CP5 = new ConnectPoint(DID5, P1);
+    protected static final ConnectPoint CP6 = new ConnectPoint(DID6, P1);
+    protected static final ConnectPoint CP7 = new ConnectPoint(DID4, P2);
+    protected static final ConnectPoint CP8 = new ConnectPoint(DID3, P2);
+    protected static final ConnectPoint CP9 = new ConnectPoint(DID5, P1);
+    protected static final ConnectPoint CP10 = new ConnectPoint(DID5, P2);
 
-    private static final VlanId VLAN100 = VlanId.vlanId((short) 100);
-    private static final VlanId VLAN200 = VlanId.vlanId((short) 200);
-    private static final VlanId VLAN300 = VlanId.vlanId((short) 300);
-    private static final VlanId VLAN400 = VlanId.vlanId((short) 400);
-    private static final VlanId VLAN_NONE = VlanId.NONE;
+    protected static final VlanId VLAN100 = VlanId.vlanId((short) 100);
+    protected static final VlanId VLAN200 = VlanId.vlanId((short) 200);
+    protected static final VlanId VLAN300 = VlanId.vlanId((short) 300);
+    protected static final VlanId VLAN400 = VlanId.vlanId((short) 400);
+    protected static final VlanId VLAN_NONE = VlanId.NONE;
 
-    private static final MacAddress MAC1 = getMac(1);
-    private static final MacAddress MAC2 = getMac(2);
-    private static final MacAddress MAC3 = getMac(3);
-    private static final MacAddress MAC4 = getMac(4);
-    private static final MacAddress MAC5 = getMac(5);
-    private static final MacAddress MAC6 = getMac(6);
-    private static final MacAddress MAC7 = getMac(7);
-    private static final MacAddress MAC8 = getMac(8);
-    private static final MacAddress MAC9 = getMac(9);
-    private static final MacAddress MAC10 = getMac(10);
-    private static final MacAddress MAC11 = getMac(11);
+    protected static final MacAddress MAC1 = getMac(1);
+    protected static final MacAddress MAC2 = getMac(2);
+    protected static final MacAddress MAC3 = getMac(3);
+    protected static final MacAddress MAC4 = getMac(4);
+    protected static final MacAddress MAC5 = getMac(5);
+    protected static final MacAddress MAC6 = getMac(6);
+    protected static final MacAddress MAC7 = getMac(7);
+    protected static final MacAddress MAC8 = getMac(8);
+    protected static final MacAddress MAC9 = getMac(9);
+    protected static final MacAddress MAC10 = getMac(10);
+    protected static final MacAddress MAC11 = getMac(11);
 
-    private static final Ip4Address IP1 = Ip4Address.valueOf("192.168.1.1");
-    private static final Ip4Address IP2 = Ip4Address.valueOf("192.168.1.2");
+    protected static final Ip4Address IP1 = Ip4Address.valueOf("192.168.1.1");
+    protected static final Ip4Address IP2 = Ip4Address.valueOf("192.168.1.2");
 
-    private static final HostId HID1 = HostId.hostId(MAC1, VLAN100);
-    private static final HostId HID2 = HostId.hostId(MAC2, VLAN100);
-    private static final HostId HID3 = HostId.hostId(MAC3, VLAN200);
-    private static final HostId HID4 = HostId.hostId(MAC4, VLAN200);
-    private static final HostId HID5 = HostId.hostId(MAC5, VLAN300);
-    private static final HostId HID6 = HostId.hostId(MAC6, VLAN300);
-    private static final HostId HID7 = HostId.hostId(MAC7, VLAN300);
-    private static final HostId HID8 = HostId.hostId(MAC8, VLAN400);
-    private static final HostId HID9 = HostId.hostId(MAC9);
-    private static final HostId HID10 = HostId.hostId(MAC10);
-    private static final HostId HID11 = HostId.hostId(MAC11);
+    protected static final HostId HID1 = HostId.hostId(MAC1, VLAN100);
+    protected static final HostId HID2 = HostId.hostId(MAC2, VLAN100);
+    protected static final HostId HID3 = HostId.hostId(MAC3, VLAN200);
+    protected static final HostId HID4 = HostId.hostId(MAC4, VLAN200);
+    protected static final HostId HID5 = HostId.hostId(MAC5, VLAN300);
+    protected static final HostId HID6 = HostId.hostId(MAC6, VLAN300);
+    protected static final HostId HID7 = HostId.hostId(MAC7, VLAN300);
+    protected static final HostId HID8 = HostId.hostId(MAC8, VLAN400);
+    protected static final HostId HID9 = HostId.hostId(MAC9);
+    protected static final HostId HID10 = HostId.hostId(MAC10);
+    protected static final HostId HID11 = HostId.hostId(MAC11);
 
-    private static final ProviderId PID = new ProviderId("of", "foo");
+    protected static final ProviderId PID = new ProviderId("of", "foo");
 
-    private static IdGenerator idGenerator;
+    protected static final NodeId NODE_ID_1 = new NodeId("Node1");
+    protected static final NodeId NODE_ID_2 = new NodeId("Node2");
 
-    private static final Interface V100H1 =
+    protected static IdGenerator idGenerator;
+
+    protected static final Interface V100H1 =
             new Interface("v100h1", CP1, null, null, VLAN100);
-    private static final Interface V100H2 =
+    protected static final Interface V100H2 =
             new Interface("v100h2", CP2, null, null, VLAN100);
-    private static final Interface V200H1 =
+    protected static final Interface V200H1 =
             new Interface("v200h1", CP3, null, null, VLAN200);
-    private static final Interface V200H2 =
+    protected static final Interface V200H2 =
             new Interface("v200h2", CP4, null, null, VLAN200);
-    private static final Interface V300H1 =
+    protected static final Interface V300H1 =
             new Interface("v300h1", CP5, null, null, VLAN300);
-    private static final Interface V300H2 =
+    protected static final Interface V300H2 =
             new Interface("v300h2", CP6, null, null, VLAN300);
-    private static final Interface V400H1 =
+    protected static final Interface V400H1 =
             new Interface("v400h1", CP7, null, null, VLAN400);
 
-    private static final Interface VNONEH1 =
+    protected static final Interface VNONEH1 =
             new Interface("vNoneh1", CP8, null, null, VLAN_NONE);
-    private static final Interface VNONEH2 =
+    protected static final Interface VNONEH2 =
             new Interface("vNoneh2", CP9, null, null, VLAN_NONE);
-    private static final Interface VNONEH3 =
+    protected static final Interface VNONEH3 =
             new Interface("vNoneh3", CP10, null, null, VLAN_NONE);
 
-    private static final Host V100HOST1 =
+    protected static final Host V100HOST1 =
             new DefaultHost(PID, HID1, MAC1, VLAN100,
                             getLocation(1), Collections.singleton(IP1));
-    private static final Host V100HOST2 =
+    protected static final Host V100HOST2 =
             new DefaultHost(PID, HID2, MAC2, VLAN100,
                             getLocation(2), Sets.newHashSet());
-    private static final Host V200HOST1 =
+    protected static final Host V200HOST1 =
             new DefaultHost(PID, HID3, MAC3, VLAN200,
                             getLocation(3), Collections.singleton(IP2));
-    private static final Host V200HOST2 =
+    protected static final Host V200HOST2 =
             new DefaultHost(PID, HID4, MAC4, VLAN200,
                             getLocation(4), Sets.newHashSet());
-    private static final Host V300HOST1 =
+    protected static final Host V300HOST1 =
             new DefaultHost(PID, HID5, MAC5, VLAN300,
                             getLocation(5), Sets.newHashSet());
-    private static final Host V300HOST2 =
+    protected static final Host V300HOST2 =
             new DefaultHost(PID, HID6, MAC6, VLAN300,
                             getLocation(6), Sets.newHashSet());
-    private static final Host V300HOST3 =
+    protected static final Host V300HOST3 =
             new DefaultHost(PID, HID7, MAC7, VLAN300,
                             getLocation(7), Sets.newHashSet());
-    private static final Host V400HOST1 =
+    protected static final Host V400HOST1 =
             new DefaultHost(PID, HID8, MAC8, VLAN400,
                             getLocation(4, 2), Sets.newHashSet());
 
-    private static final Host VNONEHOST1 =
+    protected static final Host VNONEHOST1 =
             new DefaultHost(PID, HID9, MAC9, VlanId.NONE,
                             getLocation(3, 2), Sets.newHashSet());
-    private static final Host VNONEHOST2 =
+    protected static final Host VNONEHOST2 =
             new DefaultHost(PID, HID10, MAC10, VlanId.NONE,
                             getLocation(5, 1), Sets.newHashSet());
-    private static final Host VNONEHOST3 =
+    protected static final Host VNONEHOST3 =
             new DefaultHost(PID, HID11, MAC11, VlanId.NONE,
                             getLocation(5, 2), Sets.newHashSet());
 
-    private static final Set<Interface> AVAILABLE_INTERFACES =
+    protected static final Set<Interface> AVAILABLE_INTERFACES =
             ImmutableSet.of(V100H1, V100H2, V200H1, V200H2, V300H1, V300H2,
-                            V400H1, VNONEH1, VNONEH2);
+                            V400H1, VNONEH1, VNONEH2, VNONEH3);
 
-    private static final Set<Host> AVAILABLE_HOSTS =
+    protected static final Set<Host> AVAILABLE_HOSTS =
             ImmutableSet.of(V100HOST1, V100HOST2, V200HOST1,
                             V200HOST2, V300HOST1, V300HOST2, V300HOST3,
                             VNONEHOST1, VNONEHOST2,
                             V400HOST1, VNONEHOST3);
 
-    private SetMultimap<String, Interface> interfacesByVpls = HashMultimap.create();
-
-    private ApplicationService applicationService;
-    private CoreService coreService;
-    private HostListener hostListener;
-    private NetworkConfigService configService;
-    private Set<Host> hostsAvailable;
-    private HostService hostService;
-    private IntentService intentService;
-    private InterfaceService interfaceService;
-    private VplsConfigService vplsConfigService;
-    private Vpls vpls;
-
-    @Before
-    public void setUp() throws Exception {
-        idGenerator = new TestIdGenerator();
-        Intent.unbindIdGenerator(idGenerator);
-        Intent.bindIdGenerator(idGenerator);
-
-        applicationService = createMock(ApplicationService.class);
-
-        configService = createMock(NetworkConfigService.class);
-
-        coreService = createMock(CoreService.class);
-        expect(coreService.registerApplication(APP_NAME))
-                .andReturn(APPID);
-        replay(coreService);
-
-        hostsAvailable = Sets.newHashSet();
-        hostService = new TestHostService(hostsAvailable);
-
-        intentService = new TestIntentService();
-
-        TestIntentSynchronizer intentSynchronizer =
-                new TestIntentSynchronizer(intentService);
-
-        interfaceService = createMock(InterfaceService.class);
-        interfaceService.addListener(anyObject(InterfaceListener.class));
-        expectLastCall().anyTimes();
-        addIfaceConfig();
-
-        interfacesByVpls.put(VPLS1, V100H1);
-        interfacesByVpls.put(VPLS1, V200H1);
-        interfacesByVpls.put(VPLS1, V300H1);
-        interfacesByVpls.put(VPLS2, V100H2);
-        interfacesByVpls.put(VPLS2, V200H2);
-        interfacesByVpls.put(VPLS2, V300H2);
-        interfacesByVpls.put(VPLS3, VNONEH1);
-        interfacesByVpls.put(VPLS3, VNONEH2);
-        interfacesByVpls.put(VPLS4, V400H1);
-        interfacesByVpls.put(VPLS4, VNONEH3);
-
-        Map<String, EncapsulationType> encapByVpls = new HashMap<>();
-        encapByVpls.put(VPLS1, VLAN);
-        encapByVpls.put(VPLS2, NONE);
-        encapByVpls.put(VPLS3, NONE);
-        encapByVpls.put(VPLS4, NONE);
-
-        vplsConfigService = new TestVplsConfigService(interfacesByVpls, encapByVpls);
-
-        vpls = new Vpls();
-        vpls.applicationService = applicationService;
-        vpls.coreService = coreService;
-        vpls.hostService = hostService;
-        vpls.vplsConfigService = vplsConfigService;
-        vpls.intentService = intentService;
-        vpls.interfaceService = interfaceService;
-        vpls.configService = configService;
-        vpls.intentSynchronizer = intentSynchronizer;
-
-    }
-
-    @After
-    public void tearDown() {
-        Intent.unbindIdGenerator(idGenerator);
-    }
-
-    /**
-     * Creates the interface configuration:
-     *  On devices 1 and 2 is configured an interface on port 1 with vlan 100.
-     *  On device 3 is configured an interface on port 3 with no vlan.
-     *  On devices 3 and 4 is configured an interface on port 1 with vlan 200.
-     *  On device 4 is an interface configured on port 2 with vlan 400.
-     *  On device 5 are configured two interfaces on port 1 and 2 with no vlan.
-     *  On device 5 and 6 is configured an interface on port 1 with vlan 300.
-     */
-    private void addIfaceConfig() {
-        Set<Interface> interfaces = ImmutableSet.copyOf(AVAILABLE_INTERFACES);
-        Set<Interface> vlanOneSet = ImmutableSet.of(V100H1, V100H2);
-        Set<Interface> vlanTwoSet = ImmutableSet.of(V200H1, V200H2);
-        Set<Interface> vlanThreeSet = ImmutableSet.of(VNONEH1, VNONEH2);
-        Set<Interface> vlanFourSet = ImmutableSet.of(V400H1, VNONEH3);
-
-        AVAILABLE_INTERFACES.forEach(intf -> {
-            expect(interfaceService.getInterfacesByPort(intf.connectPoint()))
-                    .andReturn(Sets.newHashSet(intf)).anyTimes();
-        });
-        expect(interfaceService.getInterfacesByVlan(VLAN100))
-                .andReturn(vlanOneSet).anyTimes();
-        expect(interfaceService.getInterfacesByVlan(VLAN200))
-                .andReturn(vlanTwoSet).anyTimes();
-        expect(interfaceService.getInterfacesByVlan(VLAN300))
-                .andReturn(vlanThreeSet).anyTimes();
-        expect(interfaceService.getInterfacesByVlan(VLAN400))
-                .andReturn(vlanFourSet).anyTimes();
-        expect(interfaceService.getInterfacesByVlan(VlanId.NONE))
-                .andReturn(vlanFourSet).anyTimes();
-        expect(interfaceService.getInterfaces()).andReturn(interfaces).anyTimes();
-
-        replay(interfaceService);
-    }
-
-    /**
-     * Seven ports are configured with VLANs, while three ports are not. No hosts are
-     * registered by the HostService.
-     *
-     * The first three ports have an interface configured on VPLS 1,
-     * the other three on VPLS 2. Two ports are defined for VPLS 3, while
-     * the two remaining ports are configured on VPLS 4.
-     *
-     * The number of intents expected is 10: three for VPLS 1, three for VPLS 2,
-     * two for VPLS 3, two for VPLS 4. Eight MP2SP intents.
-     * Checks if the number of intents submitted to the intent framework is
-     * equal to the number of intents expected and if all intents are equivalent.
-     */
-    @Test
-    public void activateNoHosts() {
-        vpls.activate();
-
-        List<Intent> expectedIntents = Lists.newArrayList();
-        Set<FilteredConnectPoint> fcPoints;
-
-        fcPoints = buildFCPoints(ImmutableSet.of(V100H1, V200H1, V300H1));
-        expectedIntents.addAll(generateVplsBrc(fcPoints, VPLS1, VLAN));
-
-        fcPoints = buildFCPoints(ImmutableSet.of(V100H2, V200H2, V300H2));
-        expectedIntents.addAll(generateVplsBrc(fcPoints, VPLS2, NONE));
-
-        fcPoints = buildFCPoints(ImmutableSet.of(VNONEH1, VNONEH2));
-        expectedIntents.addAll(generateVplsBrc(fcPoints, VPLS3, NONE));
-
-        fcPoints = buildFCPoints(ImmutableSet.of(V400H1, VNONEH3));
-        expectedIntents.addAll(generateVplsBrc(fcPoints, VPLS4, NONE));
-
-        checkIntents(expectedIntents);
-    }
-
-    /**
-     * Ten ports are configured with VLANs and ten hosts are registered by the
-     * HostService.
-     *
-     * The first three ports have an interface configured on VPLS 1,
-     * the other three on VPLS 2, two on VPLS3 and two on VPLS4.
-     *
-     * The number of intents expected is twenty: six
-     * for VPLS 1, six for VPLS 2. four for VPLS 3, four for VPLS 4.
-     * That is ten sp2mp intents, ten mp2sp intents. For VPLS 1
-     * IPs are added to demonstrate this doesn't influence the number of intents
-     * created. Checks if the number of intents submitted to the intent
-     * framework is equal to the number of intents expected and if all intents
-     * are equivalent.
-     */
-    @Test
-    public void tenInterfacesConfiguredHostsPresent() {
-        hostsAvailable.addAll(AVAILABLE_HOSTS);
-
-        vpls.activate();
-
-        List<Intent> expectedIntents = Lists.newArrayList();
-        Set<FilteredConnectPoint> fcPoints;
-        Set<Host> hosts;
-
-        fcPoints = buildFCPoints(ImmutableSet.of(V100H1, V200H1, V300H1));
-        hosts = ImmutableSet.of(V100HOST1, V200HOST1, V300HOST1);
-        expectedIntents.addAll(generateVplsBrc(fcPoints, VPLS1, VLAN));
-        expectedIntents.addAll(generateVplsUni(fcPoints, hosts, VPLS1, VLAN));
-
-        fcPoints = buildFCPoints(ImmutableSet.of(V100H2, V200H2, V300H2));
-        hosts = ImmutableSet.of(V100HOST2, V200HOST2, V300HOST2);
-        expectedIntents.addAll(generateVplsBrc(fcPoints, VPLS2, NONE));
-        expectedIntents.addAll(generateVplsUni(fcPoints, hosts, VPLS2, NONE));
-
-        fcPoints = buildFCPoints(ImmutableSet.of(VNONEH1, VNONEH2));
-        hosts = ImmutableSet.of(VNONEHOST1, VNONEHOST2);
-        expectedIntents.addAll(generateVplsBrc(fcPoints, VPLS3, NONE));
-        expectedIntents.addAll(generateVplsUni(fcPoints, hosts, VPLS3, NONE));
-
-        fcPoints = buildFCPoints(ImmutableSet.of(V400H1, VNONEH3));
-        hosts = ImmutableSet.of(V400HOST1, VNONEHOST3);
-        expectedIntents.addAll(generateVplsBrc(fcPoints, VPLS4, NONE));
-        expectedIntents.addAll(generateVplsUni(fcPoints, hosts, VPLS4, NONE));
-
-        checkIntents(expectedIntents);
-    }
-
-    /**
-     * Ten ports are configured; seven have VLANs and three do not.
-     * Initially, no hosts are registered by the HostService.
-     *
-     * The first three ports have an interface configured on
-     * VPLS 1, three have an interface configured on VPLS 2, two have an
-     * interface configured on VPLS 3 and two have an interface configured
-     * on VPLS 4, three have an interface configure. When the
-     * module starts up, three hosts attached to device one, two and three -
-     * port 1, are registered by the HostService and events are sent to the
-     * application. sp2mp intents are created for all interfaces configured and
-     * mp2sp intents are created only for the hosts attached.
-     *
-     * The number of intents expected is seventeen: six for VPLS 1,
-     * three for VPLS 2, four for VPLS3 and four for VPLS4.
-     * Ten sp2mp intents, seven mp2sp intents. IPs are added on the first two
-     * hosts only to demonstrate this doesn't influence the number of intents
-     * created.
-     * An additional host is added on device seven - port 1, to demonstrate that
-     * the application does not generate intents, even if the interface uses the
-     * same VLAN Id of the other interfaces configured for the specifc VPLS.
-     * Checks if the number of intents submitted to the intent framework is equal
-     * to the number of intents expected and if all intents are equivalent.
-     */
-    @Test
-    public void tenInterfacesThreeHostEventsSameVpls() {
-        vpls.activate();
-
-        List<Intent> expectedIntents = Lists.newArrayList();
-        Set<FilteredConnectPoint> fcPoints;
-        Set<Host> hosts;
-
-        hostsAvailable.addAll(Sets.newHashSet(V100HOST1, V200HOST1,
-                                              V300HOST1, V300HOST3,
-                                              VNONEHOST1, VNONEHOST2,
-                                              V400HOST1, VNONEHOST3));
-        hostsAvailable.forEach(host ->
-                                       hostListener.event(new HostEvent(HostEvent.Type.HOST_ADDED, host)));
-
-        fcPoints = buildFCPoints(ImmutableSet.of(V100H1, V200H1, V300H1));
-        hosts = ImmutableSet.of(V100HOST1, V200HOST1, V300HOST1);
-        expectedIntents.addAll(generateVplsBrc(fcPoints, VPLS1, VLAN));
-        expectedIntents.addAll(generateVplsUni(fcPoints, hosts, VPLS1, VLAN));
-
-        fcPoints = buildFCPoints(ImmutableSet.of(V100H2, V200H2, V300H2));
-        expectedIntents.addAll(generateVplsBrc(fcPoints, VPLS2, NONE));
-
-        fcPoints = buildFCPoints(ImmutableSet.of(VNONEH1, VNONEH2));
-        hosts = ImmutableSet.of(VNONEHOST1, VNONEHOST2);
-        expectedIntents.addAll(generateVplsBrc(fcPoints, VPLS3, NONE));
-        expectedIntents.addAll(generateVplsUni(fcPoints, hosts, VPLS3, NONE));
-
-        fcPoints = buildFCPoints(ImmutableSet.of(V400H1, VNONEH3));
-        hosts = ImmutableSet.of(V400HOST1, VNONEHOST3);
-        expectedIntents.addAll(generateVplsBrc(fcPoints, VPLS4, NONE));
-        expectedIntents.addAll(generateVplsUni(fcPoints, hosts, VPLS4, NONE));
-
-        checkIntents(expectedIntents);
-    }
-
-    /**
-     * Generates a list of the expected sp2mp intents for a VPLS.
-     *
-     * @param fcPoints the filtered connect point
-     * @param name the name of the VPLS
-     * @param encap the encapsulation type
-     * @return the list of expected sp2mp intents for the given VPLS
-     */
-    private List<SinglePointToMultiPointIntent>
-    generateVplsBrc(Set<FilteredConnectPoint> fcPoints, String name, EncapsulationType encap) {
-        List<SinglePointToMultiPointIntent> intents = Lists.newArrayList();
-
-        fcPoints.forEach(point -> {
-            Set<FilteredConnectPoint> otherPoints =
-                    fcPoints.stream()
-                            .filter(fcp -> !fcp.equals(point))
-                            .collect(Collectors.toSet());
-
-            Key brckey = buildKey(PREFIX_BROADCAST,
-                                  point.connectPoint(),
-                                  name,
-                                  MacAddress.BROADCAST);
-
-            intents.add(buildBrcIntent(brckey, point, otherPoints, encap));
-        });
-
-        return intents;
-    }
-
-    /**
-     * Generates a list of expected mp2sp intents for a given VPLS.
-     *
-     * @param fcPoints the filtered connect point
-     * @param hosts the hosts
-     * @param name the name of the VPLS
-     * @param encap the encapsulation type
-     * @return the list of expected mp2sp intents for the given VPLS
-     */
-    private List<MultiPointToSinglePointIntent>
-    generateVplsUni(Set<FilteredConnectPoint> fcPoints, Set<Host> hosts,
-                    String name, EncapsulationType encap) {
-        List<MultiPointToSinglePointIntent> intents = Lists.newArrayList();
-
-        hosts.forEach(host -> {
-            FilteredConnectPoint hostPoint = getHostPoint(host, fcPoints);
-
-            Set<FilteredConnectPoint> otherPoints =
-                    fcPoints.stream()
-                            .filter(fcp -> !fcp.equals(hostPoint))
-                            .collect(Collectors.toSet());
-
-            Key uniKey = buildKey(PREFIX_UNICAST,
-                                  host.location(), name, host.mac());
-
-            intents.add(buildUniIntent(uniKey, otherPoints, hostPoint, host, encap));
-        });
-
-        return intents;
-    }
-
-    /**
-     * Checks if the number of intents submitted to the intent framework is equal
-     * to the number of intents expected and if all intents are equivalent.
-     *
-     * @param intents the list of intents expected
-     */
-    private void checkIntents(List<Intent> intents) {
-        assertEquals("The number of intents submitted differs from the number" +
-                             " of intents expected. ",
-                     intents.size(), intentService.getIntentCount());
-
-        for (Intent intentOne : intents) {
-            boolean found = false;
-            for (Intent intentTwo : intentService.getIntents()) {
-                if (intentOne.key().equals(intentTwo.key())) {
-                    found = true;
-                    assertTrue(format("The intent submitted is different from" +
-                                              " the intent expected. %s %s",
-                                      intentOne, intentTwo),
-                               IntentUtils.intentsAreEqual(intentOne, intentTwo));
-                    break;
-                }
-            }
-            assertTrue("The intent submitted is not equal to any of the expected" +
-                               " intents. ", found);
-        }
-    }
-
-    /**
-     * Builds a broadcast intent.
-     *
-     * @param key the key to identify the intent
-     * @param src the ingress connect point
-     * @param dsts the egress connect points
-     * @return the generated single-point to multi-point intent
-     */
-    private SinglePointToMultiPointIntent buildBrcIntent(Key key,
-                                                         FilteredConnectPoint src,
-                                                         Set<FilteredConnectPoint> dsts,
-                                                         EncapsulationType encap) {
-        SinglePointToMultiPointIntent.Builder intentBuilder;
-
-        TrafficSelector selector = DefaultTrafficSelector.builder()
-                .matchEthDst(MacAddress.BROADCAST)
-                .build();
-
-        intentBuilder = SinglePointToMultiPointIntent.builder()
-                .appId(APPID)
-                .key(key)
-                .selector(selector)
-                .filteredIngressPoint(src)
-                .filteredEgressPoints(dsts)
-                .constraints(PARTIAL_FAILURE_CONSTRAINT)
-                .priority(PRIORITY_OFFSET);
-
-        setEncap(intentBuilder, PARTIAL_FAILURE_CONSTRAINT, encap);
-
-        return intentBuilder.build();
-    }
-
-    /**
-     * Builds a unicast intent.
-     *
-     * @param key the key to identify the intent
-     * @param srcs the ingress connect points
-     * @param dst the egress connect point
-     * @param host the destination Host
-     * @return the generated multi-point to single-point intent
-     */
-    private MultiPointToSinglePointIntent buildUniIntent(Key key,
-                                                         Set<FilteredConnectPoint> srcs,
-                                                         FilteredConnectPoint dst,
-                                                         Host host,
-                                                         EncapsulationType encap) {
-        MultiPointToSinglePointIntent.Builder intentBuilder;
-
-        TrafficSelector selector = DefaultTrafficSelector.builder()
-                .matchEthDst(host.mac())
-                .build();
-
-        intentBuilder = MultiPointToSinglePointIntent.builder()
-                .appId(APPID)
-                .key(key)
-                .selector(selector)
-                .filteredIngressPoints(srcs)
-                .filteredEgressPoint(dst)
-                .constraints(PARTIAL_FAILURE_CONSTRAINT)
-                .priority(PRIORITY_OFFSET);
-
-        setEncap(intentBuilder, PARTIAL_FAILURE_CONSTRAINT, encap);
-
-        return intentBuilder.build();
-    }
-
-    /**
-     * Returns the filtered connect point associated to a given host.
-     *
-     * @param host the target host
-     * @param fcps the filtered connected points
-     * @return the filtered connect point associated to the given host; null
-     * otherwise
-     */
-    private FilteredConnectPoint getHostPoint(Host host,
-                                              Set<FilteredConnectPoint> fcps) {
-        return fcps.stream()
-                .filter(fcp -> fcp.connectPoint().equals(host.location()))
-                .filter(fcp -> {
-                    VlanIdCriterion vlanCriterion =
-                            (VlanIdCriterion) fcp.trafficSelector().
-                                    getCriterion(Criterion.Type.VLAN_VID);
-                    return vlanCriterion == null ||
-                            vlanCriterion.vlanId().equals(host.vlan());
-                })
-                .findFirst()
-                .orElse(null);
-    }
-
-    /**
-     * Computes a set of filtered connect points from a list of given interfaces.
-     *
-     * @param interfaces the interfaces to compute
-     * @return the set of filtered connect points
-     */
-    private Set<FilteredConnectPoint> buildFCPoints(Collection<Interface> interfaces) {
-        // Build all filtered connected points in the VPLS
-        return interfaces
-                .stream()
-                .map(intf -> {
-                    TrafficSelector.Builder selectorBuilder =
-                            DefaultTrafficSelector.builder();
-                    if (!intf.vlan().equals(VlanId.NONE)) {
-                        selectorBuilder.matchVlanId(intf.vlan());
-                    }
-                    return new FilteredConnectPoint(intf.connectPoint(),
-                                                    selectorBuilder.build());
-                })
-                .collect(Collectors.toSet());
-    }
-
-    /**
-     * Builds an intent Key either for a single-point to multi-point or
-     * multi-point to single-point intent, based on a prefix that defines
-     * the intent type, the connection point representing the source or the
-     * destination and the VLAN Id representing the VPLS.
-     *
-     * @param prefix the key prefix
-     * @param cPoint the ingress/egress connect point
-     * @param vplsName the VPLS name
-     * @param hostMac the ingress/egress MAC address
-     * @return the key to identify the intent
-     */
-    private Key buildKey(String prefix,
-                         ConnectPoint cPoint,
-                         String vplsName,
-                         MacAddress hostMac) {
-        String keyString = vplsName +
-                DASH +
-                prefix +
-                DASH +
-                cPoint.deviceId() +
-                DASH +
-                cPoint.port() +
-                DASH +
-                hostMac;
-
-        return Key.of(keyString, APPID);
-    }
 
     /**
      * Returns the device Id of the ith device.
@@ -718,38 +227,91 @@
      * @param i the device to get the Id of
      * @return the device Id
      */
-    private static DeviceId getDeviceId(int i) {
+    protected static DeviceId getDeviceId(int i) {
         return DeviceId.deviceId("" + i);
     }
 
-    private static MacAddress getMac(int n) {
+    /**
+     * Generates a mac address by given number.
+     *
+     * @param n the number to generate mac address
+     * @return the mac address
+     */
+    protected static MacAddress getMac(int n) {
         return MacAddress.valueOf(String.format("00:00:00:00:00:%s", n));
     }
 
-    private static HostLocation getLocation(int i) {
+    /**
+     * Generates a host location by given device number.
+     *
+     * @param i the given number
+     * @return the host location
+     */
+    protected static HostLocation getLocation(int i) {
         return new HostLocation(new ConnectPoint(getDeviceId(i), P1), 123L);
     }
 
-    private static HostLocation getLocation(int d, int p) {
+    /**
+     * Generates host location by given device number and port number.
+     *
+     * @param d the device number
+     * @param p the port number
+     * @return the host location
+     */
+    protected static HostLocation getLocation(int d, int p) {
         return new HostLocation(new ConnectPoint(getDeviceId(d),
                                                  PortNumber.portNumber(p)), 123L);
     }
 
     /**
-     * Represents a fake IntentService class that allows to store and retrieve
-     * intents without implementing the IntentService logic.
+     * Test core service; For generate test application ID.
      */
-    private class TestIntentService extends IntentServiceAdapter {
+    public class TestCoreService extends CoreServiceAdapter {
+        @Override
+        public ApplicationId registerApplication(String name) {
+            return TestApplicationId.create(name);
+        }
+    }
 
-        private Map<Key, Intent> intents;
+    /**
+     * Test intent service.
+     * Always install or withdraw success for any Intents.
+     */
+    public class TestIntentService extends IntentServiceAdapter {
+        IntentListener listener;
+        List<IntentData> intents;
 
         public TestIntentService() {
-            intents = Maps.newHashMap();
+            intents = Lists.newArrayList();
         }
 
         @Override
         public void submit(Intent intent) {
-            intents.put(intent.key(), intent);
+            intents.add(new IntentData(intent, IntentState.INSTALLED, new WallClockTimestamp()));
+            if (listener != null) {
+                IntentEvent.getEvent(IntentState.INSTALLED, intent).ifPresent(listener::event);
+
+            }
+        }
+
+        @Override
+        public void withdraw(Intent intent) {
+            intents.forEach(intentData -> {
+                if (intentData.intent().key().equals(intent.key())) {
+                    intentData.setState(IntentState.WITHDRAWN);
+
+                    if (listener != null) {
+                        IntentEvent.getEvent(IntentState.WITHDRAWN, intent).ifPresent(listener::event);
+                    }
+                }
+            });
+        }
+
+        @Override
+        public Iterable<Intent> getIntents() {
+            return intents.stream()
+                    .map(IntentData::intent)
+                    .collect(Collectors.toList());
         }
 
         @Override
@@ -758,52 +320,227 @@
         }
 
         @Override
-        public Iterable<Intent> getIntents() {
-            return intents.values();
+        public void addListener(IntentListener listener) {
+            this.listener = listener;
         }
 
         @Override
-        public Intent getIntent(Key intentKey) {
-            for (Intent intent : intents.values()) {
-                if (intent.key().equals(intentKey)) {
-                    return intent;
-                }
-            }
-            return null;
+        public void removeListener(IntentListener listener) {
+            this.listener = null;
         }
     }
 
     /**
-     * Represents a fake HostService class which allows to add hosts manually
-     * in each test, when needed.
+     * Test leadership service.
      */
-    private class TestHostService extends HostServiceAdapter {
+    public class TestLeadershipService extends LeadershipServiceAdapter {
+        LeadershipEventListener listener;
 
-        private Set<Host> hosts;
-
-        public TestHostService(Set<Host> hosts) {
-            this.hosts = hosts;
+        @Override
+        public void addListener(LeadershipEventListener listener) {
+            this.listener = listener;
         }
 
         @Override
-        public void addListener(HostListener listener) {
-            VplsTest.this.hostListener = listener;
+        public void removeListener(LeadershipEventListener listener) {
+            this.listener = null;
+        }
+
+        /**
+         * Sends the leadership event to the listener.
+         *
+         * @param event the Intent event
+         */
+        public void sendEvent(LeadershipEvent event) {
+            if (listener != null && listener.isRelevant(event)) {
+                listener.event(event);
+            }
         }
 
         @Override
-        public Set<Host> getConnectedHosts(ConnectPoint connectPoint) {
-            return hosts.stream()
-                    .filter(h -> h.location().equals(connectPoint))
+        public NodeId getLeader(String path) {
+            return NODE_ID_1;
+        }
+    }
+
+    /**
+     * Test interface service; contains all interfaces which already generated.
+     */
+    public class TestInterfaceService implements InterfaceService {
+
+        @Override
+        public void addListener(InterfaceListener listener) {
+        }
+
+        @Override
+        public void removeListener(InterfaceListener listener) {
+        }
+
+        @Override
+        public Set<Interface> getInterfaces() {
+            return AVAILABLE_INTERFACES;
+        }
+
+        @Override
+        public Interface getInterfaceByName(ConnectPoint connectPoint,
+                                            String name) {
+            return AVAILABLE_INTERFACES.stream()
+                    .filter(intf -> intf.name().equals(name))
+                    .findFirst()
+                    .orElse(null);
+        }
+
+        @Override
+        public Set<Interface> getInterfacesByPort(ConnectPoint port) {
+            return AVAILABLE_INTERFACES.stream()
+                    .filter(intf -> intf.connectPoint().equals(port))
                     .collect(Collectors.toSet());
         }
 
+        @Override
+        public Set<Interface> getInterfacesByIp(IpAddress ip) {
+            return AVAILABLE_INTERFACES.stream()
+                    .filter(intf -> intf.ipAddressesList().contains(ip))
+                    .collect(Collectors.toSet());
+        }
+
+        @Override
+        public Set<Interface> getInterfacesByVlan(VlanId vlan) {
+            return AVAILABLE_INTERFACES.stream()
+                    .filter(intf -> intf.vlan().equals(vlan))
+                    .collect(Collectors.toSet());
+        }
+
+        @Override
+        public Interface getMatchingInterface(IpAddress ip) {
+            return AVAILABLE_INTERFACES.stream()
+                    .filter(intf -> intf.ipAddressesList().contains(ip))
+                    .findFirst()
+                    .orElse(null);
+        }
+
+        @Override
+        public Set<Interface> getMatchingInterfaces(IpAddress ip) {
+            return AVAILABLE_INTERFACES.stream()
+                    .filter(intf -> intf.ipAddressesList().contains(ip))
+                    .collect(Collectors.toSet());
+        }
+    }
+
+    /**
+     * Test VPLS store.
+     */
+    public class TestVplsStore extends VplsStoreAdapter {
+        /**
+         * Clears the store.
+         */
+        public void clear() {
+            vplsDataMap.clear();
+        }
+
+        /**
+         * Gets the store delegate.
+         *
+         * @return the store delegate
+         */
+        public StoreDelegate<VplsStoreEvent> delegate() {
+            return this.delegate;
+        }
+    }
+
+    /**
+     * Test VPLS.
+     * Provides basic VPLS functionality and stores VPLS information.
+     */
+    public class TestVpls implements Vpls {
+        public Map<String, VplsData> testData;
+
+        public TestVpls() {
+            testData = Maps.newHashMap();
+        }
+
+        public void initSampleData() {
+            testData.clear();
+            VplsData vplsData = VplsData.of(VPLS1);
+            vplsData.addInterfaces(ImmutableSet.of(V100H1, V100H2));
+            vplsData.state(VplsData.VplsState.ADDED);
+            testData.put(VPLS1, vplsData);
+
+            vplsData = VplsData.of(VPLS2);
+            vplsData.addInterfaces(ImmutableSet.of(V200H1, V200H2));
+            vplsData.state(VplsData.VplsState.ADDED);
+            testData.put(VPLS2, vplsData);
+        }
+
+        @Override
+        public VplsData createVpls(String vplsName, EncapsulationType encapsulationType) {
+            VplsData vplsData = VplsData.of(vplsName, encapsulationType);
+            testData.put(vplsName, vplsData);
+            return vplsData;
+        }
+
+        @Override
+        public VplsData removeVpls(VplsData vplsData) {
+            if (!testData.containsKey(vplsData.name())) {
+                return null;
+            }
+
+            testData.remove(vplsData.name());
+            return vplsData;
+        }
+
+        @Override
+        public void addInterfaces(VplsData vplsData, Collection<Interface> interfaces) {
+            vplsData.addInterfaces(interfaces);
+            testData.put(vplsData.name(), vplsData);
+        }
+
+        @Override
+        public void addInterface(VplsData vplsData, Interface iface) {
+            vplsData.addInterface(iface);
+            testData.put(vplsData.name(), vplsData);
+        }
+
+        @Override
+        public void setEncapsulationType(VplsData vplsData, EncapsulationType encapsulationType) {
+            vplsData.encapsulationType(encapsulationType);
+            testData.put(vplsData.name(), vplsData);
+        }
+
+        @Override
+        public VplsData getVpls(String vplsName) {
+            return testData.get(vplsName);
+        }
+
+        @Override
+        public Collection<VplsData> getAllVpls() {
+            return testData.values();
+        }
+
+        @Override
+        public Collection<Interface> removeInterfaces(VplsData vplsData, Collection<Interface> interfaces) {
+            vplsData.removeInterfaces(interfaces);
+            testData.put(vplsData.name(), vplsData);
+            return interfaces;
+        }
+
+        @Override
+        public Interface removeInterface(VplsData vplsData, Interface iface) {
+            vplsData.removeInterface(iface);
+            testData.put(vplsData.name(), vplsData);
+            return iface;
+        }
+
+        @Override
+        public void removeAllVpls() {
+            testData.clear();
+        }
     }
 
     /**
      * Represents a fake IdGenerator class for intents.
      */
-    private static class TestIdGenerator implements IdGenerator {
-
+    protected static class TestIdGenerator implements IdGenerator {
         private final AtomicLong id = new AtomicLong(0);
 
         @Override
@@ -814,170 +551,135 @@
     }
 
     /**
-     * Test IntentSynchronizer that passes all intents straight through to the
-     * intent service.
+     * Test host service; contains all hosts which already generated.
+     *
      */
-    private class TestIntentSynchronizer implements IntentSynchronizationService {
+    public class TestHostService extends HostServiceAdapter {
 
-        private final IntentService intentService;
+        private HostListener listener;
 
-        /**
-         * Creates a new intent test synchronizer.
-         *
-         * @param intentService intent service
-         */
-        public TestIntentSynchronizer(IntentService intentService) {
-            this.intentService = intentService;
+        @Override
+        public Set<Host> getConnectedHosts(ConnectPoint connectPoint) {
+            return AVAILABLE_HOSTS.stream()
+                    .filter(host -> host.location().equals(connectPoint))
+                    .collect(Collectors.toSet());
         }
 
         @Override
-        public void submit(Intent intent) {
-            intentService.submit(intent);
+        public Set<Host> getHostsByMac(MacAddress mac) {
+            return AVAILABLE_HOSTS.stream()
+                    .filter(host -> host.mac().equals(mac))
+                    .collect(Collectors.toSet());
         }
 
         @Override
-        public void withdraw(Intent intent) {
-            intentService.withdraw(intent);
+        public Iterable<Host> getHosts() {
+            return AVAILABLE_HOSTS;
         }
 
         @Override
-        public void removeIntentsByAppId(ApplicationId applicationId) {
+        public Set<Host> getHostsByVlan(VlanId vlanId) {
+            return AVAILABLE_HOSTS.stream()
+                    .filter(host -> host.vlan().equals(vlanId))
+                    .collect(Collectors.toSet());
+        }
+
+        @Override
+        public int getHostCount() {
+            return AVAILABLE_HOSTS.size();
+        }
+
+        @Override
+        public Host getHost(HostId hostId) {
+            return AVAILABLE_HOSTS.stream()
+                    .filter(host -> host.id().equals(hostId))
+                    .findFirst()
+                    .orElse(null);
+        }
+
+        @Override
+        public void addListener(HostListener listener) {
+            this.listener = listener;
+        }
+
+        public void postHostEvent(HostEvent hostEvent) {
+            this.listener.event(hostEvent);
         }
     }
 
     /**
-     * Represents a fake VplsConfigService class which is needed for testing.
+     * Test network configuration service.
      */
-    private class TestVplsConfigService extends VplsConfigServiceAdapter {
+    public class TestConfigService extends NetworkConfigServiceAdapter {
+        public static final String EMPTY_JSON_TREE = "{}";
+        NetworkConfigListener listener;
+        VplsAppConfig vplsAppConfig;
 
-        private final SetMultimap<String, Interface> ifacesByVplsName;
-        private final Map<String, EncapsulationType> encapsByVplsName;
-
-        private Set<String> vplsAffectByApi = new HashSet<>();
-
-        TestVplsConfigService(SetMultimap<String, Interface> ifacesByVplsName,
-                              Map<String, EncapsulationType> encapsByVplsName) {
-            this.ifacesByVplsName = ifacesByVplsName;
-            this.encapsByVplsName = encapsByVplsName;
+        @Override
+        public void addListener(NetworkConfigListener listener) {
+            this.listener = listener;
         }
 
         @Override
-        public void addVpls(String vplsName, Set<String> ifaceNames, String encap) {
-            if (!ifacesByVplsName.containsKey(vplsName)) {
-                ifaceNames.forEach(ifaceName -> {
-                    AVAILABLE_INTERFACES.forEach(iface -> {
-                        if (iface.name().equals(ifaceName)) {
-                            ifacesByVplsName.put(vplsName, iface);
-                        }
-                    });
-                });
-            }
-            if (!ifacesByVplsName.containsKey(vplsName)) {
-                encapsByVplsName.put(vplsName, valueOf(encap));
+        public void removeListener(NetworkConfigListener listener) {
+            this.listener = null;
+        }
+
+        /**
+         * Sends network config event to listener.
+         *
+         * @param event the network config event
+         */
+        public void sendEvent(NetworkConfigEvent event) {
+            if (listener != null) {
+                listener.event(event);
             }
         }
 
-        @Override
-        public void removeVpls(String vplsName) {
-            if (ifacesByVplsName.containsKey(vplsName)) {
-                ifacesByVplsName.removeAll(vplsName);
+        /**
+         * Constructs test config service.
+         * Generates an VPLS configuration with sample VPLS configs.
+         */
+        public TestConfigService() {
+            vplsAppConfig = new VplsAppConfig();
+            final ObjectMapper mapper = new ObjectMapper();
+            final ConfigApplyDelegate delegate = new VplsAppConfigTest.MockCfgDelegate();
+            JsonNode tree = null;
+            try {
+                tree = new ObjectMapper().readTree(EMPTY_JSON_TREE);
+            } catch (IOException e) {
+                e.printStackTrace();
             }
+            vplsAppConfig.init(APPID, APP_NAME, tree, mapper, delegate);
+            VplsConfig vplsConfig = new VplsConfig(VPLS1,
+                                                   ImmutableSet.of(V100H1.name(), V100H2.name()),
+                                                   EncapsulationType.NONE);
+            vplsAppConfig.addVpls(vplsConfig);
+            vplsConfig = new VplsConfig(VPLS2,
+                                        ImmutableSet.of(V200H1.name(), V200H2.name()),
+                                        EncapsulationType.VLAN);
+            vplsAppConfig.addVpls(vplsConfig);
+
+        }
+
+        /**
+         * Overrides VPLS config to the config service.
+         *
+         * @param vplsAppConfig the new VPLS config
+         */
+        public void setConfig(VplsAppConfig vplsAppConfig) {
+            this.vplsAppConfig = vplsAppConfig;
         }
 
         @Override
-        public void addIface(String vplsName, String iface) {
-            if (!ifacesByVplsName.containsKey(vplsName)) {
-                AVAILABLE_INTERFACES.forEach(intf -> {
-                    if (intf.name().equals(iface)) {
-                        ifacesByVplsName.put(vplsName, intf);
-                    }
-                });
-            }
+        public <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass) {
+            return (C) vplsAppConfig;
         }
 
         @Override
-        public void setEncap(String vplsName, String encap) {
-            encapsByVplsName.put(vplsName, EncapsulationType.enumFromString(encap));
-        }
-
-        @Override
-        public void removeIface(String iface) {
-            SetMultimap<String, Interface> search = HashMultimap.create(ifacesByVplsName);
-            search.entries().forEach(e -> {
-                if (e.getValue().name().equals(iface)) {
-                    ifacesByVplsName.remove(e.getKey(), iface);
-                }
-            });
-        }
-
-        @Override
-        public void cleanVplsConfig() {
-            ifacesByVplsName.clear();
-        }
-
-        @Override
-        public EncapsulationType encap(String vplsName) {
-            EncapsulationType encap = null;
-            if (encapsByVplsName.containsKey(vplsName)) {
-                encap = encapsByVplsName.get(vplsName);
-            }
-            return encap;
-        }
-
-        @Override
-        public Set<String> vplsAffectedByApi() {
-            Set<String> vplsNames = ImmutableSet.copyOf(vplsAffectByApi);
-
-            vplsAffectByApi.clear();
-
-            return vplsNames;
-        }
-
-        @Override
-        public Set<Interface> allIfaces() {
-            return ifacesByVplsName.values()
-                    .stream()
-                    .collect(Collectors.toSet());
-        }
-
-        @Override
-        public Set<Interface> ifaces(String name) {
-            return ifacesByVplsName.get(name)
-                    .stream()
-                    .collect(Collectors.toSet());
-        }
-
-        @Override
-        public Set<String> vplsNames() {
-            return ifacesByVplsName.keySet();
-        }
-
-        @Override
-        public Set<String> vplsNamesOld() {
-            return ifacesByVplsName.keySet();
-        }
-
-        public SetMultimap<String, Interface> ifacesByVplsName() {
-            return ImmutableSetMultimap.copyOf(ifacesByVplsName);
-        }
-
-        @Override
-        public SetMultimap<String, Interface> ifacesByVplsName(VlanId vlan,
-                                                               ConnectPoint connectPoint) {
-            String vplsName =
-                    ifacesByVplsName.entries().stream()
-                            .filter(e -> e.getValue().connectPoint().equals(connectPoint))
-                            .filter(e -> e.getValue().vlan().equals(vlan))
-                            .map(Map.Entry::getKey)
-                            .findFirst()
-                            .orElse(null);
-            SetMultimap<String, Interface> result = HashMultimap.create();
-            if (vplsName != null && ifacesByVplsName.containsKey(vplsName)) {
-                ifacesByVplsName.get(vplsName)
-                        .forEach(intf -> result.put(vplsName, intf));
-                return result;
-            }
-            return null;
+        public <S, C extends Config<S>> C addConfig(S subject, Class<C> configClass) {
+            return (C) vplsAppConfig;
         }
     }
+
 }
