blob: 288d8deff363290731048c5cf9d7d2ba39711fc6 [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));
239 }
240
241 /**
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700242 * Tests adding and removing a group.
243 */
244 @Test
245 public void testRemoveGroupDescription() throws Exception {
246 groupStore.deviceInitialAuditCompleted(deviceId1, true);
247
248 groupStore.storeGroupDescription(groupDescription1);
249
250 groupStore.deleteGroupDescription(deviceId1, groupKey1);
251
252 // Group should still be there, marked for removal
253 assertThat(groupStore.getGroupCount(deviceId1), is(1));
254 Group queriedGroup = groupStore.getGroup(deviceId1, groupId1);
255 assertThat(queriedGroup.state(), is(Group.GroupState.PENDING_DELETE));
256
257 }
258
259 /**
260 * Tests pushing group metrics.
261 */
262 @Test
263 public void testPushGroupMetrics() {
264 groupStore.deviceInitialAuditCompleted(deviceId1, true);
265 groupStore.deviceInitialAuditCompleted(deviceId2, true);
266
267 GroupDescription groupDescription3 = new DefaultGroupDescription(
268 deviceId1,
Jayasree Ghosh2d459852016-07-02 19:06:52 +0530269 SELECT,
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700270 buckets,
271 new DefaultGroupKey("aaa".getBytes()),
272 null,
273 APP_ID);
274
275 groupStore.storeGroupDescription(groupDescription1);
276 groupStore.storeGroupDescription(groupDescription2);
277 groupStore.storeGroupDescription(groupDescription3);
278 Group group1 = groupStore.getGroup(deviceId1, groupId1);
279
280 assertThat(group1, instanceOf(DefaultGroup.class));
281 DefaultGroup defaultGroup1 = (DefaultGroup) group1;
282 defaultGroup1.setPackets(55L);
283 defaultGroup1.setBytes(66L);
284 groupStore.pushGroupMetrics(deviceId1, ImmutableList.of(group1));
285
286 // Make sure the group was updated.
287
288 Group requeryGroup1 = groupStore.getGroup(deviceId1, groupId1);
289 assertThat(requeryGroup1.packets(), is(55L));
290 assertThat(requeryGroup1.bytes(), is(66L));
291
292 }
293
294 class TestDelegate implements GroupStoreDelegate {
295 private List<GroupEvent> eventsSeen = new LinkedList<>();
296 @Override
297 public void notify(GroupEvent event) {
298 eventsSeen.add(event);
299 }
300
301 public List<GroupEvent> eventsSeen() {
302 return eventsSeen;
303 }
304
305 public void resetEvents() {
306 eventsSeen.clear();
307 }
308 }
309
310 /**
311 * Tests group operation failed interface.
312 */
313 @Test
314 public void testGroupOperationFailed() {
315 TestDelegate delegate = new TestDelegate();
316 groupStore.setDelegate(delegate);
317 groupStore.deviceInitialAuditCompleted(deviceId1, true);
318 groupStore.deviceInitialAuditCompleted(deviceId2, true);
319
320 groupStore.storeGroupDescription(groupDescription1);
321 groupStore.storeGroupDescription(groupDescription2);
322
323 List<GroupEvent> eventsAfterAdds = delegate.eventsSeen();
324 assertThat(eventsAfterAdds, hasSize(2));
Sho SHIMIZUa09e1bb2016-08-01 14:25:25 -0700325 eventsAfterAdds.forEach(event -> assertThat(event.type(), is(GroupEvent.Type.GROUP_ADD_REQUESTED)));
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700326 delegate.resetEvents();
327
328 GroupOperation opAdd =
329 GroupOperation.createAddGroupOperation(groupId1,
Jayasree Ghosh2d459852016-07-02 19:06:52 +0530330 INDIRECT,
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700331 buckets);
332 groupStore.groupOperationFailed(deviceId1, opAdd);
333
334 List<GroupEvent> eventsAfterAddFailed = delegate.eventsSeen();
335 assertThat(eventsAfterAddFailed, hasSize(2));
336 assertThat(eventsAfterAddFailed.get(0).type(),
337 is(GroupEvent.Type.GROUP_ADD_FAILED));
338 assertThat(eventsAfterAddFailed.get(1).type(),
339 is(GroupEvent.Type.GROUP_REMOVED));
340 delegate.resetEvents();
341
342 GroupOperation opModify =
343 GroupOperation.createModifyGroupOperation(groupId2,
Jayasree Ghosh2d459852016-07-02 19:06:52 +0530344 INDIRECT,
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700345 buckets);
346 groupStore.groupOperationFailed(deviceId2, opModify);
347 List<GroupEvent> eventsAfterModifyFailed = delegate.eventsSeen();
348 assertThat(eventsAfterModifyFailed, hasSize(1));
349 assertThat(eventsAfterModifyFailed.get(0).type(),
350 is(GroupEvent.Type.GROUP_UPDATE_FAILED));
351 delegate.resetEvents();
352
353 GroupOperation opDelete =
354 GroupOperation.createDeleteGroupOperation(groupId2,
Jayasree Ghosh2d459852016-07-02 19:06:52 +0530355 INDIRECT);
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700356 groupStore.groupOperationFailed(deviceId2, opDelete);
357 List<GroupEvent> eventsAfterDeleteFailed = delegate.eventsSeen();
358 assertThat(eventsAfterDeleteFailed, hasSize(1));
359 assertThat(eventsAfterDeleteFailed.get(0).type(),
360 is(GroupEvent.Type.GROUP_REMOVE_FAILED));
361 delegate.resetEvents();
362 }
363
364 /**
365 * Tests extraneous group operations.
366 */
367 @Test
368 public void testExtraneousOperations() {
369 ArrayList<Group> extraneous;
370 groupStore.deviceInitialAuditCompleted(deviceId1, true);
371
372 groupStore.storeGroupDescription(groupDescription1);
373 Group group1 = groupStore.getGroup(deviceId1, groupId1);
374
375 extraneous = Lists.newArrayList(groupStore.getExtraneousGroups(deviceId1));
376 assertThat(extraneous, hasSize(0));
377
378 groupStore.addOrUpdateExtraneousGroupEntry(group1);
379 extraneous = Lists.newArrayList(groupStore.getExtraneousGroups(deviceId1));
380 assertThat(extraneous, hasSize(1));
381
382 groupStore.removeExtraneousGroupEntry(group1);
383 extraneous = Lists.newArrayList(groupStore.getExtraneousGroups(deviceId1));
384 assertThat(extraneous, hasSize(0));
385 }
386
387 /**
388 * Tests updating of group descriptions.
389 */
390 @Test
391 public void testUpdateGroupDescription() {
392
393 GroupBuckets buckets =
Victor Silvadf1eeae2016-08-12 15:28:57 -0300394 new GroupBuckets(ImmutableList.of(failoverGroupBucket, selectGroupBucket));
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700395
396 groupStore.deviceInitialAuditCompleted(deviceId1, true);
397 groupStore.storeGroupDescription(groupDescription1);
398
399 GroupKey newKey = new DefaultGroupKey("123".getBytes());
400 groupStore.updateGroupDescription(deviceId1,
401 groupKey1,
Jayasree Ghosh2d459852016-07-02 19:06:52 +0530402 ADD,
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700403 buckets,
404 newKey);
405 Group group1 = groupStore.getGroup(deviceId1, groupId1);
406 assertThat(group1.appCookie(), is(newKey));
407 assertThat(group1.buckets().buckets(), hasSize(2));
Victor Silvadf1eeae2016-08-12 15:28:57 -0300408
409 short weight = 5;
410 GroupBucket selectGroupBucketWithWeight =
411 DefaultGroupBucket.createSelectGroupBucket(treatment, weight);
412 buckets = new GroupBuckets(ImmutableList.of(failoverGroupBucket,
413 selectGroupBucketWithWeight));
414
415 groupStore.updateGroupDescription(deviceId1,
416 newKey,
417 ADD,
418 buckets,
419 newKey);
420
421 group1 = groupStore.getGroup(deviceId1, groupId1);
422 assertThat(group1.appCookie(), is(newKey));
423 assertThat(group1.buckets().buckets(), hasSize(2));
424 for (GroupBucket bucket : group1.buckets().buckets()) {
425 if (bucket.type() == SELECT) {
426 assertEquals(weight, bucket.weight());
427 }
428 }
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700429 }
430
431 @Test
432 public void testEqualsGroupStoreIdMapKey() {
433 DistributedGroupStore.GroupStoreIdMapKey key1 =
434 new DistributedGroupStore.GroupStoreIdMapKey(deviceId1, groupId1);
435 DistributedGroupStore.GroupStoreIdMapKey sameAsKey1 =
436 new DistributedGroupStore.GroupStoreIdMapKey(deviceId1, groupId1);
437 DistributedGroupStore.GroupStoreIdMapKey key2 =
438 new DistributedGroupStore.GroupStoreIdMapKey(deviceId2, groupId1);
439 DistributedGroupStore.GroupStoreIdMapKey key3 =
440 new DistributedGroupStore.GroupStoreIdMapKey(deviceId1, groupId2);
441
442 new EqualsTester()
443 .addEqualityGroup(key1, sameAsKey1)
444 .addEqualityGroup(key2)
445 .addEqualityGroup(key3)
446 .testEquals();
447 }
448
449 @Test
450 public void testEqualsGroupStoreKeyMapKey() {
451 DistributedGroupStore.GroupStoreKeyMapKey key1 =
452 new DistributedGroupStore.GroupStoreKeyMapKey(deviceId1, groupKey1);
453 DistributedGroupStore.GroupStoreKeyMapKey sameAsKey1 =
454 new DistributedGroupStore.GroupStoreKeyMapKey(deviceId1, groupKey1);
455 DistributedGroupStore.GroupStoreKeyMapKey key2 =
456 new DistributedGroupStore.GroupStoreKeyMapKey(deviceId2, groupKey1);
457 DistributedGroupStore.GroupStoreKeyMapKey key3 =
458 new DistributedGroupStore.GroupStoreKeyMapKey(deviceId1, groupKey2);
459
460 new EqualsTester()
461 .addEqualityGroup(key1, sameAsKey1)
462 .addEqualityGroup(key2)
463 .addEqualityGroup(key3)
464 .testEquals();
465 }
466
467 @Test
468 public void testEqualsGroupStoreMapKey() {
469 DistributedGroupStore.GroupStoreMapKey key1 =
470 new DistributedGroupStore.GroupStoreMapKey(deviceId1);
471 DistributedGroupStore.GroupStoreMapKey sameAsKey1 =
472 new DistributedGroupStore.GroupStoreMapKey(deviceId1);
473 DistributedGroupStore.GroupStoreMapKey key2 =
474 new DistributedGroupStore.GroupStoreMapKey(deviceId2);
475 DistributedGroupStore.GroupStoreMapKey key3 =
476 new DistributedGroupStore.GroupStoreMapKey(did("dev3"));
477
478 new EqualsTester()
479 .addEqualityGroup(key1, sameAsKey1)
480 .addEqualityGroup(key2)
481 .addEqualityGroup(key3)
482 .testEquals();
483 }
484}