X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=southbound%2Fsouthbound-it%2Fsrc%2Ftest%2Fjava%2Forg%2Fopendaylight%2Fovsdb%2Fsouthbound%2Fit%2FSouthboundIT.java;h=6817bfa1850b8b5a615816fdd105922c7f495e98;hb=b280e0059271cf85d51d6ab241e6c135c2a81832;hp=425ba4c9da7820166853926fd5941225a24d143c;hpb=22222f3cdfd17381b1e1c9b194e82b9f9fb16a69;p=ovsdb.git diff --git a/southbound/southbound-it/src/test/java/org/opendaylight/ovsdb/southbound/it/SouthboundIT.java b/southbound/southbound-it/src/test/java/org/opendaylight/ovsdb/southbound/it/SouthboundIT.java index 425ba4c9d..6817bfa18 100644 --- a/southbound/southbound-it/src/test/java/org/opendaylight/ovsdb/southbound/it/SouthboundIT.java +++ b/southbound/southbound-it/src/test/java/org/opendaylight/ovsdb/southbound/it/SouthboundIT.java @@ -11,14 +11,11 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; import static org.ops4j.pax.exam.CoreOptions.composite; import static org.ops4j.pax.exam.CoreOptions.maven; +import static org.ops4j.pax.exam.CoreOptions.propagateSystemProperties; import static org.ops4j.pax.exam.CoreOptions.vmOption; import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.editConfigurationFilePut; import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.keepRuntimeFolder; -import com.google.common.collect.ImmutableBiMap; -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; - import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.net.InetAddress; @@ -35,9 +32,11 @@ import javax.inject.Inject; import org.junit.After; import org.junit.Assert; +import org.junit.Assume; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; +import org.junit.internal.AssumptionViolatedException; import org.junit.runner.RunWith; import org.opendaylight.controller.md.sal.binding.api.DataBroker; import org.opendaylight.controller.md.sal.binding.api.DataChangeListener; @@ -45,15 +44,19 @@ import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker; import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent; import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType; import org.opendaylight.controller.mdsal.it.base.AbstractMdsalTestBase; +import org.opendaylight.ovsdb.lib.OvsdbClient; +import org.opendaylight.ovsdb.lib.notation.Version; +import org.opendaylight.ovsdb.lib.schema.DatabaseSchema; import org.opendaylight.ovsdb.southbound.SouthboundConstants; import org.opendaylight.ovsdb.southbound.SouthboundMapper; import org.opendaylight.ovsdb.southbound.SouthboundProvider; import org.opendaylight.ovsdb.southbound.SouthboundUtil; import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils; import org.opendaylight.ovsdb.utils.southbound.utils.SouthboundUtils; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber; -import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid; import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathTypeBase; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeBase; @@ -67,6 +70,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.re import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbPortInterfaceAttributes.VlanMode; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentationBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.QosTypeBase; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeExternalIds; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeExternalIdsBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigs; @@ -75,14 +79,40 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.re import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntryBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntry; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntryBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.Autoattach; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.AutoattachBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.AutoattachKey; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfoBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.DatapathTypeEntry; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.InterfaceTypeEntryBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagedNodeEntry; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchOtherConfigs; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.QosEntries; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.QosEntriesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.QosEntriesKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.Queues; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.QueuesBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.QueuesKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.autoattach.AutoattachExternalIds; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.autoattach.AutoattachExternalIdsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.autoattach.Mappings; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.autoattach.MappingsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QosExternalIds; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QosExternalIdsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QosOtherConfig; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QosOtherConfigBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QueueList; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QueueListBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.qos.entries.QueueListKey; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.queues.QueuesExternalIds; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.queues.QueuesExternalIdsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.queues.QueuesOtherConfig; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.queues.QueuesOtherConfigBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIds; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIdsBuilder; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceLldp; +import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceLldpBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceOtherConfigs; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceOtherConfigsBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.Options; @@ -107,6 +137,7 @@ import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology. import org.opendaylight.yangtools.concepts.Builder; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; +import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier; import org.ops4j.pax.exam.Configuration; import org.ops4j.pax.exam.Option; import org.ops4j.pax.exam.junit.PaxExam; @@ -118,6 +149,11 @@ import org.osgi.framework.BundleContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.common.collect.ImmutableBiMap; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; + /** * Integration tests for southbound-impl * @@ -131,6 +167,8 @@ public class SouthboundIT extends AbstractMdsalTestBase { private static final int OVSDB_UPDATE_TIMEOUT = 1000; private static final int OVSDB_ROUNDTRIP_TIMEOUT = 10000; private static final String FORMAT_STR = "%s_%s_%d"; + private static final Version AUTOATTACH_FROM_VERSION = Version.fromString("7.11.2"); + private static final Version IF_INDEX_FROM_VERSION = Version.fromString("7.2.1"); private static String addressStr; private static int portNumber; private static String connectionType; @@ -138,6 +176,10 @@ public class SouthboundIT extends AbstractMdsalTestBase { private static MdsalUtils mdsalUtils = null; private static Node ovsdbNode; private static int testMethodsRemaining; + private static DataBroker dataBroker; + private static Version schemaVersion; + private static OvsdbClient ovsdbClient; + private static DatabaseSchema dbSchema; @Inject private BundleContext bundleContext; @@ -152,9 +194,17 @@ public class SouthboundIT extends AbstractMdsalTestBase { private final Set> createdIids = new HashSet<>(); private final Set> removedIids = new HashSet<>(); private final Set> updatedIids = new HashSet<>(); + private final InstanceIdentifier iid; + private final int RETRY_WAIT = 100; private NotifyingDataChangeListener(LogicalDatastoreType type) { this.type = type; + this.iid = null; + } + + private NotifyingDataChangeListener(LogicalDatastoreType type, InstanceIdentifier iid) { + this.type = type; + this.iid = iid; } @Override @@ -190,6 +240,50 @@ public class SouthboundIT extends AbstractMdsalTestBase { public boolean isUpdated(InstanceIdentifier iid) { return updatedIids.remove(iid); } + + public void clear() { + createdIids.clear(); + removedIids.clear(); + updatedIids.clear(); + } + + public void registerDataChangeListener() { + dataBroker.registerDataChangeListener(type, iid, this, AsyncDataBroker.DataChangeScope.SUBTREE); + } + + public void waitForCreation(long timeout) throws InterruptedException { + synchronized (this) { + long _start = System.currentTimeMillis(); + LOG.info("Waiting for {} DataChanged creation on {}", type, iid); + while (!isCreated(iid) && (System.currentTimeMillis() - _start) < timeout) { + wait(RETRY_WAIT); + } + LOG.info("Woke up, waited {}ms for creation of {}", (System.currentTimeMillis() - _start), iid); + } + } + + public void waitForDeletion(long timeout) throws InterruptedException { + synchronized (this) { + long _start = System.currentTimeMillis(); + LOG.info("Waiting for {} DataChanged deletion on {}", type, iid); + while (!isRemoved(iid) && (System.currentTimeMillis() - _start) < timeout) { + wait(RETRY_WAIT); + } + LOG.info("Woke up, waited {}ms for deletion of {}", (System.currentTimeMillis() - _start), iid); + } + } + + public void waitForUpdate(long timeout) throws InterruptedException { + synchronized (this) { + long _start = System.currentTimeMillis(); + LOG.info("Waiting for {} DataChanged update on {}", type, iid); + while (!isUpdated(iid) && (System.currentTimeMillis() - _start) < timeout) { + wait(RETRY_WAIT); + } + LOG.info("Woke up, waited {}ms for update of {}", (System.currentTimeMillis() - _start), iid); + } + } + } @Configuration @@ -222,16 +316,6 @@ public class SouthboundIT extends AbstractMdsalTestBase { .getURL(); } - @Override - public String getModuleName() { - return "southbound-impl"; - } - - @Override - public String getInstanceName() { - return "southbound-default"; - } - @Override public MavenUrlReference getFeatureRepo() { return maven() @@ -275,6 +359,10 @@ public class SouthboundIT extends AbstractMdsalTestBase { connectionType, addressStr, portStr); return new Option[] { + propagateSystemProperties( + SouthboundITConstants.SERVER_IPADDRESS, + SouthboundITConstants.SERVER_PORT, + SouthboundITConstants.CONNECTION_TYPE), editConfigurationFilePut(SouthboundITConstants.CUSTOM_PROPERTIES, SouthboundITConstants.SERVER_IPADDRESS, addressStr), editConfigurationFilePut(SouthboundITConstants.CUSTOM_PROPERTIES, @@ -295,11 +383,11 @@ public class SouthboundIT extends AbstractMdsalTestBase { try { super.setup(); } catch (Exception e) { - e.printStackTrace(); + LOG.warn("Failed to setup test", e); } //dataBroker = getSession().getSALService(DataBroker.class); Thread.sleep(3000); - DataBroker dataBroker = SouthboundProvider.getDb(); + dataBroker = SouthboundProvider.getDb(); Assert.assertNotNull("db should not be null", dataBroker); addressStr = bundleContext.getProperty(SouthboundITConstants.SERVER_IPADDRESS); @@ -328,6 +416,17 @@ public class SouthboundIT extends AbstractMdsalTestBase { iid, OPERATIONAL_LISTENER, AsyncDataBroker.DataChangeScope.SUBTREE); ovsdbNode = connectOvsdbNode(connectionInfo); + try { + ovsdbClient = SouthboundIntegrationTestUtils.getTestConnection(this); + assertNotNull("Invalid Client. Check connection params", ovsdbClient); + + dbSchema = ovsdbClient.getSchema(SouthboundIntegrationTestUtils.OPEN_VSWITCH_SCHEMA).get(); + assertNotNull("Invalid dbSchema.", dbSchema); + schemaVersion = dbSchema.getVersion(); + LOG.info("{} schema version = {}", SouthboundIntegrationTestUtils.OPEN_VSWITCH_SCHEMA, schemaVersion); + } catch (Exception e) { + fail("Error accessing schemaVersion in SouthboundIT setUp()." + usage()); + } // Let's count the test methods (we need to use this instead of @AfterClass on teardown() since the latter is // useless with pax-exam) @@ -763,6 +862,314 @@ public class SouthboundIT extends AbstractMdsalTestBase { } } + private static class TestAutoAttach implements AutoCloseable { + private final ConnectionInfo connectionInfo; + private final Uri autoattachId; + private final Uri bridgeId; + + public TestAutoAttach (final ConnectionInfo connectionInfo, + final Uri autoattachId, + final Uri bridgeId, + @Nullable final String systemName, + @Nullable final String systemDescription, + @Nullable final List mappings, + @Nullable final List externalIds) { + this.connectionInfo = connectionInfo; + this.autoattachId = autoattachId; + this.bridgeId = bridgeId; + + Autoattach aaEntry = new AutoattachBuilder() + .setAutoattachId(autoattachId) + .setBridgeId(bridgeId) + .setSystemName(systemName) + .setSystemDescription(systemDescription) + .setMappings(mappings) + .setAutoattachExternalIds(externalIds) + .build(); + InstanceIdentifier iid = SouthboundUtils.createInstanceIdentifier(connectionInfo) + .augmentation(OvsdbNodeAugmentation.class) + .child(Autoattach.class, aaEntry.getKey()); + final NotifyingDataChangeListener aaOperationalListener = + new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, iid); + aaOperationalListener.registerDataChangeListener(); + + Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, iid, aaEntry)); + try { + aaOperationalListener.waitForCreation(OVSDB_ROUNDTRIP_TIMEOUT); + } catch (InterruptedException e) { + LOG.warn("Sleep interrupted while waiting for queue {}", iid, e); + } + } + @Override + public void close() { + final InstanceIdentifier iid = SouthboundUtils.createInstanceIdentifier(connectionInfo) + .augmentation(OvsdbNodeAugmentation.class) + .child(Autoattach.class, new AutoattachKey(this.autoattachId)); + final NotifyingDataChangeListener aaOperationalListener = + new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, iid); + aaOperationalListener.registerDataChangeListener(); + + Assert.assertTrue(mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, iid)); + try { + aaOperationalListener.waitForDeletion(OVSDB_ROUNDTRIP_TIMEOUT); + } catch (InterruptedException e) { + LOG.warn("Sleep interrupted while waiting for qos deletion (qos {})", iid, e); + } + } + } + + @Test + public void testCRUDAutoAttach() throws InterruptedException { + final boolean isOldSchema = schemaVersion.compareTo(AUTOATTACH_FROM_VERSION) < 0; + + ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber); + String testAutoattachId = new String("testAutoattachEntry"); + String testSystemName = new String("testSystemName"); + String testSystemDescription = new String("testSystemDescription"); + String testAutoattachExternalKey = new String("testAutoattachExternalKey"); + String testAutoattachExternalValue = new String("testAutoattachExternalValue"); + + try (TestBridge testBridge = new TestBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME)) { + OvsdbBridgeAugmentation bridge = getBridge(connectionInfo); + Assert.assertNotNull(bridge); + + // CREATE: Create Autoattach table + NodeId nodeId = SouthboundUtils.createManagedNodeId(SouthboundUtils.createInstanceIdentifier( + connectionInfo, bridge.getBridgeName())); + String bridgeId = nodeId.getValue(); + try(TestAutoAttach testAutoattach = new TestAutoAttach(connectionInfo, new Uri(testAutoattachId), + new Uri(bridgeId), testSystemName, testSystemDescription, null, null)) { + // READ: Read md-sal operational datastore to see if the AutoAttach table was created + // and if Bridge table was updated with AutoAttach Uuid + OvsdbNodeAugmentation ovsdbNodeAugmentation = getOvsdbNode(connectionInfo, + LogicalDatastoreType.OPERATIONAL); + Autoattach operAa = getAutoAttach(ovsdbNodeAugmentation, new Uri(testAutoattachId)); + + // skip tests after verifying that Autoattach doesn't break with unsupported schema + Assume.assumeFalse(isOldSchema); + + // FIXME: Remove once CRUD is supported + Assume.assumeFalse(operAa == null); + + Assert.assertNotNull(operAa); + Assert.assertEquals(testSystemName, operAa.getSystemName()); + bridge = getBridge(connectionInfo); + Uuid aaUuid = new Uuid(operAa.getAutoattachUuid().getValue()); + Assert.assertEquals(aaUuid, bridge.getAutoAttach()); + + // UPDATE: Update mappings column of AutoAttach table that was created + List mappings = ImmutableList.of(new MappingsBuilder().setMappingsKey(100L).setMappingsValue(200).build()); + Autoattach updatedAa = new AutoattachBuilder() + .setAutoattachId(new Uri(testAutoattachId)) + .setMappings(mappings) + .build(); + InstanceIdentifier iid = SouthboundUtils.createInstanceIdentifier(connectionInfo) + .augmentation(OvsdbNodeAugmentation.class) + .child(Autoattach.class, updatedAa.getKey()); + final NotifyingDataChangeListener aaOperationalListener = + new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, iid); + aaOperationalListener.registerDataChangeListener(); + Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, iid, updatedAa)); + aaOperationalListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT); + + // UPDATE: Update external_ids column of AutoAttach table that was created + List externalIds = new ArrayList<>(); + externalIds.add(new AutoattachExternalIdsBuilder() + .setAutoattachExternalIdKey(testAutoattachExternalKey) + .setAutoattachExternalIdValue(testAutoattachExternalValue) + .build()); + updatedAa = new AutoattachBuilder() + .setAutoattachId(new Uri(testAutoattachId)) + .setAutoattachExternalIds(externalIds) + .build(); + Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, iid, updatedAa)); + aaOperationalListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT); + + // READ: Read the updated AutoAttach table for latest mappings and external_ids column value + ovsdbNodeAugmentation = getOvsdbNode(connectionInfo, + LogicalDatastoreType.OPERATIONAL); + operAa = getAutoAttach(ovsdbNodeAugmentation, new Uri(testAutoattachId)); + Assert.assertNotNull(operAa); + List operMappingsList = operAa.getMappings(); + for (Mappings operMappings: operMappingsList) { + Assert.assertEquals(mappings.get(operMappingsList.indexOf(operMappings)).getMappingsKey(), operMappings.getMappingsKey()); + Assert.assertEquals(mappings.get(operMappingsList.indexOf(operMappings)).getMappingsValue(), operMappings.getMappingsValue()); + } + List operExternalIds = operAa.getAutoattachExternalIds(); + externalIds.add(new AutoattachExternalIdsBuilder() + .setAutoattachExternalIdKey(SouthboundConstants.AUTOATTACH_ID_EXTERNAL_ID_KEY) + .setAutoattachExternalIdValue(operAa.getAutoattachId().getValue()) + .build()); + for (AutoattachExternalIds operExternalId : operExternalIds) { + Assert.assertEquals(externalIds.get(operExternalIds.indexOf(operExternalId)).getAutoattachExternalIdKey(), + operExternalId.getAutoattachExternalIdKey()); + Assert.assertEquals(externalIds.get(operExternalIds.indexOf(operExternalId)).getAutoattachExternalIdValue(), + operExternalId.getAutoattachExternalIdValue()); + } + + // DELETE: Delete AutoAttach table + Assert.assertTrue(mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, iid)); + aaOperationalListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT); + ovsdbNodeAugmentation = getOvsdbNode(connectionInfo, + LogicalDatastoreType.OPERATIONAL); + operAa = getAutoAttach(ovsdbNodeAugmentation, new Uri(testAutoattachId)); + Assert.assertNull(operAa); + } catch (AssumptionViolatedException e) { + LOG.warn("Skipped test for Autoattach due to unsupported schema", e); + } catch (Exception e) { + fail("Unexpected exception in CRUD test for Autoattach table for schema:" + schemaVersion.toString() +". " + e); + } + } + } + + private Autoattach getAutoAttach(OvsdbNodeAugmentation ovsdbNodeAugmentation, Uri uri) { + if (ovsdbNodeAugmentation.getAutoattach() != null + && !ovsdbNodeAugmentation.getAutoattach().isEmpty()) { + for (Autoattach aa : ovsdbNodeAugmentation.getAutoattach()) { + if (aa.getKey().getAutoattachId().equals(uri)) { + return aa; + } + } + } + return null; + } + + private static class TestQos implements AutoCloseable { + private final ConnectionInfo connectionInfo; + private final Uri qosId; + + /** + * Creates a test qos entry which can be automatically removed when no longer necessary. + * + * @param connectionInfo The connection information. + * @param qosId The Qos identifier. + * @param qosType The qos type. + * @param externalIds The external identifiers if any. + * @param otherConfigs The other configuration items if any. + */ + public TestQos(final ConnectionInfo connectionInfo, + final Uri qosId, + final Class qosType, + @Nullable final List externalIds, + @Nullable final List otherConfigs) { + this.connectionInfo = connectionInfo; + this.qosId = qosId; + + QosEntries qosEntry = new QosEntriesBuilder() + .setQosId(qosId) + .setQosType(qosType) + .setQosExternalIds(externalIds) + .setQosOtherConfig(otherConfigs) + .build(); + InstanceIdentifier qeIid = SouthboundUtils.createInstanceIdentifier(connectionInfo) + .augmentation(OvsdbNodeAugmentation.class) + .child(QosEntries.class, qosEntry.getKey()); + final NotifyingDataChangeListener qosOperationalListener = + new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, qeIid); + qosOperationalListener.registerDataChangeListener(); + + Assert.assertTrue( + mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, + qeIid, qosEntry)); + + try { + qosOperationalListener.waitForCreation(OVSDB_ROUNDTRIP_TIMEOUT); + } catch (InterruptedException e) { + LOG.warn("Sleep interrupted while waiting for queue {}", qeIid, e); + } + + } + + @Override + public void close() { + final InstanceIdentifier qeIid = SouthboundUtils.createInstanceIdentifier(connectionInfo) + .augmentation(OvsdbNodeAugmentation.class) + .child(QosEntries.class, new QosEntriesKey(this.qosId)); + final NotifyingDataChangeListener qosOperationalListener = + new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, qeIid); + qosOperationalListener.registerDataChangeListener(); + + Assert.assertTrue(mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, qeIid)); + try { + qosOperationalListener.waitForDeletion(OVSDB_ROUNDTRIP_TIMEOUT); + } catch (InterruptedException e) { + LOG.warn("Sleep interrupted while waiting for qos deletion (qos {})", qeIid, e); + } + } + } + + private static class TestQueue implements AutoCloseable { + private final ConnectionInfo connectionInfo; + private final Uri queueId; + + /** + * Creates a test queue entry which can be automatically removed when no longer necessary. + * + * @param connectionInfo The connection information. + * @param queueId The Queue identifier. + * @param queueDscp The queue dscp value. + * @param externalIds The external identifiers if any. + * @param otherConfigs The other configuration items if any. + */ + public TestQueue(final ConnectionInfo connectionInfo, + final Uri queueId, + final Short queueDscp, + @Nullable final List externalIds, + @Nullable final List otherConfigs) { + this.connectionInfo = connectionInfo; + this.queueId = queueId; + + Queues queue = new QueuesBuilder() + .setQueueId(queueId) + .setDscp(queueDscp) + .setQueuesExternalIds(externalIds) + .setQueuesOtherConfig(otherConfigs) + .build(); + InstanceIdentifier qIid = SouthboundUtils.createInstanceIdentifier(connectionInfo) + .augmentation(OvsdbNodeAugmentation.class) + .child(Queues.class, queue.getKey()); + final NotifyingDataChangeListener queueOperationalListener = + new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, qIid); + queueOperationalListener.registerDataChangeListener(); + + Assert.assertTrue( + mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, + qIid, queue)); + + try { + queueOperationalListener.waitForCreation(OVSDB_ROUNDTRIP_TIMEOUT); + } catch (InterruptedException e) { + LOG.warn("Sleep interrupted while waiting for queue {}", queueId, e); + } + } + + @Override + public void close() { + InstanceIdentifier qIid = SouthboundUtils.createInstanceIdentifier(connectionInfo) + .augmentation(OvsdbNodeAugmentation.class) + .child(Queues.class, new QueuesKey(this.queueId)); + final NotifyingDataChangeListener queueOperationalListener = + new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, qIid); + queueOperationalListener.registerDataChangeListener(); + + Assert.assertTrue(mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, qIid)); + try { + queueOperationalListener.waitForDeletion(OVSDB_ROUNDTRIP_TIMEOUT); + } catch (InterruptedException e) { + LOG.warn("Sleep interrupted while waiting for queue deletion (queue {})", queueId, e); + } + } + } + + private OvsdbNodeAugmentation getOvsdbNode(ConnectionInfo connectionInfo, LogicalDatastoreType store) { + InstanceIdentifier nodeIid = SouthboundUtils.createInstanceIdentifier(connectionInfo); + Node node = mdsalUtils.read(store, nodeIid); + Assert.assertNotNull(node); + OvsdbNodeAugmentation ovsdbNodeAugmentation = node.getAugmentation(OvsdbNodeAugmentation.class); + Assert.assertNotNull(ovsdbNodeAugmentation); + return ovsdbNodeAugmentation; + } + private OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo) { return getBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME); } @@ -860,6 +1267,45 @@ public class SouthboundIT extends AbstractMdsalTestBase { return tpList.get(index).getAugmentation(OvsdbTerminationPointAugmentation.class); } + @Test + public void testCRUDTerminationPointIfIndex() throws InterruptedException { + final boolean isOldSchema = schemaVersion.compareTo(IF_INDEX_FROM_VERSION) < 0; + Assume.assumeFalse(isOldSchema); + ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber); + + // Test create ifIndex + try (TestBridge testBridge = new TestBridge(connectionInfo, null, SouthboundITConstants.BRIDGE_NAME, null, true, + SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"), + true, SouthboundMapper.createDatapathType("netdev"), null, null, null)) { + OvsdbBridgeAugmentation bridge = getBridge(connectionInfo); + Assert.assertNotNull(bridge); + LOG.info("bridge: {}", bridge); + NodeId nodeId = SouthboundMapper.createManagedNodeId(SouthboundUtils.createInstanceIdentifier( + connectionInfo, bridge.getBridgeName())); + OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder = + createGenericOvsdbTerminationPointAugmentationBuilder(); + String portName = "testIfIndex"; + ovsdbTerminationBuilder.setName(portName); + + Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder)); + InstanceIdentifier terminationPointIid = getTpIid(connectionInfo, bridge); + Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid); + Assert.assertNotNull(terminationPointNode); + + // Test read ifIndex + List terminationPoints = terminationPointNode.getTerminationPoint(); + for (TerminationPoint terminationPoint : terminationPoints) { + OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation = + terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class); + if (ovsdbTerminationPointAugmentation.getName().equals(portName)) { + Long ifIndex = ovsdbTerminationPointAugmentation.getIfindex(); + Assert.assertNotNull(ifIndex); + LOG.info("ifIndex: {} for the port:{}", ifIndex, portName); + } + } + } + } + @Test public void testCRDTerminationPointOfPort() throws InterruptedException { final Long OFPORT_EXPECTED = 45002L; @@ -1092,6 +1538,17 @@ public class SouthboundIT extends AbstractMdsalTestBase { new InterfaceExternalIdsSouthboundHelper()); } + /* + * Tests the CRUD operations for Interface lldp. + * + * @see SouthboundIT.generateInterfaceLldpTestCases() for specific test case information + */ + @Test + public void testCRUDTerminationPointInterfaceLldp() throws InterruptedException { + testCRUDTerminationPoint(new SouthboundInterfaceLldpBuilder(), "TPInterfaceLldp", + new InterfaceLldpSouthboundHelper()); + } + /* * Tests the CRUD operations for TerminationPoint options. * @@ -1124,6 +1581,89 @@ public class SouthboundIT extends AbstractMdsalTestBase { new PortOtherConfigsSouthboundHelper()); } + @Test + public void testCRUDTerminationPoints() throws InterruptedException { + String port1 = "vx1"; + String port2 = "vxlanport"; + ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber); + + try (TestBridge testBridge = new TestBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME)) { + OvsdbBridgeAugmentation bridge = getBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME); + Assert.assertNotNull(bridge); + NodeId nodeId = SouthboundUtils.createManagedNodeId(SouthboundUtils.createInstanceIdentifier( + connectionInfo, bridge.getBridgeName())); + OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder = + createGenericOvsdbTerminationPointAugmentationBuilder(); + + // add and delete a single port + String portName = port1; + ovsdbTerminationBuilder.setName(portName); + Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder)); + InstanceIdentifier terminationPointIid = getTpIid(connectionInfo, bridge); + Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid); + Assert.assertNotNull(terminationPointNode); + + SouthboundUtils.createInstanceIdentifier(connectionInfo, + new OvsdbBridgeName(SouthboundITConstants.BRIDGE_NAME)); + portName = port1; + InstanceIdentifier nodePath = + SouthboundUtils.createInstanceIdentifier(connectionInfo, + new OvsdbBridgeName(SouthboundITConstants.BRIDGE_NAME)) + .child(TerminationPoint.class, new TerminationPointKey(new TpId(portName))); + + Assert.assertTrue("failed to delete port " + portName, + mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, nodePath)); + LOG.info("shague: waiting for delete {}", portName); + Thread.sleep(1000); + TerminationPoint terminationPoint = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, nodePath); + Assert.assertNull(terminationPoint); + + // add two ports, then delete them + portName = port1; + ovsdbTerminationBuilder.setName(portName); + Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder)); + terminationPointIid = getTpIid(connectionInfo, bridge); + terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid); + Assert.assertNotNull(terminationPointNode); + + portName = port2; + ovsdbTerminationBuilder.setName(portName); + Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder)); + terminationPointIid = getTpIid(connectionInfo, bridge); + terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid); + Assert.assertNotNull(terminationPointNode); + + SouthboundUtils.createInstanceIdentifier(connectionInfo, + new OvsdbBridgeName(SouthboundITConstants.BRIDGE_NAME)); + portName = port1; + nodePath = + SouthboundUtils.createInstanceIdentifier(connectionInfo, + new OvsdbBridgeName(SouthboundITConstants.BRIDGE_NAME)) + .child(TerminationPoint.class, new TerminationPointKey(new TpId(portName))); + + Assert.assertTrue("failed to delete port " + portName, + mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, nodePath)); + LOG.info("shague: waiting for delete {}", portName); + Thread.sleep(1000); + terminationPoint = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, nodePath); + Assert.assertNull(terminationPoint); + + portName = port2; + nodePath = SouthboundUtils.createInstanceIdentifier(connectionInfo, + new OvsdbBridgeName(SouthboundITConstants.BRIDGE_NAME)) + .child(TerminationPoint.class, new TerminationPointKey(new TpId(portName))); + + Assert.assertTrue("failed to delete port " + portName, + mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, nodePath)); + LOG.info("shague: waiting for delete {}", portName); + Thread.sleep(1000); + terminationPoint = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, nodePath); + Assert.assertNull(terminationPoint); + + // DELETE handled by TestBridge + } + } + @Test public void testCRUDTerminationPointVlan() throws InterruptedException { final Integer CREATED_VLAN_ID = 4000; @@ -1361,6 +1901,69 @@ public class SouthboundIT extends AbstractMdsalTestBase { } } + /* + * Tests setting and deleting qos field in a port. + */ + @Test + public void testCRUDTerminationPointQos() throws InterruptedException { + ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber); + String testQosId = new String("testQosEntry"); + + // CREATE + try (TestBridge testBridge = new TestBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME); + TestQos testQos = new TestQos(connectionInfo, new Uri(testQosId), + SouthboundMapper.createQosType(SouthboundConstants.QOS_LINUX_HFSC), null, null)) { + OvsdbNodeAugmentation ovsdbNodeAugmentation = getOvsdbNode(connectionInfo, + LogicalDatastoreType.OPERATIONAL); + QosEntries operQos = getQos(new Uri(testQosId), ovsdbNodeAugmentation); + Assert.assertNotNull(operQos); + Uuid qosUuid = new Uuid(operQos.getQosUuid().getValue()); + + OvsdbBridgeAugmentation bridge = getBridge(connectionInfo); + Assert.assertNotNull(bridge); + NodeId nodeId = SouthboundUtils.createManagedNodeId(connectionInfo, bridge.getBridgeName()); + OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder = + createGenericOvsdbTerminationPointAugmentationBuilder(); + String portName = "testTerminationPointQos"; + ovsdbTerminationBuilder.setName(portName); + ovsdbTerminationBuilder.setQos(qosUuid); + Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder)); + + // READ and check that qos uuid has been added to the port + InstanceIdentifier tpEntryIid = getTpIid(connectionInfo, bridge) + .child(TerminationPoint.class, new TerminationPointKey(new TpId(portName))); + TerminationPoint terminationPoint = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, tpEntryIid); + Assert.assertNotNull(terminationPoint); + OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation = + terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class); + Assert.assertEquals(ovsdbTerminationPointAugmentation.getQos(), qosUuid); + + // UPDATE - remove the qos entry from the port + OvsdbTerminationPointAugmentationBuilder tpUpdateAugmentationBuilder = + new OvsdbTerminationPointAugmentationBuilder(); + tpUpdateAugmentationBuilder.setName(portName); + TerminationPointBuilder tpUpdateBuilder = new TerminationPointBuilder(); + tpUpdateBuilder.setKey(new TerminationPointKey(new TpId(portName))); + tpUpdateBuilder.addAugmentation( + OvsdbTerminationPointAugmentation.class, + tpUpdateAugmentationBuilder.build()); + tpUpdateBuilder.setTpId(new TpId(portName)); + + Assert.assertTrue( + mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, tpEntryIid, tpUpdateBuilder.build())); + Thread.sleep(OVSDB_UPDATE_TIMEOUT); + + // READ and verify that qos uuid has been removed from port + TerminationPoint terminationPointUpdate = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, tpEntryIid); + Assert.assertNotNull(terminationPointUpdate); + OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentationUpdate = + terminationPointUpdate.getAugmentation(OvsdbTerminationPointAugmentation.class); + Assert.assertNull(ovsdbTerminationPointAugmentationUpdate.getQos()); + + // DELETE handled by TestBridge + } + } + @Test public void testGetOvsdbNodes() throws InterruptedException { ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber); @@ -1480,6 +2083,464 @@ public class SouthboundIT extends AbstractMdsalTestBase { new BridgeExternalIdsSouthboundHelper()); } + @Test + public void testAddDeleteQos() throws InterruptedException { + ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber); + OvsdbNodeAugmentation ovsdbNodeAugmentation; + Uri qosUri = new Uri("QOS-ROW"); + List typeList = new ArrayList(); + typeList.add(SouthboundConstants.QOS_LINUX_HTB); + typeList.add(SouthboundConstants.QOS_LINUX_HFSC); + + for (String qosType : typeList) { + try (TestQos testQos = new TestQos(connectionInfo, qosUri, SouthboundMapper.createQosType(qosType), null, null)) { + ovsdbNodeAugmentation = getOvsdbNode(connectionInfo, + LogicalDatastoreType.OPERATIONAL); + QosEntries operQosHtb = getQos(qosUri, ovsdbNodeAugmentation); + Assert.assertNotNull(operQosHtb); + } + ovsdbNodeAugmentation = getOvsdbNode(connectionInfo, + LogicalDatastoreType.OPERATIONAL); + QosEntries operQosHtb = getQos(qosUri, ovsdbNodeAugmentation); + Assert.assertNull(operQosHtb); + } + } + + @Test + public void testAddDeleteQueue() throws InterruptedException { + ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber); + Uri queueUri = new Uri("QUEUE-A1"); + + try (TestQueue testQueue = new TestQueue(connectionInfo, queueUri, new Short("25"), null, null)) { + OvsdbNodeAugmentation ovsdbNodeAugmentation = getOvsdbNode(connectionInfo, + LogicalDatastoreType.OPERATIONAL); + Queues operQueue = getQueue(queueUri, ovsdbNodeAugmentation); + Assert.assertNotNull(operQueue); + } + OvsdbNodeAugmentation ovsdbNodeAugmentation = getOvsdbNode(connectionInfo, + LogicalDatastoreType.OPERATIONAL); + Queues operQueue = getQueue(queueUri, ovsdbNodeAugmentation); + Assert.assertNull(operQueue); + } + + private static class SouthboundQueuesExternalIdsHelper implements SouthboundQueueHelper { + @Override + public void writeValues(QueuesBuilder builder, List values) { + builder.setQueuesExternalIds(values); + } + + @Override + public List readValues(Queues queue) { + return queue.getQueuesExternalIds(); + } + } + + private static class SouthboundQueuesOtherConfigHelper implements SouthboundQueueHelper { + @Override + public void writeValues(QueuesBuilder builder, List values) { + builder.setQueuesOtherConfig(values); + } + + @Override + public List readValues(Queues queue) { + return queue.getQueuesOtherConfig(); + } + } + + private interface SouthboundQueueHelper { + void writeValues(QueuesBuilder builder, List values); + List readValues(Queues queue); + } + + private Queues getQueue(Uri queueId, OvsdbNodeAugmentation node) { + for (Queues queue : node.getQueues()) { + if (queue.getKey().getQueueId().getValue().equals(queueId.getValue())) + return queue; + } + return null; + } + + private static class SouthboundQosExternalIdsHelper implements SouthboundQosHelper { + @Override + public void writeValues(QosEntriesBuilder builder, List values) { + builder.setQosExternalIds(values); + } + + @Override + public List readValues(QosEntries qos) { + return qos.getQosExternalIds(); + } + } + + private static class SouthboundQosOtherConfigHelper implements SouthboundQosHelper { + @Override + public void writeValues(QosEntriesBuilder builder, List values) { + builder.setQosOtherConfig(values); + } + + @Override + public List readValues(QosEntries qos) { + return qos.getQosOtherConfig(); + } + } + + private interface SouthboundQosHelper { + void writeValues(QosEntriesBuilder builder, List values); + List readValues(QosEntries qos); + } + + private QosEntries getQos(Uri qosId, OvsdbNodeAugmentation node) { + for (QosEntries qos : node.getQosEntries()) { + if (qos.getKey().getQosId().equals(qosId)) + return qos; + } + return null; + } + + private void testCRUDQueue( + KeyValueBuilder builder, String prefix, SouthboundQueueHelper helper) + throws InterruptedException { + + ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber); + + // updateFromTestCases represent the original test case value. updateToTestCases represent the new value after + // the update has been performed. + List> updateFromTestCases = generateKeyValueTestCases(builder, prefix + "From"); + List> updateToTestCases = generateKeyValueTestCases(builder, prefix + "To"); + + for (SouthboundTestCase updateFromTestCase : updateFromTestCases) { + for (SouthboundTestCase updateToTestCase : updateToTestCases) { + String testQueueId = String.format("%s_%s", prefix, updateToTestCase.name); + + // CREATE: and update the test queue with starting values. + try (TestQueue testQueue = new TestQueue(connectionInfo, new Uri(testQueueId), new Short("45"), null, null)) { + QueuesBuilder queuesBuilder = new QueuesBuilder(); + queuesBuilder.setQueueId(new Uri(testQueueId)); + InstanceIdentifier queueIid = SouthboundUtils.createInstanceIdentifier(connectionInfo) + .augmentation(OvsdbNodeAugmentation.class) + .child(Queues.class, queuesBuilder.build().getKey()); + final NotifyingDataChangeListener queueConfigurationListener = + new NotifyingDataChangeListener(LogicalDatastoreType.CONFIGURATION, queueIid); + queueConfigurationListener.registerDataChangeListener(); + final NotifyingDataChangeListener queueOperationalListener = + new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, queueIid); + queueOperationalListener.registerDataChangeListener(); + + helper.writeValues(queuesBuilder, updateFromTestCase.inputValues); + Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, + queueIid, queuesBuilder.build())); + queueConfigurationListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT); + + // READ: Read the test queue and ensure changes are propagated to the CONFIGURATION data store, + // then repeat for OPERATIONAL data store + OvsdbNodeAugmentation updateFromConfigurationOvsdbNodeAugmentation = getOvsdbNode(connectionInfo, + LogicalDatastoreType.CONFIGURATION); + Queues queueFromConfig = getQueue(new Uri(testQueueId), updateFromConfigurationOvsdbNodeAugmentation); + if (queueFromConfig != null) { + List updateFromConfigurationValues = + helper.readValues(queueFromConfig); + assertExpectedExist(updateFromTestCase.expectedValues, updateFromConfigurationValues); + } + + queueOperationalListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT); + OvsdbNodeAugmentation updateFromOperationalOvsdbNodeAugmentation = getOvsdbNode(connectionInfo, + LogicalDatastoreType.OPERATIONAL); + Queues queueFromOper = getQueue(new Uri(testQueueId), updateFromOperationalOvsdbNodeAugmentation); + if (queueFromOper != null) { + List updateFromOperationalValues = + helper.readValues(queueFromOper); + assertExpectedExist(updateFromTestCase.expectedValues, updateFromOperationalValues); + } + + // UPDATE: update the values + QueuesBuilder queuesUpdateBuilder = new QueuesBuilder(); + queuesUpdateBuilder.setQueueId(new Uri(testQueueId)); + helper.writeValues(queuesUpdateBuilder, updateToTestCase.inputValues); + Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, + queueIid, queuesUpdateBuilder.build())); + queueConfigurationListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT); + + // READ: the test queue and ensure changes are propagated to the CONFIGURATION data store, + // then repeat for OPERATIONAL data store + OvsdbNodeAugmentation updateToConfigurationOvsdbNodeAugmentation = getOvsdbNode(connectionInfo, + LogicalDatastoreType.CONFIGURATION); + Queues queueToConfig = getQueue(new Uri(testQueueId), updateToConfigurationOvsdbNodeAugmentation); + if (queueToConfig != null) { + List updateToConfigurationValues = + helper.readValues(queueToConfig); + assertExpectedExist(updateToTestCase.expectedValues, updateToConfigurationValues); + } + + queueOperationalListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT); + OvsdbNodeAugmentation updateToOperationalOvsdbNodeAugmentation = getOvsdbNode(connectionInfo, + LogicalDatastoreType.OPERATIONAL); + Queues queueToOper = getQueue(new Uri(testQueueId), updateToOperationalOvsdbNodeAugmentation); + if (queueToOper != null) { + List updateToOperationalValues = + helper.readValues(queueToOper); + assertExpectedExist(updateToTestCase.expectedValues, updateToOperationalValues); + } + + // DELETE handled by TestQueue + } + } + } + } + + @Test + public void testCRUDQueueExternalIds() throws InterruptedException { + testCRUDQueue(new SouthboundQueuesExternalIdsBuilder(), "QueueExternalIds", + new SouthboundQueuesExternalIdsHelper()); + } + + @Test + public void testCRUDQueueOtherConfig() throws InterruptedException { + testCRUDQueue(new SouthboundQueuesOtherConfigBuilder(), "QueueOtherConfig", + new SouthboundQueuesOtherConfigHelper()); + } + + @Test + public void testCRUDQueueDscp() throws InterruptedException { + ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber); + String testQueueId = "testQueueDscp"; + + // CREATE: and update the test queue with starting values. + try (TestQueue testQueue = new TestQueue(connectionInfo, new Uri(testQueueId), new Short("0"), null, null)) { + for (Short dscp = 1; dscp < 64; dscp++) { + QueuesBuilder queuesBuilder = new QueuesBuilder(); + queuesBuilder.setQueueId(new Uri(testQueueId)); + InstanceIdentifier queueIid = SouthboundUtils.createInstanceIdentifier(connectionInfo) + .augmentation(OvsdbNodeAugmentation.class) + .child(Queues.class, queuesBuilder.build().getKey()); + final NotifyingDataChangeListener queueOperationalListener = + new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, queueIid); + queueOperationalListener.registerDataChangeListener(); + + queuesBuilder.setDscp(dscp); + Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, + queueIid, queuesBuilder.build())); + queueOperationalListener.waitForUpdate(OVSDB_ROUNDTRIP_TIMEOUT); + + // READ: Read the test queue and ensure changes are propagated to the OPERATIONAL data store + // assumption is that CONFIGURATION was updated if OPERATIONAL is correct + OvsdbNodeAugmentation ovsdbNodeAugmentation = getOvsdbNode(connectionInfo, + LogicalDatastoreType.OPERATIONAL); + Queues operQueue = getQueue(new Uri(testQueueId), ovsdbNodeAugmentation); + Assert.assertNotNull(operQueue); + Short operDscp = operQueue.getDscp(); + Assert.assertNotNull(operDscp); + Assert.assertEquals(dscp, operDscp); + } + + // DELETE handled by TestQueue + } + + } + + private void testCRUDQos( + KeyValueBuilder builder, String prefix, SouthboundQosHelper helper) + throws InterruptedException { + + ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber); + + // updateFromTestCases represent the original test case value. updateToTestCases represent the new value after + // the update has been performed. + List> updateFromTestCases = generateKeyValueTestCases(builder, prefix + "From"); + List> updateToTestCases = generateKeyValueTestCases(builder, prefix + "To"); + + for (SouthboundTestCase updateFromTestCase : updateFromTestCases) { + for (SouthboundTestCase updateToTestCase : updateToTestCases) { + String testQosId = String.format("%s_%s", prefix, updateToTestCase.name); + + // CREATE: and update the test qos with starting values. + try (TestQos testQos = new TestQos(connectionInfo, new Uri(testQosId), SouthboundMapper.createQosType(SouthboundConstants.QOS_LINUX_HTB), null, null)) { + QosEntriesBuilder qosBuilder = new QosEntriesBuilder(); + qosBuilder.setQosId(new Uri(testQosId)); + InstanceIdentifier qosIid = SouthboundUtils.createInstanceIdentifier(connectionInfo) + .augmentation(OvsdbNodeAugmentation.class) + .child(QosEntries.class, qosBuilder.build().getKey()); + final NotifyingDataChangeListener qosConfigurationListener = + new NotifyingDataChangeListener(LogicalDatastoreType.CONFIGURATION, qosIid); + qosConfigurationListener.registerDataChangeListener(); + final NotifyingDataChangeListener qosOperationalListener = + new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, qosIid); + qosOperationalListener.registerDataChangeListener(); + + helper.writeValues(qosBuilder, updateFromTestCase.inputValues); + Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, + qosIid, qosBuilder.build())); + qosConfigurationListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT); + + // READ: Read the test queue and ensure changes are propagated to the CONFIGURATION data store, + // then repeat for OPERATIONAL data store + OvsdbNodeAugmentation updateFromConfigurationOvsdbNodeAugmentation = getOvsdbNode(connectionInfo, + LogicalDatastoreType.CONFIGURATION); + QosEntries qosFromConfig = getQos(new Uri(testQosId), updateFromConfigurationOvsdbNodeAugmentation); + if (qosFromConfig != null) { + List updateFromConfigurationValues = + helper.readValues(qosFromConfig); + assertExpectedExist(updateFromTestCase.expectedValues, updateFromConfigurationValues); + } + + qosOperationalListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT); + OvsdbNodeAugmentation updateFromOperationalOvsdbNodeAugmentation = getOvsdbNode(connectionInfo, + LogicalDatastoreType.OPERATIONAL); + QosEntries qosFromOper = getQos(new Uri(testQosId), updateFromOperationalOvsdbNodeAugmentation); + if (qosFromOper != null) { + List updateFromOperationalValues = + helper.readValues(qosFromOper); + assertExpectedExist(updateFromTestCase.expectedValues, updateFromOperationalValues); + } + + // UPDATE: update the values + QosEntriesBuilder qosUpdateBuilder = new QosEntriesBuilder(); + qosUpdateBuilder.setQosId(new Uri(testQosId)); + helper.writeValues(qosUpdateBuilder, updateToTestCase.inputValues); + Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, + qosIid, qosUpdateBuilder.build())); + qosConfigurationListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT); + + // READ: the test queue and ensure changes are propagated to the CONFIGURATION data store, + // then repeat for OPERATIONAL data store + OvsdbNodeAugmentation updateToConfigurationOvsdbNodeAugmentation = getOvsdbNode(connectionInfo, + LogicalDatastoreType.CONFIGURATION); + QosEntries qosToConfig = getQos(new Uri(testQosId), updateToConfigurationOvsdbNodeAugmentation); + if (qosToConfig != null) { + List updateToConfigurationValues = + helper.readValues(qosToConfig); + assertExpectedExist(updateToTestCase.expectedValues, updateToConfigurationValues); + } + + qosOperationalListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT); + OvsdbNodeAugmentation updateToOperationalOvsdbNodeAugmentation = getOvsdbNode(connectionInfo, + LogicalDatastoreType.OPERATIONAL); + QosEntries qosToOper = getQos(new Uri(testQosId), updateToOperationalOvsdbNodeAugmentation); + if (qosToOper != null) { + List updateToOperationalValues = + helper.readValues(qosToOper); + assertExpectedExist(updateToTestCase.expectedValues, updateToOperationalValues); + } + + // DELETE handled by TestQueue + } + } + } + } + + @Test + public void testCRUDQosExternalIds() throws InterruptedException { + testCRUDQos(new SouthboundQosExternalIdsBuilder(), "QosExternalIds", + new SouthboundQosExternalIdsHelper()); + } + + @Test + public void testCRUDQosOtherConfig() throws InterruptedException { + testCRUDQos(new SouthboundQosOtherConfigBuilder(), "QosOtherConfig", + new SouthboundQosOtherConfigHelper()); + } + @Test + public void testCRUDQosQueues() throws InterruptedException { + ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber); + String testQosId = "testQosQueues"; + + // CREATE: and update the test queue with starting values. + try (TestQos testQos = new TestQos(connectionInfo, new Uri(testQosId), + SouthboundMapper.createQosType(SouthboundConstants.QOS_LINUX_HTB), null, null); + TestQueue testQueue1 = new TestQueue(connectionInfo, new Uri("queue1"), new Short("12"), null, null); + TestQueue testQueue2 = new TestQueue(connectionInfo, new Uri("queue2"), new Short("35"), null, null)) { + QosEntriesBuilder qosBuilder = new QosEntriesBuilder(); + qosBuilder.setQosId(new Uri(testQosId)); + InstanceIdentifier qosIid = SouthboundUtils.createInstanceIdentifier(connectionInfo) + .augmentation(OvsdbNodeAugmentation.class) + .child(QosEntries.class, qosBuilder.build().getKey()); + final NotifyingDataChangeListener qosOperationalListener = + new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL, qosIid); + qosOperationalListener.registerDataChangeListener(); + + // READ, UPDATE: Read the UUIDs of the Queue rows and add them to the + // configuration of the Qos row. + OvsdbNodeAugmentation ovsdbNodeAugmentation = getOvsdbNode(connectionInfo, + LogicalDatastoreType.OPERATIONAL); + Queues operQueue1 = getQueue(new Uri("queue1"), ovsdbNodeAugmentation); + Assert.assertNotNull(operQueue1); + Uuid queue1Uuid = new Uuid(operQueue1.getQueueUuid().getValue()); + Queues operQueue2 = getQueue(new Uri("queue2"), ovsdbNodeAugmentation); + Assert.assertNotNull(operQueue2); + Uuid queue2Uuid = new Uuid(operQueue2.getQueueUuid().getValue()); + + List queueList = new ArrayList<>(); + queueList.add(new QueueListBuilder().setQueueNumber(new Long("0")) + .setQueueUuid(queue1Uuid).build()); + queueList.add(new QueueListBuilder().setQueueNumber(new Long("1")) + .setQueueUuid(queue2Uuid).build()); + qosBuilder.setQueueList(queueList); + + Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, + qosIid, qosBuilder.build())); + qosOperationalListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT); + + // READ: Read the test qos and ensure changes are propagated to the OPERATIONAL data store + // assumption is that CONFIGURATION was updated if OPERATIONAL is correct + ovsdbNodeAugmentation = getOvsdbNode(connectionInfo, + LogicalDatastoreType.OPERATIONAL); + QosEntries operQos = getQos(new Uri(testQosId), ovsdbNodeAugmentation); + Assert.assertNotNull(operQos); + List operQueueList = operQos.getQueueList(); + Assert.assertNotNull(operQueueList); + for (QueueList queueEntry : queueList) { + Assert.assertTrue(isQueueInList(operQueueList, queueEntry)); + } + + // DELETE one queue from queue list and check that one remains + KeyedInstanceIdentifier qosQueueIid = qosIid + .child(QueueList.class, new QueueListKey(new Long("0"))); + Assert.assertTrue(mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, qosQueueIid)); + qosOperationalListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT); + + // READ: Read the test qos and ensure changes are propagated to the OPERATIONAL data store + // assumption is that CONFIGURATION was updated if OPERATIONAL is correct + ovsdbNodeAugmentation = getOvsdbNode(connectionInfo, + LogicalDatastoreType.OPERATIONAL); + operQos = getQos(new Uri(testQosId), ovsdbNodeAugmentation); + Assert.assertNotNull(operQos); + operQueueList = operQos.getQueueList(); + Assert.assertNotNull(operQueueList); + for (QueueList queueEntry : queueList) { + if (queueEntry.getQueueUuid().equals(queue2Uuid)) { + Assert.assertTrue(isQueueInList(operQueueList, queueEntry)); + } else if (queueEntry.getQueueUuid().equals(queue1Uuid)) { + Assert.assertFalse(isQueueInList(operQueueList, queueEntry)); + } else { + Assert.assertTrue("Unknown queue entry in qos queue list", false); + } + } + + // DELETE queue list and check that list is empty + qosQueueIid = qosIid + .child(QueueList.class, new QueueListKey(new Long("1"))); + Assert.assertTrue(mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, qosQueueIid)); + qosOperationalListener.waitForUpdate(OVSDB_UPDATE_TIMEOUT); + + ovsdbNodeAugmentation = getOvsdbNode(connectionInfo, + LogicalDatastoreType.OPERATIONAL); + operQos = getQos(new Uri(testQosId), ovsdbNodeAugmentation); + Assert.assertNotNull(operQos); + operQueueList = operQos.getQueueList(); + Assert.assertNotNull(operQueueList); + Assert.assertTrue(operQueueList.isEmpty()); + } + } + + private Boolean isQueueInList(List queueList, QueueList queue) { + for (QueueList queueEntry : queueList) { + if (queueEntry.getQueueNumber().equals(queue.getQueueNumber()) + && queueEntry.getQueueUuid().equals(queue.getQueueUuid())) { + return true; + } + } + return false; + } + /** *

* Representation of a southbound test case. Each test case has a name, a list of input values and a list of @@ -1594,6 +2655,8 @@ public class SouthboundIT extends AbstractMdsalTestBase { protected abstract void setValue(Builder builder, String value); + protected abstract boolean isValueMandatory(); + public final T build(final String testName, final String key, final String value) { final Builder builder = builder(); this.counter++; @@ -1611,6 +2674,94 @@ public class SouthboundIT extends AbstractMdsalTestBase { } } + private static final class SouthboundQueuesExternalIdsBuilder extends KeyValueBuilder { + @Override + protected Builder builder() { + return new QueuesExternalIdsBuilder(); + } + + @Override + protected void setKey(Builder builder, String key) { + ((QueuesExternalIdsBuilder) builder).setQueuesExternalIdKey(key); + } + + @Override + protected void setValue(Builder builder, String value) { + ((QueuesExternalIdsBuilder) builder).setQueuesExternalIdValue(value); + } + + @Override + protected boolean isValueMandatory() { + return true; + } + } + + private static final class SouthboundQueuesOtherConfigBuilder extends KeyValueBuilder { + @Override + protected Builder builder() { + return new QueuesOtherConfigBuilder(); + } + + @Override + protected void setKey(Builder builder, String key) { + ((QueuesOtherConfigBuilder) builder).setQueueOtherConfigKey(key); + } + + @Override + protected void setValue(Builder builder, String value) { + ((QueuesOtherConfigBuilder) builder).setQueueOtherConfigValue(value); + } + + @Override + protected boolean isValueMandatory() { + return false; + } + } + + private static final class SouthboundQosExternalIdsBuilder extends KeyValueBuilder { + @Override + protected Builder builder() { + return new QosExternalIdsBuilder(); + } + + @Override + protected void setKey(Builder builder, String key) { + ((QosExternalIdsBuilder) builder).setQosExternalIdKey(key); + } + + @Override + protected void setValue(Builder builder, String value) { + ((QosExternalIdsBuilder) builder).setQosExternalIdValue(value); + } + + @Override + protected boolean isValueMandatory() { + return true; + } + } + + private static final class SouthboundQosOtherConfigBuilder extends KeyValueBuilder { + @Override + protected Builder builder() { + return new QosOtherConfigBuilder(); + } + + @Override + protected void setKey(Builder builder, String key) { + ((QosOtherConfigBuilder) builder).setOtherConfigKey(key); + } + + @Override + protected void setValue(Builder builder, String value) { + ((QosOtherConfigBuilder) builder).setOtherConfigValue(value); + } + + @Override + protected boolean isValueMandatory() { + return false; + } + } + private static final class SouthboundPortExternalIdsBuilder extends KeyValueBuilder { @Override protected Builder builder() { @@ -1626,6 +2777,11 @@ public class SouthboundIT extends AbstractMdsalTestBase { protected void setValue(Builder builder, String value) { ((PortExternalIdsBuilder) builder).setExternalIdValue(value); } + + @Override + protected boolean isValueMandatory() { + return true; + } } private static final class SouthboundInterfaceExternalIdsBuilder extends KeyValueBuilder { @@ -1643,6 +2799,33 @@ public class SouthboundIT extends AbstractMdsalTestBase { protected void setValue(Builder builder, String value) { ((InterfaceExternalIdsBuilder) builder).setExternalIdValue(value); } + + @Override + protected boolean isValueMandatory() { + return true; + } + } + + private static final class SouthboundInterfaceLldpBuilder extends KeyValueBuilder { + @Override + protected Builder builder() { + return new InterfaceLldpBuilder(); + } + + @Override + protected void setKey(Builder builder, String key) { + ((InterfaceLldpBuilder) builder).setLldpKey((key)); + } + + @Override + protected void setValue(Builder builder, String value) { + ((InterfaceLldpBuilder) builder).setLldpValue(value); + } + + @Override + protected boolean isValueMandatory() { + return true; + } } private static final class SouthboundOptionsBuilder extends KeyValueBuilder { @@ -1660,6 +2843,11 @@ public class SouthboundIT extends AbstractMdsalTestBase { protected void setValue(Builder builder, String value) { ((OptionsBuilder) builder).setValue(value); } + + @Override + protected boolean isValueMandatory() { + return false; + } } private static final class SouthboundInterfaceOtherConfigsBuilder extends KeyValueBuilder { @@ -1677,6 +2865,11 @@ public class SouthboundIT extends AbstractMdsalTestBase { protected void setValue(Builder builder, String value) { ((InterfaceOtherConfigsBuilder) builder).setOtherConfigValue(value); } + + @Override + protected boolean isValueMandatory() { + return false; + } } private static final class SouthboundPortOtherConfigsBuilder extends KeyValueBuilder { @@ -1694,6 +2887,11 @@ public class SouthboundIT extends AbstractMdsalTestBase { protected void setValue(Builder builder, String value) { ((PortOtherConfigsBuilder) builder).setOtherConfigValue(value); } + + @Override + protected boolean isValueMandatory() { + return false; + } } private static final class SouthboundBridgeOtherConfigsBuilder extends KeyValueBuilder { @@ -1711,6 +2909,11 @@ public class SouthboundIT extends AbstractMdsalTestBase { protected void setValue(Builder builder, String value) { ((BridgeOtherConfigsBuilder) builder).setBridgeOtherConfigValue(value); } + + @Override + protected boolean isValueMandatory() { + return false; + } } private static final class SouthboundBridgeExternalIdsBuilder extends KeyValueBuilder { @@ -1728,6 +2931,11 @@ public class SouthboundIT extends AbstractMdsalTestBase { protected void setValue(Builder builder, String value) { ((BridgeExternalIdsBuilder) builder).setBridgeExternalIdValue(value); } + + @Override + protected boolean isValueMandatory() { + return true; + } } /* @@ -1755,13 +2963,13 @@ public class SouthboundIT extends AbstractMdsalTestBase { .input(builder.build(testOneName, idKey, idValue)) .expectInputAsOutput() .build()); + builder.reset(); // Test Case 2: TestFive // Test Type: Positive // Description: Create a termination point with multiple (five) values // Expected: A port is created with the five values specified below final String testFiveName = "TestFive" + testName; - builder.reset(); testCases.add(new SouthboundTestCaseBuilder() .name(testFiveName) .input( @@ -1772,37 +2980,32 @@ public class SouthboundIT extends AbstractMdsalTestBase { builder.build(testFiveName, idKey, idValue)) .expectInputAsOutput() .build()); + builder.reset(); - if ((builder instanceof SouthboundBridgeExternalIdsBuilder) || - (builder instanceof SouthboundInterfaceExternalIdsBuilder) || - (builder instanceof SouthboundPortExternalIdsBuilder)) { - LOG.info("generateKeyValueTestCases: instance skipping test case 3 TestOneGoodOneMalformedValue"); + if (!builder.isValueMandatory()) { + // Test Case 3: TestOneGoodOneMalformedValue + // Test Type: Negative + // Description: + // One perfectly fine input + // (TestOneGoodOneMalformedValue_GoodKey_1, + // TestOneGoodOneMalformedValue_GoodValue_1) + // and one malformed input which only has key specified + // (TestOneGoodOneMalformedValue_NoValueForKey_2, + // UNSPECIFIED) + // Expected: A port is created without any values + final String testOneGoodOneMalformedValueName = "TestOneGoodOneMalformedValue" + testName; + testCases.add(new SouthboundTestCaseBuilder() + .name(testOneGoodOneMalformedValueName) + .input( + builder.build(testOneGoodOneMalformedValueName, GOOD_KEY, GOOD_VALUE), + builder.build(testOneGoodOneMalformedValueName, NO_VALUE_FOR_KEY, null)) + .expectNoOutput() + .build()); builder.reset(); - - return testCases; + } else { + LOG.info("generateKeyValueTestCases: skipping test case 3 for {}", builder.getClass().getSimpleName()); } - // Test Case 3: TestOneGoodOneMalformedValue - // Test Type: Negative - // Description: - // One perfectly fine input - // (TestOneGoodOneMalformedValue_GoodKey_1, - // TestOneGoodOneMalformedValue_GoodValue_1) - // and one malformed input which only has key specified - // (TestOneGoodOneMalformedValue_NoValueForKey_2, - // UNSPECIFIED) - // Expected: A port is created without any values - final String testOneGoodOneMalformedValueName = "TestOneGoodOneMalformedValue" + testName; - builder.reset(); - testCases.add(new SouthboundTestCaseBuilder() - .name(testOneGoodOneMalformedValueName) - .input( - builder.build(testOneGoodOneMalformedValueName, GOOD_KEY, GOOD_VALUE), - builder.build(testOneGoodOneMalformedValueName, NO_VALUE_FOR_KEY, null)) - .expectNoOutput() - .build()); - builder.reset(); - return testCases; } @@ -1832,6 +3035,20 @@ public class SouthboundIT extends AbstractMdsalTestBase { } } + private static class InterfaceLldpSouthboundHelper implements + SouthboundTerminationPointHelper { + @Override + public void writeValues( + OvsdbTerminationPointAugmentationBuilder builder, List values) { + builder.setInterfaceLldp(values); + } + + @Override + public List readValues(OvsdbTerminationPointAugmentation augmentation) { + return augmentation.getInterfaceLldp(); + } + } + private static class OptionsSouthboundHelper implements SouthboundTerminationPointHelper { @Override public void writeValues(