2 * Copyright 2014-2015 Open Networking Laboratory
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package org.onosproject.store.trivial;
18 import static org.junit.Assert.assertEquals;
19 import static org.onosproject.net.DeviceId.deviceId;
21 import java.util.ArrayList;
22 import java.util.Arrays;
23 import java.util.Collections;
24 import java.util.List;
25 import java.util.Optional;
27 import org.junit.After;
28 import org.junit.Before;
29 import org.junit.Test;
30 import org.onlab.packet.MacAddress;
31 import org.onlab.packet.MplsLabel;
32 import org.onosproject.core.ApplicationId;
33 import org.onosproject.core.DefaultApplicationId;
34 import org.onosproject.core.GroupId;
35 import org.onosproject.net.DeviceId;
36 import org.onosproject.net.PortNumber;
37 import org.onosproject.net.flow.DefaultTrafficTreatment;
38 import org.onosproject.net.flow.TrafficTreatment;
39 import org.onosproject.net.group.DefaultGroup;
40 import org.onosproject.net.group.DefaultGroupBucket;
41 import org.onosproject.net.group.DefaultGroupDescription;
42 import org.onosproject.net.group.DefaultGroupKey;
43 import org.onosproject.net.group.Group;
44 import org.onosproject.net.group.GroupBucket;
45 import org.onosproject.net.group.GroupBuckets;
46 import org.onosproject.net.group.GroupDescription;
47 import org.onosproject.net.group.GroupEvent;
48 import org.onosproject.net.group.GroupKey;
49 import org.onosproject.net.group.GroupOperation;
50 import org.onosproject.net.group.GroupStore.UpdateType;
51 import org.onosproject.net.group.GroupStoreDelegate;
52 import org.onosproject.net.group.StoredGroupBucketEntry;
53 import org.onosproject.net.group.StoredGroupEntry;
55 import com.google.common.collect.Iterables;
58 * Test of the simple DeviceStore implementation.
60 public class SimpleGroupStoreTest {
62 private SimpleGroupStore simpleGroupStore;
63 private final ApplicationId appId =
64 new DefaultApplicationId(2, "org.groupstore.test");
66 public static final DeviceId D1 = deviceId("of:1");
69 public void setUp() throws Exception {
70 simpleGroupStore = new SimpleGroupStore();
71 simpleGroupStore.activate();
75 public void tearDown() throws Exception {
76 simpleGroupStore.deactivate();
79 private class InternalGroupStoreDelegate
80 implements GroupStoreDelegate {
81 private GroupId createdGroupId = null;
82 private GroupKey createdGroupKey;
83 private GroupBuckets createdBuckets;
84 private GroupEvent.Type expectedEvent;
86 public InternalGroupStoreDelegate(GroupKey key,
88 GroupEvent.Type expectedEvent) {
89 this.createdBuckets = buckets;
90 this.createdGroupKey = key;
91 this.expectedEvent = expectedEvent;
94 public void notify(GroupEvent event) {
95 assertEquals(expectedEvent, event.type());
96 assertEquals(Group.Type.SELECT, event.subject().type());
97 assertEquals(D1, event.subject().deviceId());
98 assertEquals(createdGroupKey, event.subject().appCookie());
99 assertEquals(createdBuckets.buckets(), event.subject().buckets().buckets());
100 if (expectedEvent == GroupEvent.Type.GROUP_ADD_REQUESTED) {
101 createdGroupId = event.subject().id();
102 assertEquals(Group.GroupState.PENDING_ADD,
103 event.subject().state());
104 } else if (expectedEvent == GroupEvent.Type.GROUP_ADDED) {
105 createdGroupId = event.subject().id();
106 assertEquals(Group.GroupState.ADDED,
107 event.subject().state());
108 } else if (expectedEvent == GroupEvent.Type.GROUP_UPDATED) {
109 createdGroupId = event.subject().id();
111 event.subject().buckets().
112 buckets().containsAll(createdBuckets.buckets()));
114 createdBuckets.buckets().
115 containsAll(event.subject().buckets().buckets()));
116 for (GroupBucket bucket:event.subject().buckets().buckets()) {
117 Optional<GroupBucket> matched = createdBuckets.buckets()
119 .filter((expected) -> expected.equals(bucket))
121 assertEquals(matched.get().packets(),
123 assertEquals(matched.get().bytes(),
126 assertEquals(Group.GroupState.ADDED,
127 event.subject().state());
128 } else if (expectedEvent == GroupEvent.Type.GROUP_UPDATE_REQUESTED) {
129 assertEquals(Group.GroupState.PENDING_UPDATE,
130 event.subject().state());
131 } else if (expectedEvent == GroupEvent.Type.GROUP_REMOVE_REQUESTED) {
132 assertEquals(Group.GroupState.PENDING_DELETE,
133 event.subject().state());
134 } else if (expectedEvent == GroupEvent.Type.GROUP_REMOVED) {
135 createdGroupId = event.subject().id();
136 assertEquals(Group.GroupState.PENDING_DELETE,
137 event.subject().state());
138 } else if (expectedEvent == GroupEvent.Type.GROUP_ADD_FAILED) {
139 createdGroupId = event.subject().id();
140 assertEquals(Group.GroupState.PENDING_ADD,
141 event.subject().state());
142 } else if (expectedEvent == GroupEvent.Type.GROUP_UPDATE_FAILED) {
143 createdGroupId = event.subject().id();
144 assertEquals(Group.GroupState.PENDING_UPDATE,
145 event.subject().state());
146 } else if (expectedEvent == GroupEvent.Type.GROUP_REMOVE_FAILED) {
147 createdGroupId = event.subject().id();
148 assertEquals(Group.GroupState.PENDING_DELETE,
149 event.subject().state());
153 public void verifyGroupId(GroupId id) {
154 assertEquals(createdGroupId, id);
159 * Tests group store operations. The following operations are tested:
160 * a)Tests device group audit completion status change
161 * b)Tests storeGroup operation
162 * c)Tests getGroupCount operation
163 * d)Tests getGroup operation
164 * e)Tests getGroups operation
165 * f)Tests addOrUpdateGroupEntry operation from southbound
166 * g)Tests updateGroupDescription for ADD operation from northbound
167 * h)Tests updateGroupDescription for REMOVE operation from northbound
168 * i)Tests deleteGroupDescription operation from northbound
169 * j)Tests removeGroupEntry operation from southbound
172 public void testGroupStoreOperations() {
173 // Set the Device AUDIT completed in the store
174 simpleGroupStore.deviceInitialAuditCompleted(D1, true);
176 // Testing storeGroup operation
177 GroupKey newKey = new DefaultGroupKey("group1".getBytes());
178 testStoreAndGetGroup(newKey);
180 // Testing addOrUpdateGroupEntry operation from southbound
181 GroupKey currKey = newKey;
182 testAddGroupEntryFromSB(currKey);
184 // Testing updateGroupDescription for ADD operation from northbound
185 newKey = new DefaultGroupKey("group1AddBuckets".getBytes());
186 testAddBuckets(currKey, newKey);
188 // Testing updateGroupDescription for REMOVE operation from northbound
190 newKey = new DefaultGroupKey("group1RemoveBuckets".getBytes());
191 testRemoveBuckets(currKey, newKey);
193 // Testing addOrUpdateGroupEntry operation from southbound
195 testUpdateGroupEntryFromSB(currKey);
197 // Testing deleteGroupDescription operation from northbound
198 testDeleteGroup(currKey);
200 // Testing removeGroupEntry operation from southbound
201 testRemoveGroupFromSB(currKey);
204 // Testing storeGroup operation
205 private void testStoreAndGetGroup(GroupKey key) {
206 PortNumber[] ports = {PortNumber.portNumber(31),
207 PortNumber.portNumber(32)};
208 List<PortNumber> outPorts = new ArrayList<PortNumber>();
209 outPorts.addAll(Arrays.asList(ports));
211 List<GroupBucket> buckets = new ArrayList<GroupBucket>();
212 for (PortNumber portNumber: outPorts) {
213 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
214 tBuilder.setOutput(portNumber)
215 .setEthDst(MacAddress.valueOf("00:00:00:00:00:02"))
216 .setEthSrc(MacAddress.valueOf("00:00:00:00:00:01"))
218 .setMpls(MplsLabel.mplsLabel(106));
219 buckets.add(DefaultGroupBucket.createSelectGroupBucket(
222 GroupBuckets groupBuckets = new GroupBuckets(buckets);
223 GroupDescription groupDesc = new DefaultGroupDescription(
230 InternalGroupStoreDelegate checkStoreGroupDelegate =
231 new InternalGroupStoreDelegate(key,
233 GroupEvent.Type.GROUP_ADD_REQUESTED);
234 simpleGroupStore.setDelegate(checkStoreGroupDelegate);
235 // Testing storeGroup operation
236 simpleGroupStore.storeGroupDescription(groupDesc);
238 // Testing getGroupCount operation
239 assertEquals(1, simpleGroupStore.getGroupCount(D1));
241 // Testing getGroup operation
242 Group createdGroup = simpleGroupStore.getGroup(D1, key);
243 checkStoreGroupDelegate.verifyGroupId(createdGroup.id());
245 // Testing getGroups operation
246 Iterable<Group> createdGroups = simpleGroupStore.getGroups(D1);
248 for (Group group:createdGroups) {
249 checkStoreGroupDelegate.verifyGroupId(group.id());
252 assertEquals(1, groupCount);
253 simpleGroupStore.unsetDelegate(checkStoreGroupDelegate);
256 // Testing addOrUpdateGroupEntry operation from southbound
257 private void testAddGroupEntryFromSB(GroupKey currKey) {
258 Group existingGroup = simpleGroupStore.getGroup(D1, currKey);
260 InternalGroupStoreDelegate addGroupEntryDelegate =
261 new InternalGroupStoreDelegate(currKey,
262 existingGroup.buckets(),
263 GroupEvent.Type.GROUP_ADDED);
264 simpleGroupStore.setDelegate(addGroupEntryDelegate);
265 simpleGroupStore.addOrUpdateGroupEntry(existingGroup);
266 simpleGroupStore.unsetDelegate(addGroupEntryDelegate);
269 // Testing addOrUpdateGroupEntry operation from southbound
270 private void testUpdateGroupEntryFromSB(GroupKey currKey) {
271 Group existingGroup = simpleGroupStore.getGroup(D1, currKey);
274 List<GroupBucket> newBucketList = new ArrayList<GroupBucket>();
275 for (GroupBucket bucket:existingGroup.buckets().buckets()) {
276 StoredGroupBucketEntry newBucket =
277 (StoredGroupBucketEntry)
278 DefaultGroupBucket.createSelectGroupBucket(bucket.treatment());
279 newBucket.setPackets(10);
280 newBucket.setBytes(10 * 256 * 8);
282 totalBytes += 10 * 256 * 8;
283 newBucketList.add(newBucket);
285 GroupBuckets updatedBuckets = new GroupBuckets(newBucketList);
286 Group updatedGroup = new DefaultGroup(existingGroup.id(),
287 existingGroup.deviceId(),
288 existingGroup.type(),
290 ((StoredGroupEntry) updatedGroup).setPackets(totalPkts);
291 ((StoredGroupEntry) updatedGroup).setBytes(totalBytes);
293 InternalGroupStoreDelegate updateGroupEntryDelegate =
294 new InternalGroupStoreDelegate(currKey,
296 GroupEvent.Type.GROUP_UPDATED);
297 simpleGroupStore.setDelegate(updateGroupEntryDelegate);
298 simpleGroupStore.addOrUpdateGroupEntry(updatedGroup);
299 simpleGroupStore.unsetDelegate(updateGroupEntryDelegate);
302 // Testing updateGroupDescription for ADD operation from northbound
303 private void testAddBuckets(GroupKey currKey, GroupKey addKey) {
304 Group existingGroup = simpleGroupStore.getGroup(D1, currKey);
305 List<GroupBucket> buckets = new ArrayList<GroupBucket>();
306 buckets.addAll(existingGroup.buckets().buckets());
308 PortNumber[] newNeighborPorts = {PortNumber.portNumber(41),
309 PortNumber.portNumber(42)};
310 List<PortNumber> newOutPorts = new ArrayList<PortNumber>();
311 newOutPorts.addAll(Collections.singletonList(newNeighborPorts[0]));
313 List<GroupBucket> toAddBuckets = new ArrayList<GroupBucket>();
314 for (PortNumber portNumber: newOutPorts) {
315 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
316 tBuilder.setOutput(portNumber)
317 .setEthDst(MacAddress.valueOf("00:00:00:00:00:03"))
318 .setEthSrc(MacAddress.valueOf("00:00:00:00:00:01"))
320 .setMpls(MplsLabel.mplsLabel(106));
321 toAddBuckets.add(DefaultGroupBucket.createSelectGroupBucket(
324 GroupBuckets toAddGroupBuckets = new GroupBuckets(toAddBuckets);
325 buckets.addAll(toAddBuckets);
326 GroupBuckets updatedGroupBuckets = new GroupBuckets(buckets);
327 InternalGroupStoreDelegate updateGroupDescDelegate =
328 new InternalGroupStoreDelegate(addKey,
330 GroupEvent.Type.GROUP_UPDATE_REQUESTED);
331 simpleGroupStore.setDelegate(updateGroupDescDelegate);
332 simpleGroupStore.updateGroupDescription(D1,
337 simpleGroupStore.unsetDelegate(updateGroupDescDelegate);
340 // Testing updateGroupDescription for REMOVE operation from northbound
341 private void testRemoveBuckets(GroupKey currKey, GroupKey removeKey) {
342 Group existingGroup = simpleGroupStore.getGroup(D1, currKey);
343 List<GroupBucket> buckets = new ArrayList<GroupBucket>();
344 buckets.addAll(existingGroup.buckets().buckets());
346 List<GroupBucket> toRemoveBuckets = new ArrayList<GroupBucket>();
348 // There should be 4 buckets in the current group
349 toRemoveBuckets.add(buckets.remove(0));
350 toRemoveBuckets.add(buckets.remove(1));
351 GroupBuckets toRemoveGroupBuckets = new GroupBuckets(toRemoveBuckets);
353 GroupBuckets remainingGroupBuckets = new GroupBuckets(buckets);
354 InternalGroupStoreDelegate removeGroupDescDelegate =
355 new InternalGroupStoreDelegate(removeKey,
356 remainingGroupBuckets,
357 GroupEvent.Type.GROUP_UPDATE_REQUESTED);
358 simpleGroupStore.setDelegate(removeGroupDescDelegate);
359 simpleGroupStore.updateGroupDescription(D1,
362 toRemoveGroupBuckets,
364 simpleGroupStore.unsetDelegate(removeGroupDescDelegate);
367 // Testing deleteGroupDescription operation from northbound
368 private void testDeleteGroup(GroupKey currKey) {
369 Group existingGroup = simpleGroupStore.getGroup(D1, currKey);
370 InternalGroupStoreDelegate deleteGroupDescDelegate =
371 new InternalGroupStoreDelegate(currKey,
372 existingGroup.buckets(),
373 GroupEvent.Type.GROUP_REMOVE_REQUESTED);
374 simpleGroupStore.setDelegate(deleteGroupDescDelegate);
375 simpleGroupStore.deleteGroupDescription(D1, currKey);
376 simpleGroupStore.unsetDelegate(deleteGroupDescDelegate);
379 // Testing removeGroupEntry operation from southbound
380 private void testRemoveGroupFromSB(GroupKey currKey) {
381 Group existingGroup = simpleGroupStore.getGroup(D1, currKey);
382 InternalGroupStoreDelegate removeGroupEntryDelegate =
383 new InternalGroupStoreDelegate(currKey,
384 existingGroup.buckets(),
385 GroupEvent.Type.GROUP_REMOVED);
386 simpleGroupStore.setDelegate(removeGroupEntryDelegate);
387 simpleGroupStore.removeGroupEntry(existingGroup);
389 // Testing getGroup operation
390 existingGroup = simpleGroupStore.getGroup(D1, currKey);
391 assertEquals(null, existingGroup);
392 assertEquals(0, Iterables.size(simpleGroupStore.getGroups(D1)));
393 assertEquals(0, simpleGroupStore.getGroupCount(D1));
395 simpleGroupStore.unsetDelegate(removeGroupEntryDelegate);
399 public void testGroupOperationFailure() {
401 simpleGroupStore.deviceInitialAuditCompleted(D1, true);
403 ApplicationId appId =
404 new DefaultApplicationId(2, "org.groupstore.test");
405 GroupKey key = new DefaultGroupKey("group1".getBytes());
406 PortNumber[] ports = {PortNumber.portNumber(31),
407 PortNumber.portNumber(32)};
408 List<PortNumber> outPorts = new ArrayList<PortNumber>();
409 outPorts.add(ports[0]);
410 outPorts.add(ports[1]);
412 List<GroupBucket> buckets = new ArrayList<GroupBucket>();
413 for (PortNumber portNumber: outPorts) {
414 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
415 tBuilder.setOutput(portNumber)
416 .setEthDst(MacAddress.valueOf("00:00:00:00:00:02"))
417 .setEthSrc(MacAddress.valueOf("00:00:00:00:00:01"))
419 .setMpls(MplsLabel.mplsLabel(106));
420 buckets.add(DefaultGroupBucket.createSelectGroupBucket(
423 GroupBuckets groupBuckets = new GroupBuckets(buckets);
424 GroupDescription groupDesc = new DefaultGroupDescription(
431 InternalGroupStoreDelegate checkStoreGroupDelegate =
432 new InternalGroupStoreDelegate(key,
434 GroupEvent.Type.GROUP_ADD_REQUESTED);
435 simpleGroupStore.setDelegate(checkStoreGroupDelegate);
436 // Testing storeGroup operation
437 simpleGroupStore.storeGroupDescription(groupDesc);
438 simpleGroupStore.unsetDelegate(checkStoreGroupDelegate);
440 // Testing Group add operation failure
441 Group createdGroup = simpleGroupStore.getGroup(D1, key);
442 checkStoreGroupDelegate.verifyGroupId(createdGroup.id());
444 GroupOperation groupAddOp = GroupOperation.
445 createAddGroupOperation(createdGroup.id(),
447 createdGroup.buckets());
448 InternalGroupStoreDelegate checkGroupAddFailureDelegate =
449 new InternalGroupStoreDelegate(key,
451 GroupEvent.Type.GROUP_ADD_FAILED);
452 simpleGroupStore.setDelegate(checkGroupAddFailureDelegate);
453 simpleGroupStore.groupOperationFailed(D1, groupAddOp);
456 // Testing Group modify operation failure
457 simpleGroupStore.unsetDelegate(checkGroupAddFailureDelegate);
458 GroupOperation groupModOp = GroupOperation.
459 createModifyGroupOperation(createdGroup.id(),
461 createdGroup.buckets());
462 InternalGroupStoreDelegate checkGroupModFailureDelegate =
463 new InternalGroupStoreDelegate(key,
465 GroupEvent.Type.GROUP_UPDATE_FAILED);
466 simpleGroupStore.setDelegate(checkGroupModFailureDelegate);
467 simpleGroupStore.groupOperationFailed(D1, groupModOp);
469 // Testing Group modify operation failure
470 simpleGroupStore.unsetDelegate(checkGroupModFailureDelegate);
471 GroupOperation groupDelOp = GroupOperation.
472 createDeleteGroupOperation(createdGroup.id(),
473 createdGroup.type());
474 InternalGroupStoreDelegate checkGroupDelFailureDelegate =
475 new InternalGroupStoreDelegate(key,
477 GroupEvent.Type.GROUP_REMOVE_FAILED);
478 simpleGroupStore.setDelegate(checkGroupDelFailureDelegate);
479 simpleGroupStore.groupOperationFailed(D1, groupDelOp);