Merge "QoS Schema - fix type of QoS type"
[ovsdb.git] / southbound / southbound-it / src / test / java / org / opendaylight / ovsdb / southbound / it / SouthboundIT.java
1 /*
2  * Copyright (c) 2015 Red Hat, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.ovsdb.southbound.it;
9
10 import static org.junit.Assert.assertNotNull;
11 import static org.junit.Assert.fail;
12 import static org.ops4j.pax.exam.CoreOptions.composite;
13 import static org.ops4j.pax.exam.CoreOptions.maven;
14 import static org.ops4j.pax.exam.CoreOptions.vmOption;
15 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.editConfigurationFilePut;
16 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.keepRuntimeFolder;
17
18 import com.google.common.collect.ImmutableBiMap;
19 import com.google.common.collect.Lists;
20 import com.google.common.collect.Sets;
21
22 import java.lang.annotation.Annotation;
23 import java.lang.reflect.Method;
24 import java.net.InetAddress;
25 import java.net.UnknownHostException;
26 import java.util.ArrayList;
27 import java.util.Collections;
28 import java.util.HashSet;
29 import java.util.List;
30 import java.util.Properties;
31 import java.util.Set;
32
33 import javax.annotation.Nullable;
34 import javax.inject.Inject;
35
36 import org.junit.After;
37 import org.junit.Assert;
38 import org.junit.Before;
39 import org.junit.Ignore;
40 import org.junit.Test;
41 import org.junit.runner.RunWith;
42 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
43 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
44 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
45 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
46 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
47 import org.opendaylight.controller.mdsal.it.base.AbstractMdsalTestBase;
48 import org.opendaylight.ovsdb.southbound.SouthboundConstants;
49 import org.opendaylight.ovsdb.southbound.SouthboundMapper;
50 import org.opendaylight.ovsdb.southbound.SouthboundProvider;
51 import org.opendaylight.ovsdb.southbound.SouthboundUtil;
52 import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
53 import org.opendaylight.ovsdb.utils.southbound.utils.SouthboundUtils;
54 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
55 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
56 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathTypeBase;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeBase;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentationBuilder;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeName;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolBase;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbFailModeBase;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeRef;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbPortInterfaceAttributes.VlanMode;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentationBuilder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeExternalIds;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeExternalIdsBuilder;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigs;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigsBuilder;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntry;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntryBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntry;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntryBuilder;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfoBuilder;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.DatapathTypeEntry;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.InterfaceTypeEntryBuilder;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagedNodeEntry;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchOtherConfigs;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIds;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIdsBuilder;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceOtherConfigs;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceOtherConfigsBuilder;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.Options;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.OptionsBuilder;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.PortExternalIds;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.PortExternalIdsBuilder;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.PortOtherConfigs;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.PortOtherConfigsBuilder;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.Trunks;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.TrunksBuilder;
96 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
97 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
98 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
99 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
100 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
101 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
102 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
103 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
104 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
105 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
106 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
107 import org.opendaylight.yangtools.concepts.Builder;
108 import org.opendaylight.yangtools.yang.binding.DataObject;
109 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
110 import org.ops4j.pax.exam.Configuration;
111 import org.ops4j.pax.exam.Option;
112 import org.ops4j.pax.exam.junit.PaxExam;
113 import org.ops4j.pax.exam.karaf.options.LogLevelOption;
114 import org.ops4j.pax.exam.options.MavenUrlReference;
115 import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
116 import org.ops4j.pax.exam.spi.reactors.PerClass;
117 import org.osgi.framework.BundleContext;
118 import org.slf4j.Logger;
119 import org.slf4j.LoggerFactory;
120
121 /**
122  * Integration tests for southbound-impl
123  *
124  * @author Sam Hague (shague@redhat.com)
125  */
126 @RunWith(PaxExam.class)
127 @ExamReactorStrategy(PerClass.class)
128 public class SouthboundIT extends AbstractMdsalTestBase {
129     private static final String NETDEV_DP_TYPE = "netdev";
130     private static final Logger LOG = LoggerFactory.getLogger(SouthboundIT.class);
131     private static final int OVSDB_UPDATE_TIMEOUT = 1000;
132     private static final int OVSDB_ROUNDTRIP_TIMEOUT = 10000;
133     private static final String FORMAT_STR = "%s_%s_%d";
134     private static String addressStr;
135     private static int portNumber;
136     private static String connectionType;
137     private static boolean setup = false;
138     private static MdsalUtils mdsalUtils = null;
139     private static Node ovsdbNode;
140     private static int testMethodsRemaining;
141
142     @Inject
143     private BundleContext bundleContext;
144
145     private static final NotifyingDataChangeListener CONFIGURATION_LISTENER =
146             new NotifyingDataChangeListener(LogicalDatastoreType.CONFIGURATION);
147     private static final NotifyingDataChangeListener OPERATIONAL_LISTENER =
148             new NotifyingDataChangeListener(LogicalDatastoreType.OPERATIONAL);
149
150     private static class NotifyingDataChangeListener implements DataChangeListener {
151         private final LogicalDatastoreType type;
152         private final Set<InstanceIdentifier<?>> createdIids = new HashSet<>();
153         private final Set<InstanceIdentifier<?>> removedIids = new HashSet<>();
154         private final Set<InstanceIdentifier<?>> updatedIids = new HashSet<>();
155
156         private NotifyingDataChangeListener(LogicalDatastoreType type) {
157             this.type = type;
158         }
159
160         @Override
161         public void onDataChanged(
162                 AsyncDataChangeEvent<InstanceIdentifier<?>, DataObject> asyncDataChangeEvent) {
163             LOG.info("{} DataChanged: created {}", type, asyncDataChangeEvent.getCreatedData().keySet());
164             LOG.info("{} DataChanged: removed {}", type, asyncDataChangeEvent.getRemovedPaths());
165             LOG.info("{} DataChanged: updated {}", type, asyncDataChangeEvent.getUpdatedData().keySet());
166             createdIids.addAll(asyncDataChangeEvent.getCreatedData().keySet());
167             removedIids.addAll(asyncDataChangeEvent.getRemovedPaths());
168             updatedIids.addAll(asyncDataChangeEvent.getUpdatedData().keySet());
169             // Handled managed iids
170             for (DataObject obj : asyncDataChangeEvent.getCreatedData().values()) {
171                 if (obj instanceof ManagedNodeEntry) {
172                     ManagedNodeEntry managedNodeEntry = (ManagedNodeEntry) obj;
173                     LOG.info("{} DataChanged: created managed {}", managedNodeEntry.getBridgeRef().getValue());
174                     createdIids.add(managedNodeEntry.getBridgeRef().getValue());
175                 }
176             }
177             synchronized(this) {
178                 notifyAll();
179             }
180         }
181
182         public boolean isCreated(InstanceIdentifier<?> iid) {
183             return createdIids.remove(iid);
184         }
185
186         public boolean isRemoved(InstanceIdentifier<?> iid) {
187             return removedIids.remove(iid);
188         }
189
190         public boolean isUpdated(InstanceIdentifier<?> iid) {
191             return updatedIids.remove(iid);
192         }
193     }
194
195     @Configuration
196     public Option[] config() {
197         Option[] options = super.config();
198         Option[] propertyOptions = getPropertiesOptions();
199         Option[] otherOptions = getOtherOptions();
200         Option[] combinedOptions = new Option[options.length + propertyOptions.length + otherOptions.length];
201         System.arraycopy(options, 0, combinedOptions, 0, options.length);
202         System.arraycopy(propertyOptions, 0, combinedOptions, options.length, propertyOptions.length);
203         System.arraycopy(otherOptions, 0, combinedOptions, options.length + propertyOptions.length,
204                 otherOptions.length);
205         return combinedOptions;
206     }
207
208     private Option[] getOtherOptions() {
209         return new Option[] {
210                 vmOption("-javaagent:../jars/org.jacoco.agent.jar=destfile=../../jacoco-it.exec"),
211                 keepRuntimeFolder()
212         };
213     }
214
215     @Override
216     public String getKarafDistro() {
217         return maven()
218                 .groupId("org.opendaylight.ovsdb")
219                 .artifactId("southbound-karaf")
220                 .versionAsInProject()
221                 .type("zip")
222                 .getURL();
223     }
224
225     @Override
226     public String getModuleName() {
227         return "southbound-impl";
228     }
229
230     @Override
231     public String getInstanceName() {
232         return "southbound-default";
233     }
234
235     @Override
236     public MavenUrlReference getFeatureRepo() {
237         return maven()
238                 .groupId("org.opendaylight.ovsdb")
239                 .artifactId("southbound-features")
240                 .classifier("features")
241                 .type("xml")
242                 .versionAsInProject();
243     }
244
245     @Override
246     public String getFeatureName() {
247         return "odl-ovsdb-southbound-test";
248     }
249
250     protected String usage() {
251         return "Integration Test needs a valid connection configuration as follows :\n"
252                 + "active connection : mvn -Dovsdbserver.ipaddress=x.x.x.x -Dovsdbserver.port=yyyy verify\n"
253                 + "passive connection : mvn -Dovsdbserver.connection=passive verify\n";
254     }
255
256     @Override
257     public Option getLoggingOption() {
258         return composite(
259                 editConfigurationFilePut(SouthboundITConstants.ORG_OPS4J_PAX_LOGGING_CFG,
260                         "log4j.logger.org.opendaylight.ovsdb",
261                         LogLevelOption.LogLevel.TRACE.name()),
262                 super.getLoggingOption());
263     }
264
265     private Option[] getPropertiesOptions() {
266         Properties props = new Properties(System.getProperties());
267         String addressStr = props.getProperty(SouthboundITConstants.SERVER_IPADDRESS,
268                 SouthboundITConstants.DEFAULT_SERVER_IPADDRESS);
269         String portStr = props.getProperty(SouthboundITConstants.SERVER_PORT,
270                 SouthboundITConstants.DEFAULT_SERVER_PORT);
271         String connectionType = props.getProperty(SouthboundITConstants.CONNECTION_TYPE,
272                 SouthboundITConstants.CONNECTION_TYPE_ACTIVE);
273
274         LOG.info("getPropertiesOptions: Using the following properties: mode= {}, ip:port= {}:{}",
275                 connectionType, addressStr, portStr);
276
277         return new Option[] {
278                 editConfigurationFilePut(SouthboundITConstants.CUSTOM_PROPERTIES,
279                         SouthboundITConstants.SERVER_IPADDRESS, addressStr),
280                 editConfigurationFilePut(SouthboundITConstants.CUSTOM_PROPERTIES,
281                         SouthboundITConstants.SERVER_PORT, portStr),
282                 editConfigurationFilePut(SouthboundITConstants.CUSTOM_PROPERTIES,
283                         SouthboundITConstants.CONNECTION_TYPE, connectionType),
284         };
285     }
286
287     @Before
288     @Override
289     public void setup() throws InterruptedException {
290         if (setup) {
291             LOG.info("Skipping setup, already initialized");
292             return;
293         }
294
295         try {
296             super.setup();
297         } catch (Exception e) {
298             e.printStackTrace();
299         }
300         //dataBroker = getSession().getSALService(DataBroker.class);
301         Thread.sleep(3000);
302         DataBroker dataBroker = SouthboundProvider.getDb();
303         Assert.assertNotNull("db should not be null", dataBroker);
304
305         addressStr = bundleContext.getProperty(SouthboundITConstants.SERVER_IPADDRESS);
306         String portStr = bundleContext.getProperty(SouthboundITConstants.SERVER_PORT);
307         try {
308             portNumber = Integer.parseInt(portStr);
309         } catch (NumberFormatException e) {
310             fail("Invalid port number " + portStr + System.lineSeparator() + usage());
311         }
312         connectionType = bundleContext.getProperty(SouthboundITConstants.CONNECTION_TYPE);
313
314         LOG.info("setUp: Using the following properties: mode= {}, ip:port= {}:{}",
315                 connectionType, addressStr, portNumber);
316         if (connectionType.equalsIgnoreCase(SouthboundITConstants.CONNECTION_TYPE_ACTIVE)) {
317             if (addressStr == null) {
318                 fail(usage());
319             }
320         }
321
322         mdsalUtils = new MdsalUtils(dataBroker);
323         final ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
324         final InstanceIdentifier<Node> iid = SouthboundUtils.createInstanceIdentifier(connectionInfo);
325         dataBroker.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
326                 iid, CONFIGURATION_LISTENER, AsyncDataBroker.DataChangeScope.SUBTREE);
327         dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
328                 iid, OPERATIONAL_LISTENER, AsyncDataBroker.DataChangeScope.SUBTREE);
329
330         ovsdbNode = connectOvsdbNode(connectionInfo);
331
332         // Let's count the test methods (we need to use this instead of @AfterClass on teardown() since the latter is
333         // useless with pax-exam)
334         for (Method method : getClass().getMethods()) {
335             boolean testMethod = false;
336             boolean ignoreMethod = false;
337             for (Annotation annotation : method.getAnnotations()) {
338                 if (Test.class.equals(annotation.annotationType())) {
339                     testMethod = true;
340                 }
341                 if (Ignore.class.equals(annotation.annotationType())) {
342                     ignoreMethod = true;
343                 }
344             }
345             if (testMethod && !ignoreMethod) {
346                 testMethodsRemaining++;
347             }
348         }
349         LOG.info("{} test methods to run", testMethodsRemaining);
350
351         setup = true;
352     }
353
354     @After
355     public void teardown() {
356         testMethodsRemaining--;
357         LOG.info("{} test methods remaining", testMethodsRemaining);
358         if (testMethodsRemaining == 0) {
359             try {
360                 disconnectOvsdbNode(getConnectionInfo(addressStr, portNumber));
361             } catch (InterruptedException e) {
362                 LOG.warn("Interrupted while disconnecting", e);
363             }
364         }
365     }
366
367     /**
368      * Test passive connection mode. The southbound starts in a listening mode waiting for connections on port
369      * 6640. This test will wait for incoming connections for {@link SouthboundITConstants#CONNECTION_INIT_TIMEOUT} ms.
370      *
371      * @throws InterruptedException
372      */
373     @Test
374     public void testPassiveNode() throws InterruptedException {
375         if (connectionType.equalsIgnoreCase(SouthboundITConstants.CONNECTION_TYPE_PASSIVE)) {
376             //Wait for CONNECTION_INIT_TIMEOUT for the Passive connection to be initiated by the ovsdb-server.
377             Thread.sleep(SouthboundITConstants.CONNECTION_INIT_TIMEOUT);
378         }
379     }
380
381     private static ConnectionInfo getConnectionInfo(final String addressStr, final int portNumber) {
382         InetAddress inetAddress = null;
383         try {
384             inetAddress = InetAddress.getByName(addressStr);
385         } catch (UnknownHostException e) {
386             fail("Could not resolve " + addressStr + ": " + e);
387         }
388
389         IpAddress address = SouthboundMapper.createIpAddress(inetAddress);
390         PortNumber port = new PortNumber(portNumber);
391
392         final ConnectionInfo connectionInfo = new ConnectionInfoBuilder()
393                 .setRemoteIp(address)
394                 .setRemotePort(port)
395                 .build();
396         LOG.info("connectionInfo: {}", connectionInfo);
397         return connectionInfo;
398     }
399
400     @Test
401     public void testNetworkTopology() throws InterruptedException {
402         NetworkTopology networkTopology = mdsalUtils.read(LogicalDatastoreType.CONFIGURATION,
403                 InstanceIdentifier.create(NetworkTopology.class));
404         Assert.assertNotNull("NetworkTopology could not be found in " + LogicalDatastoreType.CONFIGURATION,
405                 networkTopology);
406
407         networkTopology = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL,
408                 InstanceIdentifier.create(NetworkTopology.class));
409         Assert.assertNotNull("NetworkTopology could not be found in " + LogicalDatastoreType.OPERATIONAL,
410                 networkTopology);
411     }
412
413     @Test
414     public void testOvsdbTopology() throws InterruptedException {
415         InstanceIdentifier<Topology> path = InstanceIdentifier
416                 .create(NetworkTopology.class)
417                 .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID));
418
419         Topology topology = mdsalUtils.read(LogicalDatastoreType.CONFIGURATION, path);
420         Assert.assertNotNull("Topology could not be found in " + LogicalDatastoreType.CONFIGURATION,
421                 topology);
422
423         topology = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, path);
424
425         Assert.assertNotNull("Topology could not be found in " + LogicalDatastoreType.OPERATIONAL,
426                 topology);
427     }
428
429     private Node connectOvsdbNode(final ConnectionInfo connectionInfo) throws InterruptedException {
430         final InstanceIdentifier<Node> iid = SouthboundUtils.createInstanceIdentifier(connectionInfo);
431         Assert.assertTrue(
432                 mdsalUtils.put(LogicalDatastoreType.CONFIGURATION, iid, SouthboundUtils.createNode(connectionInfo)));
433         waitForOperationalCreation(iid);
434         Node node = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, iid);
435         Assert.assertNotNull(node);
436         LOG.info("Connected to {}", SouthboundUtils.connectionInfoToString(connectionInfo));
437         return node;
438     }
439
440     private void waitForOperationalCreation(InstanceIdentifier<Node> iid) throws InterruptedException {
441         synchronized (OPERATIONAL_LISTENER) {
442             long _start = System.currentTimeMillis();
443             LOG.info("Waiting for OPERATIONAL DataChanged creation on {}", iid);
444             while (!OPERATIONAL_LISTENER.isCreated(
445                     iid) && (System.currentTimeMillis() - _start) < OVSDB_ROUNDTRIP_TIMEOUT) {
446                 OPERATIONAL_LISTENER.wait(OVSDB_UPDATE_TIMEOUT);
447             }
448             LOG.info("Woke up, waited {} for creation of {}", (System.currentTimeMillis() - _start), iid);
449         }
450     }
451
452     private static void waitForOperationalDeletion(InstanceIdentifier<Node> iid) throws InterruptedException {
453         synchronized (OPERATIONAL_LISTENER) {
454             long _start = System.currentTimeMillis();
455             LOG.info("Waiting for OPERATIONAL DataChanged deletion on {}", iid);
456             while (!OPERATIONAL_LISTENER.isRemoved(
457                     iid) && (System.currentTimeMillis() - _start) < OVSDB_ROUNDTRIP_TIMEOUT) {
458                 OPERATIONAL_LISTENER.wait(OVSDB_UPDATE_TIMEOUT);
459             }
460             LOG.info("Woke up, waited {} for deletion of {}", (System.currentTimeMillis() - _start), iid);
461         }
462     }
463
464     private void waitForOperationalUpdate(InstanceIdentifier<Node> iid) throws InterruptedException {
465         synchronized (OPERATIONAL_LISTENER) {
466             long _start = System.currentTimeMillis();
467             LOG.info("Waiting for OPERATIONAL DataChanged update on {}", iid);
468             while (!OPERATIONAL_LISTENER.isUpdated(
469                     iid) && (System.currentTimeMillis() - _start) < OVSDB_ROUNDTRIP_TIMEOUT) {
470                 OPERATIONAL_LISTENER.wait(OVSDB_UPDATE_TIMEOUT);
471             }
472             LOG.info("Woke up, waited {} for update of {}", (System.currentTimeMillis() - _start), iid);
473         }
474     }
475
476     private static void disconnectOvsdbNode(final ConnectionInfo connectionInfo) throws InterruptedException {
477         final InstanceIdentifier<Node> iid = SouthboundUtils.createInstanceIdentifier(connectionInfo);
478         Assert.assertTrue(mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, iid));
479         waitForOperationalDeletion(iid);
480         Node node = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, iid);
481         Assert.assertNull(node);
482         LOG.info("Disconnected from {}", SouthboundUtils.connectionInfoToString(connectionInfo));
483     }
484
485     @Test
486     public void testAddDeleteOvsdbNode() throws InterruptedException {
487         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
488         // At this point we're connected, disconnect and reconnect (the connection will be removed at the very end)
489         disconnectOvsdbNode(connectionInfo);
490         connectOvsdbNode(connectionInfo);
491     }
492
493     @Test
494     public void testDpdkSwitch() throws InterruptedException {
495         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
496         List<DatapathTypeEntry> datapathTypeEntries = ovsdbNode.getAugmentation(OvsdbNodeAugmentation.class)
497                 .getDatapathTypeEntry();
498         if (datapathTypeEntries == null) {
499             LOG.info("DPDK not supported on this node.");
500         } else {
501             for (DatapathTypeEntry dpTypeEntry : datapathTypeEntries) {
502                 Class<? extends DatapathTypeBase> dpType = dpTypeEntry.getDatapathType();
503                 String dpTypeStr = SouthboundConstants.DATAPATH_TYPE_MAP.get(dpType);
504                 LOG.info("dp type is {}", dpTypeStr);
505                 if (dpTypeStr.equals(NETDEV_DP_TYPE)) {
506                     LOG.info("Found a DPDK node; adding a corresponding netdev device");
507                     InstanceIdentifier<Node> bridgeIid = SouthboundUtils.createInstanceIdentifier(connectionInfo,
508                             new OvsdbBridgeName(SouthboundITConstants.BRIDGE_NAME));
509                     NodeId bridgeNodeId = SouthboundUtils.createManagedNodeId(bridgeIid);
510                     try (TestBridge testBridge = new TestBridge(connectionInfo, bridgeIid,
511                             SouthboundITConstants.BRIDGE_NAME, bridgeNodeId, false, null, true, dpType, null, null,
512                             null)) {
513                         // Verify that the device is netdev
514                         OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
515                         Assert.assertNotNull(bridge);
516                         Assert.assertEquals(dpType, bridge.getDatapathType());
517
518                         // Add port for all dpdk interface types (dpdkvhost not supported in existing dpdk ovs)
519                         List<String> dpdkTypes = new ArrayList<String>();
520                         dpdkTypes.add("dpdk");
521                         dpdkTypes.add("dpdkr");
522                         dpdkTypes.add("dpdkvhostuser");
523                         //dpdkTypes.add("dpdkvhost");
524
525                         for (String dpdkType : dpdkTypes) {
526                             String testPortname = "test"+dpdkType+"port";
527                             LOG.info("DPDK portname and type is {}, {}", testPortname, dpdkType);
528                             Class<? extends InterfaceTypeBase> dpdkIfType = SouthboundConstants.OVSDB_INTERFACE_TYPE_MAP
529                                     .get(dpdkType);
530                             OvsdbTerminationPointAugmentationBuilder ovsdbTerminationpointBuilder =
531                                     createSpecificDpdkOvsdbTerminationPointAugmentationBuilder(testPortname,
532                                             dpdkIfType);
533                             Assert.assertTrue(
534                                     addTerminationPoint(bridgeNodeId, testPortname, ovsdbTerminationpointBuilder));
535                         }
536
537                         // Verify that all DPDK ports are created
538                         InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
539                         Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL,
540                                 terminationPointIid);
541                         Assert.assertNotNull(terminationPointNode);
542
543                         // Verify that each termination point has the specific DPDK ifType
544                         for (String dpdkType : dpdkTypes) {
545                             String testPortname = "test"+dpdkType+"port";
546                             Class<? extends InterfaceTypeBase> dpdkIfType = SouthboundConstants.OVSDB_INTERFACE_TYPE_MAP
547                                     .get(dpdkType);
548                             List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
549                             for (TerminationPoint terminationPoint : terminationPoints) {
550                                 OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation = terminationPoint
551                                         .getAugmentation(OvsdbTerminationPointAugmentation.class);
552                                 if (ovsdbTerminationPointAugmentation.getName().equals(testPortname)) {
553                                     Class<? extends InterfaceTypeBase> opPort = ovsdbTerminationPointAugmentation
554                                             .getInterfaceType();
555                                     Assert.assertEquals(dpdkIfType, opPort);
556                                 }
557                             }
558                         }
559                     }
560                 }
561                 break;
562             }
563         }
564     }
565
566     @Test
567     public void testOvsdbNodeOvsVersion() throws InterruptedException {
568         OvsdbNodeAugmentation ovsdbNodeAugmentation = ovsdbNode.getAugmentation(OvsdbNodeAugmentation.class);
569         Assert.assertNotNull(ovsdbNodeAugmentation);
570         assertNotNull(ovsdbNodeAugmentation.getOvsVersion());
571     }
572
573     @Test
574     public void testOpenVSwitchOtherConfig() throws InterruptedException {
575         OvsdbNodeAugmentation ovsdbNodeAugmentation = ovsdbNode.getAugmentation(OvsdbNodeAugmentation.class);
576         Assert.assertNotNull(ovsdbNodeAugmentation);
577         List<OpenvswitchOtherConfigs> otherConfigsList = ovsdbNodeAugmentation.getOpenvswitchOtherConfigs();
578         if (otherConfigsList != null) {
579             for (OpenvswitchOtherConfigs otherConfig : otherConfigsList) {
580                 if (otherConfig.getOtherConfigKey().equals("local_ip")) {
581                     LOG.info("local_ip: {}", otherConfig.getOtherConfigValue());
582                     break;
583                 } else {
584                     LOG.info("other_config {}:{}", otherConfig.getOtherConfigKey(), otherConfig.getOtherConfigValue());
585                 }
586             }
587         } else {
588             LOG.info("other_config is not present");
589         }
590     }
591
592     @Test
593     public void testOvsdbBridgeControllerInfo() throws InterruptedException {
594         ConnectionInfo connectionInfo = getConnectionInfo(addressStr,portNumber);
595         String controllerTarget = SouthboundUtil.getControllerTarget(ovsdbNode);
596         assertNotNull("Failed to get controller target", controllerTarget);
597         List<ControllerEntry> setControllerEntry = createControllerEntry(controllerTarget);
598         Uri setUri = new Uri(controllerTarget);
599         try (TestBridge testBridge = new TestBridge(connectionInfo, null, SouthboundITConstants.BRIDGE_NAME,null, true,
600                 SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"), true, null, null,
601                 setControllerEntry, null)) {
602             OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
603             Assert.assertNotNull("bridge was not found: " + SouthboundITConstants.BRIDGE_NAME,  bridge);
604             Assert.assertNotNull("ControllerEntry was not found: " + setControllerEntry.iterator().next(),
605                     bridge.getControllerEntry());
606             List<ControllerEntry> getControllerEntries = bridge.getControllerEntry();
607             for (ControllerEntry entry : getControllerEntries) {
608                 if (entry.getTarget() != null) {
609                     Assert.assertEquals(setUri.toString(), entry.getTarget().toString());
610                 }
611             }
612         }
613     }
614
615     private List<ControllerEntry> createControllerEntry(String controllerTarget) {
616         List<ControllerEntry> controllerEntriesList = new ArrayList<>();
617         controllerEntriesList.add(new ControllerEntryBuilder()
618                 .setTarget(new Uri(controllerTarget))
619                 .build());
620         return controllerEntriesList;
621     }
622
623     private static void setManagedBy(final OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder,
624                               final ConnectionInfo connectionInfo) {
625         InstanceIdentifier<Node> connectionNodePath = SouthboundUtils.createInstanceIdentifier(connectionInfo);
626         ovsdbBridgeAugmentationBuilder.setManagedBy(new OvsdbNodeRef(connectionNodePath));
627     }
628
629     private static List<ProtocolEntry> createMdsalProtocols() {
630         List<ProtocolEntry> protocolList = new ArrayList<>();
631         ImmutableBiMap<String, Class<? extends OvsdbBridgeProtocolBase>> mapper =
632                 SouthboundConstants.OVSDB_PROTOCOL_MAP.inverse();
633         protocolList.add(new ProtocolEntryBuilder().setProtocol(mapper.get("OpenFlow13")).build());
634         return protocolList;
635     }
636
637     private OvsdbTerminationPointAugmentationBuilder createGenericOvsdbTerminationPointAugmentationBuilder() {
638         OvsdbTerminationPointAugmentationBuilder ovsdbTerminationPointAugmentationBuilder =
639                 new OvsdbTerminationPointAugmentationBuilder();
640         ovsdbTerminationPointAugmentationBuilder.setInterfaceType(
641                 new InterfaceTypeEntryBuilder()
642                         .setInterfaceType(
643                                 SouthboundMapper.createInterfaceType("internal"))
644                         .build().getInterfaceType());
645         return ovsdbTerminationPointAugmentationBuilder;
646     }
647
648     private OvsdbTerminationPointAugmentationBuilder createGenericDpdkOvsdbTerminationPointAugmentationBuilder(
649             final String portName) {
650         OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
651                 createGenericOvsdbTerminationPointAugmentationBuilder();
652         ovsdbTerminationBuilder.setName(portName);
653         Class<? extends InterfaceTypeBase> ifType = SouthboundConstants.OVSDB_INTERFACE_TYPE_MAP
654                 .get("dpdk");
655         ovsdbTerminationBuilder.setInterfaceType(ifType);
656         return ovsdbTerminationBuilder;
657     }
658
659     private OvsdbTerminationPointAugmentationBuilder createSpecificDpdkOvsdbTerminationPointAugmentationBuilder(
660             String testPortname,Class<? extends InterfaceTypeBase> dpdkIfType) {
661         OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
662                 createGenericOvsdbTerminationPointAugmentationBuilder();
663         ovsdbTerminationBuilder.setName(testPortname);
664         ovsdbTerminationBuilder.setInterfaceType(dpdkIfType);
665         return ovsdbTerminationBuilder;
666     }
667
668     private boolean addTerminationPoint(final NodeId bridgeNodeId, final String portName,
669                                         final OvsdbTerminationPointAugmentationBuilder
670                                                 ovsdbTerminationPointAugmentationBuilder)
671             throws InterruptedException {
672
673         InstanceIdentifier<Node> portIid = SouthboundMapper.createInstanceIdentifier(bridgeNodeId);
674         NodeBuilder portNodeBuilder = new NodeBuilder();
675         NodeId portNodeId = SouthboundMapper.createManagedNodeId(portIid);
676         portNodeBuilder.setNodeId(portNodeId);
677         TerminationPointBuilder entry = new TerminationPointBuilder();
678         entry.setKey(new TerminationPointKey(new TpId(portName)));
679         entry.addAugmentation(
680                 OvsdbTerminationPointAugmentation.class,
681                 ovsdbTerminationPointAugmentationBuilder.build());
682         portNodeBuilder.setTerminationPoint(Lists.newArrayList(entry.build()));
683         boolean result = mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
684                 portIid, portNodeBuilder.build());
685         Thread.sleep(OVSDB_UPDATE_TIMEOUT);
686         return result;
687     }
688
689     private static class TestBridge implements AutoCloseable {
690         private final ConnectionInfo connectionInfo;
691         private final String bridgeName;
692
693         /**
694          * Creates a test bridge which can be automatically removed when no longer necessary.
695          *
696          * @param connectionInfo The connection information.
697          * @param bridgeIid The bridge identifier; if {@code null}, one is created based on {@code bridgeName}.
698          * @param bridgeName The bridge name; must be provided.
699          * @param bridgeNodeId The bridge node identifier; if {@code null}, one is created based on {@code bridgeIid}.
700          * @param setProtocolEntries {@code true} to set default protocol entries for the bridge.
701          * @param failMode The fail mode to set for the bridge.
702          * @param setManagedBy {@code true} to specify {@code setManagedBy} for the bridge.
703          * @param dpType The datapath type.
704          * @param externalIds The external identifiers if any.
705          * @param otherConfigs The other configuration items if any.
706          */
707         public TestBridge(final ConnectionInfo connectionInfo, @Nullable InstanceIdentifier<Node> bridgeIid,
708                                   final String bridgeName, NodeId bridgeNodeId, final boolean setProtocolEntries,
709                                   final Class<? extends OvsdbFailModeBase> failMode, final boolean setManagedBy,
710                                   @Nullable final Class<? extends DatapathTypeBase> dpType,
711                                   @Nullable final List<BridgeExternalIds> externalIds,
712                                   @Nullable final List<ControllerEntry> controllerEntries,
713                                   @Nullable final List<BridgeOtherConfigs> otherConfigs) {
714             this.connectionInfo = connectionInfo;
715             this.bridgeName = bridgeName;
716             NodeBuilder bridgeNodeBuilder = new NodeBuilder();
717             if (bridgeIid == null) {
718                 bridgeIid = SouthboundUtils.createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName));
719             }
720             if (bridgeNodeId == null) {
721                 bridgeNodeId = SouthboundMapper.createManagedNodeId(bridgeIid);
722             }
723             bridgeNodeBuilder.setNodeId(bridgeNodeId);
724             OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder = new OvsdbBridgeAugmentationBuilder();
725             ovsdbBridgeAugmentationBuilder.setBridgeName(new OvsdbBridgeName(bridgeName));
726             if (setProtocolEntries) {
727                 ovsdbBridgeAugmentationBuilder.setProtocolEntry(createMdsalProtocols());
728             }
729             ovsdbBridgeAugmentationBuilder.setFailMode(failMode);
730             if (setManagedBy) {
731                 setManagedBy(ovsdbBridgeAugmentationBuilder, connectionInfo);
732             }
733             ovsdbBridgeAugmentationBuilder.setDatapathType(dpType);
734             ovsdbBridgeAugmentationBuilder.setBridgeExternalIds(externalIds);
735             ovsdbBridgeAugmentationBuilder.setControllerEntry(controllerEntries);
736             ovsdbBridgeAugmentationBuilder.setBridgeOtherConfigs(otherConfigs);
737             bridgeNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class, ovsdbBridgeAugmentationBuilder.build());
738             LOG.debug("Built with the intent to store bridge data {}", ovsdbBridgeAugmentationBuilder.toString());
739             Assert.assertTrue(
740                     mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, bridgeIid, bridgeNodeBuilder.build()));
741             try {
742                 Thread.sleep(OVSDB_UPDATE_TIMEOUT);
743             } catch (InterruptedException e) {
744                 LOG.warn("Sleep interrupted while waiting for bridge creation (bridge {})", bridgeName, e);
745             }
746         }
747
748         public TestBridge(final ConnectionInfo connectionInfo, final String bridgeName) {
749             this(connectionInfo, null, bridgeName, null, true,
750                     SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"), true, null, null, null, null);
751         }
752
753         @Override
754         public void close() {
755             final InstanceIdentifier<Node> iid =
756                     SouthboundUtils.createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName));
757             Assert.assertTrue(mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, iid));
758             try {
759                 Thread.sleep(OVSDB_UPDATE_TIMEOUT);
760             } catch (InterruptedException e) {
761                 LOG.warn("Sleep interrupted while waiting for bridge deletion (bridge {})", bridgeName, e);
762             }
763         }
764     }
765
766     private OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo) {
767         return getBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME);
768     }
769
770     /**
771      * Extract the <code>store</code> type data store contents for the particular bridge identified by
772      * <code>bridgeName</code>.
773      *
774      * @param connectionInfo the connection information
775      * @param bridgeName the bridge name
776      * @param store defined by the <code>LogicalDatastoreType</code> enumeration
777      * @return <code>store</code> type data store contents
778      */
779     private OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo, String bridgeName,
780                                               LogicalDatastoreType store) {
781         Node bridgeNode = getBridgeNode(connectionInfo, bridgeName, store);
782         Assert.assertNotNull(bridgeNode);
783         OvsdbBridgeAugmentation ovsdbBridgeAugmentation = bridgeNode.getAugmentation(OvsdbBridgeAugmentation.class);
784         Assert.assertNotNull(ovsdbBridgeAugmentation);
785         return ovsdbBridgeAugmentation;
786     }
787
788     /**
789      * extract the <code>LogicalDataStoreType.OPERATIONAL</code> type data store contents for the particular bridge
790      * identified by <code>bridgeName</code>
791      *
792      * @param connectionInfo the connection information
793      * @param bridgeName the bridge name
794      * @see <code>SouthboundIT.getBridge(ConnectionInfo, String, LogicalDatastoreType)</code>
795      * @return <code>LogicalDatastoreType.OPERATIONAL</code> type data store contents
796      */
797     private OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo, String bridgeName) {
798         return getBridge(connectionInfo, bridgeName, LogicalDatastoreType.OPERATIONAL);
799     }
800
801     /**
802      * Extract the node contents from <code>store</code> type data store for the
803      * bridge identified by <code>bridgeName</code>
804      *
805      * @param connectionInfo the connection information
806      * @param bridgeName the bridge name
807      * @param store defined by the <code>LogicalDatastoreType</code> enumeration
808      * @return <code>store</code> type data store contents
809      */
810     private Node getBridgeNode(ConnectionInfo connectionInfo, String bridgeName, LogicalDatastoreType store) {
811         InstanceIdentifier<Node> bridgeIid =
812                 SouthboundUtils.createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName));
813         return mdsalUtils.read(store, bridgeIid);
814     }
815
816     /**
817      * Extract the node contents from <code>LogicalDataStoreType.OPERATIONAL</code> data store for the
818      * bridge identified by <code>bridgeName</code>
819      *
820      * @param connectionInfo the connection information
821      * @param bridgeName the bridge name
822      * @return <code>LogicalDatastoreType.OPERATIONAL</code> type data store contents
823      */
824     private Node getBridgeNode(ConnectionInfo connectionInfo, String bridgeName) {
825         return getBridgeNode(connectionInfo, bridgeName, LogicalDatastoreType.OPERATIONAL);
826     }
827
828     @Test
829     public void testAddDeleteBridge() throws InterruptedException {
830         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
831
832         try (TestBridge testBridge = new TestBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME)) {
833             OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
834             Assert.assertNotNull(bridge);
835             LOG.info("bridge: {}", bridge);
836         }
837     }
838
839     private InstanceIdentifier<Node> getTpIid(ConnectionInfo connectionInfo, OvsdbBridgeAugmentation bridge) {
840         return SouthboundUtils.createInstanceIdentifier(connectionInfo, bridge.getBridgeName());
841     }
842
843     /**
844      * Extracts the <code>TerminationPointAugmentation</code> for the <code>index</code> <code>TerminationPoint</code>
845      * on <code>bridgeName</code>
846      *
847      * @param connectionInfo the connection information
848      * @param bridgeName the bridge name
849      * @param store defined by the <code>LogicalDatastoreType</code> enumeration
850      * @param index the index we're interested in
851      * @return the augmentation (or {@code null} if none)
852      */
853     private OvsdbTerminationPointAugmentation getOvsdbTerminationPointAugmentation(
854             ConnectionInfo connectionInfo, String bridgeName, LogicalDatastoreType store, int index) {
855
856         List<TerminationPoint> tpList = getBridgeNode(connectionInfo, bridgeName, store).getTerminationPoint();
857         if (tpList == null) {
858             return null;
859         }
860         return tpList.get(index).getAugmentation(OvsdbTerminationPointAugmentation.class);
861     }
862
863     @Test
864     public void testCRDTerminationPointOfPort() throws InterruptedException {
865         final Long OFPORT_EXPECTED = 45002L;
866
867         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
868
869         // CREATE
870         try (TestBridge testBridge = new TestBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME)) {
871             OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
872             Assert.assertNotNull(bridge);
873             LOG.info("bridge: {}", bridge);
874             NodeId nodeId = SouthboundMapper.createManagedNodeId(SouthboundUtils.createInstanceIdentifier(
875                     connectionInfo, bridge.getBridgeName()));
876             OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
877                     createGenericOvsdbTerminationPointAugmentationBuilder();
878             String portName = "testOfPort";
879             ovsdbTerminationBuilder.setName(portName);
880
881             ovsdbTerminationBuilder.setOfport(OFPORT_EXPECTED);
882             Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
883             InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
884             Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
885             Assert.assertNotNull(terminationPointNode);
886
887             // READ
888             List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
889             for (TerminationPoint terminationPoint : terminationPoints) {
890                 OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
891                         terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
892                 if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
893                     Long ofPort = ovsdbTerminationPointAugmentation.getOfport();
894                     // if ephemeral port 45002 is in use, ofPort is set to 1
895                     Assert.assertTrue(ofPort.equals(OFPORT_EXPECTED) || ofPort.equals(1L));
896                     LOG.info("ofPort: {}", ofPort);
897                 }
898             }
899
900             // UPDATE- Not Applicable.  From the OpenVSwitch Documentation:
901             //   "A client should ideally set this column’s value in the same database transaction that it uses to create
902             //   the interface."
903
904             // DELETE handled by TestBridge
905         }
906     }
907
908     @Test
909     public void testCRDTerminationPointOfPortRequest() throws InterruptedException {
910         final Long OFPORT_EXPECTED = 45008L;
911         final Long OFPORT_INPUT = 45008L;
912
913         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
914
915         // CREATE
916         try (TestBridge testBridge = new TestBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME)) {
917             OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
918             Assert.assertNotNull(bridge);
919             NodeId nodeId = SouthboundUtils.createManagedNodeId(SouthboundUtils.createInstanceIdentifier(
920                     connectionInfo, bridge.getBridgeName()));
921             OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
922                     createGenericOvsdbTerminationPointAugmentationBuilder();
923             String portName = "testOfPortRequest";
924             ovsdbTerminationBuilder.setName(portName);
925             Integer ofPortRequestExpected = OFPORT_EXPECTED.intValue();
926             ovsdbTerminationBuilder.setOfport(OFPORT_INPUT);
927             ovsdbTerminationBuilder.setOfportRequest(ofPortRequestExpected);
928             Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
929             InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
930             Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
931             Assert.assertNotNull(terminationPointNode);
932
933             // READ
934             List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
935             for (TerminationPoint terminationPoint : terminationPoints) {
936                 OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
937                         terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
938                 if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
939                     Long ofPort = ovsdbTerminationPointAugmentation.getOfport();
940                     // if ephemeral port 45008 is in use, ofPort is set to 1
941                     Assert.assertTrue(ofPort.equals(OFPORT_EXPECTED) || ofPort.equals(1L));
942                     LOG.info("ofPort: {}", ofPort);
943
944                     Integer ofPortRequest = ovsdbTerminationPointAugmentation.getOfportRequest();
945                     Assert.assertTrue(ofPortRequest.equals(ofPortRequestExpected));
946                     LOG.info("ofPortRequest: {}", ofPortRequest);
947                 }
948             }
949
950             // UPDATE- Not Applicable.  From the OpenVSwitch documentation:
951             //   "A client should ideally set this column’s value in the same database transaction that it uses to
952             //   create the interface. "
953
954             // DELETE handled by TestBridge
955         }
956     }
957
958     private <T> void assertExpectedExist(List<T> expected, List<T> test) {
959         if (expected != null && test != null) {
960             for (T exp : expected) {
961                 Assert.assertTrue("The retrieved values don't contain " + exp, test.contains(exp));
962             }
963         }
964     }
965
966     private interface SouthboundTerminationPointHelper<T> {
967         void writeValues(OvsdbTerminationPointAugmentationBuilder builder, List<T> values);
968         List<T> readValues(OvsdbTerminationPointAugmentation augmentation);
969     }
970
971     /*
972      * Tests the CRUD operations for <code>Port</code> <code>external_ids</code>.
973      *
974      * @see <code>SouthboundIT.generatePortExternalIdsTestCases()</code> for specific test case information
975      */
976     private <T> void testCRUDTerminationPoint(
977             KeyValueBuilder<T> builder, String prefix, SouthboundTerminationPointHelper<T> helper)
978             throws InterruptedException {
979         final int TERMINATION_POINT_TEST_INDEX = 0;
980
981         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
982
983         // updateFromTestCases represent the original test case value.  updateToTestCases represent the new value after
984         // the update has been performed.
985         List<SouthboundTestCase<T>> updateFromTestCases = generateKeyValueTestCases(builder, prefix + "From");
986         List<SouthboundTestCase<T>> updateToTestCases = generateKeyValueTestCases(builder, prefix + "To");
987
988         for (SouthboundTestCase<T> updateFromTestCase : updateFromTestCases) {
989             for (SouthboundTestCase<T> updateToTestCase : updateToTestCases) {
990                 String testBridgeAndPortName = String.format("%s_%s", prefix, updateToTestCase.name);
991
992                 // CREATE: Create the test bridge
993                 try (TestBridge testBridge = new TestBridge(connectionInfo, null, testBridgeAndPortName, null, true,
994                         SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"), true, null, null, null,
995                         null)) {
996                     NodeId testBridgeNodeId = SouthboundUtils.createManagedNodeId(
997                             SouthboundUtils.createInstanceIdentifier(connectionInfo,
998                                     new OvsdbBridgeName(testBridgeAndPortName)));
999                     OvsdbTerminationPointAugmentationBuilder tpCreateAugmentationBuilder =
1000                             createGenericOvsdbTerminationPointAugmentationBuilder();
1001                     tpCreateAugmentationBuilder.setName(testBridgeAndPortName);
1002                     helper.writeValues(tpCreateAugmentationBuilder, updateFromTestCase.inputValues);
1003                     Assert.assertTrue(
1004                             addTerminationPoint(testBridgeNodeId, testBridgeAndPortName, tpCreateAugmentationBuilder));
1005
1006                     // READ: Read the test port and ensure changes are propagated to the CONFIGURATION data store,
1007                     // then repeat for OPERATIONAL data store
1008                     OvsdbTerminationPointAugmentation updateFromConfigurationTerminationPointAugmentation =
1009                             getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeAndPortName,
1010                                     LogicalDatastoreType.CONFIGURATION, TERMINATION_POINT_TEST_INDEX);
1011                     if (updateFromConfigurationTerminationPointAugmentation != null) {
1012                         List<T> updateFromConfigurationValues =
1013                                 helper.readValues(updateFromConfigurationTerminationPointAugmentation);
1014                         assertExpectedExist(updateFromTestCase.expectedValues, updateFromConfigurationValues);
1015                     }
1016                     OvsdbTerminationPointAugmentation updateFromOperationalTerminationPointAugmentation =
1017                             getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeAndPortName,
1018                                     LogicalDatastoreType.OPERATIONAL, TERMINATION_POINT_TEST_INDEX);
1019                     if (updateFromOperationalTerminationPointAugmentation != null) {
1020                         List<T> updateFromOperationalValues =
1021                                 helper.readValues(updateFromOperationalTerminationPointAugmentation);
1022                         assertExpectedExist(updateFromTestCase.expectedValues, updateFromOperationalValues);
1023                     }
1024
1025                     // UPDATE:  update the values
1026                     testBridgeNodeId = getBridgeNode(connectionInfo, testBridgeAndPortName).getNodeId();
1027                     OvsdbTerminationPointAugmentationBuilder tpUpdateAugmentationBuilder =
1028                             new OvsdbTerminationPointAugmentationBuilder();
1029                     helper.writeValues(tpUpdateAugmentationBuilder, updateToTestCase.inputValues);
1030                     InstanceIdentifier<Node> portIid = SouthboundMapper.createInstanceIdentifier(testBridgeNodeId);
1031                     NodeBuilder portUpdateNodeBuilder = new NodeBuilder();
1032                     NodeId portUpdateNodeId = SouthboundUtils.createManagedNodeId(portIid);
1033                     portUpdateNodeBuilder.setNodeId(portUpdateNodeId);
1034                     TerminationPointBuilder tpUpdateBuilder = new TerminationPointBuilder();
1035                     tpUpdateBuilder.setKey(new TerminationPointKey(new TpId(testBridgeAndPortName)));
1036                     tpUpdateBuilder.addAugmentation(
1037                             OvsdbTerminationPointAugmentation.class,
1038                             tpUpdateAugmentationBuilder.build());
1039                     portUpdateNodeBuilder.setTerminationPoint(Lists.newArrayList(tpUpdateBuilder.build()));
1040                     Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
1041                             portIid, portUpdateNodeBuilder.build()));
1042                     Thread.sleep(OVSDB_UPDATE_TIMEOUT);
1043
1044                     // READ: the test port and ensure changes are propagated to the CONFIGURATION data store,
1045                     // then repeat for OPERATIONAL data store
1046                     OvsdbTerminationPointAugmentation updateToConfigurationTerminationPointAugmentation =
1047                             getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeAndPortName,
1048                                     LogicalDatastoreType.CONFIGURATION, TERMINATION_POINT_TEST_INDEX);
1049                     if (updateToConfigurationTerminationPointAugmentation != null) {
1050                         List<T> updateToConfigurationValues =
1051                                 helper.readValues(updateToConfigurationTerminationPointAugmentation);
1052                         assertExpectedExist(updateToTestCase.expectedValues, updateToConfigurationValues);
1053                         assertExpectedExist(updateFromTestCase.expectedValues, updateToConfigurationValues);
1054                     }
1055                     OvsdbTerminationPointAugmentation updateToOperationalTerminationPointAugmentation =
1056                             getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeAndPortName,
1057                                     LogicalDatastoreType.OPERATIONAL, TERMINATION_POINT_TEST_INDEX);
1058                     if (updateToOperationalTerminationPointAugmentation != null) {
1059                         List<T> updateToOperationalValues =
1060                                 helper.readValues(updateToOperationalTerminationPointAugmentation);
1061                         if (updateFromTestCase.expectedValues != null) {
1062                             assertExpectedExist(updateToTestCase.expectedValues, updateToOperationalValues);
1063                             assertExpectedExist(updateFromTestCase.expectedValues, updateToOperationalValues);
1064                         }
1065                     }
1066
1067                     // DELETE handled by TestBridge
1068                 }
1069             }
1070         }
1071     }
1072
1073     /*
1074      * Tests the CRUD operations for <code>Port</code> <code>external_ids</code>.
1075      *
1076      * @see <code>SouthboundIT.generatePortExternalIdsTestCases()</code> for specific test case information
1077      */
1078     @Test
1079     public void testCRUDTerminationPointPortExternalIds() throws InterruptedException {
1080         testCRUDTerminationPoint(new SouthboundPortExternalIdsBuilder(), "TPPortExternalIds",
1081                 new PortExternalIdsSouthboundHelper());
1082     }
1083
1084     /*
1085      * Tests the CRUD operations for <code>Interface</code> <code>external_ids</code>.
1086      *
1087      * @see <code>SouthboundIT.generateInterfaceExternalIdsTestCases()</code> for specific test case information
1088      */
1089     @Test
1090     public void testCRUDTerminationPointInterfaceExternalIds() throws InterruptedException {
1091         testCRUDTerminationPoint(new SouthboundInterfaceExternalIdsBuilder(), "TPInterfaceExternalIds",
1092                 new InterfaceExternalIdsSouthboundHelper());
1093     }
1094
1095     /*
1096      * Tests the CRUD operations for <code>TerminationPoint</code> <code>options</code>.
1097      *
1098      * @see <code>SouthboundIT.generateTerminationPointOptions()</code> for specific test case information
1099      */
1100     @Test
1101     public void testCRUDTerminationPointOptions() throws InterruptedException {
1102         testCRUDTerminationPoint(new SouthboundOptionsBuilder(), "TPOptions", new OptionsSouthboundHelper());
1103     }
1104
1105     /*
1106      * Tests the CRUD operations for <code>Interface</code> <code>other_configs</code>.
1107      *
1108      * @see <code>SouthboundIT.generateInterfaceExternalIdsTestCases()</code> for specific test case information
1109      */
1110     @Test
1111     public void testCRUDTerminationPointInterfaceOtherConfigs() throws InterruptedException {
1112         testCRUDTerminationPoint(new SouthboundInterfaceOtherConfigsBuilder(), "TPInterfaceOtherConfigs",
1113                 new InterfaceOtherConfigsSouthboundHelper());
1114     }
1115
1116     /*
1117      * Tests the CRUD operations for <code>Port</code> <code>other_configs</code>.
1118      *
1119      * @see <code>SouthboundIT.generatePortExternalIdsTestCases()</code> for specific test case information
1120      */
1121     @Test
1122     public void testCRUDTerminationPointPortOtherConfigs() throws InterruptedException {
1123         testCRUDTerminationPoint(new SouthboundPortOtherConfigsBuilder(), "TPPortOtherConfigs",
1124                 new PortOtherConfigsSouthboundHelper());
1125     }
1126
1127     @Test
1128     public void testCRUDTerminationPointVlan() throws InterruptedException {
1129         final Integer CREATED_VLAN_ID = 4000;
1130         final Integer UPDATED_VLAN_ID = 4001;
1131
1132         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
1133
1134         // CREATE
1135         try (TestBridge testBridge = new TestBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME)) {
1136             OvsdbBridgeAugmentation bridge = getBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME);
1137             Assert.assertNotNull(bridge);
1138             NodeId nodeId = SouthboundUtils.createManagedNodeId(SouthboundUtils.createInstanceIdentifier(
1139                     connectionInfo, bridge.getBridgeName()));
1140             OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
1141                     createGenericOvsdbTerminationPointAugmentationBuilder();
1142             String portName = "testTerminationPointVlanId";
1143             ovsdbTerminationBuilder.setName(portName);
1144             ovsdbTerminationBuilder.setVlanTag(new VlanId(CREATED_VLAN_ID));
1145             Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
1146             InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
1147             Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
1148             Assert.assertNotNull(terminationPointNode);
1149
1150             // READ
1151             List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
1152             OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation;
1153             for (TerminationPoint terminationPoint : terminationPoints) {
1154                 ovsdbTerminationPointAugmentation = terminationPoint.getAugmentation(
1155                         OvsdbTerminationPointAugmentation.class);
1156                 if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
1157                     VlanId actualVlanId = ovsdbTerminationPointAugmentation.getVlanTag();
1158                     Assert.assertNotNull(actualVlanId);
1159                     Integer actualVlanIdInt = actualVlanId.getValue();
1160                     Assert.assertEquals(CREATED_VLAN_ID, actualVlanIdInt);
1161                 }
1162             }
1163
1164             // UPDATE
1165             NodeId testBridgeNodeId = getBridgeNode(connectionInfo, SouthboundITConstants.BRIDGE_NAME).getNodeId();
1166             OvsdbTerminationPointAugmentationBuilder tpUpdateAugmentationBuilder =
1167                     new OvsdbTerminationPointAugmentationBuilder();
1168             tpUpdateAugmentationBuilder.setVlanTag(new VlanId(UPDATED_VLAN_ID));
1169             InstanceIdentifier<Node> portIid = SouthboundMapper.createInstanceIdentifier(testBridgeNodeId);
1170             NodeBuilder portUpdateNodeBuilder = new NodeBuilder();
1171             NodeId portUpdateNodeId = SouthboundUtils.createManagedNodeId(portIid);
1172             portUpdateNodeBuilder.setNodeId(portUpdateNodeId);
1173             TerminationPointBuilder tpUpdateBuilder = new TerminationPointBuilder();
1174             tpUpdateBuilder.setKey(new TerminationPointKey(new TpId(portName)));
1175             tpUpdateBuilder.addAugmentation(
1176                     OvsdbTerminationPointAugmentation.class,
1177                     tpUpdateAugmentationBuilder.build());
1178             tpUpdateBuilder.setTpId(new TpId(portName));
1179             portUpdateNodeBuilder.setTerminationPoint(Lists.newArrayList(tpUpdateBuilder.build()));
1180             Assert.assertTrue(
1181                     mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, portIid, portUpdateNodeBuilder.build()));
1182             Thread.sleep(OVSDB_UPDATE_TIMEOUT);
1183
1184             terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
1185             terminationPoints = terminationPointNode.getTerminationPoint();
1186             for (TerminationPoint terminationPoint : terminationPoints) {
1187                 ovsdbTerminationPointAugmentation = terminationPoint.getAugmentation(
1188                         OvsdbTerminationPointAugmentation.class);
1189                 if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
1190                     VlanId actualVlanId = ovsdbTerminationPointAugmentation.getVlanTag();
1191                     Assert.assertNotNull(actualVlanId);
1192                     Integer actualVlanIdInt = actualVlanId.getValue();
1193                     Assert.assertEquals(UPDATED_VLAN_ID, actualVlanIdInt);
1194                 }
1195             }
1196
1197             // DELETE handled by TestBridge
1198         }
1199     }
1200
1201     @Test
1202     public void testCRUDTerminationPointVlanModes() throws InterruptedException {
1203         final VlanMode UPDATED_VLAN_MODE = VlanMode.Access;
1204         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
1205         VlanMode []vlanModes = VlanMode.values();
1206         for (VlanMode vlanMode : vlanModes) {
1207             // CREATE
1208             try (TestBridge testBridge = new TestBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME)) {
1209                 OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
1210                 Assert.assertNotNull(bridge);
1211                 NodeId nodeId = SouthboundUtils.createManagedNodeId(SouthboundUtils.createInstanceIdentifier(
1212                         connectionInfo, bridge.getBridgeName()));
1213                 OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
1214                         createGenericOvsdbTerminationPointAugmentationBuilder();
1215                 String portName = "testTerminationPointVlanMode" + vlanMode.toString();
1216                 ovsdbTerminationBuilder.setName(portName);
1217                 ovsdbTerminationBuilder.setVlanMode(vlanMode);
1218                 Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
1219                 InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
1220                 Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
1221                 Assert.assertNotNull(terminationPointNode);
1222
1223                 // READ
1224                 List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
1225                 for (TerminationPoint terminationPoint : terminationPoints) {
1226                     OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
1227                             terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
1228                     if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
1229                         //test
1230                         Assert.assertTrue(ovsdbTerminationPointAugmentation.getVlanMode().equals(vlanMode));
1231                     }
1232                 }
1233
1234                 // UPDATE
1235                 NodeId testBridgeNodeId = getBridgeNode(connectionInfo, SouthboundITConstants.BRIDGE_NAME).getNodeId();
1236                 OvsdbTerminationPointAugmentationBuilder tpUpdateAugmentationBuilder =
1237                         new OvsdbTerminationPointAugmentationBuilder();
1238                 tpUpdateAugmentationBuilder.setVlanMode(UPDATED_VLAN_MODE);
1239                 InstanceIdentifier<Node> portIid = SouthboundMapper.createInstanceIdentifier(testBridgeNodeId);
1240                 NodeBuilder portUpdateNodeBuilder = new NodeBuilder();
1241                 NodeId portUpdateNodeId = SouthboundUtils.createManagedNodeId(portIid);
1242                 portUpdateNodeBuilder.setNodeId(portUpdateNodeId);
1243                 TerminationPointBuilder tpUpdateBuilder = new TerminationPointBuilder();
1244                 tpUpdateBuilder.setKey(new TerminationPointKey(new TpId(portName)));
1245                 tpUpdateBuilder.addAugmentation(
1246                         OvsdbTerminationPointAugmentation.class,
1247                         tpUpdateAugmentationBuilder.build());
1248                 tpUpdateBuilder.setTpId(new TpId(portName));
1249                 portUpdateNodeBuilder.setTerminationPoint(Lists.newArrayList(tpUpdateBuilder.build()));
1250                 Assert.assertTrue(
1251                         mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, portIid, portUpdateNodeBuilder.build()));
1252                 Thread.sleep(OVSDB_UPDATE_TIMEOUT);
1253
1254                 terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
1255                 terminationPoints = terminationPointNode.getTerminationPoint();
1256                 for (TerminationPoint terminationPoint : terminationPoints) {
1257                     OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
1258                             terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
1259                     if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
1260                         //test
1261                         Assert.assertEquals(UPDATED_VLAN_MODE, ovsdbTerminationPointAugmentation.getVlanMode());
1262                     }
1263                 }
1264
1265                 // DELETE handled by TestBridge
1266             }
1267         }
1268     }
1269
1270     @SuppressWarnings("unchecked")
1271     private List<Set<Integer>> generateVlanSets() {
1272         int min = 0;
1273         int max = 4095;
1274         return Lists.newArrayList(
1275                 Collections.<Integer>emptySet(),
1276                 Sets.newHashSet(2222),
1277                 Sets.newHashSet(min, max, min + 1, max - 1, (max - min) / 2));
1278     }
1279
1280     private List<Trunks> buildTrunkList(Set<Integer> trunkSet) {
1281         List<Trunks> trunkList = Lists.newArrayList();
1282         for (Integer trunk : trunkSet) {
1283             TrunksBuilder trunkBuilder = new TrunksBuilder();
1284             trunkBuilder.setTrunk(new VlanId(trunk));
1285             trunkList.add(trunkBuilder.build());
1286         }
1287         return trunkList;
1288     }
1289
1290     @Test
1291     public void testCRUDTerminationPointVlanTrunks() throws InterruptedException {
1292         final List<Trunks> UPDATED_TRUNKS = buildTrunkList(Sets.newHashSet(2011));
1293         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
1294         Iterable<Set<Integer>> vlanSets = generateVlanSets();
1295         int testCase = 0;
1296         for (Set<Integer> vlanSet : vlanSets) {
1297             ++testCase;
1298             // CREATE
1299             try (TestBridge testBridge = new TestBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME)) {
1300                 OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
1301                 Assert.assertNotNull(bridge);
1302                 NodeId nodeId = SouthboundUtils.createManagedNodeId(connectionInfo, bridge.getBridgeName());
1303                 OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
1304                         createGenericOvsdbTerminationPointAugmentationBuilder();
1305                 String portName = "testTerminationPointVlanTrunks" + testCase;
1306                 ovsdbTerminationBuilder.setName(portName);
1307                 List<Trunks> trunks = buildTrunkList(vlanSet);
1308                 ovsdbTerminationBuilder.setTrunks(trunks);
1309                 Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
1310                 InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
1311                 Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
1312                 Assert.assertNotNull(terminationPointNode);
1313
1314                 // READ
1315                 List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
1316                 for (TerminationPoint terminationPoint : terminationPoints) {
1317                     OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
1318                             terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
1319                     if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
1320                         List<Trunks> actualTrunks = ovsdbTerminationPointAugmentation.getTrunks();
1321                         for (Trunks trunk : trunks) {
1322                             Assert.assertTrue(actualTrunks.contains(trunk));
1323                         }
1324                     }
1325                 }
1326
1327
1328                 // UPDATE
1329                 NodeId testBridgeNodeId = getBridgeNode(connectionInfo, SouthboundITConstants.BRIDGE_NAME).getNodeId();
1330                 OvsdbTerminationPointAugmentationBuilder tpUpdateAugmentationBuilder =
1331                         new OvsdbTerminationPointAugmentationBuilder();
1332                 tpUpdateAugmentationBuilder.setTrunks(UPDATED_TRUNKS);
1333                 InstanceIdentifier<Node> portIid = SouthboundMapper.createInstanceIdentifier(testBridgeNodeId);
1334                 NodeBuilder portUpdateNodeBuilder = new NodeBuilder();
1335                 NodeId portUpdateNodeId = SouthboundUtils.createManagedNodeId(portIid);
1336                 portUpdateNodeBuilder.setNodeId(portUpdateNodeId);
1337                 TerminationPointBuilder tpUpdateBuilder = new TerminationPointBuilder();
1338                 tpUpdateBuilder.setKey(new TerminationPointKey(new TpId(portName)));
1339                 tpUpdateBuilder.addAugmentation(
1340                         OvsdbTerminationPointAugmentation.class,
1341                         tpUpdateAugmentationBuilder.build());
1342                 tpUpdateBuilder.setTpId(new TpId(portName));
1343                 portUpdateNodeBuilder.setTerminationPoint(Lists.newArrayList(tpUpdateBuilder.build()));
1344                 Assert.assertTrue(
1345                         mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, portIid, portUpdateNodeBuilder.build()));
1346                 Thread.sleep(OVSDB_UPDATE_TIMEOUT);
1347
1348                 terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
1349                 terminationPoints = terminationPointNode.getTerminationPoint();
1350                 for (TerminationPoint terminationPoint : terminationPoints) {
1351                     OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
1352                             terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
1353                     if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
1354                         //test
1355                         Assert.assertEquals(UPDATED_TRUNKS, ovsdbTerminationPointAugmentation.getTrunks());
1356                     }
1357                 }
1358
1359                 // DELETE handled by TestBridge
1360             }
1361         }
1362     }
1363
1364     @Test
1365     public void testGetOvsdbNodes() throws InterruptedException {
1366         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
1367         InstanceIdentifier<Topology> topologyPath = InstanceIdentifier
1368                 .create(NetworkTopology.class)
1369                 .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID));
1370
1371         Topology topology = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, topologyPath);
1372         InstanceIdentifier<Node> expectedNodeIid = SouthboundUtils.createInstanceIdentifier(connectionInfo);
1373         NodeId expectedNodeId = expectedNodeIid.firstKeyOf(Node.class, NodeKey.class).getNodeId();
1374         Node foundNode = null;
1375         Assert.assertNotNull("Expected to find topology: " + topologyPath, topology);
1376         Assert.assertNotNull("Expected to find some nodes" + topology.getNode());
1377         LOG.info("expectedNodeId: {}, getNode: {}", expectedNodeId, topology.getNode());
1378         for (Node node : topology.getNode()) {
1379             if (node.getNodeId().getValue().equals(expectedNodeId.getValue())) {
1380                 foundNode = node;
1381                 break;
1382             }
1383         }
1384         Assert.assertNotNull("Expected to find Node: " + expectedNodeId, foundNode);
1385     }
1386
1387     /*
1388      * @see <code>SouthboundIT.generateBridgeOtherConfigsTestCases()</code> for specific test case information.
1389      */
1390     @Test
1391     public void testCRUDBridgeOtherConfigs() throws InterruptedException {
1392         testCRUDBridge("BridgeOtherConfigs", new SouthboundBridgeOtherConfigsBuilder(),
1393                 new BridgeOtherConfigsSouthboundHelper());
1394     }
1395
1396     private interface SouthboundBridgeHelper<T> {
1397         void writeValues(OvsdbBridgeAugmentationBuilder builder, List<T> values);
1398         List<T> readValues(OvsdbBridgeAugmentation augmentation);
1399     }
1400
1401     private <T> void testCRUDBridge(String prefix, KeyValueBuilder<T> builder, SouthboundBridgeHelper<T> helper)
1402             throws InterruptedException {
1403         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
1404         // updateFromTestCases represent the original test case value.  updateToTestCases represent the new value after
1405         // the update has been performed.
1406         List<SouthboundTestCase<T>> updateFromTestCases = generateKeyValueTestCases(builder, prefix + "From");
1407         List<SouthboundTestCase<T>> updateToTestCases = generateKeyValueTestCases(builder, prefix + "To");
1408         for (SouthboundTestCase<T> updateFromTestCase : updateFromTestCases) {
1409             for (SouthboundTestCase<T> updateToTestCase : updateToTestCases) {
1410                 String testBridgeName = String.format("%s_%s", prefix, updateToTestCase.name);
1411
1412                 // CREATE: Create the test bridge
1413                 final OvsdbBridgeName ovsdbBridgeName = new OvsdbBridgeName(testBridgeName);
1414                 final InstanceIdentifier<Node> bridgeIid =
1415                         SouthboundUtils.createInstanceIdentifier(connectionInfo, ovsdbBridgeName);
1416                 final NodeId bridgeNodeId = SouthboundMapper.createManagedNodeId(bridgeIid);
1417                 final NodeBuilder bridgeCreateNodeBuilder = new NodeBuilder();
1418                 bridgeCreateNodeBuilder.setNodeId(bridgeNodeId);
1419                 OvsdbBridgeAugmentationBuilder bridgeCreateAugmentationBuilder = new OvsdbBridgeAugmentationBuilder();
1420                 bridgeCreateAugmentationBuilder.setBridgeName(ovsdbBridgeName);
1421                 bridgeCreateAugmentationBuilder.setProtocolEntry(createMdsalProtocols());
1422                 bridgeCreateAugmentationBuilder.setFailMode(
1423                         SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"));
1424                 setManagedBy(bridgeCreateAugmentationBuilder, connectionInfo);
1425                 helper.writeValues(bridgeCreateAugmentationBuilder, updateFromTestCase.inputValues);
1426                 bridgeCreateNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class,
1427                         bridgeCreateAugmentationBuilder.build());
1428                 LOG.debug("Built with the intent to store bridge data {}", bridgeCreateAugmentationBuilder.toString());
1429                 Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, bridgeIid,
1430                         bridgeCreateNodeBuilder.build()));
1431                 Thread.sleep(OVSDB_UPDATE_TIMEOUT);
1432
1433                 // READ: Read the test bridge and ensure changes are propagated to the CONFIGURATION data store,
1434                 // then repeat for OPERATIONAL data store
1435                 List<T> updateFromConfigurationExternalIds = helper.readValues(getBridge(connectionInfo, testBridgeName,
1436                         LogicalDatastoreType.CONFIGURATION));
1437                 assertExpectedExist(updateFromTestCase.expectedValues, updateFromConfigurationExternalIds);
1438                 List<T> updateFromOperationalExternalIds = helper.readValues(getBridge(connectionInfo, testBridgeName));
1439                 assertExpectedExist(updateFromTestCase.expectedValues, updateFromOperationalExternalIds);
1440
1441                 // UPDATE:  update the values
1442                 final OvsdbBridgeAugmentationBuilder bridgeUpdateAugmentationBuilder =
1443                         new OvsdbBridgeAugmentationBuilder();
1444                 helper.writeValues(bridgeUpdateAugmentationBuilder, updateToTestCase.inputValues);
1445                 final NodeBuilder bridgeUpdateNodeBuilder = new NodeBuilder();
1446                 final Node bridgeNode = getBridgeNode(connectionInfo, testBridgeName);
1447                 bridgeUpdateNodeBuilder.setNodeId(bridgeNode.getNodeId());
1448                 bridgeUpdateNodeBuilder.setKey(bridgeNode.getKey());
1449                 bridgeUpdateNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class,
1450                         bridgeUpdateAugmentationBuilder.build());
1451                 Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, bridgeIid,
1452                         bridgeUpdateNodeBuilder.build()));
1453                 Thread.sleep(OVSDB_UPDATE_TIMEOUT);
1454
1455                 // READ: the test bridge and ensure changes are propagated to the CONFIGURATION data store,
1456                 // then repeat for OPERATIONAL data store
1457                 List<T> updateToConfigurationExternalIds = helper.readValues(getBridge(connectionInfo, testBridgeName,
1458                         LogicalDatastoreType.CONFIGURATION));
1459                 assertExpectedExist(updateToTestCase.expectedValues, updateToConfigurationExternalIds);
1460                 assertExpectedExist(updateFromTestCase.expectedValues, updateToConfigurationExternalIds);
1461                 List<T> updateToOperationalExternalIds = helper.readValues(getBridge(connectionInfo, testBridgeName));
1462                 if (updateFromTestCase.expectedValues != null) {
1463                     assertExpectedExist(updateToTestCase.expectedValues, updateToOperationalExternalIds);
1464                     assertExpectedExist(updateFromTestCase.expectedValues, updateToOperationalExternalIds);
1465                 }
1466
1467                 // DELETE
1468                 Assert.assertTrue(mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION, bridgeIid));
1469                 Thread.sleep(OVSDB_UPDATE_TIMEOUT);
1470             }
1471         }
1472     }
1473
1474     /*
1475      * @see <code>SouthboundIT.generateBridgeExternalIdsTestCases()</code> for specific test case information
1476      */
1477     @Test
1478     public void testCRUDBridgeExternalIds() throws InterruptedException {
1479         testCRUDBridge("BridgeExternalIds", new SouthboundBridgeExternalIdsBuilder(),
1480                 new BridgeExternalIdsSouthboundHelper());
1481     }
1482
1483     /**
1484      * <p>
1485      * Representation of a southbound test case. Each test case has a name, a list of input values and a list of
1486      * expected values. The input values are provided to the augmentation builder, and the expected values are checked
1487      * against the output of the resulting augmentation.
1488      * </p>
1489      * <p>
1490      * Instances of this class are immutable.
1491      * </p>
1492      *
1493      * @param <T> The type of data used for the test case.
1494      */
1495     private static final class SouthboundTestCase<T> {
1496         private final String name;
1497         private final List<T> inputValues;
1498         private final List<T> expectedValues;
1499
1500         /**
1501          * Creates an instance of a southbound test case.
1502          *
1503          * @param name The test case's name.
1504          * @param inputValues The input values (provided as input to the underlying augmentation builder).
1505          * @param expectedValues The expected values (checked against the output of the underlying augmentation).
1506          */
1507         public SouthboundTestCase(
1508                 final String name, final List<T> inputValues, final List<T> expectedValues) {
1509             this.name = name;
1510             this.inputValues = inputValues;
1511             this.expectedValues = expectedValues;
1512         }
1513     }
1514
1515     /**
1516      * Southbound test case builder.
1517      *
1518      * @param <T> The type of data used for the test case.
1519      */
1520     private static final class SouthboundTestCaseBuilder<T> {
1521         private String name;
1522         private List<T> inputValues;
1523         private List<T> expectedValues;
1524
1525         /**
1526          * Creates a builder. Builders may be reused, the generated immutable instances are independent of the
1527          * builders. There are no default values.
1528          */
1529         public SouthboundTestCaseBuilder() {
1530             // Nothing to do
1531         }
1532
1533         /**
1534          * Sets the test case's name.
1535          *
1536          * @param name The test case's name.
1537          * @return The builder.
1538          */
1539         public SouthboundTestCaseBuilder<T> name(final String name) {
1540             this.name = name;
1541             return this;
1542         }
1543
1544         /**
1545          * Sets the input values.
1546          *
1547          * @param inputValues The input values.
1548          * @return The builder.
1549          */
1550         @SafeVarargs
1551         public final SouthboundTestCaseBuilder<T> input(final T... inputValues) {
1552             this.inputValues = Lists.newArrayList(inputValues);
1553             return this;
1554         }
1555
1556         /**
1557          * Indicates that the provided input values should be expected as output values.
1558          *
1559          * @return The builder.
1560          */
1561         public SouthboundTestCaseBuilder<T> expectInputAsOutput() {
1562             this.expectedValues = this.inputValues;
1563             return this;
1564         }
1565
1566         /**
1567          * Indicates that no output should be expected.
1568          *
1569          * @return The builder.
1570          */
1571         public SouthboundTestCaseBuilder<T> expectNoOutput() {
1572             this.expectedValues = null;
1573             return this;
1574         }
1575
1576         /**
1577          * Builds an immutable instance representing the test case.
1578          *
1579          * @return The test case.
1580          */
1581         @SuppressWarnings("unchecked")
1582         public SouthboundTestCase<T> build() {
1583             return new SouthboundTestCase<>(name, inputValues, expectedValues);
1584         }
1585     }
1586
1587     private abstract static class KeyValueBuilder<T> {
1588         private static final int COUNTER_START = 0;
1589         private int counter = COUNTER_START;
1590
1591         protected abstract Builder<T> builder();
1592
1593         protected abstract void setKey(Builder<T> builder, String key);
1594
1595         protected abstract void setValue(Builder<T> builder, String value);
1596
1597         public final T build(final String testName, final String key, final String value) {
1598             final Builder<T> builder = builder();
1599             this.counter++;
1600             if (key != null) {
1601                 setKey(builder, String.format(FORMAT_STR, testName, key, this.counter));
1602             }
1603             if (value != null) {
1604                 setValue(builder, String.format(FORMAT_STR, testName, value, this.counter));
1605             }
1606             return builder.build();
1607         }
1608
1609         public final void reset() {
1610             this.counter = COUNTER_START;
1611         }
1612     }
1613
1614     private static final class SouthboundPortExternalIdsBuilder extends KeyValueBuilder<PortExternalIds> {
1615         @Override
1616         protected Builder<PortExternalIds> builder() {
1617             return new PortExternalIdsBuilder();
1618         }
1619
1620         @Override
1621         protected void setKey(Builder<PortExternalIds> builder, String key) {
1622             ((PortExternalIdsBuilder) builder).setExternalIdKey(key);
1623         }
1624
1625         @Override
1626         protected void setValue(Builder<PortExternalIds> builder, String value) {
1627             ((PortExternalIdsBuilder) builder).setExternalIdValue(value);
1628         }
1629     }
1630
1631     private static final class SouthboundInterfaceExternalIdsBuilder extends KeyValueBuilder<InterfaceExternalIds> {
1632         @Override
1633         protected Builder<InterfaceExternalIds> builder() {
1634             return new InterfaceExternalIdsBuilder();
1635         }
1636
1637         @Override
1638         protected void setKey(Builder<InterfaceExternalIds> builder, String key) {
1639             ((InterfaceExternalIdsBuilder) builder).setExternalIdKey(key);
1640         }
1641
1642         @Override
1643         protected void setValue(Builder<InterfaceExternalIds> builder, String value) {
1644             ((InterfaceExternalIdsBuilder) builder).setExternalIdValue(value);
1645         }
1646     }
1647
1648     private static final class SouthboundOptionsBuilder extends KeyValueBuilder<Options> {
1649         @Override
1650         protected Builder<Options> builder() {
1651             return new OptionsBuilder();
1652         }
1653
1654         @Override
1655         protected void setKey(Builder<Options> builder, String key) {
1656             ((OptionsBuilder) builder).setOption(key);
1657         }
1658
1659         @Override
1660         protected void setValue(Builder<Options> builder, String value) {
1661             ((OptionsBuilder) builder).setValue(value);
1662         }
1663     }
1664
1665     private static final class SouthboundInterfaceOtherConfigsBuilder extends KeyValueBuilder<InterfaceOtherConfigs> {
1666         @Override
1667         protected Builder<InterfaceOtherConfigs> builder() {
1668             return new InterfaceOtherConfigsBuilder();
1669         }
1670
1671         @Override
1672         protected void setKey(Builder<InterfaceOtherConfigs> builder, String key) {
1673             ((InterfaceOtherConfigsBuilder) builder).setOtherConfigKey(key);
1674         }
1675
1676         @Override
1677         protected void setValue(Builder<InterfaceOtherConfigs> builder, String value) {
1678             ((InterfaceOtherConfigsBuilder) builder).setOtherConfigValue(value);
1679         }
1680     }
1681
1682     private static final class SouthboundPortOtherConfigsBuilder extends KeyValueBuilder<PortOtherConfigs> {
1683         @Override
1684         protected Builder<PortOtherConfigs> builder() {
1685             return new PortOtherConfigsBuilder();
1686         }
1687
1688         @Override
1689         protected void setKey(Builder<PortOtherConfigs> builder, String key) {
1690             ((PortOtherConfigsBuilder) builder).setOtherConfigKey(key);
1691         }
1692
1693         @Override
1694         protected void setValue(Builder<PortOtherConfigs> builder, String value) {
1695             ((PortOtherConfigsBuilder) builder).setOtherConfigValue(value);
1696         }
1697     }
1698
1699     private static final class SouthboundBridgeOtherConfigsBuilder extends KeyValueBuilder<BridgeOtherConfigs> {
1700         @Override
1701         protected Builder<BridgeOtherConfigs> builder() {
1702             return new BridgeOtherConfigsBuilder();
1703         }
1704
1705         @Override
1706         protected void setKey(Builder<BridgeOtherConfigs> builder, String key) {
1707             ((BridgeOtherConfigsBuilder) builder).setBridgeOtherConfigKey(key);
1708         }
1709
1710         @Override
1711         protected void setValue(Builder<BridgeOtherConfigs> builder, String value) {
1712             ((BridgeOtherConfigsBuilder) builder).setBridgeOtherConfigValue(value);
1713         }
1714     }
1715
1716     private static final class SouthboundBridgeExternalIdsBuilder extends KeyValueBuilder<BridgeExternalIds> {
1717         @Override
1718         protected Builder<BridgeExternalIds> builder() {
1719             return new BridgeExternalIdsBuilder();
1720         }
1721
1722         @Override
1723         protected void setKey(Builder<BridgeExternalIds> builder, String key) {
1724             ((BridgeExternalIdsBuilder) builder).setBridgeExternalIdKey(key);
1725         }
1726
1727         @Override
1728         protected void setValue(Builder<BridgeExternalIds> builder, String value) {
1729             ((BridgeExternalIdsBuilder) builder).setBridgeExternalIdValue(value);
1730         }
1731     }
1732
1733     /*
1734      * Generates the test cases involved in testing key-value-based data.  See inline comments for descriptions of
1735      * the particular cases considered.
1736      */
1737     private static <T> List<SouthboundTestCase<T>> generateKeyValueTestCases(
1738             KeyValueBuilder<T> builder, String testName) {
1739         List<SouthboundTestCase<T>> testCases = new ArrayList<>();
1740
1741         final String GOOD_KEY = "GoodKey";
1742         final String GOOD_VALUE = "GoodValue";
1743         final String NO_VALUE_FOR_KEY = "NoValueForKey";
1744
1745         final String idKey = testName + "Key";
1746         final String idValue = testName + "Value";
1747
1748         // Test Case 1:  TestOne
1749         // Test Type:    Positive
1750         // Description:  Create a termination point with one value
1751         // Expected:     A port is created with the single value specified below
1752         final String testOneName = "TestOne" + testName;
1753         testCases.add(new SouthboundTestCaseBuilder<T>()
1754                 .name(testOneName)
1755                 .input(builder.build(testOneName, idKey, idValue))
1756                 .expectInputAsOutput()
1757                 .build());
1758
1759         // Test Case 2:  TestFive
1760         // Test Type:    Positive
1761         // Description:  Create a termination point with multiple (five) values
1762         // Expected:     A port is created with the five values specified below
1763         final String testFiveName = "TestFive" + testName;
1764         builder.reset();
1765         testCases.add(new SouthboundTestCaseBuilder<T>()
1766                 .name(testFiveName)
1767                 .input(
1768                         builder.build(testFiveName, idKey, idValue),
1769                         builder.build(testFiveName, idKey, idValue),
1770                         builder.build(testFiveName, idKey, idValue),
1771                         builder.build(testFiveName, idKey, idValue),
1772                         builder.build(testFiveName, idKey, idValue))
1773                 .expectInputAsOutput()
1774                 .build());
1775
1776         if ((builder instanceof SouthboundBridgeExternalIdsBuilder) ||
1777                 (builder instanceof SouthboundInterfaceExternalIdsBuilder) ||
1778                 (builder instanceof SouthboundPortExternalIdsBuilder)) {
1779             LOG.info("generateKeyValueTestCases: instance skipping test case 3 TestOneGoodOneMalformedValue");
1780             builder.reset();
1781
1782             return testCases;
1783         }
1784
1785         // Test Case 3:  TestOneGoodOneMalformedValue
1786         // Test Type:    Negative
1787         // Description:
1788         //     One perfectly fine input
1789         //        (TestOneGoodOneMalformedValue_GoodKey_1,
1790         //        TestOneGoodOneMalformedValue_GoodValue_1)
1791         //     and one malformed input which only has key specified
1792         //        (TestOneGoodOneMalformedValue_NoValueForKey_2,
1793         //        UNSPECIFIED)
1794         // Expected:     A port is created without any values
1795         final String testOneGoodOneMalformedValueName = "TestOneGoodOneMalformedValue" + testName;
1796         builder.reset();
1797         testCases.add(new SouthboundTestCaseBuilder<T>()
1798                 .name(testOneGoodOneMalformedValueName)
1799                 .input(
1800                         builder.build(testOneGoodOneMalformedValueName, GOOD_KEY, GOOD_VALUE),
1801                         builder.build(testOneGoodOneMalformedValueName, NO_VALUE_FOR_KEY, null))
1802                 .expectNoOutput()
1803                 .build());
1804         builder.reset();
1805
1806         return testCases;
1807     }
1808
1809     private static class PortExternalIdsSouthboundHelper implements SouthboundTerminationPointHelper<PortExternalIds> {
1810         @Override
1811         public void writeValues(OvsdbTerminationPointAugmentationBuilder builder, List<PortExternalIds> values) {
1812             builder.setPortExternalIds(values);
1813         }
1814
1815         @Override
1816         public List<PortExternalIds> readValues(OvsdbTerminationPointAugmentation augmentation) {
1817             return augmentation.getPortExternalIds();
1818         }
1819     }
1820
1821     private static class InterfaceExternalIdsSouthboundHelper implements
1822             SouthboundTerminationPointHelper<InterfaceExternalIds> {
1823         @Override
1824         public void writeValues(
1825                 OvsdbTerminationPointAugmentationBuilder builder, List<InterfaceExternalIds> values) {
1826             builder.setInterfaceExternalIds(values);
1827         }
1828
1829         @Override
1830         public List<InterfaceExternalIds> readValues(OvsdbTerminationPointAugmentation augmentation) {
1831             return augmentation.getInterfaceExternalIds();
1832         }
1833     }
1834
1835     private static class OptionsSouthboundHelper implements SouthboundTerminationPointHelper<Options> {
1836         @Override
1837         public void writeValues(
1838                 OvsdbTerminationPointAugmentationBuilder builder, List<Options> values) {
1839             builder.setOptions(values);
1840         }
1841
1842         @Override
1843         public List<Options> readValues(OvsdbTerminationPointAugmentation augmentation) {
1844             return augmentation.getOptions();
1845         }
1846     }
1847
1848     private static class InterfaceOtherConfigsSouthboundHelper implements
1849             SouthboundTerminationPointHelper<InterfaceOtherConfigs> {
1850         @Override
1851         public void writeValues(
1852                 OvsdbTerminationPointAugmentationBuilder builder, List<InterfaceOtherConfigs> values) {
1853             builder.setInterfaceOtherConfigs(values);
1854         }
1855
1856         @Override
1857         public List<InterfaceOtherConfigs> readValues(OvsdbTerminationPointAugmentation augmentation) {
1858             return augmentation.getInterfaceOtherConfigs();
1859         }
1860     }
1861
1862     private static class PortOtherConfigsSouthboundHelper implements
1863             SouthboundTerminationPointHelper<PortOtherConfigs> {
1864         @Override
1865         public void writeValues(
1866                 OvsdbTerminationPointAugmentationBuilder builder, List<PortOtherConfigs> values) {
1867             builder.setPortOtherConfigs(values);
1868         }
1869
1870         @Override
1871         public List<PortOtherConfigs> readValues(OvsdbTerminationPointAugmentation augmentation) {
1872             return augmentation.getPortOtherConfigs();
1873         }
1874     }
1875
1876     private static class BridgeExternalIdsSouthboundHelper implements SouthboundBridgeHelper<BridgeExternalIds> {
1877         @Override
1878         public void writeValues(
1879                 OvsdbBridgeAugmentationBuilder builder, List<BridgeExternalIds> values) {
1880             builder.setBridgeExternalIds(values);
1881         }
1882
1883         @Override
1884         public List<BridgeExternalIds> readValues(OvsdbBridgeAugmentation augmentation) {
1885             return augmentation.getBridgeExternalIds();
1886         }
1887     }
1888
1889     private static class BridgeOtherConfigsSouthboundHelper implements SouthboundBridgeHelper<BridgeOtherConfigs> {
1890         @Override
1891         public void writeValues(
1892                 OvsdbBridgeAugmentationBuilder builder, List<BridgeOtherConfigs> values) {
1893             builder.setBridgeOtherConfigs(values);
1894         }
1895
1896         @Override
1897         public List<BridgeOtherConfigs> readValues(OvsdbBridgeAugmentation augmentation) {
1898             return augmentation.getBridgeOtherConfigs();
1899         }
1900     }
1901 }