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