Committed by
Gerrit Code Review
Included connect point port number in definition of UiLinkId.
Added dumpString() to ModelCache / UiTopology. Added more unit tests for ModelCache. Change-Id: I842bb418b25cc901bd12bc28c6660c836f7235bc
Showing
9 changed files
with
517 additions
and
87 deletions
... | @@ -87,6 +87,16 @@ public class UiDevice extends UiNode { | ... | @@ -87,6 +87,16 @@ public class UiDevice extends UiNode { |
87 | } | 87 | } |
88 | 88 | ||
89 | /** | 89 | /** |
90 | + * Returns the identifier of the region to which this device belongs. | ||
91 | + * This will be null if the device does not belong to any region. | ||
92 | + * | ||
93 | + * @return region identity | ||
94 | + */ | ||
95 | + public RegionId regionId() { | ||
96 | + return regionId; | ||
97 | + } | ||
98 | + | ||
99 | + /** | ||
90 | * Returns the UI region to which this device belongs. | 100 | * Returns the UI region to which this device belongs. |
91 | * | 101 | * |
92 | * @return the UI region | 102 | * @return the UI region | ... | ... |
... | @@ -177,4 +177,42 @@ public class UiLink extends UiElement { | ... | @@ -177,4 +177,42 @@ public class UiLink extends UiElement { |
177 | edgeLink = elink; | 177 | edgeLink = elink; |
178 | edgeDevice = elink.hostLocation().deviceId(); | 178 | edgeDevice = elink.hostLocation().deviceId(); |
179 | } | 179 | } |
180 | + | ||
181 | + | ||
182 | + /** | ||
183 | + * Returns the identity of device A. | ||
184 | + * | ||
185 | + * @return device A ID | ||
186 | + */ | ||
187 | + public DeviceId deviceA() { | ||
188 | + return deviceA; | ||
189 | + } | ||
190 | + | ||
191 | + /** | ||
192 | + * Returns the identity of device B. | ||
193 | + * | ||
194 | + * @return device B ID | ||
195 | + */ | ||
196 | + public DeviceId deviceB() { | ||
197 | + return deviceB; | ||
198 | + } | ||
199 | + | ||
200 | + /** | ||
201 | + * Returns backing link from A to B. | ||
202 | + * | ||
203 | + * @return backing link A to B | ||
204 | + */ | ||
205 | + public Link linkAtoB() { | ||
206 | + return linkAtoB; | ||
207 | + } | ||
208 | + | ||
209 | + /** | ||
210 | + * Returns backing link from B to A. | ||
211 | + * | ||
212 | + * @return backing link B to A | ||
213 | + */ | ||
214 | + public Link linkBtoA() { | ||
215 | + return linkBtoA; | ||
216 | + } | ||
217 | + | ||
180 | } | 218 | } | ... | ... |
... | @@ -19,6 +19,7 @@ package org.onosproject.ui.model.topo; | ... | @@ -19,6 +19,7 @@ package org.onosproject.ui.model.topo; |
19 | import org.onosproject.net.ConnectPoint; | 19 | import org.onosproject.net.ConnectPoint; |
20 | import org.onosproject.net.ElementId; | 20 | import org.onosproject.net.ElementId; |
21 | import org.onosproject.net.Link; | 21 | import org.onosproject.net.Link; |
22 | +import org.onosproject.net.PortNumber; | ||
22 | 23 | ||
23 | /** | 24 | /** |
24 | * A canonical representation of an identifier for {@link UiLink}s. | 25 | * A canonical representation of an identifier for {@link UiLink}s. |
... | @@ -33,10 +34,14 @@ public final class UiLinkId { | ... | @@ -33,10 +34,14 @@ public final class UiLinkId { |
33 | B_TO_A | 34 | B_TO_A |
34 | } | 35 | } |
35 | 36 | ||
36 | - private static final String ID_DELIMITER = "~"; | 37 | + private static final String CP_DELIMITER = "~"; |
38 | + private static final String ID_PORT_DELIMITER = "/"; | ||
37 | 39 | ||
38 | private final ElementId idA; | 40 | private final ElementId idA; |
41 | + private final PortNumber portA; | ||
39 | private final ElementId idB; | 42 | private final ElementId idB; |
43 | + private final PortNumber portB; | ||
44 | + | ||
40 | private final String idStr; | 45 | private final String idStr; |
41 | 46 | ||
42 | /** | 47 | /** |
... | @@ -46,13 +51,18 @@ public final class UiLinkId { | ... | @@ -46,13 +51,18 @@ public final class UiLinkId { |
46 | * underlying link. | 51 | * underlying link. |
47 | * | 52 | * |
48 | * @param a first element ID | 53 | * @param a first element ID |
54 | + * @param pa first element port | ||
49 | * @param b second element ID | 55 | * @param b second element ID |
56 | + * @param pb second element port | ||
50 | */ | 57 | */ |
51 | - private UiLinkId(ElementId a, ElementId b) { | 58 | + private UiLinkId(ElementId a, PortNumber pa, ElementId b, PortNumber pb) { |
52 | idA = a; | 59 | idA = a; |
60 | + portA = pa; | ||
53 | idB = b; | 61 | idB = b; |
62 | + portB = pb; | ||
54 | 63 | ||
55 | - idStr = a.toString() + ID_DELIMITER + b.toString(); | 64 | + idStr = a + ID_PORT_DELIMITER + pa + CP_DELIMITER + |
65 | + b + ID_PORT_DELIMITER + pb; | ||
56 | } | 66 | } |
57 | 67 | ||
58 | @Override | 68 | @Override |
... | @@ -70,6 +80,15 @@ public final class UiLinkId { | ... | @@ -70,6 +80,15 @@ public final class UiLinkId { |
70 | } | 80 | } |
71 | 81 | ||
72 | /** | 82 | /** |
83 | + * Returns the port of the first element. | ||
84 | + * | ||
85 | + * @return first element port | ||
86 | + */ | ||
87 | + public PortNumber portA() { | ||
88 | + return portA; | ||
89 | + } | ||
90 | + | ||
91 | + /** | ||
73 | * Returns the identifier of the second element. | 92 | * Returns the identifier of the second element. |
74 | * | 93 | * |
75 | * @return second element identity | 94 | * @return second element identity |
... | @@ -78,6 +97,15 @@ public final class UiLinkId { | ... | @@ -78,6 +97,15 @@ public final class UiLinkId { |
78 | return idB; | 97 | return idB; |
79 | } | 98 | } |
80 | 99 | ||
100 | + /** | ||
101 | + * Returns the port of the second element. | ||
102 | + * | ||
103 | + * @return second element port | ||
104 | + */ | ||
105 | + public PortNumber portB() { | ||
106 | + return portB; | ||
107 | + } | ||
108 | + | ||
81 | @Override | 109 | @Override |
82 | public boolean equals(Object o) { | 110 | public boolean equals(Object o) { |
83 | if (this == o) { | 111 | if (this == o) { |
... | @@ -127,13 +155,10 @@ public final class UiLinkId { | ... | @@ -127,13 +155,10 @@ public final class UiLinkId { |
127 | 155 | ||
128 | ElementId srcId = src.elementId(); | 156 | ElementId srcId = src.elementId(); |
129 | ElementId dstId = dst.elementId(); | 157 | ElementId dstId = dst.elementId(); |
130 | - if (srcId == null || dstId == null) { | ||
131 | - throw new NullPointerException("null element ID in connect point: " + link); | ||
132 | - } | ||
133 | 158 | ||
134 | // canonicalize | 159 | // canonicalize |
135 | int comp = srcId.toString().compareTo(dstId.toString()); | 160 | int comp = srcId.toString().compareTo(dstId.toString()); |
136 | - return comp <= 0 ? new UiLinkId(srcId, dstId) | 161 | + return comp <= 0 ? new UiLinkId(srcId, src.port(), dstId, dst.port()) |
137 | - : new UiLinkId(dstId, srcId); | 162 | + : new UiLinkId(dstId, dst.port(), srcId, src.port()); |
138 | } | 163 | } |
139 | } | 164 | } | ... | ... |
... | @@ -16,6 +16,7 @@ | ... | @@ -16,6 +16,7 @@ |
16 | 16 | ||
17 | package org.onosproject.ui.model.topo; | 17 | package org.onosproject.ui.model.topo; |
18 | 18 | ||
19 | +import com.google.common.collect.ImmutableSet; | ||
19 | import org.onosproject.net.DeviceId; | 20 | import org.onosproject.net.DeviceId; |
20 | import org.onosproject.net.HostId; | 21 | import org.onosproject.net.HostId; |
21 | import org.onosproject.net.region.Region; | 22 | import org.onosproject.net.region.Region; |
... | @@ -117,6 +118,15 @@ public class UiRegion extends UiNode { | ... | @@ -117,6 +118,15 @@ public class UiRegion extends UiNode { |
117 | } | 118 | } |
118 | 119 | ||
119 | /** | 120 | /** |
121 | + * Returns the set of device identifiers for this region. | ||
122 | + * | ||
123 | + * @return device identifiers for this region | ||
124 | + */ | ||
125 | + public Set<DeviceId> deviceIds() { | ||
126 | + return ImmutableSet.copyOf(deviceIds); | ||
127 | + } | ||
128 | + | ||
129 | + /** | ||
120 | * Returns the devices in this region. | 130 | * Returns the devices in this region. |
121 | * | 131 | * |
122 | * @return the devices in this region | 132 | * @return the devices in this region |
... | @@ -126,6 +136,15 @@ public class UiRegion extends UiNode { | ... | @@ -126,6 +136,15 @@ public class UiRegion extends UiNode { |
126 | } | 136 | } |
127 | 137 | ||
128 | /** | 138 | /** |
139 | + * Returns the set of host identifiers for this region. | ||
140 | + * | ||
141 | + * @return host identifiers for this region | ||
142 | + */ | ||
143 | + public Set<HostId> hostIds() { | ||
144 | + return ImmutableSet.copyOf(hostIds); | ||
145 | + } | ||
146 | + | ||
147 | + /** | ||
129 | * Returns the hosts in this region. | 148 | * Returns the hosts in this region. |
130 | * | 149 | * |
131 | * @return the hosts in this region | 150 | * @return the hosts in this region |
... | @@ -135,6 +154,15 @@ public class UiRegion extends UiNode { | ... | @@ -135,6 +154,15 @@ public class UiRegion extends UiNode { |
135 | } | 154 | } |
136 | 155 | ||
137 | /** | 156 | /** |
157 | + * Returns the set of link identifiers for this region. | ||
158 | + * | ||
159 | + * @return link identifiers for this region | ||
160 | + */ | ||
161 | + public Set<UiLinkId> linkIds() { | ||
162 | + return ImmutableSet.copyOf(uiLinkIds); | ||
163 | + } | ||
164 | + | ||
165 | + /** | ||
138 | * Returns the links in this region. | 166 | * Returns the links in this region. |
139 | * | 167 | * |
140 | * @return the links in this region | 168 | * @return the links in this region | ... | ... |
... | @@ -35,6 +35,10 @@ import static com.google.common.base.MoreObjects.toStringHelper; | ... | @@ -35,6 +35,10 @@ import static com.google.common.base.MoreObjects.toStringHelper; |
35 | */ | 35 | */ |
36 | public class UiTopology extends UiElement { | 36 | public class UiTopology extends UiElement { |
37 | 37 | ||
38 | + private static final String INDENT_1 = " "; | ||
39 | + private static final String INDENT_2 = " "; | ||
40 | + private static final String EOL = String.format("%n"); | ||
41 | + | ||
38 | private static final String E_UNMAPPED = | 42 | private static final String E_UNMAPPED = |
39 | "Attempting to retrieve unmapped {}: {}"; | 43 | "Attempting to retrieve unmapped {}: {}"; |
40 | 44 | ||
... | @@ -133,15 +137,6 @@ public class UiTopology extends UiElement { | ... | @@ -133,15 +137,6 @@ public class UiTopology extends UiElement { |
133 | } | 137 | } |
134 | 138 | ||
135 | /** | 139 | /** |
136 | - * Returns the number of regions configured in the topology. | ||
137 | - * | ||
138 | - * @return number of regions | ||
139 | - */ | ||
140 | - public int regionCount() { | ||
141 | - return regionLookup.size(); | ||
142 | - } | ||
143 | - | ||
144 | - /** | ||
145 | * Adds the given region to the topology model. | 140 | * Adds the given region to the topology model. |
146 | * | 141 | * |
147 | * @param uiRegion region to add | 142 | * @param uiRegion region to add |
... | @@ -156,7 +151,19 @@ public class UiTopology extends UiElement { | ... | @@ -156,7 +151,19 @@ public class UiTopology extends UiElement { |
156 | * @param uiRegion region to remove | 151 | * @param uiRegion region to remove |
157 | */ | 152 | */ |
158 | public void remove(UiRegion uiRegion) { | 153 | public void remove(UiRegion uiRegion) { |
159 | - regionLookup.remove(uiRegion.id()); | 154 | + UiRegion r = regionLookup.remove(uiRegion.id()); |
155 | + if (r != null) { | ||
156 | + r.destroy(); | ||
157 | + } | ||
158 | + } | ||
159 | + | ||
160 | + /** | ||
161 | + * Returns the number of regions configured in the topology. | ||
162 | + * | ||
163 | + * @return number of regions | ||
164 | + */ | ||
165 | + public int regionCount() { | ||
166 | + return regionLookup.size(); | ||
160 | } | 167 | } |
161 | 168 | ||
162 | /** | 169 | /** |
... | @@ -192,6 +199,15 @@ public class UiTopology extends UiElement { | ... | @@ -192,6 +199,15 @@ public class UiTopology extends UiElement { |
192 | } | 199 | } |
193 | 200 | ||
194 | /** | 201 | /** |
202 | + * Returns the number of devices configured in the topology. | ||
203 | + * | ||
204 | + * @return number of devices | ||
205 | + */ | ||
206 | + public int deviceCount() { | ||
207 | + return deviceLookup.size(); | ||
208 | + } | ||
209 | + | ||
210 | + /** | ||
195 | * Returns the link with the specified identifier, or null if no such | 211 | * Returns the link with the specified identifier, or null if no such |
196 | * link exists. | 212 | * link exists. |
197 | * | 213 | * |
... | @@ -217,13 +233,22 @@ public class UiTopology extends UiElement { | ... | @@ -217,13 +233,22 @@ public class UiTopology extends UiElement { |
217 | * @param uiLink link to remove | 233 | * @param uiLink link to remove |
218 | */ | 234 | */ |
219 | public void remove(UiLink uiLink) { | 235 | public void remove(UiLink uiLink) { |
220 | - UiLink link = linkLookup.get(uiLink.id()); | 236 | + UiLink link = linkLookup.remove(uiLink.id()); |
221 | if (link != null) { | 237 | if (link != null) { |
222 | link.destroy(); | 238 | link.destroy(); |
223 | } | 239 | } |
224 | } | 240 | } |
225 | 241 | ||
226 | /** | 242 | /** |
243 | + * Returns the number of links configured in the topology. | ||
244 | + * | ||
245 | + * @return number of links | ||
246 | + */ | ||
247 | + public int linkCount() { | ||
248 | + return linkLookup.size(); | ||
249 | + } | ||
250 | + | ||
251 | + /** | ||
227 | * Returns the host with the specified identifier, or null if no such | 252 | * Returns the host with the specified identifier, or null if no such |
228 | * host exists. | 253 | * host exists. |
229 | * | 254 | * |
... | @@ -255,6 +280,16 @@ public class UiTopology extends UiElement { | ... | @@ -255,6 +280,16 @@ public class UiTopology extends UiElement { |
255 | } | 280 | } |
256 | } | 281 | } |
257 | 282 | ||
283 | + /** | ||
284 | + * Returns the number of hosts configured in the topology. | ||
285 | + * | ||
286 | + * @return number of hosts | ||
287 | + */ | ||
288 | + public int hostCount() { | ||
289 | + return hostLookup.size(); | ||
290 | + } | ||
291 | + | ||
292 | + | ||
258 | // == | 293 | // == |
259 | // package private methods for supporting linkage amongst topology entities | 294 | // package private methods for supporting linkage amongst topology entities |
260 | // == | 295 | // == |
... | @@ -316,4 +351,42 @@ public class UiTopology extends UiElement { | ... | @@ -316,4 +351,42 @@ public class UiTopology extends UiElement { |
316 | return uiLinks; | 351 | return uiLinks; |
317 | } | 352 | } |
318 | 353 | ||
354 | + /** | ||
355 | + * Returns a detailed (multi-line) string showing the contents of the | ||
356 | + * topology. | ||
357 | + * | ||
358 | + * @return detailed string | ||
359 | + */ | ||
360 | + public String dumpString() { | ||
361 | + StringBuilder sb = new StringBuilder("Topology:").append(EOL); | ||
362 | + | ||
363 | + sb.append(INDENT_1).append("Cluster Members").append(EOL); | ||
364 | + for (UiClusterMember m : cnodeLookup.values()) { | ||
365 | + sb.append(INDENT_2).append(m).append(EOL); | ||
366 | + } | ||
367 | + | ||
368 | + sb.append(INDENT_1).append("Regions").append(EOL); | ||
369 | + for (UiRegion r : regionLookup.values()) { | ||
370 | + sb.append(INDENT_2).append(r).append(EOL); | ||
371 | + } | ||
372 | + | ||
373 | + sb.append(INDENT_1).append("Devices").append(EOL); | ||
374 | + for (UiDevice d : deviceLookup.values()) { | ||
375 | + sb.append(INDENT_2).append(d).append(EOL); | ||
376 | + } | ||
377 | + | ||
378 | + sb.append(INDENT_1).append("Hosts").append(EOL); | ||
379 | + for (UiHost h : hostLookup.values()) { | ||
380 | + sb.append(INDENT_2).append(h).append(EOL); | ||
381 | + } | ||
382 | + | ||
383 | + sb.append(INDENT_1).append("Links").append(EOL); | ||
384 | + for (UiLink link : linkLookup.values()) { | ||
385 | + sb.append(INDENT_2).append(link).append(EOL); | ||
386 | + } | ||
387 | + sb.append("------").append(EOL); | ||
388 | + | ||
389 | + return sb.toString(); | ||
390 | + } | ||
391 | + | ||
319 | } | 392 | } | ... | ... |
... | @@ -26,6 +26,7 @@ import org.onosproject.net.provider.ProviderId; | ... | @@ -26,6 +26,7 @@ import org.onosproject.net.provider.ProviderId; |
26 | import org.onosproject.ui.model.AbstractUiModelTest; | 26 | import org.onosproject.ui.model.AbstractUiModelTest; |
27 | 27 | ||
28 | import static org.junit.Assert.assertEquals; | 28 | import static org.junit.Assert.assertEquals; |
29 | +import static org.junit.Assert.assertNotEquals; | ||
29 | import static org.onosproject.net.DeviceId.deviceId; | 30 | import static org.onosproject.net.DeviceId.deviceId; |
30 | import static org.onosproject.net.PortNumber.portNumber; | 31 | import static org.onosproject.net.PortNumber.portNumber; |
31 | 32 | ||
... | @@ -34,28 +35,34 @@ import static org.onosproject.net.PortNumber.portNumber; | ... | @@ -34,28 +35,34 @@ import static org.onosproject.net.PortNumber.portNumber; |
34 | */ | 35 | */ |
35 | public class UiLinkIdTest extends AbstractUiModelTest { | 36 | public class UiLinkIdTest extends AbstractUiModelTest { |
36 | 37 | ||
37 | - | ||
38 | - private static final ProviderId PROVIDER_ID = ProviderId.NONE; | ||
39 | - | ||
40 | private static final DeviceId DEV_X = deviceId("device-X"); | 38 | private static final DeviceId DEV_X = deviceId("device-X"); |
41 | private static final DeviceId DEV_Y = deviceId("device-Y"); | 39 | private static final DeviceId DEV_Y = deviceId("device-Y"); |
42 | private static final PortNumber P1 = portNumber(1); | 40 | private static final PortNumber P1 = portNumber(1); |
43 | private static final PortNumber P2 = portNumber(2); | 41 | private static final PortNumber P2 = portNumber(2); |
42 | + private static final PortNumber P3 = portNumber(3); | ||
43 | + | ||
44 | + private static final ConnectPoint CP_X1 = new ConnectPoint(DEV_X, P1); | ||
45 | + private static final ConnectPoint CP_Y2 = new ConnectPoint(DEV_Y, P2); | ||
46 | + private static final ConnectPoint CP_Y3 = new ConnectPoint(DEV_Y, P3); | ||
44 | 47 | ||
45 | - private static final ConnectPoint CP_X = new ConnectPoint(DEV_X, P1); | 48 | + private static final Link LINK_X1_TO_Y2 = DefaultLink.builder() |
46 | - private static final ConnectPoint CP_Y = new ConnectPoint(DEV_Y, P2); | 49 | + .providerId(ProviderId.NONE) |
50 | + .src(CP_X1) | ||
51 | + .dst(CP_Y2) | ||
52 | + .type(Link.Type.DIRECT) | ||
53 | + .build(); | ||
47 | 54 | ||
48 | - private static final Link LINK_X_TO_Y = DefaultLink.builder() | 55 | + private static final Link LINK_Y2_TO_X1 = DefaultLink.builder() |
49 | .providerId(ProviderId.NONE) | 56 | .providerId(ProviderId.NONE) |
50 | - .src(CP_X) | 57 | + .src(CP_Y2) |
51 | - .dst(CP_Y) | 58 | + .dst(CP_X1) |
52 | .type(Link.Type.DIRECT) | 59 | .type(Link.Type.DIRECT) |
53 | .build(); | 60 | .build(); |
54 | 61 | ||
55 | - private static final Link LINK_Y_TO_X = DefaultLink.builder() | 62 | + private static final Link LINK_X1_TO_Y3 = DefaultLink.builder() |
56 | .providerId(ProviderId.NONE) | 63 | .providerId(ProviderId.NONE) |
57 | - .src(CP_Y) | 64 | + .src(CP_X1) |
58 | - .dst(CP_X) | 65 | + .dst(CP_Y3) |
59 | .type(Link.Type.DIRECT) | 66 | .type(Link.Type.DIRECT) |
60 | .build(); | 67 | .build(); |
61 | 68 | ||
... | @@ -63,10 +70,20 @@ public class UiLinkIdTest extends AbstractUiModelTest { | ... | @@ -63,10 +70,20 @@ public class UiLinkIdTest extends AbstractUiModelTest { |
63 | @Test | 70 | @Test |
64 | public void canonical() { | 71 | public void canonical() { |
65 | title("canonical"); | 72 | title("canonical"); |
66 | - UiLinkId one = UiLinkId.uiLinkId(LINK_X_TO_Y); | 73 | + UiLinkId one = UiLinkId.uiLinkId(LINK_X1_TO_Y2); |
67 | - UiLinkId two = UiLinkId.uiLinkId(LINK_Y_TO_X); | 74 | + UiLinkId two = UiLinkId.uiLinkId(LINK_Y2_TO_X1); |
68 | print("link one: %s", one); | 75 | print("link one: %s", one); |
69 | print("link two: %s", two); | 76 | print("link two: %s", two); |
70 | assertEquals("not equiv", one, two); | 77 | assertEquals("not equiv", one, two); |
71 | } | 78 | } |
79 | + | ||
80 | + @Test | ||
81 | + public void sameDevsDiffPorts() { | ||
82 | + title("sameDevsDiffPorts"); | ||
83 | + UiLinkId one = UiLinkId.uiLinkId(LINK_X1_TO_Y2); | ||
84 | + UiLinkId other = UiLinkId.uiLinkId(LINK_X1_TO_Y3); | ||
85 | + print("link one: %s", one); | ||
86 | + print("link other: %s", other); | ||
87 | + assertNotEquals("equiv?", one, other); | ||
88 | + } | ||
72 | } | 89 | } | ... | ... |
... | @@ -197,6 +197,11 @@ class ModelCache { | ... | @@ -197,6 +197,11 @@ class ModelCache { |
197 | postEvent(REGION_ADDED_OR_UPDATED, uiRegion); | 197 | postEvent(REGION_ADDED_OR_UPDATED, uiRegion); |
198 | } | 198 | } |
199 | 199 | ||
200 | + // package private for unit test access | ||
201 | + UiRegion accessRegion(RegionId id) { | ||
202 | + return uiTopology.findRegion(id); | ||
203 | + } | ||
204 | + | ||
200 | // invoked from UiSharedTopologyModel region listener | 205 | // invoked from UiSharedTopologyModel region listener |
201 | void removeRegion(Region region) { | 206 | void removeRegion(Region region) { |
202 | RegionId id = region.id(); | 207 | RegionId id = region.id(); |
... | @@ -241,6 +246,11 @@ class ModelCache { | ... | @@ -241,6 +246,11 @@ class ModelCache { |
241 | postEvent(DEVICE_ADDED_OR_UPDATED, uiDevice); | 246 | postEvent(DEVICE_ADDED_OR_UPDATED, uiDevice); |
242 | } | 247 | } |
243 | 248 | ||
249 | + // package private for unit test access | ||
250 | + UiDevice accessDevice(DeviceId id) { | ||
251 | + return uiTopology.findDevice(id); | ||
252 | + } | ||
253 | + | ||
244 | // invoked from UiSharedTopologyModel device listener | 254 | // invoked from UiSharedTopologyModel device listener |
245 | void removeDevice(Device device) { | 255 | void removeDevice(Device device) { |
246 | DeviceId id = device.id(); | 256 | DeviceId id = device.id(); |
... | @@ -290,6 +300,11 @@ class ModelCache { | ... | @@ -290,6 +300,11 @@ class ModelCache { |
290 | postEvent(LINK_ADDED_OR_UPDATED, uiLink); | 300 | postEvent(LINK_ADDED_OR_UPDATED, uiLink); |
291 | } | 301 | } |
292 | 302 | ||
303 | + // package private for unit test access | ||
304 | + UiLink accessLink(UiLinkId id) { | ||
305 | + return uiTopology.findLink(id); | ||
306 | + } | ||
307 | + | ||
293 | // invoked from UiSharedTopologyModel link listener | 308 | // invoked from UiSharedTopologyModel link listener |
294 | void removeLink(Link link) { | 309 | void removeLink(Link link) { |
295 | UiLinkId id = uiLinkId(link); | 310 | UiLinkId id = uiLinkId(link); |
... | @@ -310,36 +325,55 @@ class ModelCache { | ... | @@ -310,36 +325,55 @@ class ModelCache { |
310 | 325 | ||
311 | // === HOSTS | 326 | // === HOSTS |
312 | 327 | ||
328 | + private EdgeLink synthesizeLink(Host h) { | ||
329 | + return createEdgeLink(h, true); | ||
330 | + } | ||
331 | + | ||
313 | private UiHost addNewHost(Host h) { | 332 | private UiHost addNewHost(Host h) { |
314 | UiHost host = new UiHost(uiTopology, h); | 333 | UiHost host = new UiHost(uiTopology, h); |
315 | uiTopology.add(host); | 334 | uiTopology.add(host); |
316 | 335 | ||
317 | - UiLink edgeLink = addNewEdgeLink(host); | 336 | + EdgeLink elink = synthesizeLink(h); |
318 | - host.setEdgeLinkId(edgeLink.id()); | 337 | + UiLinkId elinkId = uiLinkId(elink); |
338 | + host.setEdgeLinkId(elinkId); | ||
339 | + | ||
340 | + // add synthesized edge link to the topology | ||
341 | + UiLink edgeLink = addNewLink(elinkId); | ||
342 | + edgeLink.attachEdgeLink(elink); | ||
319 | 343 | ||
320 | return host; | 344 | return host; |
321 | } | 345 | } |
322 | 346 | ||
323 | - private void removeOldEdgeLink(UiHost uiHost) { | 347 | + private void insertNewUiLink(UiLinkId id, EdgeLink e) { |
324 | - UiLink old = uiTopology.findLink(uiHost.edgeLinkId()); | 348 | + UiLink newEdgeLink = addNewLink(id); |
325 | - if (old != null) { | 349 | + newEdgeLink.attachEdgeLink(e); |
326 | - uiTopology.remove(old); | ||
327 | - } | ||
328 | - } | ||
329 | 350 | ||
330 | - private UiLink addNewEdgeLink(UiHost uiHost) { | ||
331 | - EdgeLink elink = createEdgeLink(uiHost.backingHost(), true); | ||
332 | - UiLinkId elinkId = UiLinkId.uiLinkId(elink); | ||
333 | - UiLink uiLink = addNewLink(elinkId); | ||
334 | - uiLink.attachEdgeLink(elink); | ||
335 | - return uiLink; | ||
336 | } | 351 | } |
337 | 352 | ||
338 | private void updateHost(UiHost uiHost, Host h) { | 353 | private void updateHost(UiHost uiHost, Host h) { |
339 | - removeOldEdgeLink(uiHost); | 354 | + UiLink existing = uiTopology.findLink(uiHost.edgeLinkId()); |
355 | + | ||
356 | + EdgeLink currentElink = synthesizeLink(h); | ||
357 | + UiLinkId currentElinkId = uiLinkId(currentElink); | ||
358 | + | ||
359 | + if (existing != null) { | ||
360 | + if (!currentElinkId.equals(existing.id())) { | ||
361 | + // edge link has changed | ||
362 | + insertNewUiLink(currentElinkId, currentElink); | ||
363 | + uiHost.setEdgeLinkId(currentElinkId); | ||
364 | + | ||
365 | + uiTopology.remove(existing); | ||
366 | + } | ||
367 | + | ||
368 | + } else { | ||
369 | + // no previously existing edge link | ||
370 | + insertNewUiLink(currentElinkId, currentElink); | ||
371 | + uiHost.setEdgeLinkId(currentElinkId); | ||
372 | + | ||
373 | + } | ||
374 | + | ||
340 | HostLocation hloc = h.location(); | 375 | HostLocation hloc = h.location(); |
341 | uiHost.setLocation(hloc.deviceId(), hloc.port()); | 376 | uiHost.setLocation(hloc.deviceId(), hloc.port()); |
342 | - addNewEdgeLink(uiHost); | ||
343 | } | 377 | } |
344 | 378 | ||
345 | private void loadHosts() { | 379 | private void loadHosts() { |
... | @@ -364,9 +398,17 @@ class ModelCache { | ... | @@ -364,9 +398,17 @@ class ModelCache { |
364 | // invoked from UiSharedTopologyModel host listener | 398 | // invoked from UiSharedTopologyModel host listener |
365 | void moveHost(Host host, Host prevHost) { | 399 | void moveHost(Host host, Host prevHost) { |
366 | UiHost uiHost = uiTopology.findHost(prevHost.id()); | 400 | UiHost uiHost = uiTopology.findHost(prevHost.id()); |
367 | - updateHost(uiHost, host); | 401 | + if (uiHost != null) { |
402 | + updateHost(uiHost, host); | ||
403 | + postEvent(HOST_MOVED, uiHost); | ||
404 | + } else { | ||
405 | + log.warn(E_NO_ELEMENT, "host", prevHost.id()); | ||
406 | + } | ||
407 | + } | ||
368 | 408 | ||
369 | - postEvent(HOST_MOVED, uiHost); | 409 | + // package private for unit test access |
410 | + UiHost accessHost(HostId id) { | ||
411 | + return uiTopology.findHost(id); | ||
370 | } | 412 | } |
371 | 413 | ||
372 | // invoked from UiSharedTopologyModel host listener | 414 | // invoked from UiSharedTopologyModel host listener |
... | @@ -374,8 +416,9 @@ class ModelCache { | ... | @@ -374,8 +416,9 @@ class ModelCache { |
374 | HostId id = host.id(); | 416 | HostId id = host.id(); |
375 | UiHost uiHost = uiTopology.findHost(id); | 417 | UiHost uiHost = uiTopology.findHost(id); |
376 | if (uiHost != null) { | 418 | if (uiHost != null) { |
419 | + UiLink edgeLink = uiTopology.findLink(uiHost.edgeLinkId()); | ||
420 | + uiTopology.remove(edgeLink); | ||
377 | uiTopology.remove(uiHost); | 421 | uiTopology.remove(uiHost); |
378 | - removeOldEdgeLink(uiHost); | ||
379 | postEvent(HOST_REMOVED, uiHost); | 422 | postEvent(HOST_REMOVED, uiHost); |
380 | } else { | 423 | } else { |
381 | log.warn(E_NO_ELEMENT, "host", id); | 424 | log.warn(E_NO_ELEMENT, "host", id); |
... | @@ -386,6 +429,15 @@ class ModelCache { | ... | @@ -386,6 +429,15 @@ class ModelCache { |
386 | // === CACHE STATISTICS | 429 | // === CACHE STATISTICS |
387 | 430 | ||
388 | /** | 431 | /** |
432 | + * Returns a detailed (multi-line) string showing the contents of the cache. | ||
433 | + * | ||
434 | + * @return detailed string | ||
435 | + */ | ||
436 | + public String dumpString() { | ||
437 | + return uiTopology.dumpString(); | ||
438 | + } | ||
439 | + | ||
440 | + /** | ||
389 | * Returns the number of members in the cluster. | 441 | * Returns the number of members in the cluster. |
390 | * | 442 | * |
391 | * @return number of cluster members | 443 | * @return number of cluster members |
... | @@ -402,4 +454,31 @@ class ModelCache { | ... | @@ -402,4 +454,31 @@ class ModelCache { |
402 | public int regionCount() { | 454 | public int regionCount() { |
403 | return uiTopology.regionCount(); | 455 | return uiTopology.regionCount(); |
404 | } | 456 | } |
457 | + | ||
458 | + /** | ||
459 | + * Returns the number of devices in the topology. | ||
460 | + * | ||
461 | + * @return number of devices | ||
462 | + */ | ||
463 | + public int deviceCount() { | ||
464 | + return uiTopology.deviceCount(); | ||
465 | + } | ||
466 | + | ||
467 | + /** | ||
468 | + * Returns the number of links in the topology. | ||
469 | + * | ||
470 | + * @return number of links | ||
471 | + */ | ||
472 | + public int linkCount() { | ||
473 | + return uiTopology.linkCount(); | ||
474 | + } | ||
475 | + | ||
476 | + /** | ||
477 | + * Returns the number of hosts in the topology. | ||
478 | + * | ||
479 | + * @return number of hosts | ||
480 | + */ | ||
481 | + public int hostCount() { | ||
482 | + return uiTopology.hostCount(); | ||
483 | + } | ||
405 | } | 484 | } | ... | ... |
... | @@ -136,15 +136,15 @@ abstract class AbstractTopoModelTest extends AbstractUiImplTest { | ... | @@ -136,15 +136,15 @@ abstract class AbstractTopoModelTest extends AbstractUiImplTest { |
136 | protected static final Set<Region> REGION_SET = | 136 | protected static final Set<Region> REGION_SET = |
137 | ImmutableSet.of(REGION_1, REGION_2, REGION_3); | 137 | ImmutableSet.of(REGION_1, REGION_2, REGION_3); |
138 | 138 | ||
139 | - protected static final String D1 = "D1"; | 139 | + protected static final String D1 = "d1"; |
140 | - protected static final String D2 = "D2"; | 140 | + protected static final String D2 = "d2"; |
141 | - protected static final String D3 = "D3"; | 141 | + protected static final String D3 = "d3"; |
142 | - protected static final String D4 = "D4"; | 142 | + protected static final String D4 = "d4"; |
143 | - protected static final String D5 = "D5"; | 143 | + protected static final String D5 = "d5"; |
144 | - protected static final String D6 = "D6"; | 144 | + protected static final String D6 = "d6"; |
145 | - protected static final String D7 = "D7"; | 145 | + protected static final String D7 = "d7"; |
146 | - protected static final String D8 = "D8"; | 146 | + protected static final String D8 = "d8"; |
147 | - protected static final String D9 = "D9"; | 147 | + protected static final String D9 = "d9"; |
148 | 148 | ||
149 | protected static final String MFR = "Mfr"; | 149 | protected static final String MFR = "Mfr"; |
150 | protected static final String HW = "h/w"; | 150 | protected static final String HW = "h/w"; |
... | @@ -303,7 +303,6 @@ abstract class AbstractTopoModelTest extends AbstractUiImplTest { | ... | @@ -303,7 +303,6 @@ abstract class AbstractTopoModelTest extends AbstractUiImplTest { |
303 | private static final HostService MOCK_HOST = new MockHostService(); | 303 | private static final HostService MOCK_HOST = new MockHostService(); |
304 | 304 | ||
305 | 305 | ||
306 | - | ||
307 | private static class MockClusterService extends ClusterServiceAdapter { | 306 | private static class MockClusterService extends ClusterServiceAdapter { |
308 | private final Map<NodeId, ControllerNode> nodes = new HashMap<>(); | 307 | private final Map<NodeId, ControllerNode> nodes = new HashMap<>(); |
309 | private final Map<NodeId, ControllerNode.State> states = new HashMap<>(); | 308 | private final Map<NodeId, ControllerNode.State> states = new HashMap<>(); |
... | @@ -470,38 +469,46 @@ abstract class AbstractTopoModelTest extends AbstractUiImplTest { | ... | @@ -470,38 +469,46 @@ abstract class AbstractTopoModelTest extends AbstractUiImplTest { |
470 | 469 | ||
471 | } | 470 | } |
472 | 471 | ||
472 | + /** | ||
473 | + * Synthesizes a pair of unidirectional links between two devices. The | ||
474 | + * string array should be of the form: | ||
475 | + * <pre> | ||
476 | + * { "device-A-id", "device-A-port", "device-B-id", "device-B-port" } | ||
477 | + * </pre> | ||
478 | + * | ||
479 | + * @param linkPairData device ids and ports | ||
480 | + * @return pair of synthesized links | ||
481 | + */ | ||
482 | + protected static List<Link> makeLinkPair(String[] linkPairData) { | ||
483 | + DeviceId devA = deviceId(linkPairData[0]); | ||
484 | + PortNumber portA = portNumber(Long.valueOf(linkPairData[1])); | ||
485 | + DeviceId devB = deviceId(linkPairData[2]); | ||
486 | + PortNumber portB = portNumber(Long.valueOf(linkPairData[3])); | ||
487 | + | ||
488 | + Link linkA = DefaultLink.builder() | ||
489 | + .providerId(ProviderId.NONE) | ||
490 | + .type(Link.Type.DIRECT) | ||
491 | + .src(new ConnectPoint(devA, portA)) | ||
492 | + .dst(new ConnectPoint(devB, portB)) | ||
493 | + .build(); | ||
494 | + | ||
495 | + Link linkB = DefaultLink.builder() | ||
496 | + .providerId(ProviderId.NONE) | ||
497 | + .type(Link.Type.DIRECT) | ||
498 | + .src(new ConnectPoint(devB, portB)) | ||
499 | + .dst(new ConnectPoint(devA, portA)) | ||
500 | + .build(); | ||
501 | + | ||
502 | + return ImmutableList.of(linkA, linkB); | ||
503 | + } | ||
473 | 504 | ||
474 | private static class MockLinkService extends LinkServiceAdapter { | 505 | private static class MockLinkService extends LinkServiceAdapter { |
475 | private final Set<Link> links = new HashSet<>(); | 506 | private final Set<Link> links = new HashSet<>(); |
476 | 507 | ||
477 | MockLinkService() { | 508 | MockLinkService() { |
478 | for (String[] linkPair : LINK_CONNECT_DATA) { | 509 | for (String[] linkPair : LINK_CONNECT_DATA) { |
479 | - links.addAll(makeLinks(linkPair)); | 510 | + links.addAll(makeLinkPair(linkPair)); |
480 | } | 511 | } |
481 | - | ||
482 | - } | ||
483 | - | ||
484 | - private Set<Link> makeLinks(String[] linkPair) { | ||
485 | - DeviceId devA = deviceId(linkPair[0]); | ||
486 | - PortNumber portA = portNumber(Long.valueOf(linkPair[1])); | ||
487 | - DeviceId devB = deviceId(linkPair[2]); | ||
488 | - PortNumber portB = portNumber(Long.valueOf(linkPair[3])); | ||
489 | - | ||
490 | - Link linkA = DefaultLink.builder() | ||
491 | - .providerId(ProviderId.NONE) | ||
492 | - .type(Link.Type.DIRECT) | ||
493 | - .src(new ConnectPoint(devA, portA)) | ||
494 | - .dst(new ConnectPoint(devB, portB)) | ||
495 | - .build(); | ||
496 | - | ||
497 | - Link linkB = DefaultLink.builder() | ||
498 | - .providerId(ProviderId.NONE) | ||
499 | - .type(Link.Type.DIRECT) | ||
500 | - .src(new ConnectPoint(devB, portB)) | ||
501 | - .dst(new ConnectPoint(devA, portA)) | ||
502 | - .build(); | ||
503 | - | ||
504 | - return ImmutableSet.of(linkA, linkB); | ||
505 | } | 512 | } |
506 | 513 | ||
507 | @Override | 514 | @Override | ... | ... |
... | @@ -20,16 +20,27 @@ import org.junit.Before; | ... | @@ -20,16 +20,27 @@ import org.junit.Before; |
20 | import org.junit.Test; | 20 | import org.junit.Test; |
21 | import org.onosproject.event.Event; | 21 | import org.onosproject.event.Event; |
22 | import org.onosproject.event.EventDispatcher; | 22 | import org.onosproject.event.EventDispatcher; |
23 | +import org.onosproject.net.Device; | ||
23 | import org.onosproject.net.DeviceId; | 24 | import org.onosproject.net.DeviceId; |
25 | +import org.onosproject.net.Link; | ||
26 | +import org.onosproject.net.region.Region; | ||
24 | import org.onosproject.ui.impl.topo.model.UiModelEvent.Type; | 27 | import org.onosproject.ui.impl.topo.model.UiModelEvent.Type; |
25 | import org.onosproject.ui.model.topo.UiClusterMember; | 28 | import org.onosproject.ui.model.topo.UiClusterMember; |
29 | +import org.onosproject.ui.model.topo.UiDevice; | ||
26 | import org.onosproject.ui.model.topo.UiElement; | 30 | import org.onosproject.ui.model.topo.UiElement; |
31 | +import org.onosproject.ui.model.topo.UiLink; | ||
32 | +import org.onosproject.ui.model.topo.UiLinkId; | ||
33 | +import org.onosproject.ui.model.topo.UiRegion; | ||
34 | + | ||
35 | +import java.util.Collection; | ||
36 | +import java.util.Iterator; | ||
27 | 37 | ||
28 | import static org.junit.Assert.assertEquals; | 38 | import static org.junit.Assert.assertEquals; |
29 | import static org.junit.Assert.assertFalse; | 39 | import static org.junit.Assert.assertFalse; |
30 | import static org.junit.Assert.assertNotNull; | 40 | import static org.junit.Assert.assertNotNull; |
31 | import static org.junit.Assert.assertTrue; | 41 | import static org.junit.Assert.assertTrue; |
32 | import static org.onosproject.cluster.NodeId.nodeId; | 42 | import static org.onosproject.cluster.NodeId.nodeId; |
43 | +import static org.onosproject.ui.model.topo.UiLinkId.uiLinkId; | ||
33 | 44 | ||
34 | /** | 45 | /** |
35 | * Unit tests for {@link ModelCache}. | 46 | * Unit tests for {@link ModelCache}. |
... | @@ -64,6 +75,12 @@ public class ModelCacheTest extends AbstractTopoModelTest { | ... | @@ -64,6 +75,12 @@ public class ModelCacheTest extends AbstractTopoModelTest { |
64 | 75 | ||
65 | private ModelCache cache; | 76 | private ModelCache cache; |
66 | 77 | ||
78 | + private void assertContains(String msg, Collection<?> coll, Object... things) { | ||
79 | + for (Object o : things) { | ||
80 | + assertTrue(msg, coll.contains(o)); | ||
81 | + } | ||
82 | + } | ||
83 | + | ||
67 | @Before | 84 | @Before |
68 | public void setUp() { | 85 | public void setUp() { |
69 | cache = new ModelCache(MOCK_SERVICES, dispatcher); | 86 | cache = new ModelCache(MOCK_SERVICES, dispatcher); |
... | @@ -98,6 +115,20 @@ public class ModelCacheTest extends AbstractTopoModelTest { | ... | @@ -98,6 +115,20 @@ public class ModelCacheTest extends AbstractTopoModelTest { |
98 | } | 115 | } |
99 | 116 | ||
100 | @Test | 117 | @Test |
118 | + public void nonExistentClusterMember() { | ||
119 | + title("nonExistentClusterMember"); | ||
120 | + cache.addOrUpdateClusterMember(CNODE_1); | ||
121 | + print(cache); | ||
122 | + assertEquals("unex # members", 1, cache.clusterMemberCount()); | ||
123 | + dispatcher.assertEventCount(1); | ||
124 | + dispatcher.assertLast(Type.CLUSTER_MEMBER_ADDED_OR_UPDATED, C1); | ||
125 | + | ||
126 | + cache.removeClusterMember(CNODE_2); | ||
127 | + assertEquals("unex # members", 1, cache.clusterMemberCount()); | ||
128 | + dispatcher.assertEventCount(1); | ||
129 | + } | ||
130 | + | ||
131 | + @Test | ||
101 | public void createThreeNodeCluster() { | 132 | public void createThreeNodeCluster() { |
102 | title("createThreeNodeCluster"); | 133 | title("createThreeNodeCluster"); |
103 | cache.addOrUpdateClusterMember(CNODE_1); | 134 | cache.addOrUpdateClusterMember(CNODE_1); |
... | @@ -146,23 +177,145 @@ public class ModelCacheTest extends AbstractTopoModelTest { | ... | @@ -146,23 +177,145 @@ public class ModelCacheTest extends AbstractTopoModelTest { |
146 | public void addNodeAndDevices() { | 177 | public void addNodeAndDevices() { |
147 | title("addNodeAndDevices"); | 178 | title("addNodeAndDevices"); |
148 | cache.addOrUpdateClusterMember(CNODE_1); | 179 | cache.addOrUpdateClusterMember(CNODE_1); |
180 | + dispatcher.assertLast(Type.CLUSTER_MEMBER_ADDED_OR_UPDATED, C1); | ||
149 | cache.addOrUpdateDevice(DEV_1); | 181 | cache.addOrUpdateDevice(DEV_1); |
182 | + dispatcher.assertLast(Type.DEVICE_ADDED_OR_UPDATED, D1); | ||
150 | cache.addOrUpdateDevice(DEV_2); | 183 | cache.addOrUpdateDevice(DEV_2); |
184 | + dispatcher.assertLast(Type.DEVICE_ADDED_OR_UPDATED, D2); | ||
151 | cache.addOrUpdateDevice(DEV_3); | 185 | cache.addOrUpdateDevice(DEV_3); |
186 | + dispatcher.assertLast(Type.DEVICE_ADDED_OR_UPDATED, D3); | ||
187 | + dispatcher.assertEventCount(4); | ||
152 | print(cache); | 188 | print(cache); |
189 | + | ||
190 | + assertEquals("unex # nodes", 1, cache.clusterMemberCount()); | ||
191 | + assertEquals("unex # devices", 3, cache.deviceCount()); | ||
192 | + cache.removeDevice(DEV_4); | ||
193 | + assertEquals("unex # devices", 3, cache.deviceCount()); | ||
194 | + dispatcher.assertEventCount(4); | ||
195 | + | ||
196 | + cache.removeDevice(DEV_2); | ||
197 | + dispatcher.assertLast(Type.DEVICE_REMOVED, D2); | ||
198 | + dispatcher.assertEventCount(5); | ||
199 | + | ||
200 | + // check out details of device | ||
201 | + UiDevice dev = cache.accessDevice(DEVID_1); | ||
202 | + assertEquals("wrong id", D1, dev.idAsString()); | ||
203 | + assertEquals("wrong region", R1, dev.regionId().toString()); | ||
204 | + Device d = dev.backingDevice(); | ||
205 | + assertEquals("wrong serial", SERIAL, d.serialNumber()); | ||
153 | } | 206 | } |
154 | 207 | ||
155 | @Test | 208 | @Test |
156 | public void addRegions() { | 209 | public void addRegions() { |
157 | title("addRegions"); | 210 | title("addRegions"); |
158 | cache.addOrUpdateRegion(REGION_1); | 211 | cache.addOrUpdateRegion(REGION_1); |
212 | + dispatcher.assertLast(Type.REGION_ADDED_OR_UPDATED, R1); | ||
213 | + dispatcher.assertEventCount(1); | ||
214 | + assertEquals("unex # regions", 1, cache.regionCount()); | ||
215 | + | ||
216 | + cache.addOrUpdateRegion(REGION_2); | ||
217 | + dispatcher.assertLast(Type.REGION_ADDED_OR_UPDATED, R2); | ||
218 | + dispatcher.assertEventCount(2); | ||
219 | + assertEquals("unex # regions", 2, cache.regionCount()); | ||
220 | + | ||
159 | print(cache); | 221 | print(cache); |
222 | + | ||
223 | + cache.removeRegion(REGION_3); | ||
224 | + dispatcher.assertEventCount(2); | ||
225 | + assertEquals("unex # regions", 2, cache.regionCount()); | ||
226 | + | ||
227 | + cache.removeRegion(REGION_1); | ||
228 | + dispatcher.assertLast(Type.REGION_REMOVED, R1); | ||
229 | + dispatcher.assertEventCount(3); | ||
230 | + assertEquals("unex # regions", 1, cache.regionCount()); | ||
231 | + | ||
232 | + print(cache); | ||
233 | + | ||
234 | + UiRegion region = cache.accessRegion(REGION_2.id()); | ||
235 | + assertEquals("wrong id", REGION_2.id(), region.id()); | ||
236 | + assertEquals("unex # device IDs", 3, region.deviceIds().size()); | ||
237 | + assertContains("missing ID", region.deviceIds(), DEVID_4, DEVID_5, DEVID_6); | ||
238 | + Region r = region.backingRegion(); | ||
239 | + print(r); | ||
240 | + assertEquals("wrong region name", "Region-R2", r.name()); | ||
241 | + } | ||
242 | + | ||
243 | + private static final String[] LINKS_2_7 = {D2, "27", D7, "72"}; | ||
244 | + | ||
245 | + @Test | ||
246 | + public void addLinks() { | ||
247 | + title("addLinks"); | ||
248 | + | ||
249 | + Iterator<Link> iter = makeLinkPair(LINKS_2_7).iterator(); | ||
250 | + Link link1 = iter.next(); | ||
251 | + Link link2 = iter.next(); | ||
252 | + print(link1); | ||
253 | + print(link2); | ||
254 | + | ||
255 | + UiLinkId idA2B = uiLinkId(link1); | ||
256 | + UiLinkId idB2A = uiLinkId(link2); | ||
257 | + // remember, link IDs are canonicalized | ||
258 | + assertEquals("not same link ID", idA2B, idB2A); | ||
259 | + | ||
260 | + // we've established that the ID is the same for both | ||
261 | + UiLinkId linkId = idA2B; | ||
262 | + | ||
263 | + cache.addOrUpdateLink(link1); | ||
264 | + dispatcher.assertLast(Type.LINK_ADDED_OR_UPDATED, linkId.toString()); | ||
265 | + dispatcher.assertEventCount(1); | ||
266 | + assertEquals("unex # links", 1, cache.linkCount()); | ||
267 | + | ||
268 | + UiLink link = cache.accessLink(linkId); | ||
269 | + assertEquals("dev A not d2", DEVID_2, link.deviceA()); | ||
270 | + assertEquals("dev B not d7", DEVID_7, link.deviceB()); | ||
271 | + assertEquals("wrong backing link A-B", link1, link.linkAtoB()); | ||
272 | + assertEquals("backing link B-A?", null, link.linkBtoA()); | ||
273 | + | ||
274 | + cache.addOrUpdateLink(link2); | ||
275 | + dispatcher.assertLast(Type.LINK_ADDED_OR_UPDATED, linkId.toString()); | ||
276 | + dispatcher.assertEventCount(2); | ||
277 | + // NOTE: yes! expect 1 UiLink | ||
278 | + assertEquals("unex # links", 1, cache.linkCount()); | ||
279 | + | ||
280 | + link = cache.accessLink(linkId); | ||
281 | + assertEquals("dev A not d2", DEVID_2, link.deviceA()); | ||
282 | + assertEquals("dev B not d7", DEVID_7, link.deviceB()); | ||
283 | + assertEquals("wrong backing link A-B", link1, link.linkAtoB()); | ||
284 | + assertEquals("wrong backing link B-A", link2, link.linkBtoA()); | ||
285 | + | ||
286 | + // now remove links one at a time | ||
287 | + cache.removeLink(link1); | ||
288 | + // NOTE: yes! ADD_OR_UPDATE, since the link was updated | ||
289 | + dispatcher.assertLast(Type.LINK_ADDED_OR_UPDATED, linkId.toString()); | ||
290 | + dispatcher.assertEventCount(3); | ||
291 | + // NOTE: yes! expect 1 UiLink (still) | ||
292 | + assertEquals("unex # links", 1, cache.linkCount()); | ||
293 | + | ||
294 | + link = cache.accessLink(linkId); | ||
295 | + assertEquals("dev A not d2", DEVID_2, link.deviceA()); | ||
296 | + assertEquals("dev B not d7", DEVID_7, link.deviceB()); | ||
297 | + assertEquals("backing link A-B?", null, link.linkAtoB()); | ||
298 | + assertEquals("wrong backing link B-A", link2, link.linkBtoA()); | ||
299 | + | ||
300 | + // remove final link | ||
301 | + cache.removeLink(link2); | ||
302 | + dispatcher.assertLast(Type.LINK_REMOVED, linkId.toString()); | ||
303 | + dispatcher.assertEventCount(4); | ||
304 | + // NOTE: finally link should be removed from cache | ||
305 | + assertEquals("unex # links", 0, cache.linkCount()); | ||
160 | } | 306 | } |
161 | 307 | ||
162 | @Test | 308 | @Test |
163 | public void load() { | 309 | public void load() { |
164 | title("load"); | 310 | title("load"); |
165 | cache.load(); | 311 | cache.load(); |
166 | - print(cache); | 312 | + print(cache.dumpString()); |
313 | + | ||
314 | + // See mock service bundle for expected values (AbstractTopoModelTest) | ||
315 | + assertEquals("unex # cnodes", 3, cache.clusterMemberCount()); | ||
316 | + assertEquals("unex # regions", 3, cache.regionCount()); | ||
317 | + assertEquals("unex # devices", 9, cache.deviceCount()); | ||
318 | + assertEquals("unex # hosts", 18, cache.hostCount()); | ||
319 | + assertEquals("unex # hosts", 26, cache.linkCount()); | ||
167 | } | 320 | } |
168 | } | 321 | } | ... | ... |
-
Please register or login to post a comment