2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.openflowplugin.applications.frsync.util;
11 import com.google.common.base.Splitter;
12 import com.google.common.util.concurrent.Futures;
13 import com.google.common.util.concurrent.ListenableFuture;
14 import com.google.common.util.concurrent.SettableFuture;
15 import java.util.ArrayList;
16 import java.util.Arrays;
17 import java.util.Collections;
18 import java.util.HashMap;
19 import java.util.HashSet;
20 import java.util.List;
23 import org.junit.Assert;
24 import org.junit.Rule;
25 import org.junit.Test;
26 import org.junit.rules.ExpectedException;
27 import org.junit.runner.RunWith;
28 import org.mockito.ArgumentCaptor;
29 import org.mockito.Captor;
30 import org.mockito.Matchers;
31 import org.mockito.Mock;
32 import org.mockito.Mockito;
33 import org.mockito.runners.MockitoJUnitRunner;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.GroupActionCase;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.GroupActionCaseBuilder;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.group.action._case.GroupAction;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.group.action._case.GroupActionBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.Action;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.list.ActionBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.FlowCapableTransactionService;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.transaction.rev150304.SendBarrierInput;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupId;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.Buckets;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.BucketsBuilder;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.Bucket;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.group.buckets.BucketBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.GroupBuilder;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
53 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
54 import org.opendaylight.yangtools.yang.common.RpcResult;
55 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
58 * Test for {@link ReconcileUtil}.
60 @RunWith(MockitoJUnitRunner.class)
61 public class ReconcileUtilTest {
63 private static final NodeId NODE_ID = new NodeId("unit-node-id");
64 private final InstanceIdentifier<Node> NODE_IDENT = InstanceIdentifier.create(Nodes.class)
65 .child(Node.class, new NodeKey(NODE_ID));
66 private static final Splitter COMMA_SPLITTER = Splitter.on(",");
69 public ExpectedException thrown = ExpectedException.none();
71 private FlowCapableTransactionService flowCapableService;
73 private ArgumentCaptor<SendBarrierInput> barrierInputCaptor;
76 public void testChainBarrierFlush() throws Exception {
77 SettableFuture<RpcResult<Void>> testRabbit = SettableFuture.create();
78 final ListenableFuture<RpcResult<Void>> vehicle =
79 Futures.transform(testRabbit, ReconcileUtil.chainBarrierFlush(NODE_IDENT, flowCapableService));
80 Mockito.when(flowCapableService.sendBarrier(barrierInputCaptor.capture()))
81 .thenReturn(RpcResultBuilder.<Void>success().buildFuture());
83 Mockito.verify(flowCapableService, Mockito.never()).sendBarrier(Matchers.<SendBarrierInput>any());
84 Assert.assertFalse(vehicle.isDone());
86 testRabbit.set(RpcResultBuilder.<Void>success().build());
87 Mockito.verify(flowCapableService).sendBarrier(Matchers.<SendBarrierInput>any());
88 Assert.assertTrue(vehicle.isDone());
89 Assert.assertTrue(vehicle.get().isSuccessful());
93 public void testCreateRpcResultCondenser() throws Exception {
98 * add one missing group
103 public void testResolveAndDivideGroupDiffs1() throws Exception {
104 final Map<Long, Group> installedGroups = new HashMap<>();
105 installedGroups.put(1L, createGroup(1L));
106 installedGroups.put(2L, createGroup(2L));
107 installedGroups.put(3L, createGroup(3L));
109 final List<Group> pendingGroups = new ArrayList<>();
110 pendingGroups.add(createGroup(2L));
111 pendingGroups.add(createGroup(3L));
112 pendingGroups.add(createGroup(4L));
114 final List<ItemSyncBox<Group>> plan = ReconcileUtil.resolveAndDivideGroupDiffs(
115 NODE_ID, installedGroups, pendingGroups);
117 Assert.assertEquals(1, plan.size());
119 Assert.assertEquals(1, plan.get(0).getItemsToPush().size());
120 Assert.assertEquals(4L, plan.get(0).getItemsToPush().iterator().next().getKey().getGroupId().getValue().longValue());
121 Assert.assertEquals(0, plan.get(0).getItemsToUpdate().size());
125 * add 3 groups with dependencies - 3 steps involved
130 public void testResolveAndDivideGroupDiffs2() throws Exception {
131 final Map<Long, Group> installedGroups = new HashMap<>();
132 installedGroups.put(1L, createGroup(1L));
134 final List<Group> pendingGroups = new ArrayList<>();
135 pendingGroups.add(createGroup(2L));
136 pendingGroups.add(createGroupWithPreconditions(3L, 2L, 4L));
137 pendingGroups.add(createGroupWithPreconditions(4L, 2L));
139 final List<ItemSyncBox<Group>> plan = ReconcileUtil.resolveAndDivideGroupDiffs(
140 NODE_ID, installedGroups, pendingGroups);
142 Assert.assertEquals(3, plan.size());
144 Assert.assertEquals(1, plan.get(0).getItemsToPush().size());
145 Assert.assertEquals(2L, plan.get(0).getItemsToPush().iterator().next().getKey().getGroupId().getValue().longValue());
146 Assert.assertEquals(0, plan.get(0).getItemsToUpdate().size());
148 Assert.assertEquals(1, plan.get(1).getItemsToPush().size());
149 Assert.assertEquals(4L, plan.get(1).getItemsToPush().iterator().next().getKey().getGroupId().getValue().longValue());
150 Assert.assertEquals(0, plan.get(1).getItemsToUpdate().size());
152 Assert.assertEquals(1, plan.get(2).getItemsToPush().size());
153 Assert.assertEquals(3L, plan.get(2).getItemsToPush().iterator().next().getKey().getGroupId().getValue().longValue());
154 Assert.assertEquals(0, plan.get(2).getItemsToUpdate().size());
158 * no actions taken - installed and pending groups are the same
163 public void testResolveAndDivideGroupDiffs3() throws Exception {
164 final Map<Long, Group> installedGroups = new HashMap<>();
165 installedGroups.put(1L, createGroup(1L));
166 installedGroups.put(2L, createGroupWithPreconditions(2L, 1L));
168 final List<Group> pendingGroups = new ArrayList<>();
169 pendingGroups.add(createGroup(1L));
170 pendingGroups.add(createGroupWithPreconditions(2L, 1L));
172 final List<ItemSyncBox<Group>> plan = ReconcileUtil.resolveAndDivideGroupDiffs(
173 NODE_ID, installedGroups, pendingGroups);
175 Assert.assertEquals(0, plan.size());
184 public void testResolveAndDivideGroupDiffs4() throws Exception {
185 final Map<Long, Group> installedGroups = new HashMap<>();
186 installedGroups.put(1L, createGroup(1L));
187 installedGroups.put(2L, createGroup(2L));
189 final List<Group> pendingGroups = new ArrayList<>();
190 pendingGroups.add(createGroupWithPreconditions(1L, 2L));
191 pendingGroups.add(createGroup(2L));
193 final List<ItemSyncBox<Group>> plan = ReconcileUtil.resolveAndDivideGroupDiffs(
194 NODE_ID, installedGroups, pendingGroups);
196 Assert.assertEquals(1, plan.size());
197 Assert.assertEquals(0, plan.get(0).getItemsToPush().size());
198 Assert.assertEquals(1, plan.get(0).getItemsToUpdate().size());
199 final ItemSyncBox.ItemUpdateTuple<Group> firstItemUpdateTuple = plan.get(0).getItemsToUpdate().iterator().next();
200 Assert.assertEquals(1L, firstItemUpdateTuple.getOriginal().getGroupId().getValue().longValue());
201 Assert.assertEquals(1L, firstItemUpdateTuple.getUpdated().getGroupId().getValue().longValue());
205 * no action taken - update 1 group will be ignored
210 public void testResolveAndDivideGroupDiffs5() throws Exception {
211 final Map<Long, Group> installedGroups = new HashMap<>();
212 installedGroups.put(1L, createGroup(1L));
213 installedGroups.put(2L, createGroup(2L));
215 final List<Group> pendingGroups = new ArrayList<>();
216 pendingGroups.add(createGroupWithPreconditions(1L, 2L));
217 pendingGroups.add(createGroup(2L));
219 final List<ItemSyncBox<Group>> plan = ReconcileUtil.resolveAndDivideGroupDiffs(
220 NODE_ID, installedGroups, pendingGroups, false);
222 Assert.assertEquals(0, plan.size());
226 * should add 1 group but preconditions are not met
231 public void testResolveAndDivideGroupDiffs_negative1() throws Exception {
232 final Map<Long, Group> installedGroups = new HashMap<>();
233 installedGroups.put(1L, createGroup(1L));
234 installedGroups.put(2L, createGroup(2L));
236 final List<Group> pendingGroups = new ArrayList<>();
237 pendingGroups.add(createGroupWithPreconditions(3L, 4L));
239 thrown.expect(IllegalStateException.class);
240 final List<ItemSyncBox<Group>> plan = ReconcileUtil.resolveAndDivideGroupDiffs(
241 NODE_ID, installedGroups, pendingGroups);
245 * should update 1 group but preconditions are not met
250 public void testResolveAndDivideGroupDiffs_negative2() throws Exception {
251 final Map<Long, Group> installedGroups = new HashMap<>();
252 installedGroups.put(1L, createGroup(1L));
253 installedGroups.put(2L, createGroup(2L));
255 final List<Group> pendingGroups = new ArrayList<>();
256 pendingGroups.add(createGroupWithPreconditions(1L, 3L));
258 thrown.expect(IllegalStateException.class);
259 final List<ItemSyncBox<Group>> plan = ReconcileUtil.resolveAndDivideGroupDiffs(
260 NODE_ID, installedGroups, pendingGroups);
264 public void testCheckGroupPrecondition() throws Exception {
265 final Set<Long> installedGroups = new HashSet<>(Arrays.asList(new Long[]{1L, 2L}));
267 final Group pendingGroup1 = createGroupWithPreconditions(3L, 2L, 4L);
268 Assert.assertFalse(ReconcileUtil.checkGroupPrecondition(installedGroups, pendingGroup1));
270 final Group pendingGroup2 = createGroupWithPreconditions(1L, 2L);
271 Assert.assertTrue(ReconcileUtil.checkGroupPrecondition(installedGroups, pendingGroup2));
273 final Group pendingGroup3 = createGroupWithPreconditions(1L);
274 Assert.assertTrue(ReconcileUtil.checkGroupPrecondition(installedGroups, pendingGroup3));
277 private Group createGroupWithPreconditions(final long groupIdValue, final long... requiredId) {
278 final List<Action> actionBag = new ArrayList<>();
279 for (long groupIdPrecondition : requiredId) {
280 final GroupAction groupAction = new GroupActionBuilder()
281 .setGroupId(groupIdPrecondition)
283 final GroupActionCase groupActionCase = new GroupActionCaseBuilder()
284 .setGroupAction(groupAction)
286 final Action action = new ActionBuilder()
287 .setAction(groupActionCase)
289 actionBag.add(action);
292 final Bucket bucket = new BucketBuilder()
293 .setAction(actionBag)
295 final Buckets buckets = new BucketsBuilder()
296 .setBucket(Collections.singletonList(bucket))
299 return new GroupBuilder()
300 .setGroupId(new GroupId(groupIdValue))
305 private Group createGroup(final long groupIdValue) {
306 final Buckets buckets = new BucketsBuilder()
307 .setBucket(Collections.<Bucket>emptyList())
309 return new GroupBuilder()
310 .setGroupId(new GroupId(groupIdValue))
316 * covers {@link ReconcileUtil#countTotalUpdated(Iterable)} too
321 public void testCountTotalAdds() throws Exception {
322 List<ItemSyncBox<String>> syncPlan = new ArrayList<>();
323 ItemSyncBox<String> syncBox1 = createSyncBox("a,b", "x,y,z");
324 syncPlan.add(syncBox1);
325 syncPlan.add(syncBox1);
326 Assert.assertEquals(4, ReconcileUtil.countTotalPushed(syncPlan));
327 Assert.assertEquals(6, ReconcileUtil.countTotalUpdated(syncPlan));
330 private ItemSyncBox<String> createSyncBox(final String pushes, final String updates) {
331 ItemSyncBox<String> syncBox1 = new ItemSyncBox<>();
332 syncBox1.getItemsToPush().addAll(COMMA_SPLITTER.splitToList(pushes));
333 for (String orig : COMMA_SPLITTER.splitToList(updates)) {
334 syncBox1.getItemsToUpdate().add(new ItemSyncBox.ItemUpdateTuple<>(orig, orig + "_updated"));
340 public void testResolveMeterDiffs() throws Exception {
345 public void testResolveFlowDiffsInTable() throws Exception {
350 public void testResolveFlowDiffsInAllTables() throws Exception {