blob: d7ec3b66027c779603f5218654d6dfb1c4e9fb83 [file] [log] [blame]
Simon Hunt338a3b42016-04-14 09:43:52 -07001/*
2 * Copyright 2016-present 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 */
16
17package org.onosproject.ui.impl.topo.model;
18
Simon Hunt642bc452016-05-04 19:34:45 -070019import org.junit.Before;
Simon Hunt338a3b42016-04-14 09:43:52 -070020import org.junit.Test;
Simon Hunt642bc452016-05-04 19:34:45 -070021import org.onosproject.event.Event;
Simon Hunt338a3b42016-04-14 09:43:52 -070022import org.onosproject.event.EventDispatcher;
Simon Hunt58a0dd02016-05-17 11:54:23 -070023import org.onosproject.net.Device;
Simon Huntc0f20c12016-05-09 09:30:20 -070024import org.onosproject.net.DeviceId;
Simon Hunteae81ee2016-05-19 12:33:22 -070025import org.onosproject.net.Host;
26import org.onosproject.net.HostId;
Simon Hunt58a0dd02016-05-17 11:54:23 -070027import org.onosproject.net.Link;
28import org.onosproject.net.region.Region;
Simon Hunt642bc452016-05-04 19:34:45 -070029import org.onosproject.ui.impl.topo.model.UiModelEvent.Type;
Simon Huntc0f20c12016-05-09 09:30:20 -070030import org.onosproject.ui.model.topo.UiClusterMember;
Simon Hunt58a0dd02016-05-17 11:54:23 -070031import org.onosproject.ui.model.topo.UiDevice;
Simon Huntc13082f2016-08-03 21:20:23 -070032import org.onosproject.ui.model.topo.UiDeviceLink;
Simon Hunt642bc452016-05-04 19:34:45 -070033import org.onosproject.ui.model.topo.UiElement;
Simon Hunteae81ee2016-05-19 12:33:22 -070034import org.onosproject.ui.model.topo.UiHost;
Simon Hunt58a0dd02016-05-17 11:54:23 -070035import org.onosproject.ui.model.topo.UiLinkId;
36import org.onosproject.ui.model.topo.UiRegion;
37
38import java.util.Collection;
39import java.util.Iterator;
Simon Hunt338a3b42016-04-14 09:43:52 -070040
41import static org.junit.Assert.assertEquals;
Simon Huntc0f20c12016-05-09 09:30:20 -070042import static org.junit.Assert.assertFalse;
Simon Hunt642bc452016-05-04 19:34:45 -070043import static org.junit.Assert.assertNotNull;
Simon Hunteae81ee2016-05-19 12:33:22 -070044import static org.junit.Assert.assertNull;
Simon Huntc0f20c12016-05-09 09:30:20 -070045import static org.junit.Assert.assertTrue;
Simon Hunt642bc452016-05-04 19:34:45 -070046import static org.onosproject.cluster.NodeId.nodeId;
Simon Hunteae81ee2016-05-19 12:33:22 -070047import static org.onosproject.net.PortNumber.portNumber;
Simon Hunt58a0dd02016-05-17 11:54:23 -070048import static org.onosproject.ui.model.topo.UiLinkId.uiLinkId;
Simon Hunt338a3b42016-04-14 09:43:52 -070049
50/**
51 * Unit tests for {@link ModelCache}.
52 */
Simon Hunt642bc452016-05-04 19:34:45 -070053public class ModelCacheTest extends AbstractTopoModelTest {
Simon Hunt338a3b42016-04-14 09:43:52 -070054
Simon Hunt642bc452016-05-04 19:34:45 -070055 private class TestEvDisp implements EventDispatcher {
56
57 private Event<Type, UiElement> lastEvent = null;
58 private int eventCount = 0;
59
60 @Override
61 public void post(Event event) {
62 lastEvent = event;
63 eventCount++;
64// print("Event dispatched: %s", event);
65 }
66
67 private void assertEventCount(int exp) {
68 assertEquals("unex event count", exp, eventCount);
69 }
70
71 private void assertLast(Type expEventType, String expId) {
72 assertNotNull("no last event", lastEvent);
73 assertEquals("unex event type", expEventType, lastEvent.type());
74 assertEquals("unex element ID", expId, lastEvent.subject().idAsString());
75 }
76 }
77
Simon Hunt642bc452016-05-04 19:34:45 -070078
79 private final TestEvDisp dispatcher = new TestEvDisp();
Simon Hunt338a3b42016-04-14 09:43:52 -070080
81 private ModelCache cache;
82
Simon Hunt58a0dd02016-05-17 11:54:23 -070083 private void assertContains(String msg, Collection<?> coll, Object... things) {
84 for (Object o : things) {
85 assertTrue(msg, coll.contains(o));
86 }
87 }
88
Simon Hunt642bc452016-05-04 19:34:45 -070089 @Before
90 public void setUp() {
91 cache = new ModelCache(MOCK_SERVICES, dispatcher);
92 }
93
Simon Hunt338a3b42016-04-14 09:43:52 -070094 @Test
95 public void basic() {
Simon Hunt642bc452016-05-04 19:34:45 -070096 title("basic");
Simon Hunt338a3b42016-04-14 09:43:52 -070097 print(cache);
98 assertEquals("unex # members", 0, cache.clusterMemberCount());
99 assertEquals("unex # regions", 0, cache.regionCount());
100 }
101
Simon Hunt642bc452016-05-04 19:34:45 -0700102 @Test
103 public void addAndRemoveClusterMember() {
104 title("addAndRemoveClusterMember");
105 print(cache);
106 assertEquals("unex # members", 0, cache.clusterMemberCount());
107 dispatcher.assertEventCount(0);
108
Simon Huntc0f20c12016-05-09 09:30:20 -0700109 cache.addOrUpdateClusterMember(CNODE_1);
Simon Hunt642bc452016-05-04 19:34:45 -0700110 print(cache);
111 assertEquals("unex # members", 1, cache.clusterMemberCount());
112 dispatcher.assertEventCount(1);
113 dispatcher.assertLast(Type.CLUSTER_MEMBER_ADDED_OR_UPDATED, C1);
114
Simon Huntc0f20c12016-05-09 09:30:20 -0700115 cache.removeClusterMember(CNODE_1);
Simon Hunt642bc452016-05-04 19:34:45 -0700116 print(cache);
117 assertEquals("unex # members", 0, cache.clusterMemberCount());
118 dispatcher.assertEventCount(2);
119 dispatcher.assertLast(Type.CLUSTER_MEMBER_REMOVED, C1);
120 }
121
122 @Test
Simon Hunt58a0dd02016-05-17 11:54:23 -0700123 public void nonExistentClusterMember() {
124 title("nonExistentClusterMember");
125 cache.addOrUpdateClusterMember(CNODE_1);
126 print(cache);
127 assertEquals("unex # members", 1, cache.clusterMemberCount());
128 dispatcher.assertEventCount(1);
129 dispatcher.assertLast(Type.CLUSTER_MEMBER_ADDED_OR_UPDATED, C1);
130
131 cache.removeClusterMember(CNODE_2);
132 assertEquals("unex # members", 1, cache.clusterMemberCount());
133 dispatcher.assertEventCount(1);
134 }
135
136 @Test
Simon Hunt642bc452016-05-04 19:34:45 -0700137 public void createThreeNodeCluster() {
138 title("createThreeNodeCluster");
Simon Huntc0f20c12016-05-09 09:30:20 -0700139 cache.addOrUpdateClusterMember(CNODE_1);
Simon Hunt642bc452016-05-04 19:34:45 -0700140 dispatcher.assertLast(Type.CLUSTER_MEMBER_ADDED_OR_UPDATED, C1);
Simon Huntc0f20c12016-05-09 09:30:20 -0700141 cache.addOrUpdateClusterMember(CNODE_2);
Simon Hunt642bc452016-05-04 19:34:45 -0700142 dispatcher.assertLast(Type.CLUSTER_MEMBER_ADDED_OR_UPDATED, C2);
Simon Huntc0f20c12016-05-09 09:30:20 -0700143 cache.addOrUpdateClusterMember(CNODE_3);
Simon Hunt642bc452016-05-04 19:34:45 -0700144 dispatcher.assertLast(Type.CLUSTER_MEMBER_ADDED_OR_UPDATED, C3);
145 dispatcher.assertEventCount(3);
146 print(cache);
147 }
148
Simon Huntc0f20c12016-05-09 09:30:20 -0700149 @Test
150 public void addNodeThenExamineIt() {
151 title("addNodeThenExamineIt");
152 cache.addOrUpdateClusterMember(CNODE_1);
153 dispatcher.assertLast(Type.CLUSTER_MEMBER_ADDED_OR_UPDATED, C1);
154
155 UiClusterMember member = cache.accessClusterMember(nodeId(C1));
156 print(member);
157 // see AbstractUiImplTest Mock Environment for expected values...
158 assertEquals("wrong id str", C1, member.idAsString());
159 assertEquals("wrong id", nodeId(C1), member.id());
160 assertEquals("wrong dev count", 3, member.deviceCount());
161 assertEquals("not online", true, member.isOnline());
162 assertEquals("not ready", true, member.isReady());
163
164 assertMasterOf(member, DEVID_1, DEVID_2, DEVID_3);
165 assertNotMasterOf(member, DEVID_4, DEVID_6, DEVID_9);
166 }
167
168 private void assertMasterOf(UiClusterMember member, DeviceId... ids) {
169 for (DeviceId id : ids) {
170 assertTrue("not master of " + id, member.masterOf(id));
171 }
172 }
173
174 private void assertNotMasterOf(UiClusterMember member, DeviceId... ids) {
175 for (DeviceId id : ids) {
176 assertFalse("? master of " + id, member.masterOf(id));
177 }
178 }
179
180
181 @Test
182 public void addNodeAndDevices() {
183 title("addNodeAndDevices");
184 cache.addOrUpdateClusterMember(CNODE_1);
Simon Hunt58a0dd02016-05-17 11:54:23 -0700185 dispatcher.assertLast(Type.CLUSTER_MEMBER_ADDED_OR_UPDATED, C1);
Simon Huntc0f20c12016-05-09 09:30:20 -0700186 cache.addOrUpdateDevice(DEV_1);
Simon Hunt58a0dd02016-05-17 11:54:23 -0700187 dispatcher.assertLast(Type.DEVICE_ADDED_OR_UPDATED, D1);
Simon Huntc0f20c12016-05-09 09:30:20 -0700188 cache.addOrUpdateDevice(DEV_2);
Simon Hunt58a0dd02016-05-17 11:54:23 -0700189 dispatcher.assertLast(Type.DEVICE_ADDED_OR_UPDATED, D2);
Simon Huntc0f20c12016-05-09 09:30:20 -0700190 cache.addOrUpdateDevice(DEV_3);
Simon Hunt58a0dd02016-05-17 11:54:23 -0700191 dispatcher.assertLast(Type.DEVICE_ADDED_OR_UPDATED, D3);
192 dispatcher.assertEventCount(4);
Simon Huntc0f20c12016-05-09 09:30:20 -0700193 print(cache);
Simon Hunt58a0dd02016-05-17 11:54:23 -0700194
195 assertEquals("unex # nodes", 1, cache.clusterMemberCount());
196 assertEquals("unex # devices", 3, cache.deviceCount());
197 cache.removeDevice(DEV_4);
198 assertEquals("unex # devices", 3, cache.deviceCount());
199 dispatcher.assertEventCount(4);
200
201 cache.removeDevice(DEV_2);
202 dispatcher.assertLast(Type.DEVICE_REMOVED, D2);
203 dispatcher.assertEventCount(5);
204
205 // check out details of device
206 UiDevice dev = cache.accessDevice(DEVID_1);
207 assertEquals("wrong id", D1, dev.idAsString());
208 assertEquals("wrong region", R1, dev.regionId().toString());
209 Device d = dev.backingDevice();
210 assertEquals("wrong serial", SERIAL, d.serialNumber());
Simon Huntc0f20c12016-05-09 09:30:20 -0700211 }
212
213 @Test
214 public void addRegions() {
215 title("addRegions");
216 cache.addOrUpdateRegion(REGION_1);
Simon Hunt58a0dd02016-05-17 11:54:23 -0700217 dispatcher.assertLast(Type.REGION_ADDED_OR_UPDATED, R1);
218 dispatcher.assertEventCount(1);
219 assertEquals("unex # regions", 1, cache.regionCount());
220
221 cache.addOrUpdateRegion(REGION_2);
222 dispatcher.assertLast(Type.REGION_ADDED_OR_UPDATED, R2);
223 dispatcher.assertEventCount(2);
224 assertEquals("unex # regions", 2, cache.regionCount());
225
Simon Huntc0f20c12016-05-09 09:30:20 -0700226 print(cache);
Simon Hunt58a0dd02016-05-17 11:54:23 -0700227
228 cache.removeRegion(REGION_3);
229 dispatcher.assertEventCount(2);
230 assertEquals("unex # regions", 2, cache.regionCount());
231
232 cache.removeRegion(REGION_1);
233 dispatcher.assertLast(Type.REGION_REMOVED, R1);
234 dispatcher.assertEventCount(3);
235 assertEquals("unex # regions", 1, cache.regionCount());
236
237 print(cache);
238
239 UiRegion region = cache.accessRegion(REGION_2.id());
240 assertEquals("wrong id", REGION_2.id(), region.id());
241 assertEquals("unex # device IDs", 3, region.deviceIds().size());
242 assertContains("missing ID", region.deviceIds(), DEVID_4, DEVID_5, DEVID_6);
243 Region r = region.backingRegion();
244 print(r);
245 assertEquals("wrong region name", "Region-R2", r.name());
246 }
247
248 private static final String[] LINKS_2_7 = {D2, "27", D7, "72"};
249
250 @Test
251 public void addLinks() {
252 title("addLinks");
253
254 Iterator<Link> iter = makeLinkPair(LINKS_2_7).iterator();
255 Link link1 = iter.next();
256 Link link2 = iter.next();
257 print(link1);
258 print(link2);
259
260 UiLinkId idA2B = uiLinkId(link1);
261 UiLinkId idB2A = uiLinkId(link2);
262 // remember, link IDs are canonicalized
263 assertEquals("not same link ID", idA2B, idB2A);
264
265 // we've established that the ID is the same for both
266 UiLinkId linkId = idA2B;
267
Simon Huntc13082f2016-08-03 21:20:23 -0700268 cache.addOrUpdateDeviceLink(link1);
Simon Hunt58a0dd02016-05-17 11:54:23 -0700269 dispatcher.assertLast(Type.LINK_ADDED_OR_UPDATED, linkId.toString());
270 dispatcher.assertEventCount(1);
Simon Huntc13082f2016-08-03 21:20:23 -0700271 assertEquals("unex # links", 1, cache.deviceLinkCount());
Simon Hunt58a0dd02016-05-17 11:54:23 -0700272
Simon Huntc13082f2016-08-03 21:20:23 -0700273 UiDeviceLink link = cache.accessDeviceLink(linkId);
Simon Hunt58a0dd02016-05-17 11:54:23 -0700274 assertEquals("dev A not d2", DEVID_2, link.deviceA());
275 assertEquals("dev B not d7", DEVID_7, link.deviceB());
276 assertEquals("wrong backing link A-B", link1, link.linkAtoB());
277 assertEquals("backing link B-A?", null, link.linkBtoA());
278
Simon Huntc13082f2016-08-03 21:20:23 -0700279 cache.addOrUpdateDeviceLink(link2);
Simon Hunt58a0dd02016-05-17 11:54:23 -0700280 dispatcher.assertLast(Type.LINK_ADDED_OR_UPDATED, linkId.toString());
281 dispatcher.assertEventCount(2);
282 // NOTE: yes! expect 1 UiLink
Simon Huntc13082f2016-08-03 21:20:23 -0700283 assertEquals("unex # links", 1, cache.deviceLinkCount());
Simon Hunt58a0dd02016-05-17 11:54:23 -0700284
Simon Huntc13082f2016-08-03 21:20:23 -0700285 link = cache.accessDeviceLink(linkId);
Simon Hunt58a0dd02016-05-17 11:54:23 -0700286 assertEquals("dev A not d2", DEVID_2, link.deviceA());
287 assertEquals("dev B not d7", DEVID_7, link.deviceB());
288 assertEquals("wrong backing link A-B", link1, link.linkAtoB());
289 assertEquals("wrong backing link B-A", link2, link.linkBtoA());
290
291 // now remove links one at a time
Simon Huntc13082f2016-08-03 21:20:23 -0700292 cache.removeDeviceLink(link1);
Simon Hunt58a0dd02016-05-17 11:54:23 -0700293 // NOTE: yes! ADD_OR_UPDATE, since the link was updated
294 dispatcher.assertLast(Type.LINK_ADDED_OR_UPDATED, linkId.toString());
295 dispatcher.assertEventCount(3);
296 // NOTE: yes! expect 1 UiLink (still)
Simon Huntc13082f2016-08-03 21:20:23 -0700297 assertEquals("unex # links", 1, cache.deviceLinkCount());
Simon Hunt58a0dd02016-05-17 11:54:23 -0700298
Simon Huntc13082f2016-08-03 21:20:23 -0700299 link = cache.accessDeviceLink(linkId);
Simon Hunt58a0dd02016-05-17 11:54:23 -0700300 assertEquals("dev A not d2", DEVID_2, link.deviceA());
301 assertEquals("dev B not d7", DEVID_7, link.deviceB());
302 assertEquals("backing link A-B?", null, link.linkAtoB());
303 assertEquals("wrong backing link B-A", link2, link.linkBtoA());
304
305 // remove final link
Simon Huntc13082f2016-08-03 21:20:23 -0700306 cache.removeDeviceLink(link2);
Simon Hunt58a0dd02016-05-17 11:54:23 -0700307 dispatcher.assertLast(Type.LINK_REMOVED, linkId.toString());
308 dispatcher.assertEventCount(4);
309 // NOTE: finally link should be removed from cache
Simon Huntc13082f2016-08-03 21:20:23 -0700310 assertEquals("unex # links", 0, cache.deviceLinkCount());
Simon Huntc0f20c12016-05-09 09:30:20 -0700311 }
312
Simon Hunteae81ee2016-05-19 12:33:22 -0700313 private void assertHostLinkCounts(int nHosts, int nLinks) {
314 assertEquals("unex # hosts", nHosts, cache.hostCount());
Simon Huntc13082f2016-08-03 21:20:23 -0700315 assertEquals("unex # links", nLinks, cache.edgeLinkCount());
Simon Hunteae81ee2016-05-19 12:33:22 -0700316 }
317
318 private void assertLocation(HostId hid, DeviceId expDev, int expPort) {
319 UiHost h = cache.accessHost(hid);
320 assertEquals("unex device", expDev, h.locationDevice());
321 assertEquals("unex port", portNumber(expPort), h.locationPort());
322 }
323
324 @Test
325 public void addHosts() {
326 title("addHosts");
327
328 assertHostLinkCounts(0, 0);
329 Host hostA = createHost(DEV_1, 101, "a");
330 Host hostB = createHost(DEV_1, 102, "b");
331
332 // add a host
333 cache.addOrUpdateHost(hostA);
334 dispatcher.assertLast(Type.HOST_ADDED_OR_UPDATED, hostA.id().toString());
335 dispatcher.assertEventCount(1);
336 assertHostLinkCounts(1, 1);
337 assertLocation(hostA.id(), DEVID_1, 101);
338
339 // add a second host
340 cache.addOrUpdateHost(hostB);
341 dispatcher.assertLast(Type.HOST_ADDED_OR_UPDATED, hostB.id().toString());
342 dispatcher.assertEventCount(2);
343 assertHostLinkCounts(2, 2);
344 assertLocation(hostB.id(), DEVID_1, 102);
345
346 // update the first host
347 cache.addOrUpdateHost(hostA);
348 dispatcher.assertLast(Type.HOST_ADDED_OR_UPDATED, hostA.id().toString());
349 dispatcher.assertEventCount(3);
350 assertHostLinkCounts(2, 2);
351 assertLocation(hostA.id(), DEVID_1, 101);
352
353 print(cache.dumpString());
354
355 // remove the second host
356 cache.removeHost(hostB);
357 dispatcher.assertLast(Type.HOST_REMOVED, hostB.id().toString());
358 dispatcher.assertEventCount(4);
359 assertHostLinkCounts(1, 1);
360 assertNull("still host B?", cache.accessHost(hostB.id()));
361
362 print(cache.dumpString());
363
364 // first, verify where host A is currently residing
365 assertLocation(hostA.id(), DEVID_1, 101);
366
367 // now let's move hostA to a different port
368 Host movedHost = createHost(DEV_1, 200, "a");
369 print(hostA);
370 print(movedHost);
371
372 cache.moveHost(movedHost, hostA);
373 dispatcher.assertLast(Type.HOST_MOVED, hostA.id().toString());
374 dispatcher.assertEventCount(5);
375 assertHostLinkCounts(1, 1);
376
377 assertLocation(hostA.id(), DEVID_1, 200);
378
379 print(cache.dumpString());
380
381 // finally, let's move the host to a different device and port
382 Host movedAgain = createHost(DEV_8, 800, "a");
383
384 cache.moveHost(movedAgain, movedHost);
385 dispatcher.assertLast(Type.HOST_MOVED, hostA.id().toString());
386 dispatcher.assertEventCount(6);
387 assertHostLinkCounts(1, 1);
388
389 assertLocation(hostA.id(), DEVID_8, 800);
390
391 print(cache.dumpString());
392 }
393
394
Simon Huntc0f20c12016-05-09 09:30:20 -0700395 @Test
396 public void load() {
397 title("load");
398 cache.load();
Simon Hunt58a0dd02016-05-17 11:54:23 -0700399 print(cache.dumpString());
400
401 // See mock service bundle for expected values (AbstractTopoModelTest)
402 assertEquals("unex # cnodes", 3, cache.clusterMemberCount());
403 assertEquals("unex # regions", 3, cache.regionCount());
404 assertEquals("unex # devices", 9, cache.deviceCount());
405 assertEquals("unex # hosts", 18, cache.hostCount());
Simon Huntc13082f2016-08-03 21:20:23 -0700406 assertEquals("unex # device-links", 8, cache.deviceLinkCount());
407 assertEquals("unex # edge-links", 18, cache.edgeLinkCount());
408 assertEquals("unex # synth-links", 0, cache.synthLinkCount());
Simon Huntc0f20c12016-05-09 09:30:20 -0700409 }
Simon Hunt338a3b42016-04-14 09:43:52 -0700410}