Simon Hunt
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
......@@ -87,6 +87,16 @@ public class UiDevice extends UiNode {
}
/**
* Returns the identifier of the region to which this device belongs.
* This will be null if the device does not belong to any region.
*
* @return region identity
*/
public RegionId regionId() {
return regionId;
}
/**
* Returns the UI region to which this device belongs.
*
* @return the UI region
......
......@@ -177,4 +177,42 @@ public class UiLink extends UiElement {
edgeLink = elink;
edgeDevice = elink.hostLocation().deviceId();
}
/**
* Returns the identity of device A.
*
* @return device A ID
*/
public DeviceId deviceA() {
return deviceA;
}
/**
* Returns the identity of device B.
*
* @return device B ID
*/
public DeviceId deviceB() {
return deviceB;
}
/**
* Returns backing link from A to B.
*
* @return backing link A to B
*/
public Link linkAtoB() {
return linkAtoB;
}
/**
* Returns backing link from B to A.
*
* @return backing link B to A
*/
public Link linkBtoA() {
return linkBtoA;
}
}
......
......@@ -19,6 +19,7 @@ package org.onosproject.ui.model.topo;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.ElementId;
import org.onosproject.net.Link;
import org.onosproject.net.PortNumber;
/**
* A canonical representation of an identifier for {@link UiLink}s.
......@@ -33,10 +34,14 @@ public final class UiLinkId {
B_TO_A
}
private static final String ID_DELIMITER = "~";
private static final String CP_DELIMITER = "~";
private static final String ID_PORT_DELIMITER = "/";
private final ElementId idA;
private final PortNumber portA;
private final ElementId idB;
private final PortNumber portB;
private final String idStr;
/**
......@@ -46,13 +51,18 @@ public final class UiLinkId {
* underlying link.
*
* @param a first element ID
* @param pa first element port
* @param b second element ID
* @param pb second element port
*/
private UiLinkId(ElementId a, ElementId b) {
private UiLinkId(ElementId a, PortNumber pa, ElementId b, PortNumber pb) {
idA = a;
portA = pa;
idB = b;
portB = pb;
idStr = a.toString() + ID_DELIMITER + b.toString();
idStr = a + ID_PORT_DELIMITER + pa + CP_DELIMITER +
b + ID_PORT_DELIMITER + pb;
}
@Override
......@@ -70,6 +80,15 @@ public final class UiLinkId {
}
/**
* Returns the port of the first element.
*
* @return first element port
*/
public PortNumber portA() {
return portA;
}
/**
* Returns the identifier of the second element.
*
* @return second element identity
......@@ -78,6 +97,15 @@ public final class UiLinkId {
return idB;
}
/**
* Returns the port of the second element.
*
* @return second element port
*/
public PortNumber portB() {
return portB;
}
@Override
public boolean equals(Object o) {
if (this == o) {
......@@ -127,13 +155,10 @@ public final class UiLinkId {
ElementId srcId = src.elementId();
ElementId dstId = dst.elementId();
if (srcId == null || dstId == null) {
throw new NullPointerException("null element ID in connect point: " + link);
}
// canonicalize
int comp = srcId.toString().compareTo(dstId.toString());
return comp <= 0 ? new UiLinkId(srcId, dstId)
: new UiLinkId(dstId, srcId);
return comp <= 0 ? new UiLinkId(srcId, src.port(), dstId, dst.port())
: new UiLinkId(dstId, dst.port(), srcId, src.port());
}
}
......
......@@ -16,6 +16,7 @@
package org.onosproject.ui.model.topo;
import com.google.common.collect.ImmutableSet;
import org.onosproject.net.DeviceId;
import org.onosproject.net.HostId;
import org.onosproject.net.region.Region;
......@@ -117,6 +118,15 @@ public class UiRegion extends UiNode {
}
/**
* Returns the set of device identifiers for this region.
*
* @return device identifiers for this region
*/
public Set<DeviceId> deviceIds() {
return ImmutableSet.copyOf(deviceIds);
}
/**
* Returns the devices in this region.
*
* @return the devices in this region
......@@ -126,6 +136,15 @@ public class UiRegion extends UiNode {
}
/**
* Returns the set of host identifiers for this region.
*
* @return host identifiers for this region
*/
public Set<HostId> hostIds() {
return ImmutableSet.copyOf(hostIds);
}
/**
* Returns the hosts in this region.
*
* @return the hosts in this region
......@@ -135,6 +154,15 @@ public class UiRegion extends UiNode {
}
/**
* Returns the set of link identifiers for this region.
*
* @return link identifiers for this region
*/
public Set<UiLinkId> linkIds() {
return ImmutableSet.copyOf(uiLinkIds);
}
/**
* Returns the links in this region.
*
* @return the links in this region
......
......@@ -35,6 +35,10 @@ import static com.google.common.base.MoreObjects.toStringHelper;
*/
public class UiTopology extends UiElement {
private static final String INDENT_1 = " ";
private static final String INDENT_2 = " ";
private static final String EOL = String.format("%n");
private static final String E_UNMAPPED =
"Attempting to retrieve unmapped {}: {}";
......@@ -133,15 +137,6 @@ public class UiTopology extends UiElement {
}
/**
* Returns the number of regions configured in the topology.
*
* @return number of regions
*/
public int regionCount() {
return regionLookup.size();
}
/**
* Adds the given region to the topology model.
*
* @param uiRegion region to add
......@@ -156,7 +151,19 @@ public class UiTopology extends UiElement {
* @param uiRegion region to remove
*/
public void remove(UiRegion uiRegion) {
regionLookup.remove(uiRegion.id());
UiRegion r = regionLookup.remove(uiRegion.id());
if (r != null) {
r.destroy();
}
}
/**
* Returns the number of regions configured in the topology.
*
* @return number of regions
*/
public int regionCount() {
return regionLookup.size();
}
/**
......@@ -192,6 +199,15 @@ public class UiTopology extends UiElement {
}
/**
* Returns the number of devices configured in the topology.
*
* @return number of devices
*/
public int deviceCount() {
return deviceLookup.size();
}
/**
* Returns the link with the specified identifier, or null if no such
* link exists.
*
......@@ -217,13 +233,22 @@ public class UiTopology extends UiElement {
* @param uiLink link to remove
*/
public void remove(UiLink uiLink) {
UiLink link = linkLookup.get(uiLink.id());
UiLink link = linkLookup.remove(uiLink.id());
if (link != null) {
link.destroy();
}
}
/**
* Returns the number of links configured in the topology.
*
* @return number of links
*/
public int linkCount() {
return linkLookup.size();
}
/**
* Returns the host with the specified identifier, or null if no such
* host exists.
*
......@@ -255,6 +280,16 @@ public class UiTopology extends UiElement {
}
}
/**
* Returns the number of hosts configured in the topology.
*
* @return number of hosts
*/
public int hostCount() {
return hostLookup.size();
}
// ==
// package private methods for supporting linkage amongst topology entities
// ==
......@@ -316,4 +351,42 @@ public class UiTopology extends UiElement {
return uiLinks;
}
/**
* Returns a detailed (multi-line) string showing the contents of the
* topology.
*
* @return detailed string
*/
public String dumpString() {
StringBuilder sb = new StringBuilder("Topology:").append(EOL);
sb.append(INDENT_1).append("Cluster Members").append(EOL);
for (UiClusterMember m : cnodeLookup.values()) {
sb.append(INDENT_2).append(m).append(EOL);
}
sb.append(INDENT_1).append("Regions").append(EOL);
for (UiRegion r : regionLookup.values()) {
sb.append(INDENT_2).append(r).append(EOL);
}
sb.append(INDENT_1).append("Devices").append(EOL);
for (UiDevice d : deviceLookup.values()) {
sb.append(INDENT_2).append(d).append(EOL);
}
sb.append(INDENT_1).append("Hosts").append(EOL);
for (UiHost h : hostLookup.values()) {
sb.append(INDENT_2).append(h).append(EOL);
}
sb.append(INDENT_1).append("Links").append(EOL);
for (UiLink link : linkLookup.values()) {
sb.append(INDENT_2).append(link).append(EOL);
}
sb.append("------").append(EOL);
return sb.toString();
}
}
......
......@@ -26,6 +26,7 @@ import org.onosproject.net.provider.ProviderId;
import org.onosproject.ui.model.AbstractUiModelTest;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.onosproject.net.DeviceId.deviceId;
import static org.onosproject.net.PortNumber.portNumber;
......@@ -34,28 +35,34 @@ import static org.onosproject.net.PortNumber.portNumber;
*/
public class UiLinkIdTest extends AbstractUiModelTest {
private static final ProviderId PROVIDER_ID = ProviderId.NONE;
private static final DeviceId DEV_X = deviceId("device-X");
private static final DeviceId DEV_Y = deviceId("device-Y");
private static final PortNumber P1 = portNumber(1);
private static final PortNumber P2 = portNumber(2);
private static final PortNumber P3 = portNumber(3);
private static final ConnectPoint CP_X1 = new ConnectPoint(DEV_X, P1);
private static final ConnectPoint CP_Y2 = new ConnectPoint(DEV_Y, P2);
private static final ConnectPoint CP_Y3 = new ConnectPoint(DEV_Y, P3);
private static final ConnectPoint CP_X = new ConnectPoint(DEV_X, P1);
private static final ConnectPoint CP_Y = new ConnectPoint(DEV_Y, P2);
private static final Link LINK_X1_TO_Y2 = DefaultLink.builder()
.providerId(ProviderId.NONE)
.src(CP_X1)
.dst(CP_Y2)
.type(Link.Type.DIRECT)
.build();
private static final Link LINK_X_TO_Y = DefaultLink.builder()
private static final Link LINK_Y2_TO_X1 = DefaultLink.builder()
.providerId(ProviderId.NONE)
.src(CP_X)
.dst(CP_Y)
.src(CP_Y2)
.dst(CP_X1)
.type(Link.Type.DIRECT)
.build();
private static final Link LINK_Y_TO_X = DefaultLink.builder()
private static final Link LINK_X1_TO_Y3 = DefaultLink.builder()
.providerId(ProviderId.NONE)
.src(CP_Y)
.dst(CP_X)
.src(CP_X1)
.dst(CP_Y3)
.type(Link.Type.DIRECT)
.build();
......@@ -63,10 +70,20 @@ public class UiLinkIdTest extends AbstractUiModelTest {
@Test
public void canonical() {
title("canonical");
UiLinkId one = UiLinkId.uiLinkId(LINK_X_TO_Y);
UiLinkId two = UiLinkId.uiLinkId(LINK_Y_TO_X);
UiLinkId one = UiLinkId.uiLinkId(LINK_X1_TO_Y2);
UiLinkId two = UiLinkId.uiLinkId(LINK_Y2_TO_X1);
print("link one: %s", one);
print("link two: %s", two);
assertEquals("not equiv", one, two);
}
@Test
public void sameDevsDiffPorts() {
title("sameDevsDiffPorts");
UiLinkId one = UiLinkId.uiLinkId(LINK_X1_TO_Y2);
UiLinkId other = UiLinkId.uiLinkId(LINK_X1_TO_Y3);
print("link one: %s", one);
print("link other: %s", other);
assertNotEquals("equiv?", one, other);
}
}
......
......@@ -197,6 +197,11 @@ class ModelCache {
postEvent(REGION_ADDED_OR_UPDATED, uiRegion);
}
// package private for unit test access
UiRegion accessRegion(RegionId id) {
return uiTopology.findRegion(id);
}
// invoked from UiSharedTopologyModel region listener
void removeRegion(Region region) {
RegionId id = region.id();
......@@ -241,6 +246,11 @@ class ModelCache {
postEvent(DEVICE_ADDED_OR_UPDATED, uiDevice);
}
// package private for unit test access
UiDevice accessDevice(DeviceId id) {
return uiTopology.findDevice(id);
}
// invoked from UiSharedTopologyModel device listener
void removeDevice(Device device) {
DeviceId id = device.id();
......@@ -290,6 +300,11 @@ class ModelCache {
postEvent(LINK_ADDED_OR_UPDATED, uiLink);
}
// package private for unit test access
UiLink accessLink(UiLinkId id) {
return uiTopology.findLink(id);
}
// invoked from UiSharedTopologyModel link listener
void removeLink(Link link) {
UiLinkId id = uiLinkId(link);
......@@ -310,36 +325,55 @@ class ModelCache {
// === HOSTS
private EdgeLink synthesizeLink(Host h) {
return createEdgeLink(h, true);
}
private UiHost addNewHost(Host h) {
UiHost host = new UiHost(uiTopology, h);
uiTopology.add(host);
UiLink edgeLink = addNewEdgeLink(host);
host.setEdgeLinkId(edgeLink.id());
EdgeLink elink = synthesizeLink(h);
UiLinkId elinkId = uiLinkId(elink);
host.setEdgeLinkId(elinkId);
// add synthesized edge link to the topology
UiLink edgeLink = addNewLink(elinkId);
edgeLink.attachEdgeLink(elink);
return host;
}
private void removeOldEdgeLink(UiHost uiHost) {
UiLink old = uiTopology.findLink(uiHost.edgeLinkId());
if (old != null) {
uiTopology.remove(old);
private void insertNewUiLink(UiLinkId id, EdgeLink e) {
UiLink newEdgeLink = addNewLink(id);
newEdgeLink.attachEdgeLink(e);
}
private void updateHost(UiHost uiHost, Host h) {
UiLink existing = uiTopology.findLink(uiHost.edgeLinkId());
EdgeLink currentElink = synthesizeLink(h);
UiLinkId currentElinkId = uiLinkId(currentElink);
if (existing != null) {
if (!currentElinkId.equals(existing.id())) {
// edge link has changed
insertNewUiLink(currentElinkId, currentElink);
uiHost.setEdgeLinkId(currentElinkId);
uiTopology.remove(existing);
}
private UiLink addNewEdgeLink(UiHost uiHost) {
EdgeLink elink = createEdgeLink(uiHost.backingHost(), true);
UiLinkId elinkId = UiLinkId.uiLinkId(elink);
UiLink uiLink = addNewLink(elinkId);
uiLink.attachEdgeLink(elink);
return uiLink;
} else {
// no previously existing edge link
insertNewUiLink(currentElinkId, currentElink);
uiHost.setEdgeLinkId(currentElinkId);
}
private void updateHost(UiHost uiHost, Host h) {
removeOldEdgeLink(uiHost);
HostLocation hloc = h.location();
uiHost.setLocation(hloc.deviceId(), hloc.port());
addNewEdgeLink(uiHost);
}
private void loadHosts() {
......@@ -364,9 +398,17 @@ class ModelCache {
// invoked from UiSharedTopologyModel host listener
void moveHost(Host host, Host prevHost) {
UiHost uiHost = uiTopology.findHost(prevHost.id());
if (uiHost != null) {
updateHost(uiHost, host);
postEvent(HOST_MOVED, uiHost);
} else {
log.warn(E_NO_ELEMENT, "host", prevHost.id());
}
}
// package private for unit test access
UiHost accessHost(HostId id) {
return uiTopology.findHost(id);
}
// invoked from UiSharedTopologyModel host listener
......@@ -374,8 +416,9 @@ class ModelCache {
HostId id = host.id();
UiHost uiHost = uiTopology.findHost(id);
if (uiHost != null) {
UiLink edgeLink = uiTopology.findLink(uiHost.edgeLinkId());
uiTopology.remove(edgeLink);
uiTopology.remove(uiHost);
removeOldEdgeLink(uiHost);
postEvent(HOST_REMOVED, uiHost);
} else {
log.warn(E_NO_ELEMENT, "host", id);
......@@ -386,6 +429,15 @@ class ModelCache {
// === CACHE STATISTICS
/**
* Returns a detailed (multi-line) string showing the contents of the cache.
*
* @return detailed string
*/
public String dumpString() {
return uiTopology.dumpString();
}
/**
* Returns the number of members in the cluster.
*
* @return number of cluster members
......@@ -402,4 +454,31 @@ class ModelCache {
public int regionCount() {
return uiTopology.regionCount();
}
/**
* Returns the number of devices in the topology.
*
* @return number of devices
*/
public int deviceCount() {
return uiTopology.deviceCount();
}
/**
* Returns the number of links in the topology.
*
* @return number of links
*/
public int linkCount() {
return uiTopology.linkCount();
}
/**
* Returns the number of hosts in the topology.
*
* @return number of hosts
*/
public int hostCount() {
return uiTopology.hostCount();
}
}
......
......@@ -136,15 +136,15 @@ abstract class AbstractTopoModelTest extends AbstractUiImplTest {
protected static final Set<Region> REGION_SET =
ImmutableSet.of(REGION_1, REGION_2, REGION_3);
protected static final String D1 = "D1";
protected static final String D2 = "D2";
protected static final String D3 = "D3";
protected static final String D4 = "D4";
protected static final String D5 = "D5";
protected static final String D6 = "D6";
protected static final String D7 = "D7";
protected static final String D8 = "D8";
protected static final String D9 = "D9";
protected static final String D1 = "d1";
protected static final String D2 = "d2";
protected static final String D3 = "d3";
protected static final String D4 = "d4";
protected static final String D5 = "d5";
protected static final String D6 = "d6";
protected static final String D7 = "d7";
protected static final String D8 = "d8";
protected static final String D9 = "d9";
protected static final String MFR = "Mfr";
protected static final String HW = "h/w";
......@@ -303,7 +303,6 @@ abstract class AbstractTopoModelTest extends AbstractUiImplTest {
private static final HostService MOCK_HOST = new MockHostService();
private static class MockClusterService extends ClusterServiceAdapter {
private final Map<NodeId, ControllerNode> nodes = new HashMap<>();
private final Map<NodeId, ControllerNode.State> states = new HashMap<>();
......@@ -470,22 +469,21 @@ abstract class AbstractTopoModelTest extends AbstractUiImplTest {
}
private static class MockLinkService extends LinkServiceAdapter {
private final Set<Link> links = new HashSet<>();
MockLinkService() {
for (String[] linkPair : LINK_CONNECT_DATA) {
links.addAll(makeLinks(linkPair));
}
}
private Set<Link> makeLinks(String[] linkPair) {
DeviceId devA = deviceId(linkPair[0]);
PortNumber portA = portNumber(Long.valueOf(linkPair[1]));
DeviceId devB = deviceId(linkPair[2]);
PortNumber portB = portNumber(Long.valueOf(linkPair[3]));
/**
* Synthesizes a pair of unidirectional links between two devices. The
* string array should be of the form:
* <pre>
* { "device-A-id", "device-A-port", "device-B-id", "device-B-port" }
* </pre>
*
* @param linkPairData device ids and ports
* @return pair of synthesized links
*/
protected static List<Link> makeLinkPair(String[] linkPairData) {
DeviceId devA = deviceId(linkPairData[0]);
PortNumber portA = portNumber(Long.valueOf(linkPairData[1]));
DeviceId devB = deviceId(linkPairData[2]);
PortNumber portB = portNumber(Long.valueOf(linkPairData[3]));
Link linkA = DefaultLink.builder()
.providerId(ProviderId.NONE)
......@@ -501,7 +499,16 @@ abstract class AbstractTopoModelTest extends AbstractUiImplTest {
.dst(new ConnectPoint(devA, portA))
.build();
return ImmutableSet.of(linkA, linkB);
return ImmutableList.of(linkA, linkB);
}
private static class MockLinkService extends LinkServiceAdapter {
private final Set<Link> links = new HashSet<>();
MockLinkService() {
for (String[] linkPair : LINK_CONNECT_DATA) {
links.addAll(makeLinkPair(linkPair));
}
}
@Override
......
......@@ -20,16 +20,27 @@ import org.junit.Before;
import org.junit.Test;
import org.onosproject.event.Event;
import org.onosproject.event.EventDispatcher;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.net.region.Region;
import org.onosproject.ui.impl.topo.model.UiModelEvent.Type;
import org.onosproject.ui.model.topo.UiClusterMember;
import org.onosproject.ui.model.topo.UiDevice;
import org.onosproject.ui.model.topo.UiElement;
import org.onosproject.ui.model.topo.UiLink;
import org.onosproject.ui.model.topo.UiLinkId;
import org.onosproject.ui.model.topo.UiRegion;
import java.util.Collection;
import java.util.Iterator;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.onosproject.cluster.NodeId.nodeId;
import static org.onosproject.ui.model.topo.UiLinkId.uiLinkId;
/**
* Unit tests for {@link ModelCache}.
......@@ -64,6 +75,12 @@ public class ModelCacheTest extends AbstractTopoModelTest {
private ModelCache cache;
private void assertContains(String msg, Collection<?> coll, Object... things) {
for (Object o : things) {
assertTrue(msg, coll.contains(o));
}
}
@Before
public void setUp() {
cache = new ModelCache(MOCK_SERVICES, dispatcher);
......@@ -98,6 +115,20 @@ public class ModelCacheTest extends AbstractTopoModelTest {
}
@Test
public void nonExistentClusterMember() {
title("nonExistentClusterMember");
cache.addOrUpdateClusterMember(CNODE_1);
print(cache);
assertEquals("unex # members", 1, cache.clusterMemberCount());
dispatcher.assertEventCount(1);
dispatcher.assertLast(Type.CLUSTER_MEMBER_ADDED_OR_UPDATED, C1);
cache.removeClusterMember(CNODE_2);
assertEquals("unex # members", 1, cache.clusterMemberCount());
dispatcher.assertEventCount(1);
}
@Test
public void createThreeNodeCluster() {
title("createThreeNodeCluster");
cache.addOrUpdateClusterMember(CNODE_1);
......@@ -146,23 +177,145 @@ public class ModelCacheTest extends AbstractTopoModelTest {
public void addNodeAndDevices() {
title("addNodeAndDevices");
cache.addOrUpdateClusterMember(CNODE_1);
dispatcher.assertLast(Type.CLUSTER_MEMBER_ADDED_OR_UPDATED, C1);
cache.addOrUpdateDevice(DEV_1);
dispatcher.assertLast(Type.DEVICE_ADDED_OR_UPDATED, D1);
cache.addOrUpdateDevice(DEV_2);
dispatcher.assertLast(Type.DEVICE_ADDED_OR_UPDATED, D2);
cache.addOrUpdateDevice(DEV_3);
dispatcher.assertLast(Type.DEVICE_ADDED_OR_UPDATED, D3);
dispatcher.assertEventCount(4);
print(cache);
assertEquals("unex # nodes", 1, cache.clusterMemberCount());
assertEquals("unex # devices", 3, cache.deviceCount());
cache.removeDevice(DEV_4);
assertEquals("unex # devices", 3, cache.deviceCount());
dispatcher.assertEventCount(4);
cache.removeDevice(DEV_2);
dispatcher.assertLast(Type.DEVICE_REMOVED, D2);
dispatcher.assertEventCount(5);
// check out details of device
UiDevice dev = cache.accessDevice(DEVID_1);
assertEquals("wrong id", D1, dev.idAsString());
assertEquals("wrong region", R1, dev.regionId().toString());
Device d = dev.backingDevice();
assertEquals("wrong serial", SERIAL, d.serialNumber());
}
@Test
public void addRegions() {
title("addRegions");
cache.addOrUpdateRegion(REGION_1);
dispatcher.assertLast(Type.REGION_ADDED_OR_UPDATED, R1);
dispatcher.assertEventCount(1);
assertEquals("unex # regions", 1, cache.regionCount());
cache.addOrUpdateRegion(REGION_2);
dispatcher.assertLast(Type.REGION_ADDED_OR_UPDATED, R2);
dispatcher.assertEventCount(2);
assertEquals("unex # regions", 2, cache.regionCount());
print(cache);
cache.removeRegion(REGION_3);
dispatcher.assertEventCount(2);
assertEquals("unex # regions", 2, cache.regionCount());
cache.removeRegion(REGION_1);
dispatcher.assertLast(Type.REGION_REMOVED, R1);
dispatcher.assertEventCount(3);
assertEquals("unex # regions", 1, cache.regionCount());
print(cache);
UiRegion region = cache.accessRegion(REGION_2.id());
assertEquals("wrong id", REGION_2.id(), region.id());
assertEquals("unex # device IDs", 3, region.deviceIds().size());
assertContains("missing ID", region.deviceIds(), DEVID_4, DEVID_5, DEVID_6);
Region r = region.backingRegion();
print(r);
assertEquals("wrong region name", "Region-R2", r.name());
}
private static final String[] LINKS_2_7 = {D2, "27", D7, "72"};
@Test
public void addLinks() {
title("addLinks");
Iterator<Link> iter = makeLinkPair(LINKS_2_7).iterator();
Link link1 = iter.next();
Link link2 = iter.next();
print(link1);
print(link2);
UiLinkId idA2B = uiLinkId(link1);
UiLinkId idB2A = uiLinkId(link2);
// remember, link IDs are canonicalized
assertEquals("not same link ID", idA2B, idB2A);
// we've established that the ID is the same for both
UiLinkId linkId = idA2B;
cache.addOrUpdateLink(link1);
dispatcher.assertLast(Type.LINK_ADDED_OR_UPDATED, linkId.toString());
dispatcher.assertEventCount(1);
assertEquals("unex # links", 1, cache.linkCount());
UiLink link = cache.accessLink(linkId);
assertEquals("dev A not d2", DEVID_2, link.deviceA());
assertEquals("dev B not d7", DEVID_7, link.deviceB());
assertEquals("wrong backing link A-B", link1, link.linkAtoB());
assertEquals("backing link B-A?", null, link.linkBtoA());
cache.addOrUpdateLink(link2);
dispatcher.assertLast(Type.LINK_ADDED_OR_UPDATED, linkId.toString());
dispatcher.assertEventCount(2);
// NOTE: yes! expect 1 UiLink
assertEquals("unex # links", 1, cache.linkCount());
link = cache.accessLink(linkId);
assertEquals("dev A not d2", DEVID_2, link.deviceA());
assertEquals("dev B not d7", DEVID_7, link.deviceB());
assertEquals("wrong backing link A-B", link1, link.linkAtoB());
assertEquals("wrong backing link B-A", link2, link.linkBtoA());
// now remove links one at a time
cache.removeLink(link1);
// NOTE: yes! ADD_OR_UPDATE, since the link was updated
dispatcher.assertLast(Type.LINK_ADDED_OR_UPDATED, linkId.toString());
dispatcher.assertEventCount(3);
// NOTE: yes! expect 1 UiLink (still)
assertEquals("unex # links", 1, cache.linkCount());
link = cache.accessLink(linkId);
assertEquals("dev A not d2", DEVID_2, link.deviceA());
assertEquals("dev B not d7", DEVID_7, link.deviceB());
assertEquals("backing link A-B?", null, link.linkAtoB());
assertEquals("wrong backing link B-A", link2, link.linkBtoA());
// remove final link
cache.removeLink(link2);
dispatcher.assertLast(Type.LINK_REMOVED, linkId.toString());
dispatcher.assertEventCount(4);
// NOTE: finally link should be removed from cache
assertEquals("unex # links", 0, cache.linkCount());
}
@Test
public void load() {
title("load");
cache.load();
print(cache);
print(cache.dumpString());
// See mock service bundle for expected values (AbstractTopoModelTest)
assertEquals("unex # cnodes", 3, cache.clusterMemberCount());
assertEquals("unex # regions", 3, cache.regionCount());
assertEquals("unex # devices", 9, cache.deviceCount());
assertEquals("unex # hosts", 18, cache.hostCount());
assertEquals("unex # hosts", 26, cache.linkCount());
}
}
......