blob: e9cebeffba87acbf4c81ad8ff4854754c960be2d [file] [log] [blame]
Ray Milkeyb3c5ce22015-08-10 09:07:36 -07001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2015-present Open Networking Laboratory
Ray Milkeyb3c5ce22015-08-10 09:07:36 -07003 *
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 */
16package org.onosproject.store.group.impl;
17
18import java.util.ArrayList;
19import java.util.LinkedList;
20import java.util.List;
21
22import org.junit.After;
23import org.junit.Before;
24import org.junit.Test;
25import org.onlab.junit.TestUtils;
alshabibb0285992016-03-28 23:30:37 -070026import org.onosproject.cfg.ComponentConfigAdapter;
Charles Chanf4838a72015-12-07 18:13:45 -080027import org.onosproject.cluster.NodeId;
Ray Milkeyb3c5ce22015-08-10 09:07:36 -070028import org.onosproject.core.DefaultGroupId;
29import org.onosproject.core.GroupId;
30import org.onosproject.mastership.MastershipServiceAdapter;
31import org.onosproject.net.DeviceId;
32import org.onosproject.net.MastershipRole;
33import org.onosproject.net.PortNumber;
34import org.onosproject.net.flow.DefaultTrafficTreatment;
35import org.onosproject.net.flow.TrafficTreatment;
36import org.onosproject.net.group.DefaultGroup;
37import org.onosproject.net.group.DefaultGroupBucket;
38import org.onosproject.net.group.DefaultGroupDescription;
39import org.onosproject.net.group.DefaultGroupKey;
40import org.onosproject.net.group.Group;
41import org.onosproject.net.group.GroupBucket;
42import org.onosproject.net.group.GroupBuckets;
43import org.onosproject.net.group.GroupDescription;
44import org.onosproject.net.group.GroupEvent;
45import org.onosproject.net.group.GroupKey;
46import org.onosproject.net.group.GroupOperation;
47import org.onosproject.net.group.GroupStore;
48import org.onosproject.net.group.GroupStoreDelegate;
49import org.onosproject.store.cluster.messaging.ClusterCommunicationServiceAdapter;
Madan Jampani0b847532016-03-03 13:44:15 -080050import org.onosproject.store.service.ConsistentMap;
Ray Milkeyb3c5ce22015-08-10 09:07:36 -070051import org.onosproject.store.service.TestStorageService;
52
53import com.google.common.collect.ImmutableList;
54import com.google.common.collect.Lists;
55import com.google.common.testing.EqualsTester;
56
57import static org.hamcrest.MatcherAssert.assertThat;
58import static org.hamcrest.Matchers.hasSize;
59import static org.hamcrest.Matchers.instanceOf;
60import static org.hamcrest.Matchers.is;
61import static org.hamcrest.Matchers.notNullValue;
62import static org.hamcrest.Matchers.nullValue;
Victor Silvadf1eeae2016-08-12 15:28:57 -030063import static org.junit.Assert.assertEquals;
Ray Milkeyb3c5ce22015-08-10 09:07:36 -070064import static org.onosproject.net.NetTestTools.APP_ID;
65import static org.onosproject.net.NetTestTools.did;
Jayasree Ghosh2d459852016-07-02 19:06:52 +053066import static org.onosproject.net.group.GroupDescription.Type.*;
67import static org.onosproject.net.group.GroupStore.UpdateType.*;
Ray Milkeyb3c5ce22015-08-10 09:07:36 -070068/**
69 * Distributed group store test.
70 */
71public class DistributedGroupStoreTest {
72
73 DeviceId deviceId1 = did("dev1");
74 DeviceId deviceId2 = did("dev2");
75 GroupId groupId1 = new DefaultGroupId(1);
76 GroupId groupId2 = new DefaultGroupId(2);
Charles Chan0c7c43b2016-01-14 17:39:20 -080077 GroupId groupId3 = new DefaultGroupId(3);
Ray Milkeyb3c5ce22015-08-10 09:07:36 -070078 GroupKey groupKey1 = new DefaultGroupKey("abc".getBytes());
79 GroupKey groupKey2 = new DefaultGroupKey("def".getBytes());
Charles Chan0c7c43b2016-01-14 17:39:20 -080080 GroupKey groupKey3 = new DefaultGroupKey("ghi".getBytes());
Ray Milkeyb3c5ce22015-08-10 09:07:36 -070081
82 TrafficTreatment treatment =
83 DefaultTrafficTreatment.emptyTreatment();
84 GroupBucket selectGroupBucket =
85 DefaultGroupBucket.createSelectGroupBucket(treatment);
86 GroupBucket failoverGroupBucket =
87 DefaultGroupBucket.createFailoverGroupBucket(treatment,
88 PortNumber.IN_PORT, groupId1);
89
90 GroupBuckets buckets = new GroupBuckets(ImmutableList.of(selectGroupBucket));
91 GroupDescription groupDescription1 = new DefaultGroupDescription(
92 deviceId1,
Jayasree Ghosh2d459852016-07-02 19:06:52 +053093 ALL,
Ray Milkeyb3c5ce22015-08-10 09:07:36 -070094 buckets,
95 groupKey1,
96 groupId1.id(),
97 APP_ID);
98 GroupDescription groupDescription2 = new DefaultGroupDescription(
99 deviceId2,
Jayasree Ghosh2d459852016-07-02 19:06:52 +0530100 INDIRECT,
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700101 buckets,
102 groupKey2,
103 groupId2.id(),
104 APP_ID);
Charles Chan0c7c43b2016-01-14 17:39:20 -0800105 GroupDescription groupDescription3 = new DefaultGroupDescription(
106 deviceId2,
Jayasree Ghosh2d459852016-07-02 19:06:52 +0530107 INDIRECT,
Charles Chan0c7c43b2016-01-14 17:39:20 -0800108 buckets,
109 groupKey3,
110 groupId3.id(),
111 APP_ID);
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700112
113 DistributedGroupStore groupStoreImpl;
114 GroupStore groupStore;
Madan Jampani0b847532016-03-03 13:44:15 -0800115 ConsistentMap auditPendingReqQueue;
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700116
117 static class MasterOfAll extends MastershipServiceAdapter {
118 @Override
119 public MastershipRole getLocalRole(DeviceId deviceId) {
120 return MastershipRole.MASTER;
121 }
Charles Chanf4838a72015-12-07 18:13:45 -0800122
123 @Override
124 public NodeId getMasterFor(DeviceId deviceId) {
125 return new NodeId("foo");
126 }
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700127 }
128
129 @Before
130 public void setUp() throws Exception {
131 groupStoreImpl = new DistributedGroupStore();
132 groupStoreImpl.storageService = new TestStorageService();
133 groupStoreImpl.clusterCommunicator = new ClusterCommunicationServiceAdapter();
134 groupStoreImpl.mastershipService = new MasterOfAll();
alshabibb0285992016-03-28 23:30:37 -0700135 groupStoreImpl.cfgService = new ComponentConfigAdapter();
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700136 groupStoreImpl.activate();
137 groupStore = groupStoreImpl;
138 auditPendingReqQueue =
139 TestUtils.getField(groupStoreImpl, "auditPendingReqQueue");
140 }
141
142 @After
143 public void tearDown() throws Exception {
144 groupStoreImpl.deactivate();
145 }
146
147 /**
148 * Tests the initial state of the store.
149 */
150 @Test
151 public void testEmptyStore() {
152 assertThat(groupStore.getGroupCount(deviceId1), is(0));
153 assertThat(groupStore.getGroup(deviceId1, groupId1), nullValue());
154 assertThat(groupStore.getGroup(deviceId1, groupKey1), nullValue());
155 }
156
157 /**
158 * Tests adding a pending group.
159 */
160 @Test
161 public void testAddPendingGroup() throws Exception {
162 // Make sure the pending list starts out empty
163 assertThat(auditPendingReqQueue.size(), is(0));
164
165 // Add a new pending group. Make sure that the store remains empty
166 groupStore.storeGroupDescription(groupDescription1);
167 assertThat(groupStore.getGroupCount(deviceId1), is(0));
168 assertThat(groupStore.getGroup(deviceId1, groupId1), nullValue());
169 assertThat(groupStore.getGroup(deviceId1, groupKey1), nullValue());
170
171 // Make sure the group is pending
172 assertThat(auditPendingReqQueue.size(), is(1));
173
174 groupStore.deviceInitialAuditCompleted(deviceId1, true);
175
176 // Make sure the group isn't pending anymore
177 assertThat(auditPendingReqQueue.size(), is(0));
178 }
179
180
181 /**
182 * Tests adding and removing a group.
183 */
184 @Test
185 public void testAddRemoveGroup() throws Exception {
186 groupStore.deviceInitialAuditCompleted(deviceId1, true);
187 assertThat(groupStore.deviceInitialAuditStatus(deviceId1), is(true));
188
189 // Make sure the pending list starts out empty
190 assertThat(auditPendingReqQueue.size(), is(0));
191
192 groupStore.storeGroupDescription(groupDescription1);
193 assertThat(groupStore.getGroupCount(deviceId1), is(1));
194 assertThat(groupStore.getGroup(deviceId1, groupId1), notNullValue());
195 assertThat(groupStore.getGroup(deviceId1, groupKey1), notNullValue());
196
197 // Make sure that nothing is pending
198 assertThat(auditPendingReqQueue.size(), is(0));
199
200 Group groupById = groupStore.getGroup(deviceId1, groupId1);
201 Group groupByKey = groupStore.getGroup(deviceId1, groupKey1);
202 assertThat(groupById, notNullValue());
203 assertThat(groupByKey, notNullValue());
204 assertThat(groupById, is(groupByKey));
205 assertThat(groupById.deviceId(), is(did("dev1")));
206
207 groupStore.removeGroupEntry(groupById);
208
209 assertThat(groupStore.getGroupCount(deviceId1), is(0));
210 assertThat(groupStore.getGroup(deviceId1, groupId1), nullValue());
211 assertThat(groupStore.getGroup(deviceId1, groupKey1), nullValue());
212
213 // Make sure that nothing is pending
214 assertThat(auditPendingReqQueue.size(), is(0));
215 }
216
217 /**
Charles Chan0c7c43b2016-01-14 17:39:20 -0800218 * Tests removing all groups on the given device.
219 */
220 @Test
221 public void testRemoveGroupOnDevice() throws Exception {
222 groupStore.deviceInitialAuditCompleted(deviceId1, true);
223 assertThat(groupStore.deviceInitialAuditStatus(deviceId1), is(true));
224 groupStore.deviceInitialAuditCompleted(deviceId2, true);
225 assertThat(groupStore.deviceInitialAuditStatus(deviceId2), is(true));
226
227 // Make sure the pending list starts out empty
228 assertThat(auditPendingReqQueue.size(), is(0));
229
230 groupStore.storeGroupDescription(groupDescription1);
231 groupStore.storeGroupDescription(groupDescription2);
232 groupStore.storeGroupDescription(groupDescription3);
233 assertThat(groupStore.getGroupCount(deviceId1), is(1));
234 assertThat(groupStore.getGroupCount(deviceId2), is(2));
235
236 groupStore.purgeGroupEntry(deviceId2);
237 assertThat(groupStore.getGroupCount(deviceId1), is(1));
238 assertThat(groupStore.getGroupCount(deviceId2), is(0));
Victor Silva4e8b7832016-08-17 17:11:19 -0300239
240 groupStore.purgeGroupEntries();
241 assertThat(groupStore.getGroupCount(deviceId1), is(0));
242 assertThat(groupStore.getGroupCount(deviceId2), is(0));
Charles Chan0c7c43b2016-01-14 17:39:20 -0800243 }
244
245 /**
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700246 * Tests adding and removing a group.
247 */
248 @Test
249 public void testRemoveGroupDescription() throws Exception {
250 groupStore.deviceInitialAuditCompleted(deviceId1, true);
251
252 groupStore.storeGroupDescription(groupDescription1);
253
254 groupStore.deleteGroupDescription(deviceId1, groupKey1);
255
256 // Group should still be there, marked for removal
257 assertThat(groupStore.getGroupCount(deviceId1), is(1));
258 Group queriedGroup = groupStore.getGroup(deviceId1, groupId1);
259 assertThat(queriedGroup.state(), is(Group.GroupState.PENDING_DELETE));
260
261 }
262
263 /**
264 * Tests pushing group metrics.
265 */
266 @Test
267 public void testPushGroupMetrics() {
268 groupStore.deviceInitialAuditCompleted(deviceId1, true);
269 groupStore.deviceInitialAuditCompleted(deviceId2, true);
270
271 GroupDescription groupDescription3 = new DefaultGroupDescription(
272 deviceId1,
Jayasree Ghosh2d459852016-07-02 19:06:52 +0530273 SELECT,
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700274 buckets,
275 new DefaultGroupKey("aaa".getBytes()),
276 null,
277 APP_ID);
278
279 groupStore.storeGroupDescription(groupDescription1);
280 groupStore.storeGroupDescription(groupDescription2);
281 groupStore.storeGroupDescription(groupDescription3);
282 Group group1 = groupStore.getGroup(deviceId1, groupId1);
283
284 assertThat(group1, instanceOf(DefaultGroup.class));
285 DefaultGroup defaultGroup1 = (DefaultGroup) group1;
286 defaultGroup1.setPackets(55L);
287 defaultGroup1.setBytes(66L);
288 groupStore.pushGroupMetrics(deviceId1, ImmutableList.of(group1));
289
290 // Make sure the group was updated.
291
292 Group requeryGroup1 = groupStore.getGroup(deviceId1, groupId1);
293 assertThat(requeryGroup1.packets(), is(55L));
294 assertThat(requeryGroup1.bytes(), is(66L));
295
296 }
297
298 class TestDelegate implements GroupStoreDelegate {
299 private List<GroupEvent> eventsSeen = new LinkedList<>();
300 @Override
301 public void notify(GroupEvent event) {
302 eventsSeen.add(event);
303 }
304
305 public List<GroupEvent> eventsSeen() {
306 return eventsSeen;
307 }
308
309 public void resetEvents() {
310 eventsSeen.clear();
311 }
312 }
313
314 /**
315 * Tests group operation failed interface.
316 */
317 @Test
318 public void testGroupOperationFailed() {
319 TestDelegate delegate = new TestDelegate();
320 groupStore.setDelegate(delegate);
321 groupStore.deviceInitialAuditCompleted(deviceId1, true);
322 groupStore.deviceInitialAuditCompleted(deviceId2, true);
323
324 groupStore.storeGroupDescription(groupDescription1);
325 groupStore.storeGroupDescription(groupDescription2);
326
327 List<GroupEvent> eventsAfterAdds = delegate.eventsSeen();
328 assertThat(eventsAfterAdds, hasSize(2));
Sho SHIMIZUa09e1bb2016-08-01 14:25:25 -0700329 eventsAfterAdds.forEach(event -> assertThat(event.type(), is(GroupEvent.Type.GROUP_ADD_REQUESTED)));
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700330 delegate.resetEvents();
331
332 GroupOperation opAdd =
333 GroupOperation.createAddGroupOperation(groupId1,
Jayasree Ghosh2d459852016-07-02 19:06:52 +0530334 INDIRECT,
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700335 buckets);
336 groupStore.groupOperationFailed(deviceId1, opAdd);
337
338 List<GroupEvent> eventsAfterAddFailed = delegate.eventsSeen();
339 assertThat(eventsAfterAddFailed, hasSize(2));
340 assertThat(eventsAfterAddFailed.get(0).type(),
341 is(GroupEvent.Type.GROUP_ADD_FAILED));
342 assertThat(eventsAfterAddFailed.get(1).type(),
343 is(GroupEvent.Type.GROUP_REMOVED));
344 delegate.resetEvents();
345
346 GroupOperation opModify =
347 GroupOperation.createModifyGroupOperation(groupId2,
Jayasree Ghosh2d459852016-07-02 19:06:52 +0530348 INDIRECT,
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700349 buckets);
350 groupStore.groupOperationFailed(deviceId2, opModify);
351 List<GroupEvent> eventsAfterModifyFailed = delegate.eventsSeen();
352 assertThat(eventsAfterModifyFailed, hasSize(1));
353 assertThat(eventsAfterModifyFailed.get(0).type(),
354 is(GroupEvent.Type.GROUP_UPDATE_FAILED));
355 delegate.resetEvents();
356
357 GroupOperation opDelete =
358 GroupOperation.createDeleteGroupOperation(groupId2,
Jayasree Ghosh2d459852016-07-02 19:06:52 +0530359 INDIRECT);
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700360 groupStore.groupOperationFailed(deviceId2, opDelete);
361 List<GroupEvent> eventsAfterDeleteFailed = delegate.eventsSeen();
362 assertThat(eventsAfterDeleteFailed, hasSize(1));
363 assertThat(eventsAfterDeleteFailed.get(0).type(),
364 is(GroupEvent.Type.GROUP_REMOVE_FAILED));
365 delegate.resetEvents();
366 }
367
368 /**
369 * Tests extraneous group operations.
370 */
371 @Test
372 public void testExtraneousOperations() {
373 ArrayList<Group> extraneous;
374 groupStore.deviceInitialAuditCompleted(deviceId1, true);
375
376 groupStore.storeGroupDescription(groupDescription1);
377 Group group1 = groupStore.getGroup(deviceId1, groupId1);
378
379 extraneous = Lists.newArrayList(groupStore.getExtraneousGroups(deviceId1));
380 assertThat(extraneous, hasSize(0));
381
382 groupStore.addOrUpdateExtraneousGroupEntry(group1);
383 extraneous = Lists.newArrayList(groupStore.getExtraneousGroups(deviceId1));
384 assertThat(extraneous, hasSize(1));
385
386 groupStore.removeExtraneousGroupEntry(group1);
387 extraneous = Lists.newArrayList(groupStore.getExtraneousGroups(deviceId1));
388 assertThat(extraneous, hasSize(0));
389 }
390
391 /**
392 * Tests updating of group descriptions.
393 */
394 @Test
395 public void testUpdateGroupDescription() {
396
397 GroupBuckets buckets =
Victor Silvadf1eeae2016-08-12 15:28:57 -0300398 new GroupBuckets(ImmutableList.of(failoverGroupBucket, selectGroupBucket));
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700399
400 groupStore.deviceInitialAuditCompleted(deviceId1, true);
401 groupStore.storeGroupDescription(groupDescription1);
402
403 GroupKey newKey = new DefaultGroupKey("123".getBytes());
404 groupStore.updateGroupDescription(deviceId1,
405 groupKey1,
Jayasree Ghosh2d459852016-07-02 19:06:52 +0530406 ADD,
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700407 buckets,
408 newKey);
409 Group group1 = groupStore.getGroup(deviceId1, groupId1);
410 assertThat(group1.appCookie(), is(newKey));
411 assertThat(group1.buckets().buckets(), hasSize(2));
Victor Silvadf1eeae2016-08-12 15:28:57 -0300412
413 short weight = 5;
414 GroupBucket selectGroupBucketWithWeight =
415 DefaultGroupBucket.createSelectGroupBucket(treatment, weight);
416 buckets = new GroupBuckets(ImmutableList.of(failoverGroupBucket,
417 selectGroupBucketWithWeight));
418
419 groupStore.updateGroupDescription(deviceId1,
420 newKey,
421 ADD,
422 buckets,
423 newKey);
424
425 group1 = groupStore.getGroup(deviceId1, groupId1);
426 assertThat(group1.appCookie(), is(newKey));
427 assertThat(group1.buckets().buckets(), hasSize(2));
428 for (GroupBucket bucket : group1.buckets().buckets()) {
429 if (bucket.type() == SELECT) {
430 assertEquals(weight, bucket.weight());
431 }
432 }
Victor Silva0282ab82016-11-15 16:30:27 -0300433
434 buckets = new GroupBuckets(ImmutableList.of(selectGroupBucketWithWeight));
435
436 groupStore.updateGroupDescription(deviceId1,
437 newKey,
438 SET,
439 buckets,
440 newKey);
441
442 group1 = groupStore.getGroup(deviceId1, groupId1);
443 assertThat(group1.appCookie(), is(newKey));
444 assertThat(group1.buckets().buckets(), hasSize(1));
445 GroupBucket onlyBucket = group1.buckets().buckets().iterator().next();
446 assertEquals(weight, onlyBucket.weight());
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700447 }
448
449 @Test
450 public void testEqualsGroupStoreIdMapKey() {
451 DistributedGroupStore.GroupStoreIdMapKey key1 =
452 new DistributedGroupStore.GroupStoreIdMapKey(deviceId1, groupId1);
453 DistributedGroupStore.GroupStoreIdMapKey sameAsKey1 =
454 new DistributedGroupStore.GroupStoreIdMapKey(deviceId1, groupId1);
455 DistributedGroupStore.GroupStoreIdMapKey key2 =
456 new DistributedGroupStore.GroupStoreIdMapKey(deviceId2, groupId1);
457 DistributedGroupStore.GroupStoreIdMapKey key3 =
458 new DistributedGroupStore.GroupStoreIdMapKey(deviceId1, groupId2);
459
460 new EqualsTester()
461 .addEqualityGroup(key1, sameAsKey1)
462 .addEqualityGroup(key2)
463 .addEqualityGroup(key3)
464 .testEquals();
465 }
466
467 @Test
468 public void testEqualsGroupStoreKeyMapKey() {
469 DistributedGroupStore.GroupStoreKeyMapKey key1 =
470 new DistributedGroupStore.GroupStoreKeyMapKey(deviceId1, groupKey1);
471 DistributedGroupStore.GroupStoreKeyMapKey sameAsKey1 =
472 new DistributedGroupStore.GroupStoreKeyMapKey(deviceId1, groupKey1);
473 DistributedGroupStore.GroupStoreKeyMapKey key2 =
474 new DistributedGroupStore.GroupStoreKeyMapKey(deviceId2, groupKey1);
475 DistributedGroupStore.GroupStoreKeyMapKey key3 =
476 new DistributedGroupStore.GroupStoreKeyMapKey(deviceId1, groupKey2);
477
478 new EqualsTester()
479 .addEqualityGroup(key1, sameAsKey1)
480 .addEqualityGroup(key2)
481 .addEqualityGroup(key3)
482 .testEquals();
483 }
484
485 @Test
486 public void testEqualsGroupStoreMapKey() {
487 DistributedGroupStore.GroupStoreMapKey key1 =
488 new DistributedGroupStore.GroupStoreMapKey(deviceId1);
489 DistributedGroupStore.GroupStoreMapKey sameAsKey1 =
490 new DistributedGroupStore.GroupStoreMapKey(deviceId1);
491 DistributedGroupStore.GroupStoreMapKey key2 =
492 new DistributedGroupStore.GroupStoreMapKey(deviceId2);
493 DistributedGroupStore.GroupStoreMapKey key3 =
494 new DistributedGroupStore.GroupStoreMapKey(did("dev3"));
495
496 new EqualsTester()
497 .addEqualityGroup(key1, sameAsKey1)
498 .addEqualityGroup(key2)
499 .addEqualityGroup(key3)
500 .testEquals();
501 }
502}