From 28a83453879f7528acd02e0f90d07e53dadfe5f0 Mon Sep 17 00:00:00 2001 From: HemaTG Date: Mon, 4 May 2015 11:18:08 +0530 Subject: [PATCH] Adding Unit Test Cases for MDSALUTIL- updated Signed-off-by: HemaTG Change-Id: Id4c8fec7d4ef07097f351594cb4a356823e2430f --- mdsalutil/mdsalutil-impl/pom.xml | 80 +++--- .../mdsalutil/internal/MDSALManager.java | 249 +++++++++--------- .../mdsalutil/internal/MDSALUtilProvider.java | 40 +++ .../impl/rev150403/MdsaluttilimplModule.java | 8 +- .../AbstractMockForwardingRulesManager.java | 25 ++ .../vpnservice/test/MdSalUtilTest.java | 230 ++++++++++++++++ .../vpnservice/test/MockFlowForwarder.java | 72 +++++ .../vpnservice/test/MockGroupForwarder.java | 69 +++++ mdsalutil/pom.xml | 2 +- 9 files changed, 610 insertions(+), 165 deletions(-) create mode 100644 mdsalutil/mdsalutil-impl/src/main/java/org/opendaylight/vpnservice/mdsalutil/internal/MDSALUtilProvider.java create mode 100644 mdsalutil/mdsalutil-impl/src/test/java/org/opendaylight/vpnservice/test/AbstractMockForwardingRulesManager.java create mode 100644 mdsalutil/mdsalutil-impl/src/test/java/org/opendaylight/vpnservice/test/MdSalUtilTest.java create mode 100644 mdsalutil/mdsalutil-impl/src/test/java/org/opendaylight/vpnservice/test/MockFlowForwarder.java create mode 100644 mdsalutil/mdsalutil-impl/src/test/java/org/opendaylight/vpnservice/test/MockGroupForwarder.java diff --git a/mdsalutil/mdsalutil-impl/pom.xml b/mdsalutil/mdsalutil-impl/pom.xml index 049d293f..2101d2ad 100644 --- a/mdsalutil/mdsalutil-impl/pom.xml +++ b/mdsalutil/mdsalutil-impl/pom.xml @@ -32,26 +32,41 @@ model-flow-service 0.1.0-SNAPSHOT - - - - - + + + junit + junit + + + org.mockito + mockito-all + test + + + org.powermock + powermock-module-junit4 + 1.5.2 + test + + + org.powermock + powermock-api-mockito + 1.5.2 + test + + + org.opendaylight.controller + sal-binding-broker-impl + test + + + org.opendaylight.controller + sal-binding-broker-impl + ${mdsal.version} + test + test-jar + + commons-lang commons-lang @@ -59,7 +74,7 @@ com.google.guava guava - + ${project.groupId} mdsalutil-api ${project.version} @@ -83,21 +98,6 @@ ${project.basedir}/META-INF - maven-clean-plugin ${maven.clean.plugin.version} @@ -112,6 +112,14 @@ + + org.apache.maven.plugins + maven-surefire-plugin + + -XX:-UseSplitVerifier + + + diff --git a/mdsalutil/mdsalutil-impl/src/main/java/org/opendaylight/vpnservice/mdsalutil/internal/MDSALManager.java b/mdsalutil/mdsalutil-impl/src/main/java/org/opendaylight/vpnservice/mdsalutil/internal/MDSALManager.java index 00119d41..7a3ec91f 100644 --- a/mdsalutil/mdsalutil-impl/src/main/java/org/opendaylight/vpnservice/mdsalutil/internal/MDSALManager.java +++ b/mdsalutil/mdsalutil-impl/src/main/java/org/opendaylight/vpnservice/mdsalutil/internal/MDSALManager.java @@ -11,38 +11,24 @@ package org.opendaylight.vpnservice.mdsalutil.internal; import java.math.BigInteger; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; -import org.opendaylight.controller.md.sal.common.api.TransactionStatus; -//import org.opendaylight.controller.md.sal.common.api.data.DataModification; import org.opendaylight.vpnservice.mdsalutil.ActionInfo; import org.opendaylight.vpnservice.mdsalutil.ActionType; -import org.opendaylight.vpnservice.mdsalutil.BucketInfo; import org.opendaylight.vpnservice.mdsalutil.FlowEntity; import org.opendaylight.vpnservice.mdsalutil.GroupEntity; -import org.opendaylight.vpnservice.mdsalutil.InstructionInfo; import org.opendaylight.vpnservice.mdsalutil.MDSALUtil; -import org.opendaylight.vpnservice.mdsalutil.MatchInfo; -import org.opendaylight.vpnservice.mdsalutil.MatchFieldType; -import org.opendaylight.vpnservice.mdsalutil.MetaDataUtil; -import org.opendaylight.vpnservice.mdsalutil.InstructionType; import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager; -import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext; -import org.opendaylight.controller.sal.binding.api.BindingAwareConsumer; -import org.opendaylight.controller.sal.binding.api.data.DataBrokerService; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri; 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.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.TableBuilder; 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.FlowTableRef; -// Missing constraint -//import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev131103.TransactionId; -import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.FlowRef; import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId; import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group; import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupKey; @@ -50,7 +36,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeCon import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef; 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.OpendaylightInventoryService; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; @@ -59,113 +44,126 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.N import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder; -import org.opendaylight.yangtools.yang.common.RpcResult; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.controller.md.sal.common.api.data.OptimisticLockFailedException; import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; -import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction; import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException; import com.google.common.util.concurrent.CheckedFuture; import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; -import com.google.common.util.concurrent.ListenableFuture; -public class MDSALManager implements IMdsalApiManager,BindingAwareConsumer, AutoCloseable { +public class MDSALManager implements IMdsalApiManager, AutoCloseable { private static final Logger s_logger = LoggerFactory.getLogger(MDSALManager.class); private DataBroker m_dataBroker; - private ConsumerContext m_consumerContext = null; - private PacketProcessingService m_packetProcessingService; - + private final AtomicInteger m_atomicInteger = new AtomicInteger(); //TODO : IF ID MANAGER IS RQD - - @Override - public void onSessionInitialized(ConsumerContext session) { - - s_logger.info( " Session Initiated for MD SAL Manager") ; - - m_consumerContext = session; - - m_dataBroker = session.getSALService(DataBroker.class); - - // TODO - Verify this. - m_packetProcessingService = session.getRpcService(PacketProcessingService.class); - + + /** + * Writes the flows and Groups to the MD SAL DataStore + * which will be sent to the openflowplugin for installing flows/groups on the switch. + * Other modules of VPN service that wants to install flows / groups on the switch + * uses this utility + * + * @param db - dataBroker reference + * @param PacketProcessingService for sending the packet outs + */ + public MDSALManager(final DataBroker db, PacketProcessingService pktProcService) { + m_dataBroker = db; + m_packetProcessingService = pktProcService; + } - - + + @Override public void close() throws Exception { - s_logger.info("MDSAL Manager Closed"); + s_logger.info("MDSAL Manager Closed"); } - + @Override public void printTest() { - - s_logger.info(" INTER MODULECOMMUNICATION IS WORKING!!!!"); + + s_logger.info(" INTER MODULECOMMUNICATION IS WORKING!!!!"); } @Override public void installFlow(FlowEntity flowEntity) { + try { - s_logger.info("within installFlowX {}", flowEntity.getDpnId()); - System.out.println( " Insie installFlow -- ") ; + s_logger.info("within installFlow {}", flowEntity.getDpnId()); if (flowEntity.getCookie() == null) { - s_logger.info("Helium_sync: Cookie is null"); + // s_logger.info("Helium_sync: Cookie is null"); flowEntity.setCookie(new BigInteger("0110000", 16)); } - Flow flow = flowEntity.getFlowBuilder().build(); + FlowKey flowKey = new FlowKey( new FlowId(flowEntity.getFlowId()) ); + + FlowBuilder flowbld = flowEntity.getFlowBuilder(); + + Flow flow = flowbld.build() ; Node nodeDpn = buildDpnNode(flowEntity.getDpnId()); InstanceIdentifier nodeInstanceId = InstanceIdentifier.builder(Nodes.class) .child(Node.class, nodeDpn.getKey()).build(); + InstanceIdentifier flowInstanceId = InstanceIdentifier.builder(Nodes.class) .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class) - .child(Table.class, new TableKey(flow.getTableId())).child(Flow.class, flow.getKey()).build(); + .child(Table.class, new TableKey(flowEntity.getTableId())).child(Flow.class,flowKey).build(); String sTransactionUri = generateTransactionUri(); - // Helium Way - + + TableKey tableKey = new TableKey(flowEntity.getTableId() ); + InstanceIdentifier tableInstanceId = InstanceIdentifier.create(Nodes.class).child(Node.class, nodeDpn.getKey()) + .augmentation(FlowCapableNode.class).child(Table.class, tableKey); + Table table = new TableBuilder().setKey(tableKey).setFlow(Collections.emptyList()).build(); + WriteTransaction modification = m_dataBroker.newWriteOnlyTransaction(); - - modification.put(LogicalDatastoreType.CONFIGURATION, nodeInstanceId, nodeDpn, true); - - modification.put(LogicalDatastoreType.CONFIGURATION, flowInstanceId, flow); - - ListenableFuture> commitFuture = modification.commit(); - - Futures.addCallback(commitFuture, new FutureCallback>() { + + //CHECK IF RQD + // modification.put(LogicalDatastoreType.CONFIGURATION, nodeInstanceId, nodeDpn, true); + + + modification.put(LogicalDatastoreType.CONFIGURATION, tableInstanceId, table); + + modification.put(LogicalDatastoreType.CONFIGURATION, flowInstanceId, flowbld.build()); + + CheckedFuture submitFuture = modification.submit(); + + Futures.addCallback(submitFuture, new FutureCallback() { + @Override - public void onSuccess(RpcResult result) { - if( result.getResult() != TransactionStatus.COMMITED ) { - s_logger.debug("Failed to commit the Flow Data " + result.getErrors()); - - } - + public void onSuccess(final Void result) { + // Commited successfully + s_logger.info( "Install Flow -- Committedsuccessfully ") ; } @Override - public void onFailure(Throwable throwable) { - s_logger.error(throwable.getMessage(), throwable); - s_logger.debug(String.format("Status of Flow Data Loaded Transaction : failure. Reason : %s", throwable)); - + public void onFailure(final Throwable t) { + // Transaction failed + + if(t instanceof OptimisticLockFailedException) { + // Failed because of concurrent transaction modifying same data + s_logger.error( "Install Flow -- Failed because of concurrent transaction modifying same data ") ; + } else { + // Some other type of TransactionCommitFailedException + s_logger.error( "Install Flow -- Some other type of TransactionCommitFailedException " + t) ; + } } }); } catch (Exception e) { s_logger.error("Could not install flow: {}, exception: {}", flowEntity, e.getMessage()); } - } + @Override public void installGroup(GroupEntity groupEntity) { try { @@ -178,34 +176,35 @@ public class MDSALManager implements IMdsalApiManager,BindingAwareConsumer, Auto .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class) .child(Group.class, new GroupKey(new GroupId(groupEntity.getGroupId()))).build(); - - // Helium WriteTransaction modification = m_dataBroker.newWriteOnlyTransaction(); - - modification.put(LogicalDatastoreType.CONFIGURATION, nodeInstanceId, nodeDpn); + + //CHECK IF RQD + // modification.put(LogicalDatastoreType.CONFIGURATION, nodeInstanceId, nodeDpn); modification.put(LogicalDatastoreType.CONFIGURATION, groupInstanceId, group); - - ListenableFuture> commitFuture = modification.commit(); - - Futures.addCallback(commitFuture, new FutureCallback>() { + + CheckedFuture submitFuture = modification.submit(); + + Futures.addCallback(submitFuture, new FutureCallback() { @Override - public void onSuccess(RpcResult result) { - if( result.getResult() != TransactionStatus.COMMITED ) { - s_logger.debug("Failed to commit the group Data " + result.getErrors()); - - } - + public void onSuccess(final Void result) { + // Commited successfully + s_logger.info( "Install Group -- Committedsuccessfully ") ; } @Override - public void onFailure(Throwable throwable) { - s_logger.error(throwable.getMessage(), throwable); - s_logger.debug(String.format("Status of Group Data Loaded Transaction : failure. Reason : %s", throwable)); - + public void onFailure(final Throwable t) { + // Transaction failed + + if(t instanceof OptimisticLockFailedException) { + // Failed because of concurrent transaction modifying same data + s_logger.error( "Install Group -- Failed because of concurrent transaction modifying same data ") ; + } else { + // Some other type of TransactionCommitFailedException + s_logger.error( "Install Group -- Some other type of TransactionCommitFailedException " + t) ; + } } - }); - - } catch (Exception e) { + }); + } catch (Exception e) { s_logger.error("Could not install Group: {}, exception: {}", groupEntity, e.getMessage()); throw e; } @@ -224,24 +223,27 @@ public class MDSALManager implements IMdsalApiManager,BindingAwareConsumer, Auto WriteTransaction modification = m_dataBroker.newWriteOnlyTransaction(); modification.delete(LogicalDatastoreType.CONFIGURATION,flowInstanceId ); - ListenableFuture> commitFuture = modification.commit(); - - Futures.addCallback(commitFuture, new FutureCallback>() { + CheckedFuture submitFuture = modification.submit(); + + Futures.addCallback(submitFuture, new FutureCallback() { @Override - public void onSuccess(RpcResult result) { - if( result.getResult() != TransactionStatus.COMMITED ) { - s_logger.debug("Failed to remove the Flow Data " + result.getErrors()); - - } - + public void onSuccess(final Void result) { + // Commited successfully + s_logger.info( "Delete Flow -- Committedsuccessfully ") ; } @Override - public void onFailure(Throwable throwable) { - s_logger.error(throwable.getMessage(), throwable); - s_logger.debug(String.format("Status of Flow Data remove Transaction : failure. Reason : %s", throwable)); - + public void onFailure(final Throwable t) { + // Transaction failed + if(t instanceof OptimisticLockFailedException) { + // Failed because of concurrent transaction modifying same data + s_logger.error( "Delete Flow -- Failed because of concurrent transaction modifying same data ") ; + } else { + // Some other type of TransactionCommitFailedException + s_logger.error( "Delete Flow -- Some other type of TransactionCommitFailedException " + t) ; + } } + }); } catch (Exception e) { s_logger.error("Could not remove Flow: {}, exception: {}", flowEntity, e.getMessage()); @@ -256,33 +258,31 @@ public class MDSALManager implements IMdsalApiManager,BindingAwareConsumer, Auto .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class) .child(Group.class, new GroupKey(new GroupId(groupEntity.getGroupId()))).build(); - WriteTransaction modification = m_dataBroker.newWriteOnlyTransaction(); - + modification.delete(LogicalDatastoreType.CONFIGURATION,groupInstanceId ); - ListenableFuture> commitFuture = modification.commit(); - - Futures.addCallback(commitFuture, new FutureCallback>() { + CheckedFuture submitFuture = modification.submit(); + + Futures.addCallback(submitFuture, new FutureCallback() { @Override - public void onSuccess(RpcResult result) { - if( result.getResult() != TransactionStatus.COMMITED ) { - s_logger.debug("Failed to remove the group Data " + result.getErrors()); - - } - + public void onSuccess(final Void result) { + // Commited successfully + s_logger.info( "Install Group -- Committedsuccessfully ") ; } @Override - public void onFailure(Throwable throwable) { - s_logger.error(throwable.getMessage(), throwable); - s_logger.debug(String.format("Status of group Data remove Transaction : failure. Reason : %s", throwable)); - + public void onFailure(final Throwable t) { + // Transaction failed + if(t instanceof OptimisticLockFailedException) { + // Failed because of concurrent transaction modifying same data + s_logger.error( "Install Group -- Failed because of concurrent transaction modifying same data ") ; + } else { + // Some other type of TransactionCommitFailedException + s_logger.error( "Install Group -- Some other type of TransactionCommitFailedException " + t) ; + } } }); - - - } catch (Exception e) { s_logger.error("Could not remove Group: {}, exception: {}", groupEntity, e.getMessage()); } @@ -308,7 +308,7 @@ public class MDSALManager implements IMdsalApiManager,BindingAwareConsumer, Auto + Long.toString(nTransactionId); } */ - + @Override public void sendPacketOut(long lDpnId, int groupId, byte[] payload) { @@ -372,4 +372,5 @@ public class MDSALManager implements IMdsalApiManager,BindingAwareConsumer, Auto return nodeDpn; } + } diff --git a/mdsalutil/mdsalutil-impl/src/main/java/org/opendaylight/vpnservice/mdsalutil/internal/MDSALUtilProvider.java b/mdsalutil/mdsalutil-impl/src/main/java/org/opendaylight/vpnservice/mdsalutil/internal/MDSALUtilProvider.java new file mode 100644 index 00000000..4ef07496 --- /dev/null +++ b/mdsalutil/mdsalutil-impl/src/main/java/org/opendaylight/vpnservice/mdsalutil/internal/MDSALUtilProvider.java @@ -0,0 +1,40 @@ +package org.opendaylight.vpnservice.mdsalutil.internal; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.sal.binding.api.BindingAwareConsumer; +import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ConsumerContext; +import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager; +import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class MDSALUtilProvider implements BindingAwareConsumer, AutoCloseable { + + private static final Logger s_logger = LoggerFactory.getLogger(MDSALUtilProvider.class); + private MDSALManager mdSalMgr; + + @Override + public void onSessionInitialized(ConsumerContext session) { + + s_logger.info( " Session Initiated for MD SAL Util Provider") ; + + try { + final DataBroker dataBroker; + final PacketProcessingService packetProcessingService; + dataBroker = session.getSALService(DataBroker.class); + // TODO - Verify this. + packetProcessingService = session.getRpcService(PacketProcessingService.class); + mdSalMgr = new MDSALManager( dataBroker, packetProcessingService) ; + }catch( Exception e) { + s_logger.error( "Error initializing MD SAL Util Services " + e ); + } + } + + + @Override + public void close() throws Exception { + mdSalMgr.close(); + s_logger.info("MDSAL Manager Closed"); + } + +} diff --git a/mdsalutil/mdsalutil-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/mdsalutil/impl/rev150403/MdsaluttilimplModule.java b/mdsalutil/mdsalutil-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/mdsalutil/impl/rev150403/MdsaluttilimplModule.java index ab2776d7..473d9625 100644 --- a/mdsalutil/mdsalutil-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/mdsalutil/impl/rev150403/MdsaluttilimplModule.java +++ b/mdsalutil/mdsalutil-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/mdsalutil/impl/rev150403/MdsaluttilimplModule.java @@ -1,6 +1,6 @@ package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsalutil.impl.rev150403; -import org.opendaylight.vpnservice.mdsalutil.internal.MDSALManager; +import org.opendaylight.vpnservice.mdsalutil.internal.MDSALUtilProvider; public class MdsaluttilimplModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsalutil.impl.rev150403.AbstractMdsaluttilimplModule { public MdsaluttilimplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) { @@ -21,11 +21,11 @@ public class MdsaluttilimplModule extends org.opendaylight.yang.gen.v1.urn.opend // TODO:implement // Can use the following to get a handle to data broker - MDSALManager mdsalUtilMgr = new MDSALManager(); - getBrokerDependency().registerConsumer(mdsalUtilMgr); + MDSALUtilProvider mdsalUtilProvider = new MDSALUtilProvider(); + getBrokerDependency().registerConsumer(mdsalUtilProvider); //DataBroker dataBrokerService = getDataBrokerDependency(); //mdsalUtilMgr.setDataProvider(dataBrokerService); - return mdsalUtilMgr ; + return mdsalUtilProvider ; } } diff --git a/mdsalutil/mdsalutil-impl/src/test/java/org/opendaylight/vpnservice/test/AbstractMockForwardingRulesManager.java b/mdsalutil/mdsalutil-impl/src/test/java/org/opendaylight/vpnservice/test/AbstractMockForwardingRulesManager.java new file mode 100644 index 00000000..1bffa91a --- /dev/null +++ b/mdsalutil/mdsalutil-impl/src/test/java/org/opendaylight/vpnservice/test/AbstractMockForwardingRulesManager.java @@ -0,0 +1,25 @@ +package org.opendaylight.vpnservice.test; + +import java.util.Collection; + +import org.opendaylight.controller.md.sal.binding.api.DataObjectModification; +import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener; +import org.opendaylight.controller.md.sal.binding.api.DataTreeModification; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; +import org.opendaylight.yangtools.yang.binding.DataObject; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +import com.google.common.base.Preconditions; + +public abstract class AbstractMockForwardingRulesManager implements DataTreeChangeListener { + + public AbstractMockForwardingRulesManager() { + // Do Nothing + } + + + public void onDataTreeChanged(Collection> changes) { + // TODO Auto-generated method stub + } + +} diff --git a/mdsalutil/mdsalutil-impl/src/test/java/org/opendaylight/vpnservice/test/MdSalUtilTest.java b/mdsalutil/mdsalutil-impl/src/test/java/org/opendaylight/vpnservice/test/MdSalUtilTest.java new file mode 100644 index 00000000..8c804b8d --- /dev/null +++ b/mdsalutil/mdsalutil-impl/src/test/java/org/opendaylight/vpnservice/test/MdSalUtilTest.java @@ -0,0 +1,230 @@ +package org.opendaylight.vpnservice.test; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; +import java.util.Collections; +import java.util.concurrent.ExecutionException; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; + +import org.mockito.runners.MockitoJUnitRunner; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.WriteTransaction; +import org.opendaylight.controller.md.sal.binding.test.AbstractDataBrokerTest; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.vpnservice.mdsalutil.ActionInfo; +import org.opendaylight.vpnservice.mdsalutil.ActionType; +import org.opendaylight.vpnservice.mdsalutil.FlowEntity; +import org.opendaylight.vpnservice.mdsalutil.GroupEntity; +import org.opendaylight.vpnservice.mdsalutil.BucketInfo; +import org.opendaylight.vpnservice.mdsalutil.InstructionInfo; +import org.opendaylight.vpnservice.mdsalutil.InstructionType; +import org.opendaylight.vpnservice.mdsalutil.MDSALUtil; +import org.opendaylight.vpnservice.mdsalutil.MatchFieldType; +import org.opendaylight.vpnservice.mdsalutil.MatchInfo; +import org.opendaylight.vpnservice.mdsalutil.internal.MDSALManager; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Instructions; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.InstructionsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes; +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.NodesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +import static org.junit.Assert.assertEquals; + +@RunWith(MockitoJUnitRunner.class) +//@RunWith(PowerMockRunner.class) +@PrepareForTest(MDSALUtil.class) +public class MdSalUtilTest extends AbstractDataBrokerTest { + DataBroker dataBroker; + @Mock PacketProcessingService ppS ; + MDSALManager mdSalMgr = null ; + MockFlowForwarder flowFwder = null ; + MockGroupForwarder grpFwder = null ; + + @Before + public void setUp() throws Exception { + dataBroker = getDataBroker() ; + mdSalMgr = new MDSALManager( dataBroker, ppS); + flowFwder = new MockFlowForwarder( dataBroker ); + grpFwder = new MockGroupForwarder( dataBroker ) ; + + PowerMockito.mockStatic(MDSALUtil.class) ; + + NodeKey s1Key = new NodeKey(new NodeId("openflow:1")); + addFlowCapableNode(s1Key); + } + + @Test + public void testInstallFlow() { + String dpnId = "openflow:1"; + String tableId1 = "12"; + + //Install Flow 1 + FlowEntity testFlow1 = createFlowEntity(dpnId, tableId1) ; + mdSalMgr.installFlow(testFlow1); + assertEquals(1, flowFwder.getDataChgCount()); + + // Install FLow 2 + String tableId2 = "13" ; + FlowEntity testFlow2 = createFlowEntity(dpnId, tableId2) ; + mdSalMgr.installFlow(testFlow2); + assertEquals(2, flowFwder.getDataChgCount()); + } + + @Test + public void testRemoveFlow() { + String dpnId = "openflow:1"; + String tableId = "13" ; + FlowEntity testFlow = createFlowEntity(dpnId, tableId) ; + + // To test RemoveFlow add and then delete Flows + mdSalMgr.installFlow(testFlow) ; + assertEquals(1, flowFwder.getDataChgCount()); + mdSalMgr.removeFlow(testFlow); + assertEquals(0, flowFwder.getDataChgCount()); + } + + @Test + public void testInstallGroup() { + // Install Group 1 + String Nodeid = "1"; + String inport = "2" ; + int vlanid = 100 ; + GroupEntity grpEntity1 = createGroupEntity(Nodeid, inport, vlanid) ; + + mdSalMgr.installGroup(grpEntity1); + assertEquals(1, grpFwder.getDataChgCount()); + + // Install Group 2 + Nodeid = "1"; + inport = "3" ; + vlanid = 100 ; + GroupEntity grpEntity2 = createGroupEntity(Nodeid, inport, vlanid) ; + mdSalMgr.installGroup(grpEntity2); + assertEquals(2, grpFwder.getDataChgCount()); + } + + @Test + public void testRemoveGroup() { + String Nodeid = "1"; + String inport = "2" ; + int vlanid = 100 ; + GroupEntity grpEntity = createGroupEntity(Nodeid, inport, vlanid) ; + // To test RemoveGroup add and then delete Group + mdSalMgr.installGroup(grpEntity); + assertEquals(1, grpFwder.getDataChgCount()); + mdSalMgr.removeGroup(grpEntity); + assertEquals(0, grpFwder.getDataChgCount()); + } + + public void addFlowCapableNode(NodeKey nodeKey) throws ExecutionException, InterruptedException { + Nodes nodes = new NodesBuilder().setNode(Collections.emptyList()).build(); + InstanceIdentifier flowNodeIdentifier = InstanceIdentifier.create(Nodes.class) + .child(Node.class, nodeKey); + + FlowCapableNodeBuilder fcnBuilder = new FlowCapableNodeBuilder(); + NodeBuilder nodeBuilder = new NodeBuilder(); + nodeBuilder.setKey(nodeKey); + nodeBuilder.addAugmentation(FlowCapableNode.class, fcnBuilder.build()); + + WriteTransaction writeTx = getDataBroker().newWriteOnlyTransaction(); + writeTx.put(LogicalDatastoreType.OPERATIONAL, InstanceIdentifier.create(Nodes.class), nodes); + writeTx.put(LogicalDatastoreType.OPERATIONAL, flowNodeIdentifier, nodeBuilder.build()); + writeTx.put(LogicalDatastoreType.CONFIGURATION, InstanceIdentifier.create(Nodes.class), nodes); + writeTx.put(LogicalDatastoreType.CONFIGURATION, flowNodeIdentifier, nodeBuilder.build()); + assertCommit(writeTx.submit()); + } + + // Methods to test the install Flow and Group + + public FlowEntity createFlowEntity(String dpnId, String tableId) { + + long dpId; + int SERVICE_ID = 0; + FlowEntity terminatingServiceTableFlowEntity = null; + + List listActionInfo = new ArrayList(); + listActionInfo.add(new ActionInfo(ActionType.punt_to_controller, + new String[] {})); + + try { + dpId = Long.parseLong(dpnId.split(":")[1]); + + List mkMatches = new ArrayList(); + BigInteger COOKIE = new BigInteger("9000000", 16); + + short s_tableId = Short.parseShort(tableId) ; + + mkMatches.add(new MatchInfo(MatchFieldType.tunnel_id, new BigInteger[] { + new BigInteger("0000000000000000", 16) })); + + List mkInstructions = new ArrayList(); + mkInstructions.add(new InstructionInfo(InstructionType.write_actions, + listActionInfo)); + + terminatingServiceTableFlowEntity = MDSALUtil + .buildFlowEntity( + dpId, + s_tableId, + getFlowRef(s_tableId, + SERVICE_ID), 5, "Terminating Service Flow Entry: " + SERVICE_ID, + 0, 0, COOKIE + .add(BigInteger.valueOf(SERVICE_ID)), + null, null); + } catch (Exception e) { + //throw new Exception(e) ; + } + + return terminatingServiceTableFlowEntity; + } + + private String getFlowRef(short termSvcTable, int svcId) { + return new StringBuffer().append(termSvcTable).append(svcId).toString(); + } + + public GroupEntity createGroupEntity(String Nodeid, String inport, int vlanid) { + GroupEntity groupEntity; + long id = getUniqueValue(Nodeid, inport); + List listBucketInfo = new ArrayList(); + List listActionInfo = new ArrayList(); + if (vlanid > 0) { + listActionInfo.add(new ActionInfo(ActionType.push_vlan, new String[] { null })); + listActionInfo.add(new ActionInfo(ActionType.set_field_vlan_vid, new String[] { String.valueOf(vlanid) })); + } + listActionInfo.add(new ActionInfo(ActionType.output, new String[] { inport, "65535" })); + listBucketInfo.add(new BucketInfo(listActionInfo)); + + String groupName = "Test Group"; + groupEntity = MDSALUtil.buildGroupEntity(Long.valueOf(Nodeid), id, groupName, GroupTypes.GroupIndirect, + listBucketInfo); + + return groupEntity; + } + + private static long getUniqueValue(String nodeId, String inport) { + + Long nodeIdL = Long.valueOf(nodeId); + Long inportL = Long.valueOf(inport); + long sd_set; + sd_set = nodeIdL * 10 + inportL; + + return sd_set; + } + +} diff --git a/mdsalutil/mdsalutil-impl/src/test/java/org/opendaylight/vpnservice/test/MockFlowForwarder.java b/mdsalutil/mdsalutil-impl/src/test/java/org/opendaylight/vpnservice/test/MockFlowForwarder.java new file mode 100644 index 00000000..56ba8005 --- /dev/null +++ b/mdsalutil/mdsalutil-impl/src/test/java/org/opendaylight/vpnservice/test/MockFlowForwarder.java @@ -0,0 +1,72 @@ +package org.opendaylight.vpnservice.test; + +import java.util.Collection; + +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.DataObjectModification; +import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier; +import org.opendaylight.controller.md.sal.binding.api.DataTreeModification; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +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.inventory.rev130819.Nodes; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; + +public class MockFlowForwarder extends AbstractMockForwardingRulesManager { + + private int nFlowCount = 0; + + private ListenerRegistration listenerRegistration; + + public MockFlowForwarder( final DataBroker db) { + super() ; + registerListener(db) ; + } + + private void registerListener(final DataBroker db) { + final DataTreeIdentifier treeId = new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, getWildCardPath()); + try { + listenerRegistration = db.registerDataTreeChangeListener(treeId, MockFlowForwarder.this); + } catch (final Exception e) { + throw new IllegalStateException("FlowForwarder registration Listener fail! System needs restart.", e); + } + } + + private InstanceIdentifier getWildCardPath() { + return InstanceIdentifier.create(Nodes.class).child(Node.class) + .augmentation(FlowCapableNode.class).child(Table.class).child(Flow.class); + } + + @Override + public void onDataTreeChanged(Collection> changes) { + for (DataTreeModification change : changes) { + final InstanceIdentifier key = change.getRootPath().getRootIdentifier(); + final DataObjectModification mod = change.getRootNode(); + + switch (mod.getModificationType()) { + case DELETE: + nFlowCount -= 1; + break; + case SUBTREE_MODIFIED: + // CHECK IF RQD + break; + case WRITE: + if (mod.getDataBefore() == null) { + nFlowCount += 1; + } else { + // UPDATE COUNT UNCHANGED + } + break; + default: + throw new IllegalArgumentException("Unhandled modification type " + mod.getModificationType()); + } + } + } + + public int getDataChgCount() { + return nFlowCount; + } +} diff --git a/mdsalutil/mdsalutil-impl/src/test/java/org/opendaylight/vpnservice/test/MockGroupForwarder.java b/mdsalutil/mdsalutil-impl/src/test/java/org/opendaylight/vpnservice/test/MockGroupForwarder.java new file mode 100644 index 00000000..b47deee8 --- /dev/null +++ b/mdsalutil/mdsalutil-impl/src/test/java/org/opendaylight/vpnservice/test/MockGroupForwarder.java @@ -0,0 +1,69 @@ +package org.opendaylight.vpnservice.test; + +import java.util.Collection; +import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; +import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes; +import org.opendaylight.controller.md.sal.binding.api.DataBroker; +import org.opendaylight.controller.md.sal.binding.api.DataObjectModification; +import org.opendaylight.controller.md.sal.binding.api.DataTreeIdentifier; +import org.opendaylight.controller.md.sal.binding.api.DataTreeModification; +import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; +import org.opendaylight.yangtools.concepts.ListenerRegistration; +import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node; + +public class MockGroupForwarder extends AbstractMockForwardingRulesManager{ + + private int nGroupCount = 0; + private ListenerRegistration listenerRegistration ; + + public MockGroupForwarder( final DataBroker db) { + super() ; + registerListener(db) ; + } + + private void registerListener(final DataBroker db) { + final DataTreeIdentifier treeId = new DataTreeIdentifier<>(LogicalDatastoreType.CONFIGURATION, getWildCardPath()); + try { + listenerRegistration = db.registerDataTreeChangeListener(treeId, MockGroupForwarder.this); + } catch (final Exception e) { + throw new IllegalStateException("GroupForwarder registration Listener fail! System needs restart.", e); + } + } + + private InstanceIdentifier getWildCardPath() { + return InstanceIdentifier.create(Nodes.class).child(Node.class). + augmentation(FlowCapableNode.class).child(Group.class); + } + + @Override + public void onDataTreeChanged(Collection> changes) { + for (DataTreeModification change : changes) { + final InstanceIdentifier key = change.getRootPath().getRootIdentifier(); + final DataObjectModification mod = change.getRootNode(); + + switch (mod.getModificationType()) { + case DELETE: + nGroupCount -= 1; + break; + case SUBTREE_MODIFIED: + // CHECK IF RQD + break; + case WRITE: + if (mod.getDataBefore() == null) { + nGroupCount += 1; + } else { + // UPDATE COUNT UNCHANGED + } + break; + default: + throw new IllegalArgumentException("Unhandled modification type " + mod.getModificationType()); + } + } + } + + public int getDataChgCount() { + return nGroupCount; + } +} diff --git a/mdsalutil/pom.xml b/mdsalutil/pom.xml index 0e362dc9..3d52a99d 100644 --- a/mdsalutil/pom.xml +++ b/mdsalutil/pom.xml @@ -11,7 +11,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL org.opendaylight.odlparent odlparent 1.5.0-SNAPSHOT - + org.opendaylight.vpnservice -- 2.36.6