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