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