/** * 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 com.google.common.collect.Lists; import com.google.common.collect.Range; import com.google.common.util.concurrent.ListenableFuture; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; 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.openflowplugin.applications.frsync.util.ItemSyncBox; import org.opendaylight.openflowplugin.applications.frsync.util.SyncCrudCounters; import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.ProcessFlatBatchInput; import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.ProcessFlatBatchOutputBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.SalFlatBatchService; import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.Batch; import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.BatchBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchAddFlowCase; import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchAddFlowCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchAddGroupCase; import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchAddGroupCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchAddMeterCase; import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchAddMeterCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchRemoveFlowCase; import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchRemoveFlowCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchRemoveGroupCase; import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchRemoveGroupCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchRemoveMeterCase; import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchRemoveMeterCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchUpdateFlowCase; import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchUpdateFlowCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchUpdateGroupCase; import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchUpdateGroupCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchUpdateMeterCase; import org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.process.flat.batch.input.batch.batch.choice.FlatBatchUpdateMeterCaseBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode; import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter; 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.group.types.rev131018.groups.Group; 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.common.RpcResult; import org.opendaylight.yangtools.yang.common.RpcResultBuilder; /** * Test for {@link SyncPlanPushStrategyFlatBatchImpl}. */ @RunWith(MockitoJUnitRunner.class) public class SyncPlanPushStrategyFlatBatchImplTest { private static final NodeId NODE_ID = new NodeId("ut-node-id"); private static final InstanceIdentifier<FlowCapableNode> NODE_IDENT = InstanceIdentifier.create(Nodes.class) .child(Node.class, new NodeKey(NODE_ID)) .augmentation(FlowCapableNode.class); @Mock private SalFlatBatchService flatBatchService; @Mock private TableForwarder tableForwarder; @Captor private ArgumentCaptor<ProcessFlatBatchInput> processFlatBatchInputCpt; private final List<ItemSyncBox<Group>> groupsToAddOrUpdate; private final List<ItemSyncBox<Group>> groupsToRemove; private final ItemSyncBox<Meter> metersToAddOrUpdate; private final ItemSyncBox<Meter> metersToRemove; private final Map<TableKey, ItemSyncBox<Flow>> flowsToAddOrUpdate; private final Map<TableKey, ItemSyncBox<Flow>> flowsToRemove; private List<Batch> batchBag; private SyncPlanPushStrategyFlatBatchImpl syncPlanPushStrategy; public SyncPlanPushStrategyFlatBatchImplTest() { groupsToAddOrUpdate = Lists.newArrayList(DiffInputFactory.createGroupSyncBox(1, 2, 3), DiffInputFactory.createGroupSyncBoxWithUpdates(4, 5, 6)); groupsToRemove = Lists.newArrayList(DiffInputFactory.createGroupSyncBox(1, 2, 3), DiffInputFactory.createGroupSyncBox(4, 5, 6)); metersToAddOrUpdate = DiffInputFactory.createMeterSyncBoxWithUpdates(1, 2, 3); metersToRemove = DiffInputFactory.createMeterSyncBox(1, 2, 3); flowsToAddOrUpdate = new HashMap<>(); flowsToAddOrUpdate.put(new TableKey((short) 0), DiffInputFactory.createFlowSyncBox("1", "2", "3")); flowsToAddOrUpdate.put(new TableKey((short) 1), DiffInputFactory.createFlowSyncBoxWithUpdates("4", "5", "6")); flowsToRemove = new HashMap<>(); flowsToRemove.put(new TableKey((short) 0), DiffInputFactory.createFlowSyncBox("1", "2", "3")); flowsToRemove.put(new TableKey((short) 1), DiffInputFactory.createFlowSyncBox("4", "5", "6")); } @Before public void setUp() throws Exception { syncPlanPushStrategy = new SyncPlanPushStrategyFlatBatchImpl(); syncPlanPushStrategy.setFlatBatchService(flatBatchService); syncPlanPushStrategy.setTableForwarder(tableForwarder); batchBag = new ArrayList<>(); } @Test public void testExecuteSyncStrategy() throws Exception { final SynchronizationDiffInput diffInput = new SynchronizationDiffInput(NODE_IDENT, groupsToAddOrUpdate, metersToAddOrUpdate, flowsToAddOrUpdate, flowsToRemove, metersToRemove, groupsToRemove); Mockito.when(flatBatchService.processFlatBatch(Matchers.<ProcessFlatBatchInput>any())) .thenReturn(RpcResultBuilder.success(new ProcessFlatBatchOutputBuilder().build()).buildFuture()); final SyncCrudCounters counters = new SyncCrudCounters(); final ListenableFuture<RpcResult<Void>> rpcResult = syncPlanPushStrategy.executeSyncStrategy( RpcResultBuilder.<Void>success().buildFuture(), diffInput, counters); Mockito.verify(flatBatchService).processFlatBatch(processFlatBatchInputCpt.capture()); final ProcessFlatBatchInput processFlatBatchInput = processFlatBatchInputCpt.getValue(); Assert.assertFalse(processFlatBatchInput.isExitOnFirstError()); Assert.assertEquals(13, processFlatBatchInput.getBatch().size()); Assert.assertTrue(rpcResult.isDone()); Assert.assertTrue(rpcResult.get().isSuccessful()); Assert.assertEquals(6, counters.getFlowCrudCounts().getAdded()); Assert.assertEquals(3, counters.getFlowCrudCounts().getUpdated()); Assert.assertEquals(6, counters.getFlowCrudCounts().getRemoved()); Assert.assertEquals(6, counters.getGroupCrudCounts().getAdded()); Assert.assertEquals(3, counters.getGroupCrudCounts().getUpdated()); Assert.assertEquals(6, counters.getGroupCrudCounts().getRemoved()); Assert.assertEquals(3, counters.getMeterCrudCounts().getAdded()); Assert.assertEquals(3, counters.getMeterCrudCounts().getUpdated()); Assert.assertEquals(3, counters.getMeterCrudCounts().getRemoved()); } @Test public void testAssembleRemoveFlows() throws Exception { final int lastOrder = SyncPlanPushStrategyFlatBatchImpl.assembleRemoveFlows(batchBag, 0, flowsToRemove); Assert.assertEquals(6, lastOrder); Assert.assertEquals(2, batchBag.size()); Assert.assertEquals(FlatBatchRemoveFlowCase.class, batchBag.get(0).getBatchChoice().getImplementedInterface()); Assert.assertEquals(3, ((FlatBatchRemoveFlowCase) batchBag.get(0).getBatchChoice()) .getFlatBatchRemoveFlow().size()); Assert.assertEquals(FlatBatchRemoveFlowCase.class, batchBag.get(1).getBatchChoice().getImplementedInterface()); Assert.assertEquals(3, ((FlatBatchRemoveFlowCase) batchBag.get(1).getBatchChoice()) .getFlatBatchRemoveFlow().size()); } @Test public void testAssembleAddOrUpdateGroups() throws Exception { final int lastOrder = SyncPlanPushStrategyFlatBatchImpl.assembleAddOrUpdateGroups(batchBag, 0, groupsToAddOrUpdate); Assert.assertEquals(9, lastOrder); Assert.assertEquals(3, batchBag.size()); Assert.assertEquals(FlatBatchAddGroupCase.class, batchBag.get(0).getBatchChoice().getImplementedInterface()); Assert.assertEquals(3, ((FlatBatchAddGroupCase) batchBag.get(0).getBatchChoice()) .getFlatBatchAddGroup().size()); Assert.assertEquals(FlatBatchAddGroupCase.class, batchBag.get(1).getBatchChoice().getImplementedInterface()); Assert.assertEquals(3, ((FlatBatchAddGroupCase) batchBag.get(1).getBatchChoice()) .getFlatBatchAddGroup().size()); Assert.assertEquals(FlatBatchUpdateGroupCase.class, batchBag.get(2).getBatchChoice().getImplementedInterface()); Assert.assertEquals(3, ((FlatBatchUpdateGroupCase) batchBag.get(2).getBatchChoice()) .getFlatBatchUpdateGroup().size()); } @Test public void testAssembleRemoveGroups() throws Exception { final int lastOrder = SyncPlanPushStrategyFlatBatchImpl.assembleRemoveGroups(batchBag, 0, groupsToRemove); Assert.assertEquals(6, lastOrder); Assert.assertEquals(2, batchBag.size()); Assert.assertEquals(FlatBatchRemoveGroupCase.class, batchBag.get(0).getBatchChoice().getImplementedInterface()); Assert.assertEquals(3, ((FlatBatchRemoveGroupCase) batchBag.get(0).getBatchChoice()) .getFlatBatchRemoveGroup().size()); Assert.assertEquals(FlatBatchRemoveGroupCase.class, batchBag.get(1).getBatchChoice().getImplementedInterface()); Assert.assertEquals(3, ((FlatBatchRemoveGroupCase) batchBag.get(1).getBatchChoice()) .getFlatBatchRemoveGroup().size()); } @Test public void testAssembleAddOrUpdateMeters() throws Exception { final int lastOrder = SyncPlanPushStrategyFlatBatchImpl.assembleAddOrUpdateMeters(batchBag, 0, metersToAddOrUpdate); Assert.assertEquals(6, lastOrder); Assert.assertEquals(2, batchBag.size()); Assert.assertEquals(FlatBatchAddMeterCase.class, batchBag.get(0).getBatchChoice().getImplementedInterface()); Assert.assertEquals(3, ((FlatBatchAddMeterCase) batchBag.get(0).getBatchChoice()) .getFlatBatchAddMeter().size()); Assert.assertEquals(FlatBatchUpdateMeterCase.class, batchBag.get(1).getBatchChoice().getImplementedInterface()); Assert.assertEquals(3, ((FlatBatchUpdateMeterCase) batchBag.get(1).getBatchChoice()) .getFlatBatchUpdateMeter().size()); } @Test public void testAssembleRemoveMeters() throws Exception { final int lastOrder = SyncPlanPushStrategyFlatBatchImpl.assembleRemoveMeters(batchBag, 0, metersToRemove); Assert.assertEquals(3, lastOrder); Assert.assertEquals(1, batchBag.size()); Assert.assertEquals(FlatBatchRemoveMeterCase.class, batchBag.get(0).getBatchChoice().getImplementedInterface()); Assert.assertEquals(3, ((FlatBatchRemoveMeterCase) batchBag.get(0).getBatchChoice()) .getFlatBatchRemoveMeter().size()); } @Test public void testAssembleAddOrUpdateFlows() throws Exception { final int lastOrder = SyncPlanPushStrategyFlatBatchImpl.assembleAddOrUpdateFlows(batchBag, 0, flowsToAddOrUpdate); Assert.assertEquals(9, lastOrder); Assert.assertEquals(3, batchBag.size()); Assert.assertEquals(FlatBatchAddFlowCase.class, batchBag.get(0).getBatchChoice().getImplementedInterface()); Assert.assertEquals(3, ((FlatBatchAddFlowCase) batchBag.get(0).getBatchChoice()) .getFlatBatchAddFlow().size()); Assert.assertEquals(FlatBatchUpdateFlowCase.class, batchBag.get(1).getBatchChoice().getImplementedInterface()); Assert.assertEquals(3, ((FlatBatchUpdateFlowCase) batchBag.get(1).getBatchChoice()) .getFlatBatchUpdateFlow().size()); Assert.assertEquals(FlatBatchAddFlowCase.class, batchBag.get(2).getBatchChoice().getImplementedInterface()); Assert.assertEquals(3, ((FlatBatchAddFlowCase) batchBag.get(2).getBatchChoice()) .getFlatBatchAddFlow().size()); } @Test public void testDecrementCounters() throws Exception { final SyncCrudCounters counters = new SyncCrudCounters(); counters.getFlowCrudCounts().setAdded(100); counters.getFlowCrudCounts().setUpdated(100); counters.getFlowCrudCounts().setRemoved(100); counters.getGroupCrudCounts().setAdded(100); counters.getGroupCrudCounts().setUpdated(100); counters.getGroupCrudCounts().setRemoved(100); counters.getMeterCrudCounts().setAdded(100); counters.getMeterCrudCounts().setUpdated(100); counters.getMeterCrudCounts().setRemoved(100); SyncPlanPushStrategyFlatBatchImpl.decrementCounters(new FlatBatchAddFlowCaseBuilder().build(), counters); SyncPlanPushStrategyFlatBatchImpl.decrementCounters(new FlatBatchUpdateFlowCaseBuilder().build(), counters); SyncPlanPushStrategyFlatBatchImpl.decrementCounters(new FlatBatchRemoveFlowCaseBuilder().build(), counters); SyncPlanPushStrategyFlatBatchImpl.decrementCounters(new FlatBatchAddGroupCaseBuilder().build(), counters); SyncPlanPushStrategyFlatBatchImpl.decrementCounters(new FlatBatchUpdateGroupCaseBuilder().build(), counters); SyncPlanPushStrategyFlatBatchImpl.decrementCounters(new FlatBatchRemoveGroupCaseBuilder().build(), counters); SyncPlanPushStrategyFlatBatchImpl.decrementCounters(new FlatBatchAddMeterCaseBuilder().build(), counters); SyncPlanPushStrategyFlatBatchImpl.decrementCounters(new FlatBatchUpdateMeterCaseBuilder().build(), counters); SyncPlanPushStrategyFlatBatchImpl.decrementCounters(new FlatBatchRemoveMeterCaseBuilder().build(), counters); Assert.assertEquals(99, counters.getFlowCrudCounts().getAdded()); Assert.assertEquals(99, counters.getFlowCrudCounts().getUpdated()); Assert.assertEquals(99, counters.getFlowCrudCounts().getRemoved()); Assert.assertEquals(99, counters.getGroupCrudCounts().getAdded()); Assert.assertEquals(99, counters.getGroupCrudCounts().getUpdated()); Assert.assertEquals(99, counters.getGroupCrudCounts().getRemoved()); Assert.assertEquals(99, counters.getMeterCrudCounts().getAdded()); Assert.assertEquals(99, counters.getMeterCrudCounts().getUpdated()); Assert.assertEquals(99, counters.getMeterCrudCounts().getRemoved()); } @Test public void testMapBatchesToRanges() throws Exception { final List<Batch> inputBatchBag = Lists.newArrayList( new BatchBuilder().setBatchOrder(0).build(), new BatchBuilder().setBatchOrder(5).build(), new BatchBuilder().setBatchOrder(9).build(), new BatchBuilder().setBatchOrder(15).build() ); final Map<Range<Integer>, Batch> rangeBatchMap = SyncPlanPushStrategyFlatBatchImpl.mapBatchesToRanges(inputBatchBag, 42); Assert.assertEquals(4, rangeBatchMap.size()); int idx = 0; final int[] lower = new int[]{0, 5, 9, 15}; final int[] upper = new int[]{4, 8, 14, 41}; for (Map.Entry<Range<Integer>, Batch> rangeBatchEntry : rangeBatchMap.entrySet()) { Assert.assertEquals(lower[idx], rangeBatchEntry.getKey().lowerEndpoint().intValue()); Assert.assertEquals(upper[idx], rangeBatchEntry.getKey().upperEndpoint().intValue()); Assert.assertSame(inputBatchBag.get(idx), rangeBatchEntry.getValue()); idx++; } } }