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