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