blob: 3915d8ce4c96a7b74383a3dff6a5face5472d4c5 [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;
63import static org.onosproject.net.NetTestTools.APP_ID;
64import static org.onosproject.net.NetTestTools.did;
Jayasree Ghosh2d459852016-07-02 19:06:52 +053065import static org.onosproject.net.group.GroupDescription.Type.*;
66import static org.onosproject.net.group.GroupStore.UpdateType.*;
Ray Milkeyb3c5ce22015-08-10 09:07:36 -070067/**
68 * Distributed group store test.
69 */
70public class DistributedGroupStoreTest {
71
72 DeviceId deviceId1 = did("dev1");
73 DeviceId deviceId2 = did("dev2");
74 GroupId groupId1 = new DefaultGroupId(1);
75 GroupId groupId2 = new DefaultGroupId(2);
Charles Chan0c7c43b2016-01-14 17:39:20 -080076 GroupId groupId3 = new DefaultGroupId(3);
Ray Milkeyb3c5ce22015-08-10 09:07:36 -070077 GroupKey groupKey1 = new DefaultGroupKey("abc".getBytes());
78 GroupKey groupKey2 = new DefaultGroupKey("def".getBytes());
Charles Chan0c7c43b2016-01-14 17:39:20 -080079 GroupKey groupKey3 = new DefaultGroupKey("ghi".getBytes());
Ray Milkeyb3c5ce22015-08-10 09:07:36 -070080
81 TrafficTreatment treatment =
82 DefaultTrafficTreatment.emptyTreatment();
83 GroupBucket selectGroupBucket =
84 DefaultGroupBucket.createSelectGroupBucket(treatment);
85 GroupBucket failoverGroupBucket =
86 DefaultGroupBucket.createFailoverGroupBucket(treatment,
87 PortNumber.IN_PORT, groupId1);
88
89 GroupBuckets buckets = new GroupBuckets(ImmutableList.of(selectGroupBucket));
90 GroupDescription groupDescription1 = new DefaultGroupDescription(
91 deviceId1,
Jayasree Ghosh2d459852016-07-02 19:06:52 +053092 ALL,
Ray Milkeyb3c5ce22015-08-10 09:07:36 -070093 buckets,
94 groupKey1,
95 groupId1.id(),
96 APP_ID);
97 GroupDescription groupDescription2 = new DefaultGroupDescription(
98 deviceId2,
Jayasree Ghosh2d459852016-07-02 19:06:52 +053099 INDIRECT,
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700100 buckets,
101 groupKey2,
102 groupId2.id(),
103 APP_ID);
Charles Chan0c7c43b2016-01-14 17:39:20 -0800104 GroupDescription groupDescription3 = new DefaultGroupDescription(
105 deviceId2,
Jayasree Ghosh2d459852016-07-02 19:06:52 +0530106 INDIRECT,
Charles Chan0c7c43b2016-01-14 17:39:20 -0800107 buckets,
108 groupKey3,
109 groupId3.id(),
110 APP_ID);
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700111
112 DistributedGroupStore groupStoreImpl;
113 GroupStore groupStore;
Madan Jampani0b847532016-03-03 13:44:15 -0800114 ConsistentMap auditPendingReqQueue;
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700115
116 static class MasterOfAll extends MastershipServiceAdapter {
117 @Override
118 public MastershipRole getLocalRole(DeviceId deviceId) {
119 return MastershipRole.MASTER;
120 }
Charles Chanf4838a72015-12-07 18:13:45 -0800121
122 @Override
123 public NodeId getMasterFor(DeviceId deviceId) {
124 return new NodeId("foo");
125 }
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700126 }
127
128 @Before
129 public void setUp() throws Exception {
130 groupStoreImpl = new DistributedGroupStore();
131 groupStoreImpl.storageService = new TestStorageService();
132 groupStoreImpl.clusterCommunicator = new ClusterCommunicationServiceAdapter();
133 groupStoreImpl.mastershipService = new MasterOfAll();
alshabibb0285992016-03-28 23:30:37 -0700134 groupStoreImpl.cfgService = new ComponentConfigAdapter();
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700135 groupStoreImpl.activate();
136 groupStore = groupStoreImpl;
137 auditPendingReqQueue =
138 TestUtils.getField(groupStoreImpl, "auditPendingReqQueue");
139 }
140
141 @After
142 public void tearDown() throws Exception {
143 groupStoreImpl.deactivate();
144 }
145
146 /**
147 * Tests the initial state of the store.
148 */
149 @Test
150 public void testEmptyStore() {
151 assertThat(groupStore.getGroupCount(deviceId1), is(0));
152 assertThat(groupStore.getGroup(deviceId1, groupId1), nullValue());
153 assertThat(groupStore.getGroup(deviceId1, groupKey1), nullValue());
154 }
155
156 /**
157 * Tests adding a pending group.
158 */
159 @Test
160 public void testAddPendingGroup() throws Exception {
161 // Make sure the pending list starts out empty
162 assertThat(auditPendingReqQueue.size(), is(0));
163
164 // Add a new pending group. Make sure that the store remains empty
165 groupStore.storeGroupDescription(groupDescription1);
166 assertThat(groupStore.getGroupCount(deviceId1), is(0));
167 assertThat(groupStore.getGroup(deviceId1, groupId1), nullValue());
168 assertThat(groupStore.getGroup(deviceId1, groupKey1), nullValue());
169
170 // Make sure the group is pending
171 assertThat(auditPendingReqQueue.size(), is(1));
172
173 groupStore.deviceInitialAuditCompleted(deviceId1, true);
174
175 // Make sure the group isn't pending anymore
176 assertThat(auditPendingReqQueue.size(), is(0));
177 }
178
179
180 /**
181 * Tests adding and removing a group.
182 */
183 @Test
184 public void testAddRemoveGroup() throws Exception {
185 groupStore.deviceInitialAuditCompleted(deviceId1, true);
186 assertThat(groupStore.deviceInitialAuditStatus(deviceId1), is(true));
187
188 // Make sure the pending list starts out empty
189 assertThat(auditPendingReqQueue.size(), is(0));
190
191 groupStore.storeGroupDescription(groupDescription1);
192 assertThat(groupStore.getGroupCount(deviceId1), is(1));
193 assertThat(groupStore.getGroup(deviceId1, groupId1), notNullValue());
194 assertThat(groupStore.getGroup(deviceId1, groupKey1), notNullValue());
195
196 // Make sure that nothing is pending
197 assertThat(auditPendingReqQueue.size(), is(0));
198
199 Group groupById = groupStore.getGroup(deviceId1, groupId1);
200 Group groupByKey = groupStore.getGroup(deviceId1, groupKey1);
201 assertThat(groupById, notNullValue());
202 assertThat(groupByKey, notNullValue());
203 assertThat(groupById, is(groupByKey));
204 assertThat(groupById.deviceId(), is(did("dev1")));
205
206 groupStore.removeGroupEntry(groupById);
207
208 assertThat(groupStore.getGroupCount(deviceId1), is(0));
209 assertThat(groupStore.getGroup(deviceId1, groupId1), nullValue());
210 assertThat(groupStore.getGroup(deviceId1, groupKey1), nullValue());
211
212 // Make sure that nothing is pending
213 assertThat(auditPendingReqQueue.size(), is(0));
214 }
215
216 /**
Charles Chan0c7c43b2016-01-14 17:39:20 -0800217 * Tests removing all groups on the given device.
218 */
219 @Test
220 public void testRemoveGroupOnDevice() throws Exception {
221 groupStore.deviceInitialAuditCompleted(deviceId1, true);
222 assertThat(groupStore.deviceInitialAuditStatus(deviceId1), is(true));
223 groupStore.deviceInitialAuditCompleted(deviceId2, true);
224 assertThat(groupStore.deviceInitialAuditStatus(deviceId2), is(true));
225
226 // Make sure the pending list starts out empty
227 assertThat(auditPendingReqQueue.size(), is(0));
228
229 groupStore.storeGroupDescription(groupDescription1);
230 groupStore.storeGroupDescription(groupDescription2);
231 groupStore.storeGroupDescription(groupDescription3);
232 assertThat(groupStore.getGroupCount(deviceId1), is(1));
233 assertThat(groupStore.getGroupCount(deviceId2), is(2));
234
235 groupStore.purgeGroupEntry(deviceId2);
236 assertThat(groupStore.getGroupCount(deviceId1), is(1));
237 assertThat(groupStore.getGroupCount(deviceId2), is(0));
238 }
239
240 /**
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700241 * Tests adding and removing a group.
242 */
243 @Test
244 public void testRemoveGroupDescription() throws Exception {
245 groupStore.deviceInitialAuditCompleted(deviceId1, true);
246
247 groupStore.storeGroupDescription(groupDescription1);
248
249 groupStore.deleteGroupDescription(deviceId1, groupKey1);
250
251 // Group should still be there, marked for removal
252 assertThat(groupStore.getGroupCount(deviceId1), is(1));
253 Group queriedGroup = groupStore.getGroup(deviceId1, groupId1);
254 assertThat(queriedGroup.state(), is(Group.GroupState.PENDING_DELETE));
255
256 }
257
258 /**
259 * Tests pushing group metrics.
260 */
261 @Test
262 public void testPushGroupMetrics() {
263 groupStore.deviceInitialAuditCompleted(deviceId1, true);
264 groupStore.deviceInitialAuditCompleted(deviceId2, true);
265
266 GroupDescription groupDescription3 = new DefaultGroupDescription(
267 deviceId1,
Jayasree Ghosh2d459852016-07-02 19:06:52 +0530268 SELECT,
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700269 buckets,
270 new DefaultGroupKey("aaa".getBytes()),
271 null,
272 APP_ID);
273
274 groupStore.storeGroupDescription(groupDescription1);
275 groupStore.storeGroupDescription(groupDescription2);
276 groupStore.storeGroupDescription(groupDescription3);
277 Group group1 = groupStore.getGroup(deviceId1, groupId1);
278
279 assertThat(group1, instanceOf(DefaultGroup.class));
280 DefaultGroup defaultGroup1 = (DefaultGroup) group1;
281 defaultGroup1.setPackets(55L);
282 defaultGroup1.setBytes(66L);
283 groupStore.pushGroupMetrics(deviceId1, ImmutableList.of(group1));
284
285 // Make sure the group was updated.
286
287 Group requeryGroup1 = groupStore.getGroup(deviceId1, groupId1);
288 assertThat(requeryGroup1.packets(), is(55L));
289 assertThat(requeryGroup1.bytes(), is(66L));
290
291 }
292
293 class TestDelegate implements GroupStoreDelegate {
294 private List<GroupEvent> eventsSeen = new LinkedList<>();
295 @Override
296 public void notify(GroupEvent event) {
297 eventsSeen.add(event);
298 }
299
300 public List<GroupEvent> eventsSeen() {
301 return eventsSeen;
302 }
303
304 public void resetEvents() {
305 eventsSeen.clear();
306 }
307 }
308
309 /**
310 * Tests group operation failed interface.
311 */
312 @Test
313 public void testGroupOperationFailed() {
314 TestDelegate delegate = new TestDelegate();
315 groupStore.setDelegate(delegate);
316 groupStore.deviceInitialAuditCompleted(deviceId1, true);
317 groupStore.deviceInitialAuditCompleted(deviceId2, true);
318
319 groupStore.storeGroupDescription(groupDescription1);
320 groupStore.storeGroupDescription(groupDescription2);
321
322 List<GroupEvent> eventsAfterAdds = delegate.eventsSeen();
323 assertThat(eventsAfterAdds, hasSize(2));
324 eventsAfterAdds.stream().forEach(event -> assertThat(event.type(), is(GroupEvent.Type.GROUP_ADD_REQUESTED)));
325 delegate.resetEvents();
326
327 GroupOperation opAdd =
328 GroupOperation.createAddGroupOperation(groupId1,
Jayasree Ghosh2d459852016-07-02 19:06:52 +0530329 INDIRECT,
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700330 buckets);
331 groupStore.groupOperationFailed(deviceId1, opAdd);
332
333 List<GroupEvent> eventsAfterAddFailed = delegate.eventsSeen();
334 assertThat(eventsAfterAddFailed, hasSize(2));
335 assertThat(eventsAfterAddFailed.get(0).type(),
336 is(GroupEvent.Type.GROUP_ADD_FAILED));
337 assertThat(eventsAfterAddFailed.get(1).type(),
338 is(GroupEvent.Type.GROUP_REMOVED));
339 delegate.resetEvents();
340
341 GroupOperation opModify =
342 GroupOperation.createModifyGroupOperation(groupId2,
Jayasree Ghosh2d459852016-07-02 19:06:52 +0530343 INDIRECT,
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700344 buckets);
345 groupStore.groupOperationFailed(deviceId2, opModify);
346 List<GroupEvent> eventsAfterModifyFailed = delegate.eventsSeen();
347 assertThat(eventsAfterModifyFailed, hasSize(1));
348 assertThat(eventsAfterModifyFailed.get(0).type(),
349 is(GroupEvent.Type.GROUP_UPDATE_FAILED));
350 delegate.resetEvents();
351
352 GroupOperation opDelete =
353 GroupOperation.createDeleteGroupOperation(groupId2,
Jayasree Ghosh2d459852016-07-02 19:06:52 +0530354 INDIRECT);
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700355 groupStore.groupOperationFailed(deviceId2, opDelete);
356 List<GroupEvent> eventsAfterDeleteFailed = delegate.eventsSeen();
357 assertThat(eventsAfterDeleteFailed, hasSize(1));
358 assertThat(eventsAfterDeleteFailed.get(0).type(),
359 is(GroupEvent.Type.GROUP_REMOVE_FAILED));
360 delegate.resetEvents();
361 }
362
363 /**
364 * Tests extraneous group operations.
365 */
366 @Test
367 public void testExtraneousOperations() {
368 ArrayList<Group> extraneous;
369 groupStore.deviceInitialAuditCompleted(deviceId1, true);
370
371 groupStore.storeGroupDescription(groupDescription1);
372 Group group1 = groupStore.getGroup(deviceId1, groupId1);
373
374 extraneous = Lists.newArrayList(groupStore.getExtraneousGroups(deviceId1));
375 assertThat(extraneous, hasSize(0));
376
377 groupStore.addOrUpdateExtraneousGroupEntry(group1);
378 extraneous = Lists.newArrayList(groupStore.getExtraneousGroups(deviceId1));
379 assertThat(extraneous, hasSize(1));
380
381 groupStore.removeExtraneousGroupEntry(group1);
382 extraneous = Lists.newArrayList(groupStore.getExtraneousGroups(deviceId1));
383 assertThat(extraneous, hasSize(0));
384 }
385
386 /**
387 * Tests updating of group descriptions.
388 */
389 @Test
390 public void testUpdateGroupDescription() {
391
392 GroupBuckets buckets =
393 new GroupBuckets(ImmutableList.of(failoverGroupBucket));
394
395 groupStore.deviceInitialAuditCompleted(deviceId1, true);
396 groupStore.storeGroupDescription(groupDescription1);
397
398 GroupKey newKey = new DefaultGroupKey("123".getBytes());
399 groupStore.updateGroupDescription(deviceId1,
400 groupKey1,
Jayasree Ghosh2d459852016-07-02 19:06:52 +0530401 ADD,
Ray Milkeyb3c5ce22015-08-10 09:07:36 -0700402 buckets,
403 newKey);
404 Group group1 = groupStore.getGroup(deviceId1, groupId1);
405 assertThat(group1.appCookie(), is(newKey));
406 assertThat(group1.buckets().buckets(), hasSize(2));
407 }
408
409 @Test
410 public void testEqualsGroupStoreIdMapKey() {
411 DistributedGroupStore.GroupStoreIdMapKey key1 =
412 new DistributedGroupStore.GroupStoreIdMapKey(deviceId1, groupId1);
413 DistributedGroupStore.GroupStoreIdMapKey sameAsKey1 =
414 new DistributedGroupStore.GroupStoreIdMapKey(deviceId1, groupId1);
415 DistributedGroupStore.GroupStoreIdMapKey key2 =
416 new DistributedGroupStore.GroupStoreIdMapKey(deviceId2, groupId1);
417 DistributedGroupStore.GroupStoreIdMapKey key3 =
418 new DistributedGroupStore.GroupStoreIdMapKey(deviceId1, groupId2);
419
420 new EqualsTester()
421 .addEqualityGroup(key1, sameAsKey1)
422 .addEqualityGroup(key2)
423 .addEqualityGroup(key3)
424 .testEquals();
425 }
426
427 @Test
428 public void testEqualsGroupStoreKeyMapKey() {
429 DistributedGroupStore.GroupStoreKeyMapKey key1 =
430 new DistributedGroupStore.GroupStoreKeyMapKey(deviceId1, groupKey1);
431 DistributedGroupStore.GroupStoreKeyMapKey sameAsKey1 =
432 new DistributedGroupStore.GroupStoreKeyMapKey(deviceId1, groupKey1);
433 DistributedGroupStore.GroupStoreKeyMapKey key2 =
434 new DistributedGroupStore.GroupStoreKeyMapKey(deviceId2, groupKey1);
435 DistributedGroupStore.GroupStoreKeyMapKey key3 =
436 new DistributedGroupStore.GroupStoreKeyMapKey(deviceId1, groupKey2);
437
438 new EqualsTester()
439 .addEqualityGroup(key1, sameAsKey1)
440 .addEqualityGroup(key2)
441 .addEqualityGroup(key3)
442 .testEquals();
443 }
444
445 @Test
446 public void testEqualsGroupStoreMapKey() {
447 DistributedGroupStore.GroupStoreMapKey key1 =
448 new DistributedGroupStore.GroupStoreMapKey(deviceId1);
449 DistributedGroupStore.GroupStoreMapKey sameAsKey1 =
450 new DistributedGroupStore.GroupStoreMapKey(deviceId1);
451 DistributedGroupStore.GroupStoreMapKey key2 =
452 new DistributedGroupStore.GroupStoreMapKey(deviceId2);
453 DistributedGroupStore.GroupStoreMapKey key3 =
454 new DistributedGroupStore.GroupStoreMapKey(did("dev3"));
455
456 new EqualsTester()
457 .addEqualityGroup(key1, sameAsKey1)
458 .addEqualityGroup(key2)
459 .addEqualityGroup(key3)
460 .testEquals();
461 }
462}