Merge "BUG-4117: add support for flow old Notif"
authorAbhijit Kumbhare <abhijit.kumbhare@ericsson.com>
Sat, 21 May 2016 01:06:54 +0000 (01:06 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Sat, 21 May 2016 01:06:54 +0000 (01:06 +0000)
applications/old-notification-supplier/src/main/java/org/opendaylight/openflowplugin/applications/old/notification/supplier/OldNotifProviderImpl.java
applications/old-notification-supplier/src/main/java/org/opendaylight/openflowplugin/applications/old/notification/supplier/OldNotifSupplierForItem.java [new file with mode: 0644]
applications/old-notification-supplier/src/main/java/org/opendaylight/openflowplugin/applications/old/notification/supplier/impl/item/AbstractNotifSupplierForItem.java [new file with mode: 0644]
applications/old-notification-supplier/src/main/java/org/opendaylight/openflowplugin/applications/old/notification/supplier/impl/item/FlowNotificationSupplierImpl.java [new file with mode: 0644]
applications/old-notification-supplier/src/main/java/org/opendaylight/openflowplugin/applications/old/notification/supplier/impl/item/package-info.java [new file with mode: 0644]
applications/old-notification-supplier/src/test/java/org/opendaylight/openflowplugin/applications/old/notification/supplier/impl/item/FlowNotificationSupplierImplTest.java [new file with mode: 0644]

index 1a49c3d82344e6f3b6d4d11402ba7809fe67d8ea..566abde56c485a9eab5f64eb116162ce3008e615 100644 (file)
@@ -17,9 +17,14 @@ import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
 import org.opendaylight.openflowplugin.applications.old.notification.supplier.impl.NodeConnectorNotificationSupplierImpl;
 import org.opendaylight.openflowplugin.applications.old.notification.supplier.impl.NodeNotificationSupplierImpl;
+import org.opendaylight.openflowplugin.applications.old.notification.supplier.impl.item.FlowNotificationSupplierImpl;
 import org.opendaylight.openflowplugin.applications.old.notification.supplier.tools.OldNotifProviderConfig;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowAdded;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemoved;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowUpdated;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRemoved;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorUpdated;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRemoved;
@@ -38,6 +43,7 @@ public class OldNotifProviderImpl implements OldNotifProvider {
     private List<OldNotifSupplierDefinition<?>> supplierList;
     private OldNotifSupplierForItemRoot<FlowCapableNode, NodeUpdated, NodeRemoved> nodeSupp;
     private OldNotifSupplierForItemRoot<FlowCapableNodeConnector, NodeConnectorUpdated, NodeConnectorRemoved> connectorSupp;
+    private OldNotifSupplierForItem<Flow, FlowAdded, FlowUpdated, FlowRemoved> flowSupp;
 
     /**
      * Provider constructor set all needed final parameters
@@ -57,8 +63,9 @@ public class OldNotifProviderImpl implements OldNotifProvider {
     public void start() {
         nodeSupp = new NodeNotificationSupplierImpl(nps, db);
         connectorSupp = new NodeConnectorNotificationSupplierImpl(nps, db);
+        flowSupp = config.isFlowSupport() ? new FlowNotificationSupplierImpl(nps, db) : null;
 
-        supplierList = new ArrayList<>(Arrays.<OldNotifSupplierDefinition<?>> asList(nodeSupp, connectorSupp));
+        supplierList = new ArrayList<>(Arrays.asList(nodeSupp, connectorSupp, flowSupp));
     }
 
     @Override
diff --git a/applications/old-notification-supplier/src/main/java/org/opendaylight/openflowplugin/applications/old/notification/supplier/OldNotifSupplierForItem.java b/applications/old-notification-supplier/src/main/java/org/opendaylight/openflowplugin/applications/old/notification/supplier/OldNotifSupplierForItem.java
new file mode 100644 (file)
index 0000000..b6ebb40
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.applications.old.notification.supplier;
+
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.Notification;
+
+/**
+ * Supplier Item contracts definition for every Old Notifications. All items are described
+ * by three notifications. Notification for Create, Update and Delete. So interface
+ * has to contain three methods for every Notification.
+ *
+ * @param <O> - data tree item Object
+ * @param <C> - Create notification
+ * @param <U> - Update notification
+ * @param <D> - Delete notification
+ */
+public interface OldNotifSupplierForItem<O extends DataObject, C extends Notification, U extends Notification, D extends Notification>
+        extends OldNotifSupplierDefinition<O> {
+
+    /**
+     * Method produces relevant addItem kind of {@link Notification} from
+     * data tree item identified by {@link InstanceIdentifier} path.
+     *
+     * @param o - Data Tree Item object
+     * @param path - Identifier of Data Tree Item
+     * @return {@link Notification} - relevant API contract Notification
+     */
+    C createNotification(O o, InstanceIdentifier<O> path);
+
+    /**
+     * Method produces relevant updateItem kind of {@link Notification} from
+     * data tree item identified by {@link InstanceIdentifier} path.
+     *
+     * @param o - Data Tree Item object
+     * @param path - Identifier of Data Tree Item
+     * @return {@link Notification} - relevant API contract Notification
+     */
+    U updateNotification(O o, InstanceIdentifier<O> path);
+
+    /**
+     * Method produces relevant deleteItem kind of {@link Notification} from
+     * path {@link InstanceIdentifier} to deleted item.
+     *
+     * @param path - Identifier of Data Tree Item
+     * @return {@link Notification} - relevant API contract Notification
+     */
+    D deleteNotification(InstanceIdentifier<O> path);
+}
+
diff --git a/applications/old-notification-supplier/src/main/java/org/opendaylight/openflowplugin/applications/old/notification/supplier/impl/item/AbstractNotifSupplierForItem.java b/applications/old-notification-supplier/src/main/java/org/opendaylight/openflowplugin/applications/old/notification/supplier/impl/item/AbstractNotifSupplierForItem.java
new file mode 100644 (file)
index 0000000..1e929d4
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.applications.old.notification.supplier.impl.item;
+
+import com.google.common.base.Preconditions;
+import java.util.Map.Entry;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.openflowplugin.applications.old.notification.supplier.OldNotifSupplierForItem;
+import org.opendaylight.openflowplugin.applications.old.notification.supplier.impl.AbstractNotifSupplierBase;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.Notification;
+
+/**
+ * Class is package protected abstract implementation for all Old Root Items
+ * Notification Suppliers
+ *
+ * @param <O> - data tree item Object
+ * @param <C> - Create notification
+ * @param <U> - Update notification
+ * @param <D> - Delete notification
+ */
+abstract class AbstractNotifSupplierForItem<O extends DataObject,
+                                            C extends Notification,
+                                            U extends Notification,
+                                            D extends Notification>
+                    extends AbstractNotifSupplierBase<O>
+                    implements OldNotifSupplierForItem<O, C, U, D> {
+
+    private final NotificationProviderService notifProviderService;
+
+    /**
+     * Default constructor for all item Notification Supplier implementation
+     *
+     * @param notifProviderService - notification publisher
+     * @param db - DataBroker for DataChangeEvent registration
+     * @param clazz - Statistics Notification Class
+     */
+    public AbstractNotifSupplierForItem(final NotificationProviderService notifProviderService, final DataBroker db,
+            final Class<O> clazz) {
+        super(db, clazz);
+        this.notifProviderService = Preconditions.checkNotNull(notifProviderService);
+    }
+
+    @Override
+    public void onDataChanged(final AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> change) {
+        Preconditions.checkArgument(change != null, "ChangeEvent can not be null!");
+        if (change.getCreatedData() != null && !(change.getCreatedData().isEmpty())) {
+            for (final Entry<InstanceIdentifier<?>, DataObject> createDataObj : change.getCreatedData().entrySet()) {
+                if (clazz.isAssignableFrom(createDataObj.getKey().getTargetType())) {
+                    final InstanceIdentifier<O> ii = createDataObj.getKey().firstIdentifierOf(clazz);
+                    final C notif = createNotification((O) createDataObj.getValue(), ii);
+                    if (notif != null) {
+                        notifProviderService.publish(notif);
+                    }
+                }
+            }
+        }
+
+        if (change.getUpdatedData() != null && !(change.getUpdatedData().isEmpty())) {
+            for (final Entry<InstanceIdentifier<?>, DataObject> updateDataObj : change.getUpdatedData().entrySet()) {
+                if (clazz.isAssignableFrom(updateDataObj.getKey().getTargetType())) {
+                    final InstanceIdentifier<O> ii = updateDataObj.getKey().firstIdentifierOf(clazz);
+                    final U notif = updateNotification((O) updateDataObj.getValue(), ii);
+                    if (notif != null) {
+                        notifProviderService.publish(notif);
+                    }
+                }
+            }
+        }
+
+        if (change.getRemovedPaths() != null && !(change.getRemovedPaths().isEmpty())) {
+            for (final InstanceIdentifier<?> deleteDataPath : change.getRemovedPaths()) {
+                if (clazz.isAssignableFrom(deleteDataPath.getTargetType())) {
+                    final D notif = deleteNotification(deleteDataPath.firstIdentifierOf(clazz));
+                    if (notif != null) {
+                        notifProviderService.publish(notif);
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/applications/old-notification-supplier/src/main/java/org/opendaylight/openflowplugin/applications/old/notification/supplier/impl/item/FlowNotificationSupplierImpl.java b/applications/old-notification-supplier/src/main/java/org/opendaylight/openflowplugin/applications/old/notification/supplier/impl/item/FlowNotificationSupplierImpl.java
new file mode 100644 (file)
index 0000000..0b96ea7
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.applications.old.notification.supplier.impl.item;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowAdded;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowAddedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemoved;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemovedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowUpdatedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowRef;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ * Implementation define a contract between {@link Flow} data object
+ * and {@link FlowAdded}, {@link FlowUpdated} and {@link FlowRemoved} notifications.
+ */
+public class FlowNotificationSupplierImpl extends
+        AbstractNotifSupplierForItem<Flow, FlowAdded, FlowUpdated, FlowRemoved> {
+
+    private static final InstanceIdentifier<Flow> wildCardedInstanceIdent = getNodeWildII().augmentation(FlowCapableNode.class).child(Table.class).child(Flow.class);
+
+    /**
+     * Constructor register supplier as DataChangeLister and create wildCarded InstanceIdentifier.
+     *
+     * @param notifProviderService - {@link NotificationProviderService}
+     * @param db - {@link DataBroker}
+     */
+    public FlowNotificationSupplierImpl(final NotificationProviderService notifProviderService, final DataBroker db) {
+        super(notifProviderService, db, Flow.class);
+    }
+
+    @Override
+    public InstanceIdentifier<Flow> getWildCardPath() {
+        return wildCardedInstanceIdent;
+    }
+
+    @Override
+    public FlowAdded createNotification(final Flow o, final InstanceIdentifier<Flow> path) {
+        Preconditions.checkArgument(o != null);
+        Preconditions.checkArgument(path != null);
+        final FlowAddedBuilder builder = new FlowAddedBuilder(o);
+        builder.setFlowRef(new FlowRef(path));
+        builder.setNode(createNodeRef(path));
+        return builder.build();
+    }
+
+    @Override
+    public FlowUpdated updateNotification(final Flow o, final InstanceIdentifier<Flow> path) {
+        Preconditions.checkArgument(o != null);
+        Preconditions.checkArgument(path != null);
+        final FlowUpdatedBuilder builder = new FlowUpdatedBuilder(o);
+        builder.setFlowRef(new FlowRef(path));
+        builder.setNode(createNodeRef(path));
+        return builder.build();
+    }
+
+    @Override
+    public FlowRemoved deleteNotification(final InstanceIdentifier<Flow> path) {
+        Preconditions.checkArgument(path != null);
+        final FlowRemovedBuilder builder = new FlowRemovedBuilder();
+        builder.setFlowRef(new FlowRef(path));
+        builder.setNode(createNodeRef(path));
+        return builder.build();
+    }
+}
+
diff --git a/applications/old-notification-supplier/src/main/java/org/opendaylight/openflowplugin/applications/old/notification/supplier/impl/item/package-info.java b/applications/old-notification-supplier/src/main/java/org/opendaylight/openflowplugin/applications/old/notification/supplier/impl/item/package-info.java
new file mode 100644 (file)
index 0000000..a7a4c79
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+/**
+ * Package contains OF Items (Flow, Group, Meter ...) notification listener/supplier implementations
+ */
+package org.opendaylight.openflowplugin.applications.old.notification.supplier.impl.item;
\ No newline at end of file
diff --git a/applications/old-notification-supplier/src/test/java/org/opendaylight/openflowplugin/applications/old/notification/supplier/impl/item/FlowNotificationSupplierImplTest.java b/applications/old-notification-supplier/src/test/java/org/opendaylight/openflowplugin/applications/old/notification/supplier/impl/item/FlowNotificationSupplierImplTest.java
new file mode 100644 (file)
index 0000000..f3419ea
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.applications.old.notification.supplier.impl.item;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Matchers;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.openflowplugin.applications.old.notification.supplier.impl.helper.TestChangeEventBuildHelper;
+import org.opendaylight.openflowplugin.applications.old.notification.supplier.impl.helper.TestSupplierVerifyHelper;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowAdded;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowRemoved;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.FlowUpdated;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+/**
+ *
+ */
+public class FlowNotificationSupplierImplTest {
+
+    private static final String FLOW_NODE_ID = "test-111";
+    private static final Short FLOW_TABLE_ID = 111;
+    private static final String FLOW_ID = "test-flow-111";
+    private FlowNotificationSupplierImpl notifSupplierImpl;
+    private NotificationProviderService notifProviderService;
+    private DataBroker dataBroker;
+
+    @Before
+    public void initalization() {
+        notifProviderService = mock(NotificationProviderService.class);
+        dataBroker = mock(DataBroker.class);
+        notifSupplierImpl = new FlowNotificationSupplierImpl(notifProviderService, dataBroker);
+        TestSupplierVerifyHelper.verifyDataChangeRegistration(dataBroker);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testNullChangeEvent() {
+        notifSupplierImpl.onDataChanged(null);
+    }
+
+    @Test
+    public void testNullableChangeEvent() {
+        notifSupplierImpl.onDataChanged(TestChangeEventBuildHelper.createEmptyTestDataEvent());
+    }
+
+    @Test
+    public void testEmptyChangeEvent() {
+        notifSupplierImpl.onDataChanged(TestChangeEventBuildHelper.createEmptyTestDataEvent());
+    }
+
+    @Test
+    public void testCreate() {
+        final FlowAdded notification = notifSupplierImpl.createNotification(createTestFlow(), createTestFlowPath());
+        assertNotNull(notification);
+        assertEquals(FLOW_ID, notification.getFlowRef().getValue().firstKeyOf(Flow.class, FlowKey.class).getId().getValue());
+        assertEquals(FLOW_TABLE_ID, notification.getFlowRef().getValue().firstKeyOf(Table.class, TableKey.class).getId());
+        assertEquals(FLOW_NODE_ID, notification.getNode().getValue().firstKeyOf(Node.class, NodeKey.class).getId().getValue());
+    }
+
+    @Test
+    public void testCreateChangeEvent() {
+        final Map<InstanceIdentifier<?>, DataObject> createdData = new HashMap<>();
+        createdData.put(createTestFlowPath(), createTestFlow());
+        notifSupplierImpl.onDataChanged(TestChangeEventBuildHelper.createTestDataEvent(createdData, null, null));
+        verify(notifProviderService, times(1)).publish(Matchers.any(FlowAdded.class));
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testCreateFromNullNodeConnector() {
+        notifSupplierImpl.createNotification(null, createTestFlowPath());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testCreateFromNullPath() {
+        notifSupplierImpl.createNotification(createTestFlow(), null);
+    }
+
+    @Test
+    public void testUpdate() {
+        final FlowUpdated notification = notifSupplierImpl.updateNotification(createTestFlow(), createTestFlowPath());
+        assertNotNull(notification);
+        assertEquals(FLOW_ID, notification.getFlowRef().getValue().firstKeyOf(Flow.class, FlowKey.class).getId().getValue());
+        assertEquals(FLOW_TABLE_ID, notification.getFlowRef().getValue().firstKeyOf(Table.class, TableKey.class).getId());
+        assertEquals(FLOW_NODE_ID, notification.getNode().getValue().firstKeyOf(Node.class, NodeKey.class).getId().getValue());
+    }
+
+    @Test
+    public void testUpdateChangeEvent() {
+        final Map<InstanceIdentifier<?>, DataObject> createdData = new HashMap<>();
+        createdData.put(createTestFlowPath(), createTestFlow());
+        notifSupplierImpl.onDataChanged(TestChangeEventBuildHelper.createTestDataEvent(createdData, null, null));
+        verify(notifProviderService, times(1)).publish(Matchers.any(FlowUpdated.class));
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testUpdateFromNullNodeConnector() {
+        notifSupplierImpl.createNotification(null, createTestFlowPath());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testUpdateFromNullPath() {
+        notifSupplierImpl.createNotification(createTestFlow(), null);
+    }
+
+    @Test
+    public void testDelete() {
+        final FlowRemoved notification = notifSupplierImpl.deleteNotification(createTestFlowPath());
+        assertNotNull(notification);
+        assertEquals(FLOW_ID, notification.getFlowRef().getValue().firstKeyOf(Flow.class, FlowKey.class).getId().getValue());
+        assertEquals(FLOW_TABLE_ID, notification.getFlowRef().getValue().firstKeyOf(Table.class, TableKey.class).getId());
+        assertEquals(FLOW_NODE_ID, notification.getNode().getValue().firstKeyOf(Node.class, NodeKey.class).getId().getValue());
+    }
+
+    @Test
+    public void testDeleteChangeEvent() {
+        final Set<InstanceIdentifier<?>> removeData = new HashSet<>();
+        removeData.add(createTestFlowPath());
+        notifSupplierImpl.onDataChanged(TestChangeEventBuildHelper.createTestDataEvent(null, null, removeData));
+        verify(notifProviderService, times(1)).publish(Matchers.any(FlowRemoved.class));
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testDeleteFromNullPath() {
+        notifSupplierImpl.deleteNotification(null);
+    }
+
+    private static InstanceIdentifier<Flow> createTestFlowPath() {
+        return InstanceIdentifier.create(Nodes.class).child(Node.class, new NodeKey(new NodeId(FLOW_NODE_ID)))
+                .augmentation(FlowCapableNode.class).child(Table.class, new TableKey(FLOW_TABLE_ID))
+                .child(Flow.class, new FlowKey(new FlowId(FLOW_ID)));
+    }
+
+    private static Flow createTestFlow() {
+        final FlowBuilder builder = new FlowBuilder();
+        builder.setId(new FlowId(FLOW_ID));
+        builder.setTableId(FLOW_TABLE_ID);
+        return builder.build();
+    }
+}
+