/* * Copyright (c) 2016 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.frsync.impl.strategy; import java.math.BigInteger; import java.util.Collections; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Matchers; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.runners.MockitoJUnitRunner; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.DropActionCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder; 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.AddFlowInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowOutput; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.AddFlowOutputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowOutput; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.RemoveFlowOutputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowOutput; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.UpdateFlowOutputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.OriginalFlow; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.flow.update.UpdatedFlow; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.TransactionId; 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.instruction.ApplyActionsCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.instruction.apply.actions._case.ApplyActionsBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.InstructionBuilder; 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.InstanceIdentifier; import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; import org.opendaylight.yangtools.yang.common.RpcResult; import org.opendaylight.yangtools.yang.common.RpcResultBuilder; /** * Test for {@link FlowForwarder}. */ @RunWith(MockitoJUnitRunner.class) public class FlowForwarderTest { private final NodeKey s1Key = new NodeKey(new NodeId("S1")); private final TableKey tableKey = new TableKey((short) 2); private final FlowId flowId = new FlowId("test_Flow"); private final FlowKey flowKey = new FlowKey(flowId); private final Match emptyMatch = new MatchBuilder().build(); private final Flow flow = new FlowBuilder() .setId(flowId) .setTableId((short) 2) .setMatch(emptyMatch) .build(); private final KeyedInstanceIdentifier<Node, NodeKey> nodePath = InstanceIdentifier.create(Nodes.class) .child(Node.class, s1Key); private final InstanceIdentifier<FlowCapableNode> flowCapableNodePath = nodePath .augmentation(FlowCapableNode.class); private final InstanceIdentifier<Table> tableII = flowCapableNodePath.child(Table.class, tableKey); private final InstanceIdentifier<Flow> flowPath = tableII.child(Flow.class, flowKey); private FlowForwarder flowForwarder; @Mock private SalFlowService salFlowService; @Captor private ArgumentCaptor<AddFlowInput> addFlowInputCpt; @Captor private ArgumentCaptor<UpdateFlowInput> updateFlowInputCpt; @Captor private ArgumentCaptor<RemoveFlowInput> removeFlowInputCpt; @Before public void setUp() throws Exception { flowForwarder = new FlowForwarder(salFlowService); } @Test public void addTest() throws Exception { Mockito.when(salFlowService.addFlow(addFlowInputCpt.capture())).thenReturn( RpcResultBuilder.success( new AddFlowOutputBuilder() .setTransactionId(new TransactionId(BigInteger.ONE)) .build()).buildFuture()); final Future<RpcResult<AddFlowOutput>> addResult = flowForwarder.add(flowPath, flow, flowCapableNodePath); Mockito.verify(salFlowService).addFlow(Matchers.<AddFlowInput>any()); final AddFlowInput flowInput = addFlowInputCpt.getValue(); Assert.assertEquals(2, flowInput.getTableId().shortValue()); Assert.assertEquals(emptyMatch, flowInput.getMatch()); Assert.assertEquals(null, flowInput.getInstructions()); Assert.assertEquals(nodePath, flowInput.getNode().getValue()); Assert.assertEquals(flowPath, flowInput.getFlowRef().getValue()); Assert.assertEquals(null, flowInput.isStrict()); final RpcResult<AddFlowOutput> addFlowOutputRpcResult = addResult.get(2, TimeUnit.SECONDS); Assert.assertTrue(addFlowOutputRpcResult.isSuccessful()); final AddFlowOutput resultValue = addFlowOutputRpcResult.getResult(); Assert.assertEquals(1, resultValue.getTransactionId().getValue().intValue()); } @Test public void updateTest() throws Exception { Mockito.when(salFlowService.updateFlow(updateFlowInputCpt.capture())).thenReturn( RpcResultBuilder.success( new UpdateFlowOutputBuilder() .setTransactionId(new TransactionId(BigInteger.ONE)) .build()).buildFuture()); final Instructions originalInstructions = new InstructionsBuilder() .setInstruction(Collections.singletonList(new InstructionBuilder() .setInstruction(new ApplyActionsCaseBuilder() .setApplyActions(new ApplyActionsBuilder() .setAction(Collections.singletonList(new ActionBuilder() .setAction(new DropActionCaseBuilder() .build()) .build()) ).build() ).build()) .build()) ).build(); final Flow flowUpdated = new FlowBuilder(flow) .setInstructions(originalInstructions) .setMatch(new MatchBuilder().build()) .build(); final Future<RpcResult<UpdateFlowOutput>> updateResult = flowForwarder.update(flowPath, flow, flowUpdated, flowCapableNodePath); Mockito.verify(salFlowService).updateFlow(Matchers.<UpdateFlowInput>any()); final UpdateFlowInput updateFlowInput = updateFlowInputCpt.getValue(); final OriginalFlow flowOrigInput = updateFlowInput.getOriginalFlow(); final UpdatedFlow flowInput = updateFlowInput.getUpdatedFlow(); Assert.assertEquals(nodePath, updateFlowInput.getNode().getValue()); Assert.assertEquals(flowPath, updateFlowInput.getFlowRef().getValue()); Assert.assertEquals(2, flowInput.getTableId().shortValue()); Assert.assertEquals(emptyMatch, flowInput.getMatch()); Assert.assertEquals(originalInstructions, flowInput.getInstructions()); Assert.assertEquals(true, flowInput.isStrict()); Assert.assertEquals(2, flowOrigInput.getTableId().shortValue()); Assert.assertEquals(emptyMatch, flowOrigInput.getMatch()); Assert.assertEquals(null, flowOrigInput.getInstructions()); Assert.assertEquals(true, flowOrigInput.isStrict()); final RpcResult<UpdateFlowOutput> updateFlowOutputRpcResult = updateResult.get(2, TimeUnit.SECONDS); Assert.assertTrue(updateFlowOutputRpcResult.isSuccessful()); final UpdateFlowOutput resultValue = updateFlowOutputRpcResult.getResult(); Assert.assertEquals(1, resultValue.getTransactionId().getValue().intValue()); } @Test public void removeTest() throws Exception { Mockito.when(salFlowService.removeFlow(removeFlowInputCpt.capture())).thenReturn( RpcResultBuilder.success( new RemoveFlowOutputBuilder() .setTransactionId(new TransactionId(BigInteger.ONE)) .build()).buildFuture()); final Flow removeFlow = new FlowBuilder(flow).build(); final Future<RpcResult<RemoveFlowOutput>> removeResult = flowForwarder.remove(flowPath, removeFlow, flowCapableNodePath); Mockito.verify(salFlowService).removeFlow(Matchers.<RemoveFlowInput>any()); final RemoveFlowInput flowInput = removeFlowInputCpt.getValue(); Assert.assertEquals(2, flowInput.getTableId().shortValue()); Assert.assertEquals(emptyMatch, flowInput.getMatch()); Assert.assertEquals(null, flowInput.getInstructions()); Assert.assertEquals(true, flowInput.isStrict()); final RpcResult<RemoveFlowOutput> removeFlowOutputRpcResult = removeResult.get(2, TimeUnit.SECONDS); Assert.assertTrue(removeFlowOutputRpcResult.isSuccessful()); final RemoveFlowOutput resultValue = removeFlowOutputRpcResult.getResult(); Assert.assertEquals(1, resultValue.getTransactionId().getValue().intValue()); } }