dd6c8a58e8e0f0237444610d8bd511fc5204504b
[onosfw.git] /
1 /*
2  * Copyright 2014-2015 Open Networking Laboratory
3  *
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
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 package org.onosproject.store.trivial;
17
18 import static org.junit.Assert.assertEquals;
19 import static org.onosproject.net.DeviceId.deviceId;
20
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;
26
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;
54
55 import com.google.common.collect.Iterables;
56
57 /**
58  * Test of the simple DeviceStore implementation.
59  */
60 public class SimpleGroupStoreTest {
61
62     private SimpleGroupStore simpleGroupStore;
63     private final ApplicationId appId =
64             new DefaultApplicationId(2, "org.groupstore.test");
65
66     public static final DeviceId D1 = deviceId("of:1");
67
68     @Before
69     public void setUp() throws Exception {
70         simpleGroupStore = new SimpleGroupStore();
71         simpleGroupStore.activate();
72     }
73
74     @After
75     public void tearDown() throws Exception {
76         simpleGroupStore.deactivate();
77     }
78
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;
85
86         public InternalGroupStoreDelegate(GroupKey key,
87                                           GroupBuckets buckets,
88                                           GroupEvent.Type expectedEvent) {
89             this.createdBuckets = buckets;
90             this.createdGroupKey = key;
91             this.expectedEvent = expectedEvent;
92         }
93         @Override
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();
110                 assertEquals(true,
111                              event.subject().buckets().
112                              buckets().containsAll(createdBuckets.buckets()));
113                 assertEquals(true,
114                              createdBuckets.buckets().
115                              containsAll(event.subject().buckets().buckets()));
116                 for (GroupBucket bucket:event.subject().buckets().buckets()) {
117                     Optional<GroupBucket> matched = createdBuckets.buckets()
118                             .stream()
119                             .filter((expected) -> expected.equals(bucket))
120                             .findFirst();
121                     assertEquals(matched.get().packets(),
122                                  bucket.packets());
123                     assertEquals(matched.get().bytes(),
124                                  bucket.bytes());
125                 }
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());
150             }
151         }
152
153         public void verifyGroupId(GroupId id) {
154             assertEquals(createdGroupId, id);
155         }
156     }
157
158     /**
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
170      */
171     @Test
172     public void testGroupStoreOperations() {
173         // Set the Device AUDIT completed in the store
174         simpleGroupStore.deviceInitialAuditCompleted(D1, true);
175
176         // Testing storeGroup operation
177         GroupKey newKey = new DefaultGroupKey("group1".getBytes());
178         testStoreAndGetGroup(newKey);
179
180         // Testing addOrUpdateGroupEntry operation from southbound
181         GroupKey currKey = newKey;
182         testAddGroupEntryFromSB(currKey);
183
184         // Testing updateGroupDescription for ADD operation from northbound
185         newKey = new DefaultGroupKey("group1AddBuckets".getBytes());
186         testAddBuckets(currKey, newKey);
187
188         // Testing updateGroupDescription for REMOVE operation from northbound
189         currKey = newKey;
190         newKey = new DefaultGroupKey("group1RemoveBuckets".getBytes());
191         testRemoveBuckets(currKey, newKey);
192
193         // Testing addOrUpdateGroupEntry operation from southbound
194         currKey = newKey;
195         testUpdateGroupEntryFromSB(currKey);
196
197         // Testing deleteGroupDescription operation from northbound
198         testDeleteGroup(currKey);
199
200         // Testing removeGroupEntry operation from southbound
201         testRemoveGroupFromSB(currKey);
202     }
203
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));
210
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"))
217                     .pushMpls()
218                     .setMpls(MplsLabel.mplsLabel(106));
219             buckets.add(DefaultGroupBucket.createSelectGroupBucket(
220                                                         tBuilder.build()));
221         }
222         GroupBuckets groupBuckets = new GroupBuckets(buckets);
223         GroupDescription groupDesc = new DefaultGroupDescription(
224                                                  D1,
225                                                  Group.Type.SELECT,
226                                                  groupBuckets,
227                                                  key,
228                                                  null,
229                                                  appId);
230         InternalGroupStoreDelegate checkStoreGroupDelegate =
231                 new InternalGroupStoreDelegate(key,
232                                                groupBuckets,
233                                                GroupEvent.Type.GROUP_ADD_REQUESTED);
234         simpleGroupStore.setDelegate(checkStoreGroupDelegate);
235         // Testing storeGroup operation
236         simpleGroupStore.storeGroupDescription(groupDesc);
237
238         // Testing getGroupCount operation
239         assertEquals(1, simpleGroupStore.getGroupCount(D1));
240
241         // Testing getGroup operation
242         Group createdGroup = simpleGroupStore.getGroup(D1, key);
243         checkStoreGroupDelegate.verifyGroupId(createdGroup.id());
244
245         // Testing getGroups operation
246         Iterable<Group> createdGroups = simpleGroupStore.getGroups(D1);
247         int groupCount = 0;
248         for (Group group:createdGroups) {
249             checkStoreGroupDelegate.verifyGroupId(group.id());
250             groupCount++;
251         }
252         assertEquals(1, groupCount);
253         simpleGroupStore.unsetDelegate(checkStoreGroupDelegate);
254     }
255
256     // Testing addOrUpdateGroupEntry operation from southbound
257     private void testAddGroupEntryFromSB(GroupKey currKey) {
258         Group existingGroup = simpleGroupStore.getGroup(D1, currKey);
259
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);
267     }
268
269     // Testing addOrUpdateGroupEntry operation from southbound
270     private void testUpdateGroupEntryFromSB(GroupKey currKey) {
271         Group existingGroup = simpleGroupStore.getGroup(D1, currKey);
272         int totalPkts = 0;
273         int totalBytes = 0;
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);
281             totalPkts += 10;
282             totalBytes += 10 * 256 * 8;
283             newBucketList.add(newBucket);
284         }
285         GroupBuckets updatedBuckets = new GroupBuckets(newBucketList);
286         Group updatedGroup = new DefaultGroup(existingGroup.id(),
287                                               existingGroup.deviceId(),
288                                               existingGroup.type(),
289                                               updatedBuckets);
290         ((StoredGroupEntry) updatedGroup).setPackets(totalPkts);
291         ((StoredGroupEntry) updatedGroup).setBytes(totalBytes);
292
293         InternalGroupStoreDelegate updateGroupEntryDelegate =
294                 new InternalGroupStoreDelegate(currKey,
295                                                updatedBuckets,
296                                                GroupEvent.Type.GROUP_UPDATED);
297         simpleGroupStore.setDelegate(updateGroupEntryDelegate);
298         simpleGroupStore.addOrUpdateGroupEntry(updatedGroup);
299         simpleGroupStore.unsetDelegate(updateGroupEntryDelegate);
300     }
301
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());
307
308         PortNumber[] newNeighborPorts = {PortNumber.portNumber(41),
309                                          PortNumber.portNumber(42)};
310         List<PortNumber> newOutPorts = new ArrayList<PortNumber>();
311         newOutPorts.addAll(Collections.singletonList(newNeighborPorts[0]));
312
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"))
319                     .pushMpls()
320                     .setMpls(MplsLabel.mplsLabel(106));
321             toAddBuckets.add(DefaultGroupBucket.createSelectGroupBucket(
322                                                         tBuilder.build()));
323         }
324         GroupBuckets toAddGroupBuckets = new GroupBuckets(toAddBuckets);
325         buckets.addAll(toAddBuckets);
326         GroupBuckets updatedGroupBuckets = new GroupBuckets(buckets);
327         InternalGroupStoreDelegate updateGroupDescDelegate =
328                 new InternalGroupStoreDelegate(addKey,
329                                                updatedGroupBuckets,
330                                                GroupEvent.Type.GROUP_UPDATE_REQUESTED);
331         simpleGroupStore.setDelegate(updateGroupDescDelegate);
332         simpleGroupStore.updateGroupDescription(D1,
333                                                 currKey,
334                                                 UpdateType.ADD,
335                                                 toAddGroupBuckets,
336                                                 addKey);
337         simpleGroupStore.unsetDelegate(updateGroupDescDelegate);
338     }
339
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());
345
346         List<GroupBucket> toRemoveBuckets = new ArrayList<GroupBucket>();
347
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);
352
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,
360                                                 currKey,
361                                                 UpdateType.REMOVE,
362                                                 toRemoveGroupBuckets,
363                                                 removeKey);
364         simpleGroupStore.unsetDelegate(removeGroupDescDelegate);
365     }
366
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);
377     }
378
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);
388
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));
394
395         simpleGroupStore.unsetDelegate(removeGroupEntryDelegate);
396     }
397
398     @Test
399     public void testGroupOperationFailure() {
400
401         simpleGroupStore.deviceInitialAuditCompleted(D1, true);
402
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]);
411
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"))
418                     .pushMpls()
419                     .setMpls(MplsLabel.mplsLabel(106));
420             buckets.add(DefaultGroupBucket.createSelectGroupBucket(
421                     tBuilder.build()));
422         }
423         GroupBuckets groupBuckets = new GroupBuckets(buckets);
424         GroupDescription groupDesc = new DefaultGroupDescription(
425                 D1,
426                 Group.Type.SELECT,
427                 groupBuckets,
428                 key,
429                 null,
430                 appId);
431         InternalGroupStoreDelegate checkStoreGroupDelegate =
432                 new InternalGroupStoreDelegate(key,
433                         groupBuckets,
434                         GroupEvent.Type.GROUP_ADD_REQUESTED);
435         simpleGroupStore.setDelegate(checkStoreGroupDelegate);
436         // Testing storeGroup operation
437         simpleGroupStore.storeGroupDescription(groupDesc);
438         simpleGroupStore.unsetDelegate(checkStoreGroupDelegate);
439
440         // Testing Group add operation failure
441         Group createdGroup = simpleGroupStore.getGroup(D1, key);
442         checkStoreGroupDelegate.verifyGroupId(createdGroup.id());
443
444         GroupOperation groupAddOp = GroupOperation.
445                 createAddGroupOperation(createdGroup.id(),
446                         createdGroup.type(),
447                         createdGroup.buckets());
448         InternalGroupStoreDelegate checkGroupAddFailureDelegate =
449                 new InternalGroupStoreDelegate(key,
450                         groupBuckets,
451                         GroupEvent.Type.GROUP_ADD_FAILED);
452         simpleGroupStore.setDelegate(checkGroupAddFailureDelegate);
453         simpleGroupStore.groupOperationFailed(D1, groupAddOp);
454
455
456         // Testing Group modify operation failure
457         simpleGroupStore.unsetDelegate(checkGroupAddFailureDelegate);
458         GroupOperation groupModOp = GroupOperation.
459                 createModifyGroupOperation(createdGroup.id(),
460                         createdGroup.type(),
461                         createdGroup.buckets());
462         InternalGroupStoreDelegate checkGroupModFailureDelegate =
463                 new InternalGroupStoreDelegate(key,
464                         groupBuckets,
465                         GroupEvent.Type.GROUP_UPDATE_FAILED);
466         simpleGroupStore.setDelegate(checkGroupModFailureDelegate);
467         simpleGroupStore.groupOperationFailed(D1, groupModOp);
468
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,
476                         groupBuckets,
477                         GroupEvent.Type.GROUP_REMOVE_FAILED);
478         simpleGroupStore.setDelegate(checkGroupDelFailureDelegate);
479         simpleGroupStore.groupOperationFailed(D1, groupDelOp);
480     }
481 }
482