Change return type of events 78/60978/5
authorJozef Bacigal <jozef.bacigal@pantheon.tech>
Tue, 1 Aug 2017 10:50:56 +0000 (12:50 +0200)
committerJozef Bacigal <jozef.bacigal@pantheon.tech>
Wed, 2 Aug 2017 13:27:53 +0000 (15:27 +0200)
- remove callback from onDevicePrepared
- added ListenableFuture as return type for events
- added many tests
- small fixes found on test run

Change-Id: Id18bd669589e11a8526bdb77d70ef73df737039c
Signed-off-by: Jozef Bacigal <jozef.bacigal@pantheon.tech>
12 files changed:
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/lifecycle/ContextChainMastershipWatcher.java
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/lifecycle/OwnershipChangeListener.java
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/lifecycle/ReconciliationFrameworkRegistrar.java
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/mastership/ReconciliationFrameworkEvent.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/DeviceContextImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/lifecycle/ContextChainHolderImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/lifecycle/ContextChainImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/mastership/MastershipChangeServiceManagerImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/mastership/MastershipServiceDelegate.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/mastership/ReconciliationFrameworkServiceDelegate.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/lifecycle/ContextChainHolderImplTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/mastership/MastershipChangeServiceManagerImplTest.java

index 909a09f1fce83116a76b042376ea4b1d6038e9c3..912d21948fe89e1b8fa379fcf752eadf83942162 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.openflowplugin.api.openflow.lifecycle;
 
 import javax.annotation.Nonnull;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
+import org.opendaylight.openflowplugin.api.openflow.mastership.MastershipChangeException;
 
 /**
  * Watcher if able to start mastership for device.
index fc659ac5b1abc5e7858ec9747d54f5be948f4a42..7c0fb0a6768b2b7ddddf96bf38c04dff845c6837 100644 (file)
@@ -7,8 +7,9 @@
  */
 package org.opendaylight.openflowplugin.api.openflow.lifecycle;
 
-import com.google.common.util.concurrent.FutureCallback;
 import javax.annotation.Nonnull;
+
+import com.google.common.util.concurrent.ListenableFuture;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.rf.state.rev170713.ResultState;
 
@@ -45,9 +46,9 @@ public interface OwnershipChangeListener extends ReconciliationFrameworkRegistra
      * @see #becomeMaster(DeviceInfo)
      * @see #isReconciliationFrameworkRegistered()
      * @param deviceInfo connected switch identification
-     * @param callback future callback to be able handle device after reconciliation
+     * @return future to be able handle device after reconciliation
      */
-    void becomeMasterBeforeSubmittedDS(@Nonnull DeviceInfo deviceInfo, @Nonnull FutureCallback<ResultState> callback);
+    ListenableFuture<ResultState> becomeMasterBeforeSubmittedDS(@Nonnull DeviceInfo deviceInfo);
 
     /**
      * Set the device mastership checker.
index 70684b33fc4df88e69e636736b0807f3d76ef5c6..d1b7508fe97d525575333cf67cfa0d105db0044e 100644 (file)
@@ -13,7 +13,7 @@ import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
 public interface ReconciliationFrameworkRegistrar {
     /**
      * Check if reconciliation framework is registered.
-     * If not the event {@link OwnershipChangeListener#becomeMasterBeforeSubmittedDS(DeviceInfo, FutureCallback)}
+     * If not the event {@link OwnershipChangeListener#becomeMasterBeforeSubmittedDS(DeviceInfo)}
      * will not be triggered.
      * @return true if there exists any reconciliation framework registration
      */
index 3af361cafaccd718aa0a28e9f0c8750f7f655fd3..197e07c695170225322dfe587b233d6fbb39cfa9 100644 (file)
@@ -7,7 +7,7 @@
  */
 package org.opendaylight.openflowplugin.api.openflow.mastership;
 
-import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.ListenableFuture;
 import javax.annotation.Nonnull;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
 import org.opendaylight.openflowplugin.api.openflow.lifecycle.OwnershipChangeListener;
@@ -16,12 +16,13 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow
 /**
  * Service provide one event designed for reconciliation framework.
  * <ul>
- *     <li><i>{@link #onDevicePrepared(DeviceInfo, FutureCallback)}</i>
+ *     <li><i>{@link #onDeviceDisconnected(DeviceInfo)}</i>
  *     is called when device is being mastered by controller but not yet submitted into data store.
  *     This method is being called only if the {@link OwnershipChangeListener#isReconciliationFrameworkRegistered()}
  *     is set to {@link Boolean#TRUE}</li>
+ *     <li><i>{@link #onDevicePrepared(DeviceInfo)}</i>
+ *     is called when device is disconnected or controller loses control of the switch</li>
  * </ul>
- * Other event are defined in {@link MastershipChangeService}
  * <p>
  * <b>This event <i>onDevicePrepared</i> should be used only for reconciliation framework and application can't do anything with
  * node before the device is not stored in to data store.</b>
@@ -32,20 +33,21 @@ public interface ReconciliationFrameworkEvent extends AutoCloseable {
 
     /**
      * Event when device is ready as a master but not yet submitted in data store. This event is evoked by
-     * {@link OwnershipChangeListener#becomeMasterBeforeSubmittedDS(DeviceInfo, FutureCallback)}
+     * {@link OwnershipChangeListener#becomeMasterBeforeSubmittedDS(DeviceInfo)}
      * @param deviceInfo connected switch identification
-     * @param callback callback need to be attached to reconciliation result future
+     * @return result state if the device can continue with connecting or should be disconnected
      */
-    void onDevicePrepared(@Nonnull DeviceInfo deviceInfo, @Nonnull FutureCallback<ResultState> callback);
+    ListenableFuture<ResultState> onDevicePrepared(@Nonnull DeviceInfo deviceInfo);
 
     /**
      * This event occurs after device is disconnected or being slaved.
      * Event is similar to the {@link MastershipChangeService#onLoseOwnership(DeviceInfo)}. This event is used by
      * reconciliation framework that the framework don't need to register {@link MastershipChangeService}
      * @param deviceInfo connected switch identification
+     * @return future
      * @see MastershipChangeService
      */
-    void onDeviceDisconnected(@Nonnull DeviceInfo deviceInfo);
+    ListenableFuture<Void> onDeviceDisconnected(@Nonnull DeviceInfo deviceInfo);
 
 
 }
index f614dc8ef5fdfd3d12258d3edbe21ca72e282c92..45f5dc231f50f7f44f0960016e95b922827d2513 100644 (file)
@@ -782,7 +782,7 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
                     ContextChainMastershipState.MASTER_ON_DEVICE
             );
             if (LOG.isDebugEnabled()) {
-                LOG.debug("Role MASTER was successfully set on device, node {}", deviceInfo.getLOGValue());
+                LOG.debug("Role MASTER was successfully set on device, node {}", deviceInfo);
             }
         }
 
index 25ce05e866063951063f41806c5a0fb65151e5b3..f521e971527b72d14c1bb6ea11a5cb09cd84a5f9 100644 (file)
@@ -9,6 +9,8 @@ package org.opendaylight.openflowplugin.impl.lifecycle;
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.MoreExecutors;
 import io.netty.util.HashedWheelTimer;
 import java.util.Collections;
 import java.util.HashMap;
@@ -64,7 +66,6 @@ public class ContextChainHolderImpl implements ContextChainHolder, MasterChecker
 
     private final Map<DeviceInfo, ContextChain> contextChainMap = Collections.synchronizedMap(new HashMap<>());
     private final EntityOwnershipListenerRegistration eosListenerRegistration;
-    private final HashedWheelTimer timer;
     private final ClusterSingletonServiceProvider singletonServiceProvider;
     private final ItemScheduler<DeviceInfo, ContextChain> scheduler;
     private final ExecutorService executorService;
@@ -78,7 +79,6 @@ public class ContextChainHolderImpl implements ContextChainHolder, MasterChecker
                                   final ClusterSingletonServiceProvider singletonServiceProvider,
                                   final EntityOwnershipService entityOwnershipService,
                                   final OwnershipChangeListener ownershipChangeListener) {
-        this.timer = timer;
         this.singletonServiceProvider = singletonServiceProvider;
         this.executorService = executorService;
         this.ownershipChangeListener = ownershipChangeListener;
@@ -108,7 +108,7 @@ public class ContextChainHolderImpl implements ContextChainHolder, MasterChecker
     }
 
     @VisibleForTesting
-    ContextChain createContextChain(final ConnectionContext connectionContext) {
+    void createContextChain(final ConnectionContext connectionContext) {
         final DeviceInfo deviceInfo = connectionContext.getDeviceInfo();
 
         final DeviceContext deviceContext = deviceManager.createContext(connectionContext);
@@ -143,7 +143,6 @@ public class ContextChainHolderImpl implements ContextChainHolder, MasterChecker
                 CHECK_ROLE_MASTER_TIMEOUT / 1000L);
 
         contextChain.registerServices(singletonServiceProvider);
-        return contextChain;
     }
 
     @Override
@@ -169,8 +168,7 @@ public class ContextChainHolderImpl implements ContextChainHolder, MasterChecker
         }
 
         LOG.debug("No context chain found for device: {}, creating new.", deviceInfo);
-        final ContextChain newContextChain = createContextChain(connectionContext);
-        LOG.debug("Successfully created context chain with identifier: {}", newContextChain.getIdentifier());
+        createContextChain(connectionContext);
         return ConnectionStatus.MAY_CONTINUE;
     }
 
@@ -201,9 +199,10 @@ public class ContextChainHolderImpl implements ContextChainHolder, MasterChecker
                 } else {
                     contextChain.isMastered(mastershipState);
                     if (contextChain.isPrepared()) {
-                        ownershipChangeListener.becomeMasterBeforeSubmittedDS(
-                                deviceInfo,
-                                reconciliationFrameworkCallback(deviceInfo, contextChain));
+                        Futures.addCallback(
+                                ownershipChangeListener.becomeMasterBeforeSubmittedDS(deviceInfo),
+                                reconciliationFrameworkCallback(deviceInfo, contextChain),
+                                MoreExecutors.directExecutor());
                     }
                 }
             } else if (contextChain.isMastered(mastershipState)) {
@@ -248,7 +247,9 @@ public class ContextChainHolderImpl implements ContextChainHolder, MasterChecker
     @Override
     public void close() throws Exception {
         scheduler.close();
-        contextChainMap.keySet().forEach(this::destroyContextChain);
+        Map<DeviceInfo, ContextChain> copyOfChains = new HashMap<>(contextChainMap);
+        copyOfChains.keySet().forEach(this::destroyContextChain);
+        copyOfChains.clear();
         contextChainMap.clear();
         eosListenerRegistration.close();
     }
@@ -275,7 +276,7 @@ public class ContextChainHolderImpl implements ContextChainHolder, MasterChecker
                 deviceManager
                         .removeDeviceFromOperationalDS(nodeInstanceIdentifier)
                         .checkedGet(REMOVE_DEVICE_FROM_DS_TIMEOUT, TimeUnit.MILLISECONDS);
-            } catch (TimeoutException | TransactionCommitFailedException e) {
+            } catch (TimeoutException | TransactionCommitFailedException | NullPointerException e) {
                 LOG.info("Not able to remove device {} from operational DS. Probably removed by another cluster node.",
                         nodeId);
             }
@@ -284,7 +285,6 @@ public class ContextChainHolderImpl implements ContextChainHolder, MasterChecker
 
     private synchronized void destroyContextChain(final DeviceInfo deviceInfo) {
         scheduler.remove(deviceInfo);
-        ownershipChangeListener.becomeSlaveOrDisconnect(deviceInfo);
 
         Optional.ofNullable(contextChainMap.get(deviceInfo)).ifPresent(contextChain -> {
             deviceManager.sendNodeRemovedNotification(deviceInfo.getNodeInstanceIdentifier());
@@ -346,12 +346,14 @@ public class ContextChainHolderImpl implements ContextChainHolder, MasterChecker
                 if (ResultState.DONOTHING == result) {
                     LOG.info("Device {} connection is enabled by reconciliation framework.", deviceInfo);
                     if (!contextChain.continueInitializationAfterReconciliation()) {
+                        LOG.warn("Initialization submit after reconciliation failed for device {}", deviceInfo);
                         destroyContextChain(deviceInfo);
                     } else {
                         ownershipChangeListener.becomeMaster(deviceInfo);
+                        deviceManager.sendNodeAddedNotification(deviceInfo.getNodeInstanceIdentifier());
                     }
                 } else {
-                    LOG.warn("Reconciliation framework failure.");
+                    LOG.warn("Reconciliation framework failure for device {}", deviceInfo);
                     destroyContextChain(deviceInfo);
                 }
             }
index 1069f5b1be335779543471428205bf9ac58571e0..153945c307746a327b54d333f1743fbe10d9340b 100644 (file)
@@ -232,12 +232,13 @@ public class ContextChainImpl implements ContextChain {
 
     @Override
     public boolean continueInitializationAfterReconciliation() {
-        return isMastered(ContextChainMastershipState.INITIAL_SUBMIT) && contexts.stream()
+        return contexts.stream()
                 .filter(StatisticsContext.class::isInstance)
                 .map(StatisticsContext.class::cast)
                 .findAny()
                 .map(StatisticsContext::initialSubmitAfterReconciliation)
-                .orElse(false);
+                .orElse(false) &&
+        isMastered(ContextChainMastershipState.INITIAL_SUBMIT);
     }
 
     @Override
index 4f51430a1c2aa238961288c3aba7ce33a450d1e7..1ca178679027b1c2ee8beddea79332fda0c7c7ef 100644 (file)
@@ -8,7 +8,7 @@
 package org.opendaylight.openflowplugin.impl.mastership;
 
 import com.google.common.annotations.VisibleForTesting;
-import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.ListenableFuture;
 import java.util.ArrayList;
 import java.util.List;
 import javax.annotation.Nonnull;
@@ -21,8 +21,6 @@ import org.opendaylight.openflowplugin.api.openflow.mastership.MastershipChangeS
 import org.opendaylight.openflowplugin.api.openflow.mastership.ReconciliationFrameworkEvent;
 import org.opendaylight.openflowplugin.api.openflow.mastership.ReconciliationFrameworkRegistration;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.rf.state.rev170713.ResultState;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 public final class MastershipChangeServiceManagerImpl implements MastershipChangeServiceManager {
 
@@ -72,11 +70,8 @@ public final class MastershipChangeServiceManagerImpl implements MastershipChang
     }
 
     @Override
-    public void becomeMasterBeforeSubmittedDS(@Nonnull DeviceInfo deviceInfo,
-                                              @Nonnull FutureCallback<ResultState> callback) {
-        if (rfService != null) {
-            rfService.onDevicePrepared(deviceInfo, callback);
-        }
+    public ListenableFuture<ResultState> becomeMasterBeforeSubmittedDS(@Nonnull DeviceInfo deviceInfo) {
+        return rfService == null ? null : rfService.onDevicePrepared(deviceInfo);
     }
 
     @Override
index 7a56f9408179f95136b940f5ebbe976bd0dcb638..b0df40eefd78b8818577018c9afd9c6b67469d14 100644 (file)
@@ -11,8 +11,6 @@ import javax.annotation.Nonnull;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
 import org.opendaylight.openflowplugin.api.openflow.mastership.MastershipChangeRegistration;
 import org.opendaylight.openflowplugin.api.openflow.mastership.MastershipChangeService;
-import org.opendaylight.openflowplugin.api.openflow.mastership.MastershipChangeServiceManager;
-import org.opendaylight.openflowplugin.api.openflow.mastership.ReconciliationFrameworkRegistration;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
index fe05c29840ac9b618fc725cf08f4d75f918637a4..71b047ee411e29a34321ee2ac970ba6ae247d50e 100644 (file)
@@ -7,12 +7,12 @@
  */
 package org.opendaylight.openflowplugin.impl.mastership;
 
-import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.ListenableFuture;
+import javax.annotation.Nonnull;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
-import org.opendaylight.openflowplugin.api.openflow.mastership.*;
+import org.opendaylight.openflowplugin.api.openflow.mastership.ReconciliationFrameworkEvent;
+import org.opendaylight.openflowplugin.api.openflow.mastership.ReconciliationFrameworkRegistration;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.rf.state.rev170713.ResultState;
-
-import javax.annotation.Nonnull;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -38,13 +38,13 @@ public class ReconciliationFrameworkServiceDelegate implements ReconciliationFra
     }
 
     @Override
-    public void onDevicePrepared(@Nonnull DeviceInfo deviceInfo, @Nonnull FutureCallback<ResultState> callback) {
-        this.service.onDevicePrepared(deviceInfo, callback);
+    public ListenableFuture<ResultState> onDevicePrepared(@Nonnull DeviceInfo deviceInfo) {
+        return this.service.onDevicePrepared(deviceInfo);
     }
 
     @Override
-    public void onDeviceDisconnected(@Nonnull DeviceInfo deviceInfo) {
-        this.service.onDeviceDisconnected(deviceInfo);
+    public ListenableFuture<Void> onDeviceDisconnected(@Nonnull DeviceInfo deviceInfo) {
+        return this.service.onDeviceDisconnected(deviceInfo);
     }
 
     @Override
index 59957a230b3f0b0500ff8c897fcb72c4a6452de2..dfe08e01cc0a1ae8dfe4dec2e37c7442e7fb1f4d 100644 (file)
@@ -17,24 +17,35 @@ import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipChange;
 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipListenerRegistration;
 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceRegistration;
 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
+import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionStatus;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceManager;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.ContextChainMastershipState;
 import org.opendaylight.openflowplugin.api.openflow.lifecycle.OwnershipChangeListener;
+import org.opendaylight.openflowplugin.api.openflow.mastership.MastershipChangeServiceManager;
+import org.opendaylight.openflowplugin.api.openflow.mastership.ReconciliationFrameworkEvent;
+import org.opendaylight.openflowplugin.api.openflow.mastership.ReconciliationFrameworkRegistration;
 import org.opendaylight.openflowplugin.api.openflow.rpc.RpcContext;
 import org.opendaylight.openflowplugin.api.openflow.rpc.RpcManager;
 import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsContext;
 import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsManager;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.OpenflowProviderConfig;
+import org.opendaylight.openflowplugin.impl.mastership.MastershipChangeServiceManagerImpl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FeaturesReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.rf.state.rev170713.ResultState;
 
 @RunWith(MockitoJUnitRunner.class)
 public class ContextChainHolderImplTest {
 
+    private static final String ENTITY_TEST = "EntityTest";
+    private static final String OPENFLOW_TEST = "openflow:test";
     @Mock
     private HashedWheelTimer timer;
     @Mock
@@ -65,8 +76,15 @@ public class ContextChainHolderImplTest {
     private EntityOwnershipListenerRegistration entityOwnershipListenerRegistration;
     @Mock
     private OwnershipChangeListener ownershipChangeListener;
+    @Mock
+    private ReconciliationFrameworkEvent reconciliationFrameworkEvent;
+    @Mock
+    private FeaturesReply featuresReply;
 
     private ContextChainHolderImpl contextChainHolder;
+    private ReconciliationFrameworkRegistration registration;
+    private MastershipChangeServiceManager manager = new MastershipChangeServiceManagerImpl();
+    private final Short AUXILIARY_ID = 0;
 
     @Before
     public void setUp() throws Exception {
@@ -87,14 +105,17 @@ public class ContextChainHolderImplTest {
                 .thenReturn(clusterSingletonServiceRegistration);
         Mockito.when(entityOwnershipService.registerListener(Mockito.any(), Mockito.any()))
                 .thenReturn(entityOwnershipListenerRegistration);
-        Mockito.when(ownershipChangeListener.isReconciliationFrameworkRegistered()).thenReturn(false);
+        Mockito.when(connectionContext.getFeatures()).thenReturn(featuresReply);
+        Mockito.when(featuresReply.getAuxiliaryId()).thenReturn(AUXILIARY_ID);
+
+        registration = manager.reconciliationFrameworkRegistration(reconciliationFrameworkEvent);
 
         contextChainHolder = new ContextChainHolderImpl(
                 timer,
                 executorService,
                 singletonServicesProvider,
                 entityOwnershipService,
-                ownershipChangeListener
+                manager
         );
         contextChainHolder.addManager(statisticsManager);
         contextChainHolder.addManager(rpcManager);
@@ -114,44 +135,161 @@ public class ContextChainHolderImplTest {
         Mockito.verify(statisticsManager).createContext(Mockito.any(DeviceContext.class));
     }
 
-    @Test
-    public void destroyContextChain() throws Exception {
 
+    @Test
+    public void reconciliationFrameworkFailure() throws Exception {
+        Mockito.when(reconciliationFrameworkEvent.onDevicePrepared(deviceInfo)).thenReturn(Futures.immediateFailedFuture(new Throwable("test")));
+        contextChainHolder.createContextChain(connectionContext);
+        contextChainHolder.onMasterRoleAcquired(deviceInfo, ContextChainMastershipState.INITIAL_FLOW_REGISTRY_FILL);
+        contextChainHolder.onMasterRoleAcquired(deviceInfo, ContextChainMastershipState.INITIAL_GATHERING);
+        contextChainHolder.onMasterRoleAcquired(deviceInfo, ContextChainMastershipState.RPC_REGISTRATION);
+        contextChainHolder.onMasterRoleAcquired(deviceInfo, ContextChainMastershipState.MASTER_ON_DEVICE);
+        Mockito.verify(reconciliationFrameworkEvent).onDeviceDisconnected(deviceInfo);
     }
 
     @Test
-    public void pairConnection() throws Exception {
-
+    public void reconciliationFrameworkDisconnect() throws Exception {
+        Mockito.when(reconciliationFrameworkEvent.onDevicePrepared(deviceInfo)).thenReturn(Futures.immediateFuture(ResultState.DISCONNECT));
+        contextChainHolder.createContextChain(connectionContext);
+        contextChainHolder.onMasterRoleAcquired(deviceInfo, ContextChainMastershipState.INITIAL_FLOW_REGISTRY_FILL);
+        contextChainHolder.onMasterRoleAcquired(deviceInfo, ContextChainMastershipState.INITIAL_GATHERING);
+        contextChainHolder.onMasterRoleAcquired(deviceInfo, ContextChainMastershipState.RPC_REGISTRATION);
+        contextChainHolder.onMasterRoleAcquired(deviceInfo, ContextChainMastershipState.MASTER_ON_DEVICE);
+        Mockito.verify(reconciliationFrameworkEvent).onDeviceDisconnected(deviceInfo);
     }
 
     @Test
-    public void deviceConnected() throws Exception {
-
+    public void reconciliationFrameworkSuccess() throws Exception {
+        contextChainHolder.createContextChain(connectionContext);
+        Mockito.when(reconciliationFrameworkEvent.onDevicePrepared(deviceInfo)).thenReturn(Futures.immediateFuture(ResultState.DONOTHING));
+        Mockito.when(statisticsContext.initialSubmitAfterReconciliation()).thenReturn(true);
+        contextChainHolder.createContextChain(connectionContext);
+        contextChainHolder.onMasterRoleAcquired(deviceInfo, ContextChainMastershipState.INITIAL_FLOW_REGISTRY_FILL);
+        contextChainHolder.onMasterRoleAcquired(deviceInfo, ContextChainMastershipState.INITIAL_GATHERING);
+        contextChainHolder.onMasterRoleAcquired(deviceInfo, ContextChainMastershipState.RPC_REGISTRATION);
+        contextChainHolder.onMasterRoleAcquired(deviceInfo, ContextChainMastershipState.MASTER_ON_DEVICE);
+        Mockito.verify(reconciliationFrameworkEvent).onDevicePrepared(deviceInfo);
     }
 
     @Test
-    public void onNotAbleToStartMastership() throws Exception {
-
+    public void reconciliationFrameworkSuccessButNotSubmit() throws Exception {
+        contextChainHolder.createContextChain(connectionContext);
+        Mockito.when(reconciliationFrameworkEvent.onDevicePrepared(deviceInfo)).thenReturn(Futures.immediateFuture(ResultState.DONOTHING));
+        Mockito.when(statisticsContext.initialSubmitAfterReconciliation()).thenReturn(false);
+        contextChainHolder.createContextChain(connectionContext);
+        contextChainHolder.onMasterRoleAcquired(deviceInfo, ContextChainMastershipState.INITIAL_FLOW_REGISTRY_FILL);
+        contextChainHolder.onMasterRoleAcquired(deviceInfo, ContextChainMastershipState.INITIAL_GATHERING);
+        contextChainHolder.onMasterRoleAcquired(deviceInfo, ContextChainMastershipState.RPC_REGISTRATION);
+        contextChainHolder.onMasterRoleAcquired(deviceInfo, ContextChainMastershipState.MASTER_ON_DEVICE);
+        Mockito.verify(reconciliationFrameworkEvent).onDeviceDisconnected(deviceInfo);
     }
 
     @Test
-    public void onMasterRoleAcquired() throws Exception {
-
+    public void deviceMastered() throws Exception {
+        registration.close();
+        contextChainHolder.createContextChain(connectionContext);
+        contextChainHolder.onMasterRoleAcquired(deviceInfo, ContextChainMastershipState.INITIAL_FLOW_REGISTRY_FILL);
+        Assert.assertFalse(contextChainHolder.isAnyDeviceMastered());
+        contextChainHolder.onMasterRoleAcquired(deviceInfo, ContextChainMastershipState.INITIAL_GATHERING);
+        Assert.assertFalse(contextChainHolder.isAnyDeviceMastered());
+        contextChainHolder.onMasterRoleAcquired(deviceInfo, ContextChainMastershipState.RPC_REGISTRATION);
+        Assert.assertFalse(contextChainHolder.isAnyDeviceMastered());
+        contextChainHolder.onMasterRoleAcquired(deviceInfo, ContextChainMastershipState.MASTER_ON_DEVICE);
+        Assert.assertFalse(contextChainHolder.isAnyDeviceMastered());
+        contextChainHolder.onMasterRoleAcquired(deviceInfo, ContextChainMastershipState.INITIAL_SUBMIT);
+        Assert.assertTrue(contextChainHolder.isAnyDeviceMastered());
+        Assert.assertTrue(contextChainHolder.listOfMasteredDevices().size() == 1);
     }
 
     @Test
-    public void onSlaveRoleAcquired() throws Exception {
+    public void deviceConnected() throws Exception {
+        registration.close();
+        Assert.assertTrue(contextChainHolder.deviceConnected(connectionContext)
+                == ConnectionStatus.MAY_CONTINUE);
+        Short AUXILIARY_ID_1 = 1;
+        Mockito.when(featuresReply.getAuxiliaryId()).thenReturn(AUXILIARY_ID_1);
+        Assert.assertTrue(contextChainHolder.deviceConnected(connectionContext)
+                == ConnectionStatus.MAY_CONTINUE);
+        Mockito.when(featuresReply.getAuxiliaryId()).thenReturn(AUXILIARY_ID);
+        Assert.assertTrue(contextChainHolder.deviceConnected(connectionContext)
+                == ConnectionStatus.ALREADY_CONNECTED);
+    }
 
+    @Test
+    public void notToAbleMastership() throws Exception {
+        registration.close();
+        contextChainHolder.deviceConnected(connectionContext);
+        contextChainHolder.onNotAbleToStartMastership(deviceInfo, "Test reason", true);
+        Mockito.verify(deviceContext).close();
+        Mockito.verify(statisticsContext).close();
+        Mockito.verify(rpcContext).close();
     }
 
     @Test
-    public void onSlaveRoleNotAcquired() throws Exception {
+    public void notAbleToSetSlave() throws Exception {
+        registration.close();
+        contextChainHolder.deviceConnected(connectionContext);
+        contextChainHolder.onSlaveRoleNotAcquired(deviceInfo);
+        Mockito.verify(deviceContext).close();
+        Mockito.verify(statisticsContext).close();
+        Mockito.verify(rpcContext).close();
+    }
 
+    @Test
+    public void deviceDisconnected() throws Exception {
+        registration.close();
+        contextChainHolder.createContextChain(connectionContext);
+        contextChainHolder.onDeviceDisconnected(connectionContext);
+        Mockito.verify(deviceContext).close();
+        Mockito.verify(statisticsContext).close();
+        Mockito.verify(rpcContext).close();
     }
 
     @Test
-    public void onDeviceDisconnected() throws Exception {
+    public void onClose() throws Exception {
+        registration.close();
+        contextChainHolder.createContextChain(connectionContext);
+        contextChainHolder.close();
+        Mockito.verify(deviceContext).close();
+        Mockito.verify(statisticsContext).close();
+        Mockito.verify(rpcContext).close();
+    }
 
+    @Test
+    public void ownershipChanged() throws Exception {
+        registration.close();
+        contextChainHolder.createContextChain(connectionContext);
+        contextChainHolder.onMasterRoleAcquired(deviceInfo, ContextChainMastershipState.INITIAL_FLOW_REGISTRY_FILL);
+        contextChainHolder.onMasterRoleAcquired(deviceInfo, ContextChainMastershipState.INITIAL_GATHERING);
+        contextChainHolder.onMasterRoleAcquired(deviceInfo, ContextChainMastershipState.RPC_REGISTRATION);
+        contextChainHolder.onMasterRoleAcquired(deviceInfo, ContextChainMastershipState.MASTER_ON_DEVICE);
+        contextChainHolder.onMasterRoleAcquired(deviceInfo, ContextChainMastershipState.INITIAL_SUBMIT);
+        EntityOwnershipChange ownershipChange = new EntityOwnershipChange(
+                new Entity(ENTITY_TEST, OPENFLOW_TEST),
+                true,
+                false,
+                false
+        );
+        contextChainHolder.ownershipChanged(ownershipChange);
+        Mockito.verify(deviceManager).removeDeviceFromOperationalDS(Mockito.any());
     }
+    @Test
 
+    public void ownershipChangedButHasOwner() throws Exception {
+        registration.close();
+        contextChainHolder.createContextChain(connectionContext);
+        contextChainHolder.onMasterRoleAcquired(deviceInfo, ContextChainMastershipState.INITIAL_FLOW_REGISTRY_FILL);
+        contextChainHolder.onMasterRoleAcquired(deviceInfo, ContextChainMastershipState.INITIAL_GATHERING);
+        contextChainHolder.onMasterRoleAcquired(deviceInfo, ContextChainMastershipState.RPC_REGISTRATION);
+        contextChainHolder.onMasterRoleAcquired(deviceInfo, ContextChainMastershipState.MASTER_ON_DEVICE);
+        contextChainHolder.onMasterRoleAcquired(deviceInfo, ContextChainMastershipState.INITIAL_SUBMIT);
+        EntityOwnershipChange ownershipChange = new EntityOwnershipChange(
+                new Entity(ENTITY_TEST, OPENFLOW_TEST),
+                true,
+                false,
+                true
+        );
+        contextChainHolder.ownershipChanged(ownershipChange);
+        Mockito.verify(deviceManager,Mockito.never()).removeDeviceFromOperationalDS(Mockito.any());
+    }
 }
\ No newline at end of file
index 2e0eaf43840bcb4321c1c2914c9f3f9e1d6ca84b..6b3a996a3cbc44ec00d0eac21fa8470292a87d55 100644 (file)
@@ -7,7 +7,8 @@
  */
 package org.opendaylight.openflowplugin.impl.mastership;
 
-import com.google.common.util.concurrent.FutureCallback;
+import java.util.ArrayList;
+import java.util.List;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
@@ -17,13 +18,12 @@ import org.mockito.Mockito;
 import org.mockito.runners.MockitoJUnitRunner;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceInfo;
 import org.opendaylight.openflowplugin.api.openflow.lifecycle.MasterChecker;
-import org.opendaylight.openflowplugin.api.openflow.mastership.*;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflowplugin.rf.state.rev170713.ResultState;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import static org.junit.Assert.*;
+import org.opendaylight.openflowplugin.api.openflow.mastership.MastershipChangeException;
+import org.opendaylight.openflowplugin.api.openflow.mastership.MastershipChangeRegistration;
+import org.opendaylight.openflowplugin.api.openflow.mastership.MastershipChangeService;
+import org.opendaylight.openflowplugin.api.openflow.mastership.MastershipChangeServiceManager;
+import org.opendaylight.openflowplugin.api.openflow.mastership.ReconciliationFrameworkEvent;
+import org.opendaylight.openflowplugin.api.openflow.mastership.ReconciliationFrameworkRegistration;
 
 @RunWith(MockitoJUnitRunner.class)
 public class MastershipChangeServiceManagerImplTest {
@@ -35,8 +35,6 @@ public class MastershipChangeServiceManagerImplTest {
     @Mock
     private DeviceInfo deviceInfo;
     @Mock
-    private FutureCallback<ResultState> resultStateFutureCallback;
-    @Mock
     private MasterChecker masterChecker;
     @Mock
     private ReconciliationFrameworkEvent event;
@@ -105,8 +103,8 @@ public class MastershipChangeServiceManagerImplTest {
 
     @Test
     public void becomeMasterBeforeDS() throws Exception {
-        manager.becomeMasterBeforeSubmittedDS(deviceInfo, resultStateFutureCallback);
-        Mockito.verify(event).onDevicePrepared(deviceInfo, resultStateFutureCallback);
+        manager.becomeMasterBeforeSubmittedDS(deviceInfo);
+        Mockito.verify(event).onDevicePrepared(deviceInfo);
     }
 
     @Test