SouthboundIT: use a common builder for the input values
[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.CoreOptions.when;
16 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.editConfigurationFilePut;
17 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.karafDistributionConfiguration;
18 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.keepRuntimeFolder;
19
20 import com.google.common.collect.ImmutableBiMap;
21 import com.google.common.collect.Lists;
22 import com.google.common.collect.Sets;
23
24 import java.io.File;
25 import java.net.InetAddress;
26 import java.net.UnknownHostException;
27 import java.util.ArrayList;
28 import java.util.Collections;
29 import java.util.List;
30 import java.util.Properties;
31 import java.util.Set;
32
33 import javax.inject.Inject;
34
35 import org.junit.Assert;
36 import org.junit.Before;
37 import org.junit.Test;
38 import org.junit.runner.RunWith;
39 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
40 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
41 import org.opendaylight.controller.mdsal.it.base.AbstractMdsalTestBase;
42 import org.opendaylight.ovsdb.southbound.SouthboundConstants;
43 import org.opendaylight.ovsdb.southbound.SouthboundMapper;
44 import org.opendaylight.ovsdb.southbound.SouthboundProvider;
45 import org.opendaylight.ovsdb.southbound.SouthboundUtil;
46 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
47 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
48 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathTypeBase;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeBase;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentationBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeName;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolBase;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbFailModeBase;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentationBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeRef;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbPortInterfaceAttributes.VlanMode;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentationBuilder;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeExternalIds;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeExternalIdsBuilder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigs;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigsBuilder;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntry;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntryBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntry;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntryBuilder;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfoBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.DatapathTypeEntry;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.InterfaceTypeEntryBuilder;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchOtherConfigs;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIds;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIdsBuilder;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceOtherConfigs;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceOtherConfigsBuilder;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.Options;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.OptionsBuilder;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.PortExternalIds;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.PortExternalIdsBuilder;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.PortOtherConfigs;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.PortOtherConfigsBuilder;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.Trunks;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.TrunksBuilder;
88 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
89 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
90 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
91 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
92 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
93 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
94 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
95 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
96 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
97 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
98 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
99 import org.opendaylight.yangtools.concepts.Builder;
100 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
101 import org.ops4j.pax.exam.Configuration;
102 import org.ops4j.pax.exam.Option;
103 import org.ops4j.pax.exam.junit.PaxExam;
104 import org.ops4j.pax.exam.karaf.options.KarafDistributionOption;
105 import org.ops4j.pax.exam.karaf.options.LogLevelOption;
106 import org.ops4j.pax.exam.options.MavenUrlReference;
107 import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
108 import org.ops4j.pax.exam.spi.reactors.PerClass;
109 import org.osgi.framework.BundleContext;
110 import org.slf4j.Logger;
111 import org.slf4j.LoggerFactory;
112
113 /**
114  * Integration tests for southbound-impl
115  *
116  * @author Sam Hague (shague@redhat.com)
117  */
118 @RunWith(PaxExam.class)
119 @ExamReactorStrategy(PerClass.class)
120 public class SouthboundIT extends AbstractMdsalTestBase {
121     private static final String NETDEV_DP_TYPE = "netdev";
122     private static final Logger LOG = LoggerFactory.getLogger(SouthboundIT.class);
123     private static final int OVSDB_UPDATE_TIMEOUT = 1000;
124     private static final String FORMAT_STR = "%s_%s_%d";
125     private static String addressStr;
126     private static int portNumber;
127     private static String connectionType;
128     private static Boolean setup = false;
129     private static MdsalUtils mdsalUtils = null;
130
131     // TODO Constants copied from AbstractConfigTestBase, need to be removed (see TODO below)
132     private static final String PAX_EXAM_UNPACK_DIRECTORY = "target/exam";
133     private static final String KARAF_DEBUG_PORT = "5005";
134     private static final String KARAF_DEBUG_PROP = "karaf.debug";
135     private static final String KEEP_UNPACK_DIRECTORY_PROP = "karaf.keep.unpack";
136
137     @Inject
138     private BundleContext bundleContext;
139
140     @Configuration
141     public Option[] config() {
142         // TODO Figure out how to use the parent Karaf setup, then just use super.config()
143         Option[] options = new Option[] {
144                 when(Boolean.getBoolean(KARAF_DEBUG_PROP))
145                         .useOptions(KarafDistributionOption.debugConfiguration(KARAF_DEBUG_PORT, true)),
146                 karafDistributionConfiguration().frameworkUrl(getKarafDistro())
147                         .unpackDirectory(new File(PAX_EXAM_UNPACK_DIRECTORY))
148                         .useDeployFolder(false),
149                 when(Boolean.getBoolean(KEEP_UNPACK_DIRECTORY_PROP)).useOptions(keepRuntimeFolder()),
150                 // Works only if we don't specify the feature repo and name
151                 getLoggingOption()};
152         Option[] propertyOptions = getPropertiesOptions();
153         Option[] otherOptions = getOtherOptions();
154         Option[] combinedOptions = new Option[options.length + propertyOptions.length + otherOptions.length];
155         System.arraycopy(options, 0, combinedOptions, 0, options.length);
156         System.arraycopy(propertyOptions, 0, combinedOptions, options.length, propertyOptions.length);
157         System.arraycopy(otherOptions, 0, combinedOptions, options.length + propertyOptions.length,
158                 otherOptions.length);
159         return combinedOptions;
160     }
161
162     private Option[] getOtherOptions() {
163         return new Option[] {
164                 vmOption("-javaagent:../jars/org.jacoco.agent.jar=destfile=../../jacoco-it.exec"),
165                 keepRuntimeFolder()
166         };
167     }
168
169     @Override
170     public String getKarafDistro() {
171         return maven()
172                 .groupId("org.opendaylight.ovsdb")
173                 .artifactId("southbound-karaf")
174                 .versionAsInProject()
175                 .type("zip")
176                 .getURL();
177     }
178
179     @Override
180     public String getModuleName() {
181         return "southbound-impl";
182     }
183
184     @Override
185     public String getInstanceName() {
186         return "southbound-default";
187     }
188
189     @Override
190     public MavenUrlReference getFeatureRepo() {
191         return maven()
192                 .groupId("org.opendaylight.ovsdb")
193                 .artifactId("southbound-features")
194                 .classifier("features")
195                 .type("xml")
196                 .versionAsInProject();
197     }
198
199     @Override
200     public String getFeatureName() {
201         return "odl-ovsdb-southbound-impl-ui";
202     }
203
204     protected String usage() {
205         return "Integration Test needs a valid connection configuration as follows :\n"
206                 + "active connection : mvn -Dovsdbserver.ipaddress=x.x.x.x -Dovsdbserver.port=yyyy verify\n"
207                 + "passive connection : mvn -Dovsdbserver.connection=passive verify\n";
208     }
209
210     @Override
211     public Option getLoggingOption() {
212         return composite(
213                 editConfigurationFilePut(SouthboundITConstants.ORG_OPS4J_PAX_LOGGING_CFG,
214                         "log4j.logger.org.opendaylight.ovsdb",
215                         LogLevelOption.LogLevel.TRACE.name()),
216                 super.getLoggingOption());
217     }
218
219     private Option[] getPropertiesOptions() {
220         Properties props = new Properties(System.getProperties());
221         String addressStr = props.getProperty(SouthboundITConstants.SERVER_IPADDRESS,
222                 SouthboundITConstants.DEFAULT_SERVER_IPADDRESS);
223         String portStr = props.getProperty(SouthboundITConstants.SERVER_PORT,
224                 SouthboundITConstants.DEFAULT_SERVER_PORT);
225         String connectionType = props.getProperty(SouthboundITConstants.CONNECTION_TYPE,
226                 SouthboundITConstants.CONNECTION_TYPE_ACTIVE);
227
228         LOG.info("getPropertiesOptions: Using the following properties: mode= {}, ip:port= {}:{}",
229                 connectionType, addressStr, portStr);
230
231         return new Option[] {
232                 editConfigurationFilePut(SouthboundITConstants.CUSTOM_PROPERTIES,
233                         SouthboundITConstants.SERVER_IPADDRESS, addressStr),
234                 editConfigurationFilePut(SouthboundITConstants.CUSTOM_PROPERTIES,
235                         SouthboundITConstants.SERVER_PORT, portStr),
236                 editConfigurationFilePut(SouthboundITConstants.CUSTOM_PROPERTIES,
237                         SouthboundITConstants.CONNECTION_TYPE, connectionType),
238         };
239     }
240
241     @Before
242     @Override
243     public void setup() throws InterruptedException {
244         if (setup) {
245             LOG.info("Skipping setup, already initialized");
246             return;
247         }
248
249         try {
250             super.setup();
251         } catch (Exception e) {
252             e.printStackTrace();
253         }
254         //dataBroker = getSession().getSALService(DataBroker.class);
255         Thread.sleep(3000);
256         DataBroker dataBroker = SouthboundProvider.getDb();
257         Assert.assertNotNull("db should not be null", dataBroker);
258
259         addressStr = bundleContext.getProperty(SouthboundITConstants.SERVER_IPADDRESS);
260         String portStr = bundleContext.getProperty(SouthboundITConstants.SERVER_PORT);
261         try {
262             portNumber = Integer.parseInt(portStr);
263         } catch (NumberFormatException e) {
264             fail("Invalid port number " + portStr + System.lineSeparator() + usage());
265         }
266         connectionType = bundleContext.getProperty(SouthboundITConstants.CONNECTION_TYPE);
267
268         LOG.info("setUp: Using the following properties: mode= {}, ip:port= {}:{}",
269                 connectionType, addressStr, portNumber);
270         if (connectionType.equalsIgnoreCase(SouthboundITConstants.CONNECTION_TYPE_ACTIVE)) {
271             if (addressStr == null) {
272                 fail(usage());
273             }
274         }
275
276         mdsalUtils = new MdsalUtils(dataBroker);
277         setup = true;
278     }
279
280     /**
281      * Test passive connection mode. The southbound starts in a listening mode waiting for connections on port
282      * 6640. This test will wait for incoming connections for {@link SouthboundITConstants#CONNECTION_INIT_TIMEOUT} ms.
283      *
284      * @throws InterruptedException
285      */
286     @Test
287     public void testPassiveNode() throws InterruptedException {
288         if (connectionType.equalsIgnoreCase(SouthboundITConstants.CONNECTION_TYPE_PASSIVE)) {
289             //Wait for CONNECTION_INIT_TIMEOUT for the Passive connection to be initiated by the ovsdb-server.
290             Thread.sleep(SouthboundITConstants.CONNECTION_INIT_TIMEOUT);
291         }
292     }
293
294     private ConnectionInfo getConnectionInfo(final String addressStr, final int portNumber) {
295         InetAddress inetAddress = null;
296         try {
297             inetAddress = InetAddress.getByName(addressStr);
298         } catch (UnknownHostException e) {
299             fail("Could not resolve " + addressStr + ": " + e);
300         }
301
302         IpAddress address = SouthboundMapper.createIpAddress(inetAddress);
303         PortNumber port = new PortNumber(portNumber);
304
305         final ConnectionInfo connectionInfo = new ConnectionInfoBuilder()
306                 .setRemoteIp(address)
307                 .setRemotePort(port)
308                 .build();
309         LOG.info("connectionInfo: {}", connectionInfo);
310         return connectionInfo;
311     }
312
313     private String connectionInfoToString(final ConnectionInfo connectionInfo) {
314         return new String(connectionInfo.getRemoteIp().getValue()) + ":" + connectionInfo.getRemotePort().getValue();
315     }
316
317     @Test
318     public void testNetworkTopology() throws InterruptedException {
319         NetworkTopology networkTopology = mdsalUtils.read(LogicalDatastoreType.CONFIGURATION,
320                 InstanceIdentifier.create(NetworkTopology.class));
321         Assert.assertNotNull("NetworkTopology could not be found in " + LogicalDatastoreType.CONFIGURATION,
322                 networkTopology);
323
324         networkTopology = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL,
325                 InstanceIdentifier.create(NetworkTopology.class));
326         Assert.assertNotNull("NetworkTopology could not be found in " + LogicalDatastoreType.OPERATIONAL,
327                 networkTopology);
328     }
329
330     @Test
331     public void testOvsdbTopology() throws InterruptedException {
332         InstanceIdentifier<Topology> path = InstanceIdentifier
333                 .create(NetworkTopology.class)
334                 .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID));
335
336         Topology topology = mdsalUtils.read(LogicalDatastoreType.CONFIGURATION, path);
337         Assert.assertNotNull("Topology could not be found in " + LogicalDatastoreType.CONFIGURATION,
338                 topology);
339
340         topology = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, path);
341
342         Assert.assertNotNull("Topology could not be found in " + LogicalDatastoreType.OPERATIONAL,
343                 topology);
344     }
345
346     private boolean addOvsdbNode(final ConnectionInfo connectionInfo) throws InterruptedException {
347         boolean result = mdsalUtils.put(LogicalDatastoreType.CONFIGURATION,
348                 createInstanceIdentifier(connectionInfo),
349                 createNode(connectionInfo));
350         Thread.sleep(OVSDB_UPDATE_TIMEOUT);
351         return result;
352     }
353
354     private InstanceIdentifier<Node> createInstanceIdentifier(
355             ConnectionInfo connectionInfo) {
356         return InstanceIdentifier
357                 .create(NetworkTopology.class)
358                 .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID))
359                 .child(Node.class,
360                         createNodeKey(connectionInfo.getRemoteIp(), connectionInfo.getRemotePort()));
361     }
362
363     private Node getOvsdbNode(final ConnectionInfo connectionInfo) {
364         return mdsalUtils.read(LogicalDatastoreType.OPERATIONAL,
365                 createInstanceIdentifier(connectionInfo));
366     }
367
368     private boolean deleteOvsdbNode(final ConnectionInfo connectionInfo) throws InterruptedException {
369         boolean result = mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION,
370                 createInstanceIdentifier(connectionInfo));
371         Thread.sleep(OVSDB_UPDATE_TIMEOUT);
372         return result;
373     }
374
375     private Node connectOvsdbNode(final ConnectionInfo connectionInfo) throws InterruptedException {
376         Assert.assertTrue(addOvsdbNode(connectionInfo));
377         Node node = getOvsdbNode(connectionInfo);
378         Assert.assertNotNull(node);
379         LOG.info("Connected to {}", connectionInfoToString(connectionInfo));
380         return node;
381     }
382
383     private boolean disconnectOvsdbNode(final ConnectionInfo connectionInfo) throws InterruptedException {
384         Assert.assertTrue(deleteOvsdbNode(connectionInfo));
385         Node node = getOvsdbNode(connectionInfo);
386         Assert.assertNull(node);
387         //Assume.assumeNotNull(node); // Using assumeNotNull because there is no assumeNull
388         LOG.info("Disconnected from {}", connectionInfoToString(connectionInfo));
389         return true;
390     }
391
392     @Test
393     public void testAddDeleteOvsdbNode() throws InterruptedException {
394         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
395         connectOvsdbNode(connectionInfo);
396         Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
397     }
398
399     @Test
400     public void testDpdkSwitch() throws InterruptedException {
401         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
402         Node ovsdbNode = connectOvsdbNode(connectionInfo);
403         List<DatapathTypeEntry> datapathTypeEntries = ovsdbNode.getAugmentation(OvsdbNodeAugmentation.class)
404                 .getDatapathTypeEntry();
405         if (datapathTypeEntries == null) {
406             LOG.info("DPDK not supported on this node.");
407         } else {
408             for (DatapathTypeEntry dpTypeEntry : datapathTypeEntries) {
409                 Class<? extends DatapathTypeBase> dpType = dpTypeEntry.getDatapathType();
410                 String dpTypeStr = SouthboundConstants.DATAPATH_TYPE_MAP.get(dpType);
411                 LOG.info("dp type is {}", dpTypeStr);
412                 if (dpTypeStr.equals(NETDEV_DP_TYPE)) {
413                     LOG.info("Found a DPDK node; adding a corresponding netdev device");
414                     InstanceIdentifier<Node> bridgeIid = createInstanceIdentifier(connectionInfo,
415                             new OvsdbBridgeName(SouthboundITConstants.BRIDGE_NAME));
416                     NodeId bridgeNodeId = createManagedNodeId(bridgeIid);
417                     addBridge(connectionInfo, bridgeIid, SouthboundITConstants.BRIDGE_NAME, bridgeNodeId, false, null,
418                             true, dpType, null, null, null);
419
420                     // Verify that the device is netdev
421                     OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
422                     Assert.assertNotNull(bridge);
423                     Assert.assertEquals(dpType, bridge.getDatapathType());
424
425                     // Add dpdk port
426                     final String TEST_PORT_NAME = "testDPDKPort";
427                     OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
428                             createGenericDpdkOvsdbTerminationPointAugmentationBuilder(TEST_PORT_NAME);
429                     Assert.assertTrue(addTerminationPoint(bridgeNodeId, TEST_PORT_NAME, ovsdbTerminationBuilder));
430
431                     // Verify that DPDK port was created
432                     InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
433                     Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL,
434                             terminationPointIid);
435                     Assert.assertNotNull(terminationPointNode);
436
437                     // Verify that each termination point has DPDK ifType
438                     Class<? extends InterfaceTypeBase> dpdkIfType = SouthboundConstants.OVSDB_INTERFACE_TYPE_MAP
439                             .get("dpdk");
440                     List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
441                     for (TerminationPoint terminationPoint : terminationPoints) {
442                         OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation = terminationPoint
443                                 .getAugmentation(OvsdbTerminationPointAugmentation.class);
444                         if (ovsdbTerminationPointAugmentation.getName().equals(TEST_PORT_NAME)) {
445                             Class<? extends InterfaceTypeBase> opPort = ovsdbTerminationPointAugmentation
446                                     .getInterfaceType();
447                             Assert.assertEquals(dpdkIfType, opPort);
448                         }
449                     }
450                     Assert.assertTrue(deleteBridge(connectionInfo));
451                     break;
452                 }
453             }
454         }
455         Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
456     }
457
458     @Test
459     public void testOvsdbNodeOvsVersion() throws InterruptedException {
460         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
461         Node ovsdbNode = connectOvsdbNode(connectionInfo);
462         OvsdbNodeAugmentation ovsdbNodeAugmentation = ovsdbNode.getAugmentation(OvsdbNodeAugmentation.class);
463         Assert.assertNotNull(ovsdbNodeAugmentation);
464         assertNotNull(ovsdbNodeAugmentation.getOvsVersion());
465         Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
466     }
467
468     @Test
469     public void testOpenVSwitchOtherConfig() throws InterruptedException {
470         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
471         Node ovsdbNode = connectOvsdbNode(connectionInfo);
472         OvsdbNodeAugmentation ovsdbNodeAugmentation = ovsdbNode.getAugmentation(OvsdbNodeAugmentation.class);
473         Assert.assertNotNull(ovsdbNodeAugmentation);
474         List<OpenvswitchOtherConfigs> otherConfigsList = ovsdbNodeAugmentation.getOpenvswitchOtherConfigs();
475         if (otherConfigsList != null) {
476             for (OpenvswitchOtherConfigs otherConfig : otherConfigsList) {
477                 if (otherConfig.getOtherConfigKey().equals("local_ip")) {
478                     LOG.info("local_ip: {}", otherConfig.getOtherConfigValue());
479                     break;
480                 } else {
481                     LOG.info("other_config {}:{}", otherConfig.getOtherConfigKey(), otherConfig.getOtherConfigValue());
482                 }
483             }
484         } else {
485             LOG.info("other_config is not present");
486         }
487         Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
488     }
489
490     @Test
491     public void testOvsdbBridgeControllerInfo() throws InterruptedException {
492         ConnectionInfo connectionInfo = getConnectionInfo(addressStr,portNumber);
493         Node ovsdbNode = connectOvsdbNode(connectionInfo);
494         String controllerTarget = SouthboundUtil.getControllerTarget(ovsdbNode);
495         assertNotNull("Failed to get controller target", controllerTarget);
496         List<ControllerEntry> setControllerEntry = createControllerEntry(controllerTarget);
497         Uri setUri = new Uri(controllerTarget);
498         Assert.assertTrue(addBridge(connectionInfo, null, SouthboundITConstants.BRIDGE_NAME,null, true,
499                 SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"), true, null, null,
500                 setControllerEntry, null));
501         OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
502         Assert.assertNotNull("bridge was not found: " + SouthboundITConstants.BRIDGE_NAME,  bridge);
503         Assert.assertNotNull("ControllerEntry was not found: " + setControllerEntry.iterator().next(),
504                 bridge.getControllerEntry());
505         List<ControllerEntry> getControllerEntries = bridge.getControllerEntry();
506         for (ControllerEntry entry : getControllerEntries) {
507             if (entry.getTarget() != null) {
508                 Assert.assertEquals(setUri.toString(), entry.getTarget().toString());
509             }
510         }
511
512         Assert.assertTrue(deleteBridge(connectionInfo));
513         Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
514     }
515
516     private List<ControllerEntry> createControllerEntry(String controllerTarget) {
517         List<ControllerEntry> controllerEntriesList = new ArrayList<>();
518         controllerEntriesList.add(new ControllerEntryBuilder()
519                 .setTarget(new Uri(controllerTarget))
520                 .build());
521         return controllerEntriesList;
522     }
523
524     private void setManagedBy(final OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder,
525                               final ConnectionInfo connectionInfo) {
526         InstanceIdentifier<Node> connectionNodePath = createInstanceIdentifier(connectionInfo);
527         ovsdbBridgeAugmentationBuilder.setManagedBy(new OvsdbNodeRef(connectionNodePath));
528     }
529
530     private List<ProtocolEntry> createMdsalProtocols() {
531         List<ProtocolEntry> protocolList = new ArrayList<>();
532         ImmutableBiMap<String, Class<? extends OvsdbBridgeProtocolBase>> mapper =
533                 SouthboundConstants.OVSDB_PROTOCOL_MAP.inverse();
534         protocolList.add(new ProtocolEntryBuilder().setProtocol(mapper.get("OpenFlow13")).build());
535         return protocolList;
536     }
537
538     private OvsdbTerminationPointAugmentationBuilder createGenericOvsdbTerminationPointAugmentationBuilder() {
539         OvsdbTerminationPointAugmentationBuilder ovsdbTerminationPointAugmentationBuilder =
540                 new OvsdbTerminationPointAugmentationBuilder();
541         ovsdbTerminationPointAugmentationBuilder.setInterfaceType(
542                 new InterfaceTypeEntryBuilder()
543                         .setInterfaceType(
544                                 SouthboundMapper.createInterfaceType("internal"))
545                         .build().getInterfaceType());
546         return ovsdbTerminationPointAugmentationBuilder;
547     }
548
549     private OvsdbTerminationPointAugmentationBuilder createGenericDpdkOvsdbTerminationPointAugmentationBuilder(
550             final String portName) {
551         OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
552                 createGenericOvsdbTerminationPointAugmentationBuilder();
553         ovsdbTerminationBuilder.setName(portName);
554         Class<? extends InterfaceTypeBase> ifType = SouthboundConstants.OVSDB_INTERFACE_TYPE_MAP
555                 .get("dpdk");
556         ovsdbTerminationBuilder.setInterfaceType(ifType);
557         return ovsdbTerminationBuilder;
558     }
559
560     private boolean addTerminationPoint(final NodeId bridgeNodeId, final String portName,
561                                         final OvsdbTerminationPointAugmentationBuilder
562                                                 ovsdbTerminationPointAugmentationBuilder)
563             throws InterruptedException {
564
565         InstanceIdentifier<Node> portIid = SouthboundMapper.createInstanceIdentifier(bridgeNodeId);
566         NodeBuilder portNodeBuilder = new NodeBuilder();
567         NodeId portNodeId = SouthboundMapper.createManagedNodeId(portIid);
568         portNodeBuilder.setNodeId(portNodeId);
569         TerminationPointBuilder entry = new TerminationPointBuilder();
570         entry.setKey(new TerminationPointKey(new TpId(portName)));
571         entry.addAugmentation(
572                 OvsdbTerminationPointAugmentation.class,
573                 ovsdbTerminationPointAugmentationBuilder.build());
574         portNodeBuilder.setTerminationPoint(Lists.newArrayList(entry.build()));
575         boolean result = mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
576                 portIid, portNodeBuilder.build());
577         Thread.sleep(OVSDB_UPDATE_TIMEOUT);
578         return result;
579     }
580
581     /*
582      * base method for adding test bridges.  Other helper methods used to create bridges should utilize this method.
583      *
584      * @param connectionInfo
585      * @param bridgeIid if passed null, one is created
586      * @param bridgeName cannot be null
587      * @param bridgeNodeId if passed null, one is created based on <code>bridgeIid</code>
588      * @param setProtocolEntries toggles whether default protocol entries are set for the bridge
589      * @param failMode toggles whether default fail mode is set for the bridge
590      * @param setManagedBy toggles whether to setManagedBy for the bridge
591      * @param dpType if passed null, this parameter is ignored
592      * @param externalIds if passed null, this parameter is ignored
593      * @param otherConfigs if passed null, this parameter is ignored
594      * @return success of bridge addition
595      * @throws InterruptedException
596      */
597     private boolean addBridge(final ConnectionInfo connectionInfo, InstanceIdentifier<Node> bridgeIid,
598                               final String bridgeName, NodeId bridgeNodeId, final boolean setProtocolEntries,
599                               final Class<? extends OvsdbFailModeBase> failMode, final boolean setManagedBy,
600                               final Class<? extends DatapathTypeBase> dpType,
601                               final List<BridgeExternalIds> externalIds,
602                               final List<ControllerEntry> controllerEntries,
603                               final List<BridgeOtherConfigs> otherConfigs) throws InterruptedException {
604
605         NodeBuilder bridgeNodeBuilder = new NodeBuilder();
606         if (bridgeIid == null) {
607             bridgeIid = createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName));
608         }
609         if (bridgeNodeId == null) {
610             bridgeNodeId = SouthboundMapper.createManagedNodeId(bridgeIid);
611         }
612         bridgeNodeBuilder.setNodeId(bridgeNodeId);
613         OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder = new OvsdbBridgeAugmentationBuilder();
614         ovsdbBridgeAugmentationBuilder.setBridgeName(new OvsdbBridgeName(bridgeName));
615         if (setProtocolEntries) {
616             ovsdbBridgeAugmentationBuilder.setProtocolEntry(createMdsalProtocols());
617         }
618         if (failMode != null) {
619             ovsdbBridgeAugmentationBuilder.setFailMode(failMode);
620         }
621         if (setManagedBy) {
622             setManagedBy(ovsdbBridgeAugmentationBuilder, connectionInfo);
623         }
624         if (dpType != null) {
625             ovsdbBridgeAugmentationBuilder.setDatapathType(dpType);
626         }
627         if (externalIds != null) {
628             ovsdbBridgeAugmentationBuilder.setBridgeExternalIds(externalIds);
629         }
630         if (controllerEntries != null) {
631             ovsdbBridgeAugmentationBuilder.setControllerEntry(controllerEntries);
632         }
633         if (otherConfigs != null) {
634             ovsdbBridgeAugmentationBuilder.setBridgeOtherConfigs(otherConfigs);
635         }
636         bridgeNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class, ovsdbBridgeAugmentationBuilder.build());
637         LOG.debug("Built with the intent to store bridge data {}",
638                 ovsdbBridgeAugmentationBuilder.toString());
639         boolean result = mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
640                 bridgeIid, bridgeNodeBuilder.build());
641         Thread.sleep(OVSDB_UPDATE_TIMEOUT);
642         return result;
643     }
644
645     private boolean addBridge(final ConnectionInfo connectionInfo, final String bridgeName)
646             throws InterruptedException {
647
648         return addBridge(connectionInfo, null, bridgeName, null, true,
649                 SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"), true, null, null, null, null);
650     }
651
652     private OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo) {
653         return getBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME);
654     }
655
656     /**
657      * Extract the <code>store</code> type data store contents for the particular bridge identified by
658      * <code>bridgeName</code>.
659      *
660      * @param connectionInfo the connection information
661      * @param bridgeName the bridge name
662      * @param store defined by the <code>LogicalDatastoreType</code> enumeration
663      * @return <code>store</code> type data store contents
664      */
665     private OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo, String bridgeName,
666                                               LogicalDatastoreType store) {
667         Node bridgeNode = getBridgeNode(connectionInfo, bridgeName, store);
668         Assert.assertNotNull(bridgeNode);
669         OvsdbBridgeAugmentation ovsdbBridgeAugmentation = bridgeNode.getAugmentation(OvsdbBridgeAugmentation.class);
670         Assert.assertNotNull(ovsdbBridgeAugmentation);
671         return ovsdbBridgeAugmentation;
672     }
673
674     /**
675      * extract the <code>LogicalDataStoreType.OPERATIONAL</code> type data store contents for the particular bridge
676      * identified by <code>bridgeName</code>
677      *
678      * @param connectionInfo the connection information
679      * @param bridgeName the bridge name
680      * @see <code>SouthboundIT.getBridge(ConnectionInfo, String, LogicalDatastoreType)</code>
681      * @return <code>LogicalDatastoreType.OPERATIONAL</code> type data store contents
682      */
683     private OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo, String bridgeName) {
684         return getBridge(connectionInfo, bridgeName, LogicalDatastoreType.OPERATIONAL);
685     }
686
687     /**
688      * Extract the node contents from <code>store</code> type data store for the
689      * bridge identified by <code>bridgeName</code>
690      *
691      * @param connectionInfo the connection information
692      * @param bridgeName the bridge name
693      * @param store defined by the <code>LogicalDatastoreType</code> enumeration
694      * @return <code>store</code> type data store contents
695      */
696     private Node getBridgeNode(ConnectionInfo connectionInfo, String bridgeName, LogicalDatastoreType store) {
697         InstanceIdentifier<Node> bridgeIid =
698                 createInstanceIdentifier(connectionInfo,
699                         new OvsdbBridgeName(bridgeName));
700         return mdsalUtils.read(store, bridgeIid);
701     }
702
703     /**
704      * Extract the node contents from <code>LogicalDataStoreType.OPERATIONAL</code> data store for the
705      * bridge identified by <code>bridgeName</code>
706      *
707      * @param connectionInfo the connection information
708      * @param bridgeName the bridge name
709      * @return <code>LogicalDatastoreType.OPERATIONAL</code> type data store contents
710      */
711     private Node getBridgeNode(ConnectionInfo connectionInfo, String bridgeName) {
712         return getBridgeNode(connectionInfo, bridgeName, LogicalDatastoreType.OPERATIONAL);
713     }
714
715     private boolean deleteBridge(ConnectionInfo connectionInfo) throws InterruptedException {
716         return deleteBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME);
717     }
718
719     private boolean deleteBridge(final ConnectionInfo connectionInfo, final String bridgeName)
720             throws InterruptedException {
721
722         boolean result = mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION,
723                 createInstanceIdentifier(connectionInfo,
724                         new OvsdbBridgeName(bridgeName)));
725         Thread.sleep(OVSDB_UPDATE_TIMEOUT);
726         return result;
727     }
728
729     @Test
730     public void testAddDeleteBridge() throws InterruptedException {
731         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
732         connectOvsdbNode(connectionInfo);
733
734         Assert.assertTrue(addBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME));
735         OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
736         Assert.assertNotNull(bridge);
737         LOG.info("bridge: {}", bridge);
738
739         Assert.assertTrue(deleteBridge(connectionInfo));
740
741         Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
742     }
743
744     private InstanceIdentifier<Node> getTpIid(ConnectionInfo connectionInfo, OvsdbBridgeAugmentation bridge) {
745         return createInstanceIdentifier(connectionInfo,
746                 bridge.getBridgeName());
747     }
748
749     /**
750      * Extracts the <code>TerminationPointAugmentation</code> for the <code>index</code> <code>TerminationPoint</code>
751      * on <code>bridgeName</code>
752      *
753      * @param connectionInfo the connection information
754      * @param bridgeName the bridge name
755      * @param store defined by the <code>LogicalDatastoreType</code> enumeration
756      * @param index the index we're interested in
757      * @return the augmentation (or {@code null} if none)
758      */
759     private OvsdbTerminationPointAugmentation getOvsdbTerminationPointAugmentation(
760             ConnectionInfo connectionInfo, String bridgeName, LogicalDatastoreType store, int index) {
761
762         List<TerminationPoint> tpList = getBridgeNode(connectionInfo, bridgeName, store).getTerminationPoint();
763         if (tpList == null) {
764             return null;
765         }
766         return tpList.get(index).getAugmentation(OvsdbTerminationPointAugmentation.class);
767     }
768
769     @Test
770     public void testCRDTerminationPointOfPort() throws InterruptedException {
771         final Long OFPORT_EXPECTED = 45002L;
772
773         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
774         connectOvsdbNode(connectionInfo);
775
776         // CREATE
777         Assert.assertTrue(addBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME));
778         OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
779         Assert.assertNotNull(bridge);
780         LOG.info("bridge: {}", bridge);
781         NodeId nodeId = SouthboundMapper.createManagedNodeId(createInstanceIdentifier(
782                 connectionInfo, bridge.getBridgeName()));
783         OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
784                 createGenericOvsdbTerminationPointAugmentationBuilder();
785         String portName = "testOfPort";
786         ovsdbTerminationBuilder.setName(portName);
787
788         ovsdbTerminationBuilder.setOfport(OFPORT_EXPECTED);
789         Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
790         InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
791         Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
792         Assert.assertNotNull(terminationPointNode);
793
794         // READ
795         List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
796         for (TerminationPoint terminationPoint : terminationPoints) {
797             OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
798                     terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
799             if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
800                 Long ofPort = ovsdbTerminationPointAugmentation.getOfport();
801                 // if ephemeral port 45002 is in use, ofPort is set to 1
802                 Assert.assertTrue(ofPort.equals(OFPORT_EXPECTED) || ofPort.equals(new Long(1)));
803                 LOG.info("ofPort: {}", ofPort);
804             }
805         }
806
807         // UPDATE- Not Applicable.  From the OpenVSwitch Documentation:
808         //   "A client should ideally set this column’s value in the same database transaction that it uses to create
809         //   the interface."
810
811         // DELETE
812         Assert.assertTrue(deleteBridge(connectionInfo));
813         Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
814     }
815
816     @Test
817     public void testCRDTerminationPointOfPortRequest() throws InterruptedException {
818         final Long OFPORT_EXPECTED = 45008L;
819         final Long OFPORT_INPUT = 45008L;
820
821         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
822         connectOvsdbNode(connectionInfo);
823
824         // CREATE
825         Assert.assertTrue(addBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME));
826         OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
827         Assert.assertNotNull(bridge);
828         NodeId nodeId = createManagedNodeId(createInstanceIdentifier(
829                 connectionInfo, bridge.getBridgeName()));
830         OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
831                 createGenericOvsdbTerminationPointAugmentationBuilder();
832         String portName = "testOfPortRequest";
833         ovsdbTerminationBuilder.setName(portName);
834         Integer ofPortRequestExpected = OFPORT_EXPECTED.intValue();
835         ovsdbTerminationBuilder.setOfport(OFPORT_INPUT);
836         ovsdbTerminationBuilder.setOfportRequest(ofPortRequestExpected);
837         Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
838         InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
839         Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
840         Assert.assertNotNull(terminationPointNode);
841
842         // READ
843         List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
844         for (TerminationPoint terminationPoint : terminationPoints) {
845             OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
846                     terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
847             if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
848                 Long ofPort = ovsdbTerminationPointAugmentation.getOfport();
849                 // if ephemeral port 45008 is in use, ofPort is set to 1
850                 Assert.assertTrue(ofPort.equals(OFPORT_EXPECTED) || ofPort.equals(new Long(1)));
851                 LOG.info("ofPort: {}", ofPort);
852
853                 Integer ofPortRequest = ovsdbTerminationPointAugmentation.getOfportRequest();
854                 Assert.assertTrue(ofPortRequest.equals(ofPortRequestExpected));
855                 LOG.info("ofPortRequest: {}", ofPortRequest);
856             }
857         }
858
859         // UPDATE- Not Applicable.  From the OpenVSwitch documentation:
860         //   "A client should ideally set this column’s value in the same database transaction that it uses to create
861         //   the interface. "
862
863         // DELETE
864         Assert.assertTrue(deleteBridge(connectionInfo));
865         Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
866     }
867
868     /*
869      * Generates the test cases involved in testing PortExternalIds.  See inline comments for descriptions of
870      * the particular cases considered.
871      *
872      * The return value is a Map in the form (K,V)=(testCaseName,testCase).
873      * - testCaseName is a String
874      * - testCase is a Map in the form (K,V) s.t. K=(EXPECTED_VALUES_KEY|INPUT_VALUES_KEY) and V is a List of
875      *     either corresponding INPUT port external_ids, or EXPECTED port external_ids
876      *     INPUT    is the List we use when calling
877      *              <code>TerminationPointAugmentationBuilder.setPortExternalIds()</code>
878      *     EXPECTED is the List we expect to receive after calling
879      *              <code>TerminationPointAugmentationBuilder.getPortExternalIds()</code>
880      */
881     private List<SouthboundTestCase<PortExternalIds>> generatePortExternalIdsTestCases() {
882         List<SouthboundTestCase<PortExternalIds>> testCases = new ArrayList<>();
883
884         final String PORT_EXTERNAL_ID_KEY = "PortExternalIdKey";
885         final String PORT_EXTERNAL_ID_VALUE = "PortExternalIdValue";
886         final String GOOD_KEY = "GoodKey";
887         final String GOOD_VALUE = "GoodValue";
888         final String NO_VALUE_FOR_KEY = "NoValueForKey";
889
890         KeyValueBuilder<PortExternalIds> builder = new SouthboundPortExternalIdsBuilder();
891
892         // Test Case 1:  TestOneExternalId
893         // Test Type:    Positive
894         // Description:  Create a termination point with one PortExternalIds
895         // Expected:     A port is created with the single external_ids specified below
896         final String testOneExternalIdName = "TestOneExternalId";
897         testCases.add(SouthboundIT.<PortExternalIds>testCase()
898                 .name(testOneExternalIdName)
899                 .input(builder.build(testOneExternalIdName, PORT_EXTERNAL_ID_KEY, PORT_EXTERNAL_ID_VALUE))
900                 .expectInputAsOutput()
901                 .build());
902
903         // Test Case 2:  TestFiveExternalId
904         // Test Type:    Positive
905         // Description:  Create a termination point with multiple (five) PortExternalIds
906         // Expected:     A port is created with the five external_ids specified below
907         final String testFiveExternalIdName = "TestFiveExternalId";
908         builder.reset();
909         testCases.add(SouthboundIT.<PortExternalIds>testCase()
910                 .name(testFiveExternalIdName)
911                 .input(
912                         builder.build(testFiveExternalIdName, PORT_EXTERNAL_ID_KEY, PORT_EXTERNAL_ID_VALUE),
913                         builder.build(testFiveExternalIdName, PORT_EXTERNAL_ID_KEY, PORT_EXTERNAL_ID_VALUE),
914                         builder.build(testFiveExternalIdName, PORT_EXTERNAL_ID_KEY, PORT_EXTERNAL_ID_VALUE),
915                         builder.build(testFiveExternalIdName, PORT_EXTERNAL_ID_KEY, PORT_EXTERNAL_ID_VALUE),
916                         builder.build(testFiveExternalIdName, PORT_EXTERNAL_ID_KEY, PORT_EXTERNAL_ID_VALUE))
917                 .expectInputAsOutput()
918                 .build());
919
920         // Test Case 3:  TestOneGoodExternalIdOneMalformedExternalIdValue
921         // Test Type:    Negative
922         // Description:
923         //     One perfectly fine PortExternalId
924         //        (TestOneGoodExternalIdOneMalformedExternalIdValue_PortExternalIdKey_1,
925         //        TestOneGoodExternalIdOneMalformedExternalId_PortExternalIdValue_1)
926         //     and one malformed PortExternalId which only has key specified
927         //        (TestOneGoodExternalIdOneMalformedExternalIdValue_NoValueForKey_2,
928         //        UNSPECIFIED)
929         // Expected:     A port is created without any external_ids
930         final String testOneGoodExternalIdOneMalformedExternalIdValueName =
931                 "TestOneGoodExternalIdOneMalformedExternalIdValue";
932         builder.reset();
933         testCases.add(SouthboundIT.<PortExternalIds>testCase()
934                 .name(testOneGoodExternalIdOneMalformedExternalIdValueName)
935                 .input(
936                         builder.build(testOneGoodExternalIdOneMalformedExternalIdValueName, GOOD_KEY, GOOD_VALUE),
937                         builder.build(testOneGoodExternalIdOneMalformedExternalIdValueName, NO_VALUE_FOR_KEY, null))
938                 .expectNoOutput()
939                 .build());
940
941         return testCases;
942     }
943
944     /*
945      * @see <code>SouthboundIT.testCRUDPortExternalIds()</code>
946      * This is helper test method to compare a test "set" of BridgeExternalIds against an expected "set"
947      */
948     private void assertExpectedPortExternalIdsExist( List<PortExternalIds> expected,
949                                                      List<PortExternalIds> test ) {
950
951         if (expected != null) {
952             for (PortExternalIds expectedExternalId : expected) {
953                 Assert.assertTrue("The retrieved ids don't contain " + expectedExternalId,
954                         test.contains(expectedExternalId));
955             }
956         }
957     }
958
959     /*
960      * Tests the CRUD operations for <code>Port</code> <code>external_ids</code>.
961      *
962      * @see <code>SouthboundIT.generatePortExternalIdsTestCases()</code> for specific test case information
963      */
964     @Test
965     public void testCRUDTerminationPointPortExternalIds() throws InterruptedException {
966         final String TEST_PREFIX = "CRUDTPPortExternalIds";
967         final int TERMINATION_POINT_TEST_INDEX = 0;
968
969         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
970         connectOvsdbNode(connectionInfo);
971
972         // updateFromTestCases represent the original test case value.  updateToTestCases represent the new value after
973         // the update has been performed.
974         List<SouthboundTestCase<PortExternalIds>> updateFromTestCases = generatePortExternalIdsTestCases();
975         List<SouthboundTestCase<PortExternalIds>> updateToTestCases = generatePortExternalIdsTestCases();
976
977         for (SouthboundTestCase<PortExternalIds> updateFromTestCase : updateFromTestCases) {
978             List<PortExternalIds> updateFromInputExternalIds = updateFromTestCase.inputValues;
979             List<PortExternalIds> updateFromExpectedExternalIds = updateFromTestCase.expectedValues;
980             for (SouthboundTestCase<PortExternalIds> updateToTestCase : updateToTestCases) {
981                 String testBridgeAndPortName = String.format("%s_%s", TEST_PREFIX, updateToTestCase.name);
982                 List<PortExternalIds> updateToInputExternalIds = updateToTestCase.inputValues;
983                 List<PortExternalIds> updateToExpectedExternalIds = updateToTestCase.expectedValues;
984
985                 // CREATE: Create the test bridge
986                 Assert.assertTrue(addBridge(connectionInfo, null, testBridgeAndPortName, null, true,
987                         SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"), true, null, null, null, null));
988                 NodeId testBridgeNodeId = createManagedNodeId(createInstanceIdentifier(
989                         connectionInfo, new OvsdbBridgeName(testBridgeAndPortName)));
990                 OvsdbTerminationPointAugmentationBuilder tpCreateAugmentationBuilder =
991                         createGenericOvsdbTerminationPointAugmentationBuilder();
992                 tpCreateAugmentationBuilder.setName(testBridgeAndPortName);
993                 tpCreateAugmentationBuilder.setPortExternalIds(updateFromInputExternalIds);
994                 Assert.assertTrue(
995                         addTerminationPoint(testBridgeNodeId, testBridgeAndPortName, tpCreateAugmentationBuilder));
996
997                 // READ: Read the test port and ensure changes are propagated to the CONFIGURATION data store,
998                 // then repeat for OPERATIONAL data store
999                 OvsdbTerminationPointAugmentation updateFromConfigurationTerminationPointAugmentation =
1000                         getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeAndPortName,
1001                                 LogicalDatastoreType.CONFIGURATION, TERMINATION_POINT_TEST_INDEX);
1002                 if (updateFromConfigurationTerminationPointAugmentation != null) {
1003                     List<PortExternalIds> updateFromConfigurationExternalIds =
1004                             updateFromConfigurationTerminationPointAugmentation.getPortExternalIds();
1005                     assertExpectedPortExternalIdsExist(updateFromExpectedExternalIds,
1006                             updateFromConfigurationExternalIds);
1007                 }
1008                 OvsdbTerminationPointAugmentation updateFromOperationalTerminationPointAugmentation =
1009                         getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeAndPortName,
1010                                 LogicalDatastoreType.OPERATIONAL, TERMINATION_POINT_TEST_INDEX);
1011                 if (updateFromOperationalTerminationPointAugmentation != null) {
1012                     List<PortExternalIds> updateFromOperationalExternalIds =
1013                             updateFromOperationalTerminationPointAugmentation.getPortExternalIds();
1014                     assertExpectedPortExternalIdsExist(updateFromExpectedExternalIds, updateFromOperationalExternalIds);
1015                 }
1016
1017                 // UPDATE:  update the external_ids
1018                 testBridgeNodeId = getBridgeNode(connectionInfo, testBridgeAndPortName).getNodeId();
1019                 OvsdbTerminationPointAugmentationBuilder tpUpdateAugmentationBuilder =
1020                         new OvsdbTerminationPointAugmentationBuilder();
1021                 tpUpdateAugmentationBuilder.setPortExternalIds(updateToInputExternalIds);
1022                 InstanceIdentifier<Node> portIid = SouthboundMapper.createInstanceIdentifier(testBridgeNodeId);
1023                 NodeBuilder portUpdateNodeBuilder = new NodeBuilder();
1024                 NodeId portUpdateNodeId = createManagedNodeId(portIid);
1025                 portUpdateNodeBuilder.setNodeId(portUpdateNodeId);
1026                 TerminationPointBuilder tpUpdateBuilder = new TerminationPointBuilder();
1027                 tpUpdateBuilder.setKey(new TerminationPointKey(new TpId(testBridgeAndPortName)));
1028                 tpUpdateBuilder.addAugmentation(
1029                         OvsdbTerminationPointAugmentation.class,
1030                         tpUpdateAugmentationBuilder.build());
1031                 portUpdateNodeBuilder.setTerminationPoint(Lists.newArrayList(tpUpdateBuilder.build()));
1032                 Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
1033                         portIid, portUpdateNodeBuilder.build()));
1034                 Thread.sleep(OVSDB_UPDATE_TIMEOUT);
1035
1036                 // READ: the test port and ensure changes are propagated to the CONFIGURATION data store,
1037                 // then repeat for OPERATIONAL data store
1038                 OvsdbTerminationPointAugmentation updateToConfigurationTerminationPointAugmentation =
1039                         getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeAndPortName,
1040                                 LogicalDatastoreType.CONFIGURATION, TERMINATION_POINT_TEST_INDEX);
1041                 if (updateToConfigurationTerminationPointAugmentation != null) {
1042                     List<PortExternalIds> updateToConfigurationExternalIds =
1043                             updateToConfigurationTerminationPointAugmentation.getPortExternalIds();
1044                     assertExpectedPortExternalIdsExist(updateToExpectedExternalIds, updateToConfigurationExternalIds);
1045                     assertExpectedPortExternalIdsExist(updateFromExpectedExternalIds, updateToConfigurationExternalIds);
1046                 }
1047                 OvsdbTerminationPointAugmentation updateToOperationalTerminationPointAugmentation =
1048                         getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeAndPortName,
1049                                 LogicalDatastoreType.OPERATIONAL, TERMINATION_POINT_TEST_INDEX);
1050                 if (updateToOperationalTerminationPointAugmentation != null) {
1051                     List<PortExternalIds> updateToOperationalExternalIds =
1052                             updateToOperationalTerminationPointAugmentation.getPortExternalIds();
1053                     if (updateFromExpectedExternalIds != null ) {
1054                         assertExpectedPortExternalIdsExist(updateToExpectedExternalIds, updateToOperationalExternalIds);
1055                         assertExpectedPortExternalIdsExist(updateFromExpectedExternalIds,
1056                                 updateToOperationalExternalIds);
1057                     }
1058                     // testCRUDTerminationPointInterfaceExternalIds()'s null assertion of updateToOperationalExternalIds
1059                     // fails here
1060                 }
1061
1062                 // DELETE
1063                 Assert.assertTrue(deleteBridge(connectionInfo, testBridgeAndPortName));
1064             }
1065         }
1066         Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
1067     }
1068
1069     /*
1070      * Generates the test cases involved in testing InterfaceExternalIds.  See inline comments for descriptions of
1071      * the particular cases considered.
1072      *
1073      * The return value is a Map in the form (K,V)=(testCaseName,testCase).
1074      * - testCaseName is a String
1075      * - testCase is a Map in the form (K,V) s.t. K=(EXPECTED_VALUES_KEY|INPUT_VALUES_KEY) and V is a List of
1076      *     either corresponding INPUT interface external_ids, or EXPECTED interface external_ids
1077      *     INPUT    is the List we use when calling
1078      *              <code>TerminationPointAugmentationBuilder.setInterfaceExternalIds()</code>
1079      *     EXPECTED is the List we expect to receive after calling
1080      *              <code>TerminationPointAugmentationBuilder.getInterfaceExternalIds()</code>
1081      */
1082     private List<SouthboundTestCase<InterfaceExternalIds>> generateInterfaceExternalIdsTestCases() {
1083         List<SouthboundTestCase<InterfaceExternalIds>> testCases = new ArrayList<>();
1084
1085         final String INTERFACE_EXTERNAL_ID_KEY = "IntExternalIdKey";
1086         final String INTERFACE_EXTERNAL_ID_VALUE = "IntExternalIdValue";
1087         final String GOOD_KEY = "GoodKey";
1088         final String GOOD_VALUE = "GoodValue";
1089         final String NO_VALUE_FOR_KEY = "NoValueForKey";
1090
1091         KeyValueBuilder<InterfaceExternalIds> builder = new SouthboundInterfaceExternalIdsBuilder();
1092
1093         // Test Case 1:  TestOneExternalId
1094         // Test Type:    Positive
1095         // Description:  Create a termination point with one InterfaceExternalIds
1096         // Expected:     A termination point is created with the single external_ids specified below
1097         final String testOneExternalIdName = "TestOneExternalId";
1098         testCases.add(SouthboundIT.<InterfaceExternalIds>testCase()
1099                 .name(testOneExternalIdName)
1100                 .input(builder.build(testOneExternalIdName, INTERFACE_EXTERNAL_ID_KEY, INTERFACE_EXTERNAL_ID_VALUE))
1101                 .expectInputAsOutput()
1102                 .build());
1103
1104         // Test Case 2:  TestFiveExternalId
1105         // Test Type:    Positive
1106         // Description:  Create a termination point with multiple (five) InterfaceExternalIds
1107         // Expected:     A termination point is created with the five external_ids specified below
1108         final String testFiveExternalIdName = "TestFiveExternalId";
1109         builder.reset();
1110         testCases.add(SouthboundIT.<InterfaceExternalIds>testCase()
1111                 .name(testFiveExternalIdName)
1112                 .input(
1113                         builder.build(testFiveExternalIdName, INTERFACE_EXTERNAL_ID_KEY, INTERFACE_EXTERNAL_ID_VALUE),
1114                         builder.build(testFiveExternalIdName, INTERFACE_EXTERNAL_ID_KEY, INTERFACE_EXTERNAL_ID_VALUE),
1115                         builder.build(testFiveExternalIdName, INTERFACE_EXTERNAL_ID_KEY, INTERFACE_EXTERNAL_ID_VALUE),
1116                         builder.build(testFiveExternalIdName, INTERFACE_EXTERNAL_ID_KEY, INTERFACE_EXTERNAL_ID_VALUE),
1117                         builder.build(testFiveExternalIdName, INTERFACE_EXTERNAL_ID_KEY, INTERFACE_EXTERNAL_ID_VALUE))
1118                 .expectInputAsOutput()
1119                 .build());
1120
1121         // Test Case 3:  TestOneGoodExternalIdOneMalformedExternalIdValue
1122         // Test Type:    Negative
1123         // Description:
1124         //     One perfectly fine InterfaceExternalId
1125         //        (TestOneGoodExternalIdOneMalformedExternalIdValue_IntExternalIdKey_1,
1126         //        TestOneGoodExternalIdOneMalformedExternalId_IntExternalIdValue_1)
1127         //     and one malformed PortExternalId which only has key specified
1128         //        (TestOneGoodExternalIdOneMalformedExternalIdValue_NoValueForKey_2,
1129         //        UNSPECIFIED)
1130         // Expected:     A termination point is created without any external_ids
1131         final String testOneGoodExternalIdOneMalformedExternalIdValueName =
1132                 "TestOneGoodExternalIdOneMalformedExternalIdValue";
1133         builder.reset();
1134         testCases.add(SouthboundIT.<InterfaceExternalIds>testCase()
1135                 .name(testOneGoodExternalIdOneMalformedExternalIdValueName)
1136                 .input(
1137                         builder.build(testOneGoodExternalIdOneMalformedExternalIdValueName, GOOD_KEY, GOOD_VALUE),
1138                         builder.build(testOneGoodExternalIdOneMalformedExternalIdValueName, NO_VALUE_FOR_KEY, null))
1139                 .expectNoOutput()
1140                 .build());
1141
1142         return testCases;
1143     }
1144
1145     /*
1146      * @see <code>SouthboundIT.testCRUDInterfaceExternalIds()</code>
1147      * This is helper test method to compare a test "set" of InterfaceExternalIds against an expected "set"
1148      */
1149     private void assertExpectedInterfaceExternalIdsExist( List<InterfaceExternalIds> expected,
1150                                                           List<InterfaceExternalIds> test ) {
1151
1152         if (expected != null) {
1153             for (InterfaceExternalIds expectedExternalId : expected) {
1154                 Assert.assertTrue(test.contains(expectedExternalId));
1155             }
1156         }
1157     }
1158
1159     /*
1160      * Tests the CRUD operations for <code>Interface</code> <code>external_ids</code>.
1161      *
1162      * @see <code>SouthboundIT.generateInterfaceExternalIdsTestCases()</code> for specific test case information
1163      */
1164     @Test
1165     public void testCRUDTerminationPointInterfaceExternalIds() throws InterruptedException {
1166         final String TEST_PREFIX = "CRUDTPInterfaceExternalIds";
1167         final int TERMINATION_POINT_TEST_INDEX = 0;
1168
1169         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
1170         connectOvsdbNode(connectionInfo);
1171
1172         // updateFromTestCases represent the original test case value.  updateToTestCases represent the new value after
1173         // the update has been performed.
1174         List<SouthboundTestCase<InterfaceExternalIds>> updateFromTestCases = generateInterfaceExternalIdsTestCases();
1175         List<SouthboundTestCase<InterfaceExternalIds>> updateToTestCases = generateInterfaceExternalIdsTestCases();
1176
1177         for (SouthboundTestCase<InterfaceExternalIds> updateFromTestCase : updateFromTestCases) {
1178             List<InterfaceExternalIds> updateFromInputExternalIds = updateFromTestCase.inputValues;
1179             List<InterfaceExternalIds> updateFromExpectedExternalIds = updateFromTestCase.expectedValues;
1180             for (SouthboundTestCase<InterfaceExternalIds> updateToTestCase : updateToTestCases) {
1181                 String testBridgeAndPortName = String.format("%s_%s", TEST_PREFIX, updateToTestCase.name);
1182                 List<InterfaceExternalIds> updateToInputExternalIds = updateToTestCase.inputValues;
1183                 List<InterfaceExternalIds> updateToExpectedExternalIds = updateToTestCase.expectedValues;
1184
1185                 // CREATE: Create the test interface
1186                 Assert.assertTrue(addBridge(connectionInfo, null, testBridgeAndPortName, null, true,
1187                         SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"), true, null, null, null, null));
1188                 NodeId testBridgeNodeId = createManagedNodeId(createInstanceIdentifier(
1189                         connectionInfo, new OvsdbBridgeName(testBridgeAndPortName)));
1190                 OvsdbTerminationPointAugmentationBuilder tpCreateAugmentationBuilder =
1191                         createGenericOvsdbTerminationPointAugmentationBuilder();
1192                 tpCreateAugmentationBuilder.setName(testBridgeAndPortName);
1193                 tpCreateAugmentationBuilder.setInterfaceExternalIds(updateFromInputExternalIds);
1194                 Assert.assertTrue(
1195                         addTerminationPoint(testBridgeNodeId, testBridgeAndPortName, tpCreateAugmentationBuilder));
1196
1197                 // READ: Read the test interface and ensure changes are propagated to the CONFIGURATION data store,
1198                 // then repeat for OPERATIONAL data store
1199                 OvsdbTerminationPointAugmentation updateFromConfigurationTerminationPointAugmentation =
1200                         getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeAndPortName,
1201                                 LogicalDatastoreType.CONFIGURATION, TERMINATION_POINT_TEST_INDEX);
1202                 if (updateFromConfigurationTerminationPointAugmentation != null) {
1203                     List<InterfaceExternalIds> updateFromConfigurationExternalIds =
1204                             updateFromConfigurationTerminationPointAugmentation.getInterfaceExternalIds();
1205                     assertExpectedInterfaceExternalIdsExist(updateFromExpectedExternalIds,
1206                             updateFromConfigurationExternalIds);
1207                 }
1208                 OvsdbTerminationPointAugmentation updateFromOperationalTerminationPointAugmentation =
1209                         getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeAndPortName,
1210                                 LogicalDatastoreType.OPERATIONAL, TERMINATION_POINT_TEST_INDEX);
1211                 if (updateFromOperationalTerminationPointAugmentation != null) {
1212                     List<InterfaceExternalIds> updateFromOperationalExternalIds =
1213                             updateFromOperationalTerminationPointAugmentation.getInterfaceExternalIds();
1214                     assertExpectedInterfaceExternalIdsExist(updateFromExpectedExternalIds,
1215                             updateFromOperationalExternalIds);
1216                 }
1217
1218                 // UPDATE:  update the external_ids
1219                 testBridgeNodeId = getBridgeNode(connectionInfo, testBridgeAndPortName).getNodeId();
1220                 OvsdbTerminationPointAugmentationBuilder tpUpdateAugmentationBuilder =
1221                         new OvsdbTerminationPointAugmentationBuilder();
1222                 tpUpdateAugmentationBuilder.setInterfaceExternalIds(updateToInputExternalIds);
1223                 InstanceIdentifier<Node> portIid = SouthboundMapper.createInstanceIdentifier(testBridgeNodeId);
1224                 NodeBuilder portUpdateNodeBuilder = new NodeBuilder();
1225                 NodeId portUpdateNodeId = createManagedNodeId(portIid);
1226                 portUpdateNodeBuilder.setNodeId(portUpdateNodeId);
1227                 TerminationPointBuilder tpUpdateBuilder = new TerminationPointBuilder();
1228                 tpUpdateBuilder.setKey(new TerminationPointKey(new TpId(testBridgeAndPortName)));
1229                 tpUpdateBuilder.addAugmentation(
1230                         OvsdbTerminationPointAugmentation.class,
1231                         tpUpdateAugmentationBuilder.build());
1232                 portUpdateNodeBuilder.setTerminationPoint(Lists.newArrayList(tpUpdateBuilder.build()));
1233                 Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
1234                         portIid, portUpdateNodeBuilder.build()));
1235                 Thread.sleep(OVSDB_UPDATE_TIMEOUT);
1236
1237                 // READ: the test interface and ensure changes are propagated to the CONFIGURATION data store,
1238                 // then repeat for OPERATIONAL data store
1239                 OvsdbTerminationPointAugmentation updateToConfigurationTerminationPointAugmentation =
1240                         getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeAndPortName,
1241                                 LogicalDatastoreType.CONFIGURATION, TERMINATION_POINT_TEST_INDEX);
1242                 if (updateToConfigurationTerminationPointAugmentation != null) {
1243                     List<InterfaceExternalIds> updateToConfigurationExternalIds =
1244                             updateToConfigurationTerminationPointAugmentation.getInterfaceExternalIds();
1245                     assertExpectedInterfaceExternalIdsExist(updateToExpectedExternalIds,
1246                             updateToConfigurationExternalIds);
1247                     assertExpectedInterfaceExternalIdsExist(updateFromExpectedExternalIds,
1248                             updateToConfigurationExternalIds);
1249                 }
1250                 OvsdbTerminationPointAugmentation updateToOperationalTerminationPointAugmentation =
1251                         getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeAndPortName,
1252                                 LogicalDatastoreType.OPERATIONAL, TERMINATION_POINT_TEST_INDEX);
1253                 if (updateToOperationalTerminationPointAugmentation != null) {
1254                     List<InterfaceExternalIds> updateToOperationalExternalIds =
1255                             updateToOperationalTerminationPointAugmentation.getInterfaceExternalIds();
1256                     if (updateFromExpectedExternalIds != null) {
1257                         assertExpectedInterfaceExternalIdsExist(updateToExpectedExternalIds,
1258                                 updateToOperationalExternalIds);
1259                         assertExpectedInterfaceExternalIdsExist(updateFromExpectedExternalIds,
1260                                 updateToOperationalExternalIds);
1261                     } else {
1262                         Assert.assertNull(updateToOperationalExternalIds);
1263                     }
1264                 }
1265
1266                 // DELETE
1267                 Assert.assertTrue(deleteBridge(connectionInfo, testBridgeAndPortName));
1268             }
1269         }
1270         Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
1271     }
1272
1273     /*
1274      * Generates the test cases involved in testing TP Options.  See inline comments for descriptions of
1275      * the particular cases considered.
1276      *
1277      * The return value is a Map in the form (K,V)=(testCaseName,testCase).
1278      * - testCaseName is a String
1279      * - testCase is a Map in the form (K,V) s.t. K=(EXPECTED_VALUES_KEY|INPUT_VALUES_KEY) and V is a List of
1280      *     either corresponding INPUT TP Options, or EXPECTED TP Options
1281      *     INPUT    is the List we use when calling
1282      *              <code>TerminationPointAugmentationBuilder.setOptions()</code>
1283      *     EXPECTED is the List we expect to receive after calling
1284      *              <code>TerminationPointAugmentationBuilder.getOptions()</code>
1285      */
1286     private List<SouthboundTestCase<Options>> generateTerminationPointOptionsTestCases() {
1287         List<SouthboundTestCase<Options>> testCases = new ArrayList<>();
1288
1289         final String TP_OPTIONS_KEY = "TPOptionsKey";
1290         final String TP_OPTIONS_VALUE = "TPOptionsValue";
1291         final String GOOD_KEY = "GoodKey";
1292         final String GOOD_VALUE = "GoodValue";
1293         final String NO_VALUE_FOR_KEY = "NoValueForKey";
1294
1295         KeyValueBuilder<Options> builder = new SouthboundOptionsBuilder();
1296
1297         // Test Case 1:  TestOneOptions
1298         // Test Type:    Positive
1299         // Description:  Create a termination point with one Options
1300         // Expected:     A termination point is created with the single Options specified below
1301         final String testOneOptionsName = "TestOneOptions";
1302         testCases.add(SouthboundIT.<Options>testCase()
1303                 .name(testOneOptionsName)
1304                 .input(builder.build(testOneOptionsName, TP_OPTIONS_KEY, TP_OPTIONS_VALUE))
1305                 .expectInputAsOutput()
1306                 .build());
1307
1308         // Test Case 2:  TestFiveOptions
1309         // Test Type:    Positive
1310         // Description:  Create a termination point with multiple (five) Options
1311         // Expected:     A termination point is created with the five options specified below
1312         final String testFiveOptionsName = "TestFiveOptions";
1313         builder.reset();
1314         testCases.add(SouthboundIT.<Options>testCase()
1315                 .name(testFiveOptionsName)
1316                 .input(
1317                         builder.build(testFiveOptionsName, TP_OPTIONS_KEY, TP_OPTIONS_VALUE),
1318                         builder.build(testFiveOptionsName, TP_OPTIONS_KEY, TP_OPTIONS_VALUE),
1319                         builder.build(testFiveOptionsName, TP_OPTIONS_KEY, TP_OPTIONS_VALUE),
1320                         builder.build(testFiveOptionsName, TP_OPTIONS_KEY, TP_OPTIONS_VALUE),
1321                         builder.build(testFiveOptionsName, TP_OPTIONS_KEY, TP_OPTIONS_VALUE))
1322                 .expectInputAsOutput()
1323                 .build());
1324
1325         // Test Case 3:  TestOneGoodOptionsOneMalformedOptionsValue
1326         // Test Type:    Negative
1327         // Description:
1328         //     One perfectly fine Options
1329         //        (TestOneGoodOptionsOneMalformedOptionsValue_OptionsKey_1,
1330         //        TestOneGoodOptionsOneMalformedOptions_OptionsValue_1)
1331         //     and one malformed Options which only has key specified
1332         //        (TestOneGoodOptionsOneMalformedOptionsValue_NoValueForKey_2,
1333         //        UNSPECIFIED)
1334         // Expected:     A termination point is created without any options
1335         final String testOneGoodOptionsOneMalformedOptionsValueName =
1336                 "TestOneGoodOptionsOneMalformedOptionsValue";
1337         builder.reset();
1338         testCases.add(SouthboundIT.<Options>testCase()
1339                 .name(testOneGoodOptionsOneMalformedOptionsValueName)
1340                 .input(
1341                         builder.build(testOneGoodOptionsOneMalformedOptionsValueName, GOOD_KEY, GOOD_VALUE),
1342                         builder.build(testOneGoodOptionsOneMalformedOptionsValueName, NO_VALUE_FOR_KEY, null))
1343                 .expectNoOutput()
1344                 .build());
1345
1346         return testCases;
1347     }
1348
1349     /*
1350      * @see <code>SouthboundIT.testCRUDTerminationPointOptions()</code>
1351      * This is helper test method to compare a test "set" of Options against an expected "set"
1352      */
1353     private void assertExpectedOptionsExist( List<Options> expected,
1354                                              List<Options> test ) {
1355
1356         if (expected != null) {
1357             for (Options expectedOption : expected) {
1358                 Assert.assertTrue(test.contains(expectedOption));
1359             }
1360         }
1361     }
1362
1363     /*
1364      * Tests the CRUD operations for <code>TerminationPoint</code> <code>options</code>.
1365      *
1366      * @see <code>SouthboundIT.generateTerminationPointOptions()</code> for specific test case information
1367      */
1368     @Test
1369     public void testCRUDTerminationPointOptions() throws InterruptedException {
1370         final String TEST_PREFIX = "CRUDTPOptions";
1371         final int TERMINATION_POINT_TEST_INDEX = 0;
1372
1373         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
1374         connectOvsdbNode(connectionInfo);
1375
1376         // updateFromTestCases represent the original test case value.  updateToTestCases represent the new value after
1377         // the update has been performed.
1378         List<SouthboundTestCase<Options>> updateFromTestCases = generateTerminationPointOptionsTestCases();
1379         List<SouthboundTestCase<Options>> updateToTestCases = generateTerminationPointOptionsTestCases();
1380
1381         for (SouthboundTestCase<Options> updateFromTestCase : updateFromTestCases) {
1382             List<Options> updateFromInputOptions = updateFromTestCase.inputValues;
1383             List<Options> updateFromExpectedOptions = updateFromTestCase.expectedValues;
1384             for (SouthboundTestCase<Options> updateToTestCase : updateToTestCases) {
1385                 String testBridgeAndPortName = String.format("%s_%s", TEST_PREFIX, updateToTestCase.name);
1386                 List<Options> updateToInputOptions = updateToTestCase.inputValues;
1387                 List<Options> updateToExpectedOptions = updateToTestCase.expectedValues;
1388
1389                 // CREATE: Create the test interface
1390                 Assert.assertTrue(addBridge(connectionInfo, null, testBridgeAndPortName, null, true,
1391                         SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"), true, null, null, null, null));
1392                 NodeId testBridgeNodeId = createManagedNodeId(createInstanceIdentifier(
1393                         connectionInfo, new OvsdbBridgeName(testBridgeAndPortName)));
1394                 OvsdbTerminationPointAugmentationBuilder tpCreateAugmentationBuilder =
1395                         createGenericOvsdbTerminationPointAugmentationBuilder();
1396                 tpCreateAugmentationBuilder.setName(testBridgeAndPortName);
1397                 tpCreateAugmentationBuilder.setOptions(updateFromInputOptions);
1398                 Assert.assertTrue(
1399                         addTerminationPoint(testBridgeNodeId, testBridgeAndPortName, tpCreateAugmentationBuilder));
1400
1401                 // READ: Read the test interface and ensure changes are propagated to the CONFIGURATION data store,
1402                 // then repeat for OPERATIONAL data store
1403                 OvsdbTerminationPointAugmentation updateFromConfigurationTerminationPointAugmentation =
1404                         getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeAndPortName,
1405                                 LogicalDatastoreType.CONFIGURATION, TERMINATION_POINT_TEST_INDEX);
1406                 if (updateFromConfigurationTerminationPointAugmentation != null) {
1407                     List<Options> updateFromConfigurationOptions =
1408                             updateFromConfigurationTerminationPointAugmentation.getOptions();
1409                     assertExpectedOptionsExist(updateFromExpectedOptions, updateFromConfigurationOptions);
1410                 }
1411                 OvsdbTerminationPointAugmentation updateFromOperationalTerminationPointAugmentation =
1412                         getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeAndPortName,
1413                                 LogicalDatastoreType.OPERATIONAL, TERMINATION_POINT_TEST_INDEX);
1414                 if (updateFromOperationalTerminationPointAugmentation != null) {
1415                     List<Options> updateFromOperationalOptions =
1416                             updateFromOperationalTerminationPointAugmentation.getOptions();
1417                     assertExpectedOptionsExist(updateFromExpectedOptions, updateFromOperationalOptions);
1418                 }
1419
1420                 // UPDATE:  update the external_ids
1421                 testBridgeNodeId = getBridgeNode(connectionInfo, testBridgeAndPortName).getNodeId();
1422                 OvsdbTerminationPointAugmentationBuilder tpUpdateAugmentationBuilder =
1423                         new OvsdbTerminationPointAugmentationBuilder();
1424                 tpUpdateAugmentationBuilder.setOptions(updateToInputOptions);
1425                 InstanceIdentifier<Node> portIid = SouthboundMapper.createInstanceIdentifier(testBridgeNodeId);
1426                 NodeBuilder portUpdateNodeBuilder = new NodeBuilder();
1427                 NodeId portUpdateNodeId = createManagedNodeId(portIid);
1428                 portUpdateNodeBuilder.setNodeId(portUpdateNodeId);
1429                 TerminationPointBuilder tpUpdateBuilder = new TerminationPointBuilder();
1430                 tpUpdateBuilder.setKey(new TerminationPointKey(new TpId(testBridgeAndPortName)));
1431                 tpUpdateBuilder.addAugmentation(
1432                         OvsdbTerminationPointAugmentation.class,
1433                         tpUpdateAugmentationBuilder.build());
1434                 portUpdateNodeBuilder.setTerminationPoint(Lists.newArrayList(tpUpdateBuilder.build()));
1435                 Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
1436                         portIid, portUpdateNodeBuilder.build()));
1437                 Thread.sleep(OVSDB_UPDATE_TIMEOUT);
1438
1439                 // READ: the test interface and ensure changes are propagated to the CONFIGURATION data store,
1440                 // then repeat for OPERATIONAL data store
1441                 OvsdbTerminationPointAugmentation updateToConfigurationTerminationPointAugmentation =
1442                         getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeAndPortName,
1443                                 LogicalDatastoreType.CONFIGURATION, TERMINATION_POINT_TEST_INDEX);
1444                 if (updateToConfigurationTerminationPointAugmentation != null) {
1445                     List<Options> updateToConfigurationOptions =
1446                             updateToConfigurationTerminationPointAugmentation.getOptions();
1447                     assertExpectedOptionsExist(updateToExpectedOptions, updateToConfigurationOptions);
1448                     assertExpectedOptionsExist(updateFromExpectedOptions, updateToConfigurationOptions);
1449                 }
1450                 OvsdbTerminationPointAugmentation updateToOperationalTerminationPointAugmentation =
1451                         getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeAndPortName,
1452                                 LogicalDatastoreType.OPERATIONAL, TERMINATION_POINT_TEST_INDEX);
1453                 if (updateToOperationalTerminationPointAugmentation != null) {
1454                     List<Options> updateToOperationalOptions =
1455                             updateToOperationalTerminationPointAugmentation.getOptions();
1456                     if (updateFromExpectedOptions != null) {
1457                         assertExpectedOptionsExist(updateToExpectedOptions, updateToOperationalOptions);
1458                         assertExpectedOptionsExist(updateFromExpectedOptions, updateToOperationalOptions);
1459                     }
1460                 }
1461
1462                 // DELETE
1463                 Assert.assertTrue(deleteBridge(connectionInfo, testBridgeAndPortName));
1464             }
1465         }
1466         Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
1467     }
1468
1469     /*
1470      * Generates the test cases involved in testing Interface other_configs.  See inline comments for descriptions of
1471      * the particular cases considered.
1472      *
1473      * The return value is a Map in the form (K,V)=(testCaseName,testCase).
1474      * - testCaseName is a String
1475      * - testCase is a Map in the form (K,V) s.t. K=(EXPECTED_VALUES_KEY|INPUT_VALUES_KEY) and V is a List of
1476      *     either corresponding INPUT interface other_configs, or EXPECTED interface other_configs
1477      *     INPUT    is the List we use when calling
1478      *              <code>TerminationPointAugmentationBuilder.setInterfaceOtherConfigs()</code>
1479      *     EXPECTED is the List we expect to receive after calling
1480      *              <code>TerminationPointAugmentationBuilder.getInterfaceOtherConfigs()</code>
1481      */
1482     private List<SouthboundTestCase<InterfaceOtherConfigs>> generateInterfaceOtherConfigsTestCases() {
1483         List<SouthboundTestCase<InterfaceOtherConfigs>> testCases = new ArrayList<>();
1484
1485         final String INT_OTHER_CONFIGS_KEY = "IntOtherConfigsKey";
1486         final String INT_OTHER_CONFIGS_VALUE = "IntOtherConfigsValue";
1487         final String GOOD_KEY = "GoodKey";
1488         final String GOOD_VALUE = "GoodValue";
1489         final String NO_VALUE_FOR_KEY = "NoValueForKey";
1490
1491         KeyValueBuilder<InterfaceOtherConfigs> builder = new SouthboundInterfaceOtherConfigsBuilder();
1492
1493         // Test Case 1:  TestOneOtherConfigs
1494         // Test Type:    Positive
1495         // Description:  Create an interface with one other_Configs
1496         // Expected:     An interface is created with the single other_configs specified below
1497         final String testOneOtherConfigsName = "TestOneInterfaceOtherConfigs";
1498         testCases.add(SouthboundIT.<InterfaceOtherConfigs>testCase()
1499                 .name(testOneOtherConfigsName)
1500                 .input(builder.build(testOneOtherConfigsName, INT_OTHER_CONFIGS_KEY, INT_OTHER_CONFIGS_VALUE))
1501                 .expectInputAsOutput()
1502                 .build());
1503
1504         // Test Case 2:  TestFiveInterfaceOtherConfigs
1505         // Test Type:    Positive
1506         // Description:  Create a termination point with multiple (five) InterfaceOtherConfigs
1507         // Expected:     A termination point is created with the five InterfaceOtherConfigs specified below
1508         final String testFiveInterfaceOtherConfigsName = "TestFiveInterfaceOtherConfigs";
1509         builder.reset();
1510         testCases.add(SouthboundIT.<InterfaceOtherConfigs>testCase()
1511                 .name(testFiveInterfaceOtherConfigsName)
1512                 .input(
1513                         builder.build(testFiveInterfaceOtherConfigsName, INT_OTHER_CONFIGS_KEY,
1514                                 INT_OTHER_CONFIGS_VALUE),
1515                         builder.build(testFiveInterfaceOtherConfigsName, INT_OTHER_CONFIGS_KEY,
1516                                 INT_OTHER_CONFIGS_VALUE),
1517                         builder.build(testFiveInterfaceOtherConfigsName, INT_OTHER_CONFIGS_KEY,
1518                                 INT_OTHER_CONFIGS_VALUE),
1519                         builder.build(testFiveInterfaceOtherConfigsName, INT_OTHER_CONFIGS_KEY,
1520                                 INT_OTHER_CONFIGS_VALUE),
1521                         builder.build(testFiveInterfaceOtherConfigsName, INT_OTHER_CONFIGS_KEY,
1522                                 INT_OTHER_CONFIGS_VALUE))
1523                 .expectInputAsOutput()
1524                 .build());
1525
1526         // Test Case 3:  TestOneGoodInterfaceOtherConfigsOneMalformedInterfaceOtherConfigsValue
1527         // Test Type:    Negative
1528         // Description:
1529         //     One perfectly fine InterfaceOtherConfigs
1530         //        (TestOneGoodInterfaceOtherConfigsOneMalformedInterfaceOtherConfigsValue_InterfaceOtherConfigsKey_1,
1531         //        TestOneGoodInterfaceOtherConfigsOneMalformedInterfaceOtherConfigs_InterfaceOtherConfigsValue_1)
1532         //     and one malformed InterfaceOtherConfigs which only has key specified
1533         //        (TestOneGoodInterfaceOtherConfigsOneMalformedInterfaceOtherConfigsValue_NoValueForKey_2,
1534         //        UNSPECIFIED)
1535         // Expected:     A termination point is created without any InterfaceOtherConfigs
1536         final String testOneGoodInterfaceOtherConfigsOneMalformedInterfaceOtherConfigsValueName =
1537                 "TestOneGoodInterfaceOtherConfigsOneMalformedInterfaceOtherConfigsValue";
1538         builder.reset();
1539         testCases.add(SouthboundIT.<InterfaceOtherConfigs>testCase()
1540                 .name(testOneGoodInterfaceOtherConfigsOneMalformedInterfaceOtherConfigsValueName)
1541                 .input(
1542                         builder.build(testOneGoodInterfaceOtherConfigsOneMalformedInterfaceOtherConfigsValueName,
1543                                 GOOD_KEY, GOOD_VALUE),
1544                         builder.build(testOneGoodInterfaceOtherConfigsOneMalformedInterfaceOtherConfigsValueName,
1545                                 NO_VALUE_FOR_KEY, null))
1546                 .expectNoOutput()
1547                 .build());
1548
1549         return testCases;
1550     }
1551
1552     /*
1553      * @see <code>SouthboundIT.testCRUDInterfaceOtherConfigs()</code>
1554      * This is helper test method to compare a test "set" of Options against an expected "set"
1555      */
1556     private void assertExpectedInterfaceOtherConfigsExist( List<InterfaceOtherConfigs> expected,
1557                                                            List<InterfaceOtherConfigs> test ) {
1558
1559         if (expected != null && test != null) {
1560             for (InterfaceOtherConfigs expectedOtherConfigs : expected) {
1561                 Assert.assertTrue(test.contains(expectedOtherConfigs));
1562             }
1563         }
1564     }
1565
1566     /*
1567      * Tests the CRUD operations for <code>Interface</code> <code>other_configs</code>.
1568      *
1569      * @see <code>SouthboundIT.generateInterfaceExternalIdsTestCases()</code> for specific test case information
1570      */
1571     @Test
1572     public void testCRUDTerminationPointInterfaceOtherConfigs() throws InterruptedException {
1573         final String TEST_PREFIX = "CRUDTPInterfaceOtherConfigs";
1574         final int TERMINATION_POINT_TEST_INDEX = 0;
1575
1576         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
1577         connectOvsdbNode(connectionInfo);
1578
1579         // updateFromTestCases represent the original test case value.  updateToTestCases represent the new value after
1580         // the update has been performed.
1581         List<SouthboundTestCase<InterfaceOtherConfigs>> updateFromTestCases = generateInterfaceOtherConfigsTestCases();
1582         List<SouthboundTestCase<InterfaceOtherConfigs>> updateToTestCases = generateInterfaceOtherConfigsTestCases();
1583
1584         for (SouthboundTestCase<InterfaceOtherConfigs> updateFromTestCase : updateFromTestCases) {
1585             List<InterfaceOtherConfigs> updateFromInputOtherConfigs = updateFromTestCase.inputValues;
1586             List<InterfaceOtherConfigs> updateFromExpectedOtherConfigs = updateFromTestCase.expectedValues;
1587             for (SouthboundTestCase<InterfaceOtherConfigs> updateToTestCase : updateToTestCases) {
1588                 String testBridgeAndPortName = String.format("%s_%s", TEST_PREFIX, updateToTestCase.name);
1589                 List<InterfaceOtherConfigs> updateToInputOtherConfigs = updateToTestCase.inputValues;
1590                 List<InterfaceOtherConfigs> updateToExpectedOtherConfigs = updateToTestCase.expectedValues;
1591
1592                 // CREATE: Create the test interface
1593                 Assert.assertTrue(addBridge(connectionInfo, null, testBridgeAndPortName, null, true,
1594                         SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"), true, null, null, null, null));
1595                 NodeId testBridgeNodeId = createManagedNodeId(createInstanceIdentifier(
1596                         connectionInfo, new OvsdbBridgeName(testBridgeAndPortName)));
1597                 OvsdbTerminationPointAugmentationBuilder tpCreateAugmentationBuilder =
1598                         createGenericOvsdbTerminationPointAugmentationBuilder();
1599                 tpCreateAugmentationBuilder.setName(testBridgeAndPortName);
1600                 tpCreateAugmentationBuilder.setInterfaceOtherConfigs(updateFromInputOtherConfigs);
1601                 Assert.assertTrue(
1602                         addTerminationPoint(testBridgeNodeId, testBridgeAndPortName, tpCreateAugmentationBuilder));
1603
1604                 // READ: Read the test interface and ensure changes are propagated to the CONFIGURATION data store,
1605                 // then repeat for OPERATIONAL data store
1606                 OvsdbTerminationPointAugmentation updateFromConfigurationTerminationPointAugmentation =
1607                         getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeAndPortName,
1608                                 LogicalDatastoreType.CONFIGURATION, TERMINATION_POINT_TEST_INDEX);
1609                 if (updateFromConfigurationTerminationPointAugmentation != null) {
1610                     List<InterfaceOtherConfigs> updateFromConfigurationOtherConfigs =
1611                             updateFromConfigurationTerminationPointAugmentation.getInterfaceOtherConfigs();
1612                     assertExpectedInterfaceOtherConfigsExist(updateFromExpectedOtherConfigs,
1613                             updateFromConfigurationOtherConfigs);
1614                 }
1615                 OvsdbTerminationPointAugmentation updateFromOperationalTerminationPointAugmentation =
1616                         getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeAndPortName,
1617                                 LogicalDatastoreType.OPERATIONAL, TERMINATION_POINT_TEST_INDEX);
1618                 if (updateFromOperationalTerminationPointAugmentation != null) {
1619                     List<InterfaceOtherConfigs> updateFromOperationalOtherConfigs =
1620                             updateFromOperationalTerminationPointAugmentation.getInterfaceOtherConfigs();
1621                     assertExpectedInterfaceOtherConfigsExist(updateFromExpectedOtherConfigs,
1622                             updateFromOperationalOtherConfigs);
1623                 }
1624
1625                 // UPDATE:  update the other_configs
1626                 testBridgeNodeId = getBridgeNode(connectionInfo, testBridgeAndPortName).getNodeId();
1627                 OvsdbTerminationPointAugmentationBuilder tpUpdateAugmentationBuilder =
1628                         new OvsdbTerminationPointAugmentationBuilder();
1629                 tpUpdateAugmentationBuilder.setInterfaceOtherConfigs(updateToInputOtherConfigs);
1630                 InstanceIdentifier<Node> portIid = SouthboundMapper.createInstanceIdentifier(testBridgeNodeId);
1631                 NodeBuilder portUpdateNodeBuilder = new NodeBuilder();
1632                 NodeId portUpdateNodeId = createManagedNodeId(portIid);
1633                 portUpdateNodeBuilder.setNodeId(portUpdateNodeId);
1634                 TerminationPointBuilder tpUpdateBuilder = new TerminationPointBuilder();
1635                 tpUpdateBuilder.setKey(new TerminationPointKey(new TpId(testBridgeAndPortName)));
1636                 tpUpdateBuilder.addAugmentation(
1637                         OvsdbTerminationPointAugmentation.class,
1638                         tpUpdateAugmentationBuilder.build());
1639                 portUpdateNodeBuilder.setTerminationPoint(Lists.newArrayList(tpUpdateBuilder.build()));
1640                 Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
1641                         portIid, portUpdateNodeBuilder.build()));
1642                 Thread.sleep(OVSDB_UPDATE_TIMEOUT);
1643
1644                 // READ: the test interface and ensure changes are propagated to the CONFIGURATION data store,
1645                 // then repeat for OPERATIONAL data store
1646                 OvsdbTerminationPointAugmentation updateToConfigurationTerminationPointAugmentation =
1647                         getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeAndPortName,
1648                                 LogicalDatastoreType.CONFIGURATION, TERMINATION_POINT_TEST_INDEX);
1649                 if (updateToConfigurationTerminationPointAugmentation != null) {
1650                     List<InterfaceOtherConfigs> updateToConfigurationOtherConfigs =
1651                             updateToConfigurationTerminationPointAugmentation.getInterfaceOtherConfigs();
1652                     assertExpectedInterfaceOtherConfigsExist(updateToExpectedOtherConfigs,
1653                             updateToConfigurationOtherConfigs);
1654                     assertExpectedInterfaceOtherConfigsExist(updateFromExpectedOtherConfigs,
1655                             updateToConfigurationOtherConfigs);
1656                 }
1657                 OvsdbTerminationPointAugmentation updateToOperationalTerminationPointAugmentation =
1658                         getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeAndPortName,
1659                                 LogicalDatastoreType.OPERATIONAL, TERMINATION_POINT_TEST_INDEX);
1660                 if (updateToOperationalTerminationPointAugmentation != null) {
1661                     List<InterfaceOtherConfigs> updateToOperationalOtherConfigs =
1662                             updateToOperationalTerminationPointAugmentation.getInterfaceOtherConfigs();
1663                     if (updateFromExpectedOtherConfigs != null) {
1664                         assertExpectedInterfaceOtherConfigsExist(updateToExpectedOtherConfigs,
1665                                 updateToOperationalOtherConfigs);
1666                         assertExpectedInterfaceOtherConfigsExist(updateFromExpectedOtherConfigs,
1667                                 updateToOperationalOtherConfigs);
1668                     }
1669                 }
1670
1671                 // DELETE
1672                 Assert.assertTrue(deleteBridge(connectionInfo, testBridgeAndPortName));
1673             }
1674         }
1675         Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
1676     }
1677
1678     /*
1679      * Generates the test cases involved in testing Port other_configs.  See inline comments for descriptions of
1680      * the particular cases considered.
1681      *
1682      * The return value is a Map in the form (K,V)=(testCaseName,testCase).
1683      * - testCaseName is a String
1684      * - testCase is a Map in the form (K,V) s.t. K=(EXPECTED_VALUES_KEY|INPUT_VALUES_KEY) and V is a List of
1685      *     either corresponding INPUT port other_configs, or EXPECTED port other_configs
1686      *     INPUT    is the List we use when calling
1687      *              <code>TerminationPointAugmentationBuilder.setPortOtherConfigs()</code>
1688      *     EXPECTED is the List we expect to receive after calling
1689      *              <code>TerminationPointAugmentationBuilder.getPortOtherConfigs()</code>
1690      */
1691     private List<SouthboundTestCase<PortOtherConfigs>> generatePortOtherConfigsTestCases() {
1692         List<SouthboundTestCase<PortOtherConfigs>> testCases = new ArrayList<>();
1693
1694         final String PORT_OTHER_CONFIGS_KEY = "PortOtherConfigsKey";
1695         final String PORT_OTHER_CONFIGS_VALUE = "PortOtherConfigsValue";
1696         final String GOOD_KEY = "GoodKey";
1697         final String GOOD_VALUE = "GoodValue";
1698         final String NO_VALUE_FOR_KEY = "NoValueForKey";
1699
1700         KeyValueBuilder<PortOtherConfigs> builder = new SouthboundPortOtherConfigsBuilder();
1701
1702         // Test Case 1:  TestOneOtherConfigs
1703         // Test Type:    Positive
1704         // Description:  Create an port with one other_Configs
1705         // Expected:     A port is created with the single other_configs specified below
1706         final String testOneOtherConfigsName = "TestOnePortOtherConfigs";
1707         testCases.add(SouthboundIT.<PortOtherConfigs>testCase()
1708                 .name(testOneOtherConfigsName)
1709                 .input(builder.build(testOneOtherConfigsName, PORT_OTHER_CONFIGS_KEY, PORT_OTHER_CONFIGS_VALUE))
1710                 .expectInputAsOutput()
1711                 .build());
1712
1713         // Test Case 2:  TestFivePortOtherConfigs
1714         // Test Type:    Positive
1715         // Description:  Create a termination point with multiple (five) PortOtherConfigs
1716         // Expected:     A termination point is created with the five PortOtherConfigs specified below
1717         final String testFivePortOtherConfigsName = "TestFivePortOtherConfigs";
1718         builder.reset();
1719         testCases.add(SouthboundIT.<PortOtherConfigs>testCase()
1720                 .name(testFivePortOtherConfigsName)
1721                 .input(
1722                         builder.build(testFivePortOtherConfigsName, PORT_OTHER_CONFIGS_KEY, PORT_OTHER_CONFIGS_VALUE),
1723                         builder.build(testFivePortOtherConfigsName, PORT_OTHER_CONFIGS_KEY, PORT_OTHER_CONFIGS_VALUE),
1724                         builder.build(testFivePortOtherConfigsName, PORT_OTHER_CONFIGS_KEY, PORT_OTHER_CONFIGS_VALUE),
1725                         builder.build(testFivePortOtherConfigsName, PORT_OTHER_CONFIGS_KEY, PORT_OTHER_CONFIGS_VALUE),
1726                         builder.build(testFivePortOtherConfigsName, PORT_OTHER_CONFIGS_KEY, PORT_OTHER_CONFIGS_VALUE))
1727                 .expectInputAsOutput()
1728                 .build());
1729
1730         // Test Case 3:  TestOneGoodPortOtherConfigsOneMalformedPortOtherConfigsValue
1731         // Test Type:    Negative
1732         // Description:
1733         //     One perfectly fine PortOtherConfigs
1734         //        (TestOneGoodPortOtherConfigsOneMalformedPortOtherConfigsValue_PortOtherConfigsKey_1,
1735         //        TestOneGoodPortOtherConfigsOneMalformedPortOtherConfigs_PortOtherConfigsValue_1)
1736         //     and one malformed PortOtherConfigs which only has key specified
1737         //        (TestOneGoodPortOtherConfigsOneMalformedPortOtherConfigsValue_NoValueForKey_2,
1738         //        UNSPECIFIED)
1739         // Expected:     A termination point is created without any PortOtherConfigs
1740         final String testOneGoodPortOtherConfigsOneMalformedPortOtherConfigsValueName =
1741                 "TestOneGoodPortOtherConfigsOneMalformedPortOtherConfigsValue";
1742         builder.reset();
1743         testCases.add(SouthboundIT.<PortOtherConfigs>testCase()
1744                 .name(testOneGoodPortOtherConfigsOneMalformedPortOtherConfigsValueName)
1745                 .input(
1746                         builder.build(testOneGoodPortOtherConfigsOneMalformedPortOtherConfigsValueName, GOOD_KEY,
1747                                 GOOD_VALUE),
1748                         builder.build(testOneGoodPortOtherConfigsOneMalformedPortOtherConfigsValueName,
1749                                 NO_VALUE_FOR_KEY, null))
1750                 .expectNoOutput()
1751                 .build());
1752
1753         return testCases;
1754     }
1755
1756     /*
1757      * @see <code>SouthboundIT.testCRUDPortOtherConfigs()</code>
1758      * This is helper test method to compare a test "set" of Options against an expected "set"
1759      */
1760     private void assertExpectedPortOtherConfigsExist( List<PortOtherConfigs> expected,
1761                                                       List<PortOtherConfigs> test ) {
1762
1763         if (expected != null && test != null) {
1764             for (PortOtherConfigs expectedOtherConfigs : expected) {
1765                 Assert.assertTrue(test.contains(expectedOtherConfigs));
1766             }
1767         }
1768     }
1769
1770     /*
1771      * Tests the CRUD operations for <code>Port</code> <code>other_configs</code>.
1772      *
1773      * @see <code>SouthboundIT.generatePortExternalIdsTestCases()</code> for specific test case information
1774      */
1775     @Test
1776     public void testCRUDTerminationPointPortOtherConfigs() throws InterruptedException {
1777         final String TEST_PREFIX = "CRUDTPPortOtherConfigs";
1778         final int TERMINATION_POINT_TEST_INDEX = 0;
1779
1780         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
1781         connectOvsdbNode(connectionInfo);
1782
1783         // updateFromTestCases represent the original test case value.  updateToTestCases represent the new value after
1784         // the update has been performed.
1785         List<SouthboundTestCase<PortOtherConfigs>> updateFromTestCases = generatePortOtherConfigsTestCases();
1786         List<SouthboundTestCase<PortOtherConfigs>> updateToTestCases = generatePortOtherConfigsTestCases();
1787
1788         for (SouthboundTestCase<PortOtherConfigs> updateFromTestCase : updateFromTestCases) {
1789             List<PortOtherConfigs> updateFromInputOtherConfigs = updateFromTestCase.inputValues;
1790             List<PortOtherConfigs> updateFromExpectedOtherConfigs = updateFromTestCase.expectedValues;
1791             for (SouthboundTestCase<PortOtherConfigs> updateToTestCase : updateToTestCases) {
1792                 String testBridgeAndPortName = String.format("%s_%s", TEST_PREFIX, updateToTestCase.name);
1793                 List<PortOtherConfigs> updateToInputOtherConfigs = updateToTestCase.inputValues;
1794                 List<PortOtherConfigs> updateToExpectedOtherConfigs = updateToTestCase.expectedValues;
1795
1796                 // CREATE: Create the test port
1797                 Assert.assertTrue(addBridge(connectionInfo, null, testBridgeAndPortName, null, true,
1798                         SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"), true, null, null, null, null));
1799                 NodeId testBridgeNodeId = createManagedNodeId(createInstanceIdentifier(
1800                         connectionInfo, new OvsdbBridgeName(testBridgeAndPortName)));
1801                 OvsdbTerminationPointAugmentationBuilder tpCreateAugmentationBuilder =
1802                         createGenericOvsdbTerminationPointAugmentationBuilder();
1803                 tpCreateAugmentationBuilder.setName(testBridgeAndPortName);
1804                 tpCreateAugmentationBuilder.setPortOtherConfigs(updateFromInputOtherConfigs);
1805                 Assert.assertTrue(
1806                         addTerminationPoint(testBridgeNodeId, testBridgeAndPortName, tpCreateAugmentationBuilder));
1807
1808                 // READ: Read the test port and ensure changes are propagated to the CONFIGURATION data store,
1809                 // then repeat for OPERATIONAL data store
1810                 OvsdbTerminationPointAugmentation updateFromConfigurationTerminationPointAugmentation =
1811                         getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeAndPortName,
1812                                 LogicalDatastoreType.CONFIGURATION, TERMINATION_POINT_TEST_INDEX);
1813                 if (updateFromConfigurationTerminationPointAugmentation != null) {
1814                     List<PortOtherConfigs> updateFromConfigurationOtherConfigs =
1815                             updateFromConfigurationTerminationPointAugmentation.getPortOtherConfigs();
1816                     assertExpectedPortOtherConfigsExist(updateFromExpectedOtherConfigs,
1817                             updateFromConfigurationOtherConfigs);
1818                 }
1819                 OvsdbTerminationPointAugmentation updateFromOperationalTerminationPointAugmentation =
1820                         getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeAndPortName,
1821                                 LogicalDatastoreType.OPERATIONAL, TERMINATION_POINT_TEST_INDEX);
1822                 if (updateFromOperationalTerminationPointAugmentation != null) {
1823                     List<PortOtherConfigs> updateFromOperationalOtherConfigs =
1824                             updateFromOperationalTerminationPointAugmentation.getPortOtherConfigs();
1825                     assertExpectedPortOtherConfigsExist(updateFromExpectedOtherConfigs,
1826                             updateFromOperationalOtherConfigs);
1827                 }
1828
1829                 // UPDATE:  update the other_configs
1830                 testBridgeNodeId = getBridgeNode(connectionInfo, testBridgeAndPortName).getNodeId();
1831                 OvsdbTerminationPointAugmentationBuilder tpUpdateAugmentationBuilder =
1832                         new OvsdbTerminationPointAugmentationBuilder();
1833                 tpUpdateAugmentationBuilder.setPortOtherConfigs(updateToInputOtherConfigs);
1834                 InstanceIdentifier<Node> portIid = SouthboundMapper.createInstanceIdentifier(testBridgeNodeId);
1835                 NodeBuilder portUpdateNodeBuilder = new NodeBuilder();
1836                 NodeId portUpdateNodeId = createManagedNodeId(portIid);
1837                 portUpdateNodeBuilder.setNodeId(portUpdateNodeId);
1838                 TerminationPointBuilder tpUpdateBuilder = new TerminationPointBuilder();
1839                 tpUpdateBuilder.setKey(new TerminationPointKey(new TpId(testBridgeAndPortName)));
1840                 tpUpdateBuilder.addAugmentation(
1841                         OvsdbTerminationPointAugmentation.class,
1842                         tpUpdateAugmentationBuilder.build());
1843                 portUpdateNodeBuilder.setTerminationPoint(Lists.newArrayList(tpUpdateBuilder.build()));
1844                 Assert.assertTrue(mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
1845                         portIid, portUpdateNodeBuilder.build()));
1846                 Thread.sleep(OVSDB_UPDATE_TIMEOUT);
1847
1848                 // READ: the test port and ensure changes are propagated to the CONFIGURATION data store,
1849                 // then repeat for OPERATIONAL data store
1850                 OvsdbTerminationPointAugmentation updateToConfigurationTerminationPointAugmentation =
1851                         getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeAndPortName,
1852                                 LogicalDatastoreType.CONFIGURATION, TERMINATION_POINT_TEST_INDEX);
1853                 if (updateToConfigurationTerminationPointAugmentation != null) {
1854                     List<PortOtherConfigs> updateToConfigurationOtherConfigs =
1855                             updateToConfigurationTerminationPointAugmentation.getPortOtherConfigs();
1856                     assertExpectedPortOtherConfigsExist(updateToExpectedOtherConfigs,
1857                             updateToConfigurationOtherConfigs);
1858                     assertExpectedPortOtherConfigsExist(updateFromExpectedOtherConfigs,
1859                             updateToConfigurationOtherConfigs);
1860                 }
1861                 OvsdbTerminationPointAugmentation updateToOperationalTerminationPointAugmentation =
1862                         getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeAndPortName,
1863                                 LogicalDatastoreType.OPERATIONAL, TERMINATION_POINT_TEST_INDEX);
1864                 if (updateToOperationalTerminationPointAugmentation != null) {
1865                     List<PortOtherConfigs> updateToOperationalOtherConfigs =
1866                             updateToOperationalTerminationPointAugmentation.getPortOtherConfigs();
1867                     if (updateFromExpectedOtherConfigs != null) {
1868                         assertExpectedPortOtherConfigsExist(updateToExpectedOtherConfigs,
1869                                 updateToOperationalOtherConfigs);
1870                         assertExpectedPortOtherConfigsExist(updateFromExpectedOtherConfigs,
1871                                 updateToOperationalOtherConfigs);
1872                     }
1873                 }
1874
1875                 // DELETE
1876                 Assert.assertTrue(deleteBridge(connectionInfo, testBridgeAndPortName));
1877             }
1878         }
1879         Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
1880     }
1881
1882     @Test
1883     public void testCRUDTerminationPointVlan() throws InterruptedException {
1884         final Integer CREATED_VLAN_ID = 4000;
1885         final Integer UPDATED_VLAN_ID = 4001;
1886
1887         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
1888         connectOvsdbNode(connectionInfo);
1889
1890         // CREATE
1891         Assert.assertTrue(addBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME));
1892         OvsdbBridgeAugmentation bridge = getBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME);
1893         Assert.assertNotNull(bridge);
1894         NodeId nodeId = createManagedNodeId(createInstanceIdentifier(
1895                 connectionInfo, bridge.getBridgeName()));
1896         OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
1897                 createGenericOvsdbTerminationPointAugmentationBuilder();
1898         String portName = "testTerminationPointVlanId";
1899         ovsdbTerminationBuilder.setName(portName);
1900         ovsdbTerminationBuilder.setVlanTag(new VlanId(CREATED_VLAN_ID));
1901         Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
1902         InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
1903         Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
1904         Assert.assertNotNull(terminationPointNode);
1905
1906         // READ
1907         List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
1908         OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation;
1909         for (TerminationPoint terminationPoint : terminationPoints) {
1910             ovsdbTerminationPointAugmentation = terminationPoint.getAugmentation(
1911                     OvsdbTerminationPointAugmentation.class);
1912             if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
1913                 VlanId actualVlanId = ovsdbTerminationPointAugmentation.getVlanTag();
1914                 Assert.assertNotNull(actualVlanId);
1915                 Integer actualVlanIdInt = actualVlanId.getValue();
1916                 Assert.assertEquals(CREATED_VLAN_ID, actualVlanIdInt);
1917             }
1918         }
1919
1920         // UPDATE
1921         NodeId testBridgeNodeId = getBridgeNode(connectionInfo, SouthboundITConstants.BRIDGE_NAME).getNodeId();
1922         OvsdbTerminationPointAugmentationBuilder tpUpdateAugmentationBuilder =
1923                 new OvsdbTerminationPointAugmentationBuilder();
1924         tpUpdateAugmentationBuilder.setVlanTag(new VlanId(UPDATED_VLAN_ID));
1925         InstanceIdentifier<Node> portIid = SouthboundMapper.createInstanceIdentifier(testBridgeNodeId);
1926         NodeBuilder portUpdateNodeBuilder = new NodeBuilder();
1927         NodeId portUpdateNodeId = createManagedNodeId(portIid);
1928         portUpdateNodeBuilder.setNodeId(portUpdateNodeId);
1929         TerminationPointBuilder tpUpdateBuilder = new TerminationPointBuilder();
1930         tpUpdateBuilder.setKey(new TerminationPointKey(new TpId(portName)));
1931         tpUpdateBuilder.addAugmentation(
1932                 OvsdbTerminationPointAugmentation.class,
1933                 tpUpdateAugmentationBuilder.build());
1934         tpUpdateBuilder.setTpId(new TpId(portName));
1935         portUpdateNodeBuilder.setTerminationPoint(Lists.newArrayList(tpUpdateBuilder.build()));
1936         boolean result = mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
1937                 portIid, portUpdateNodeBuilder.build());
1938         Assert.assertTrue(result);
1939         Thread.sleep(OVSDB_UPDATE_TIMEOUT);
1940
1941         terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
1942         terminationPoints = terminationPointNode.getTerminationPoint();
1943         for (TerminationPoint terminationPoint : terminationPoints) {
1944             ovsdbTerminationPointAugmentation = terminationPoint.getAugmentation(
1945                     OvsdbTerminationPointAugmentation.class);
1946             if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
1947                 VlanId actualVlanId = ovsdbTerminationPointAugmentation.getVlanTag();
1948                 Assert.assertNotNull(actualVlanId);
1949                 Integer actualVlanIdInt = actualVlanId.getValue();
1950                 Assert.assertEquals(UPDATED_VLAN_ID, actualVlanIdInt);
1951             }
1952         }
1953
1954         // DELETE
1955         Assert.assertTrue(deleteBridge(connectionInfo));
1956         Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
1957     }
1958
1959     @Test
1960     public void testCRUDTerminationPointVlanModes() throws InterruptedException {
1961         final VlanMode UPDATED_VLAN_MODE = VlanMode.Access;
1962         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
1963         connectOvsdbNode(connectionInfo);
1964         VlanMode []vlanModes = VlanMode.values();
1965         for (VlanMode vlanMode : vlanModes) {
1966             // CREATE
1967             Assert.assertTrue(addBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME));
1968             OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
1969             Assert.assertNotNull(bridge);
1970             NodeId nodeId = createManagedNodeId(createInstanceIdentifier(
1971                     connectionInfo, bridge.getBridgeName()));
1972             OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
1973                     createGenericOvsdbTerminationPointAugmentationBuilder();
1974             String portName = "testTerminationPointVlanMode" + vlanMode.toString();
1975             ovsdbTerminationBuilder.setName(portName);
1976             ovsdbTerminationBuilder.setVlanMode(vlanMode);
1977             Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
1978             InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
1979             Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
1980             Assert.assertNotNull(terminationPointNode);
1981
1982             // READ
1983             List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
1984             for (TerminationPoint terminationPoint : terminationPoints) {
1985                 OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
1986                         terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
1987                 if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
1988                     //test
1989                     Assert.assertTrue(ovsdbTerminationPointAugmentation.getVlanMode().equals(vlanMode));
1990                 }
1991             }
1992
1993             // UPDATE
1994             NodeId testBridgeNodeId = getBridgeNode(connectionInfo, SouthboundITConstants.BRIDGE_NAME).getNodeId();
1995             OvsdbTerminationPointAugmentationBuilder tpUpdateAugmentationBuilder =
1996                     new OvsdbTerminationPointAugmentationBuilder();
1997             tpUpdateAugmentationBuilder.setVlanMode(UPDATED_VLAN_MODE);
1998             InstanceIdentifier<Node> portIid = SouthboundMapper.createInstanceIdentifier(testBridgeNodeId);
1999             NodeBuilder portUpdateNodeBuilder = new NodeBuilder();
2000             NodeId portUpdateNodeId = createManagedNodeId(portIid);
2001             portUpdateNodeBuilder.setNodeId(portUpdateNodeId);
2002             TerminationPointBuilder tpUpdateBuilder = new TerminationPointBuilder();
2003             tpUpdateBuilder.setKey(new TerminationPointKey(new TpId(portName)));
2004             tpUpdateBuilder.addAugmentation(
2005                     OvsdbTerminationPointAugmentation.class,
2006                     tpUpdateAugmentationBuilder.build());
2007             tpUpdateBuilder.setTpId(new TpId(portName));
2008             portUpdateNodeBuilder.setTerminationPoint(Lists.newArrayList(tpUpdateBuilder.build()));
2009             boolean result = mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
2010                     portIid, portUpdateNodeBuilder.build());
2011             Assert.assertTrue(result);
2012             Thread.sleep(OVSDB_UPDATE_TIMEOUT);
2013
2014             terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
2015             terminationPoints = terminationPointNode.getTerminationPoint();
2016             for (TerminationPoint terminationPoint : terminationPoints) {
2017                 OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
2018                         terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
2019                 if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
2020                     //test
2021                     Assert.assertEquals(UPDATED_VLAN_MODE, ovsdbTerminationPointAugmentation.getVlanMode());
2022                 }
2023             }
2024
2025             // DELETE
2026             Assert.assertTrue(deleteBridge(connectionInfo));
2027         }
2028         Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
2029     }
2030
2031     @SuppressWarnings("unchecked")
2032     private List<Set<Integer>> generateVlanSets() {
2033         int min = 0;
2034         int max = 4095;
2035         return Lists.newArrayList(
2036                 Collections.<Integer>emptySet(),
2037                 Sets.newHashSet(2222),
2038                 Sets.newHashSet(min, max, min + 1, max - 1, (max - min) / 2));
2039     }
2040
2041     private List<Trunks> buildTrunkList(Set<Integer> trunkSet) {
2042         List<Trunks> trunkList = Lists.newArrayList();
2043         for (Integer trunk : trunkSet) {
2044             TrunksBuilder trunkBuilder = new TrunksBuilder();
2045             trunkBuilder.setTrunk(new VlanId(trunk));
2046             trunkList.add(trunkBuilder.build());
2047         }
2048         return trunkList;
2049     }
2050
2051     @Test
2052     public void testCRUDTerminationPointVlanTrunks() throws InterruptedException {
2053         final List<Trunks> UPDATED_TRUNKS = buildTrunkList(Sets.newHashSet(2011));
2054         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
2055         connectOvsdbNode(connectionInfo);
2056         Iterable<Set<Integer>> vlanSets = generateVlanSets();
2057         int testCase = 0;
2058         for (Set<Integer> vlanSet : vlanSets) {
2059             ++testCase;
2060             // CREATE
2061             Assert.assertTrue(addBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME));
2062             OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
2063             Assert.assertNotNull(bridge);
2064             NodeId nodeId = createManagedNodeId(createInstanceIdentifier(
2065                     connectionInfo, bridge.getBridgeName()));
2066             OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
2067                     createGenericOvsdbTerminationPointAugmentationBuilder();
2068             String portName = "testTerminationPointVlanTrunks" + testCase;
2069             ovsdbTerminationBuilder.setName(portName);
2070             List<Trunks> trunks = buildTrunkList(vlanSet);
2071             ovsdbTerminationBuilder.setTrunks(trunks);
2072             Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
2073             InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
2074             Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
2075             Assert.assertNotNull(terminationPointNode);
2076
2077             // READ
2078             List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
2079             for (TerminationPoint terminationPoint : terminationPoints) {
2080                 OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
2081                         terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
2082                 if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
2083                     List<Trunks> actualTrunks = ovsdbTerminationPointAugmentation.getTrunks();
2084                     for (Trunks trunk : trunks) {
2085                         Assert.assertTrue(actualTrunks.contains(trunk));
2086                     }
2087                 }
2088             }
2089
2090
2091             // UPDATE
2092             NodeId testBridgeNodeId = getBridgeNode(connectionInfo, SouthboundITConstants.BRIDGE_NAME).getNodeId();
2093             OvsdbTerminationPointAugmentationBuilder tpUpdateAugmentationBuilder =
2094                     new OvsdbTerminationPointAugmentationBuilder();
2095             tpUpdateAugmentationBuilder.setTrunks(UPDATED_TRUNKS);
2096             InstanceIdentifier<Node> portIid = SouthboundMapper.createInstanceIdentifier(testBridgeNodeId);
2097             NodeBuilder portUpdateNodeBuilder = new NodeBuilder();
2098             NodeId portUpdateNodeId = createManagedNodeId(portIid);
2099             portUpdateNodeBuilder.setNodeId(portUpdateNodeId);
2100             TerminationPointBuilder tpUpdateBuilder = new TerminationPointBuilder();
2101             tpUpdateBuilder.setKey(new TerminationPointKey(new TpId(portName)));
2102             tpUpdateBuilder.addAugmentation(
2103                     OvsdbTerminationPointAugmentation.class,
2104                     tpUpdateAugmentationBuilder.build());
2105             tpUpdateBuilder.setTpId(new TpId(portName));
2106             portUpdateNodeBuilder.setTerminationPoint(Lists.newArrayList(tpUpdateBuilder.build()));
2107             boolean result = mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
2108                     portIid, portUpdateNodeBuilder.build());
2109             Assert.assertTrue(result);
2110             Thread.sleep(OVSDB_UPDATE_TIMEOUT);
2111
2112             terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
2113             terminationPoints = terminationPointNode.getTerminationPoint();
2114             for (TerminationPoint terminationPoint : terminationPoints) {
2115                 OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
2116                         terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
2117                 if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
2118                     //test
2119                     Assert.assertEquals(UPDATED_TRUNKS, ovsdbTerminationPointAugmentation.getTrunks());
2120                 }
2121             }
2122
2123             // DELETE
2124             Assert.assertTrue(deleteBridge(connectionInfo));
2125         }
2126         Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
2127     }
2128
2129     @Test
2130     public void testGetOvsdbNodes() throws InterruptedException {
2131         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
2132         connectOvsdbNode(connectionInfo);
2133         InstanceIdentifier<Topology> topologyPath = InstanceIdentifier
2134                 .create(NetworkTopology.class)
2135                 .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID));
2136
2137         Topology topology = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, topologyPath);
2138         InstanceIdentifier<Node> expectedNodeIid = createInstanceIdentifier(connectionInfo);
2139         NodeId expectedNodeId = expectedNodeIid.firstKeyOf(Node.class, NodeKey.class).getNodeId();
2140         Node foundNode = null;
2141         Assert.assertNotNull("Expected to find topology: " + topologyPath, topology);
2142         Assert.assertNotNull("Expected to find some nodes" + topology.getNode());
2143         LOG.info("expectedNodeId: {}, getNode: {}", expectedNodeId, topology.getNode());
2144         for (Node node : topology.getNode()) {
2145             if (node.getNodeId().getValue().equals(expectedNodeId.getValue())) {
2146                 foundNode = node;
2147                 break;
2148             }
2149         }
2150         Assert.assertNotNull("Expected to find Node: " + expectedNodeId, foundNode);
2151         Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
2152     }
2153
2154     /*
2155      * Generates the test cases involved in testing BridgeOtherConfigs.  See inline comments for descriptions of
2156      * the particular cases considered.
2157      *
2158      * The return value is a Map in the form (K,V)=(testCaseName,testCase).
2159      * - testCaseName is a String
2160      * - testCase is a Map in the form (K,V) s.t. K=(EXPECTED_VALUES_KEY|INPUT_VALUES_KEY) and V is a List of
2161      *     either corresponding INPUT bridge other_configs, or EXPECTED bridge other_configs
2162      *     INPUT is the List we use when calling BridgeAugmentationBuilder.setBridgeOtherConfigs()
2163      *     EXPECTED is the List we expect to receive after calling BridgeAugmentationBuilder.getBridgeOtherConfigs()
2164      */
2165     private List<SouthboundTestCase<BridgeOtherConfigs>> generateBridgeOtherConfigsTestCases() {
2166         List<SouthboundTestCase<BridgeOtherConfigs>> testCases = new ArrayList<>();
2167
2168         final String BRIDGE_OTHER_CONFIGS_KEY = "BridgeOtherConfigKey";
2169         final String BRIDGE_OTHER_CONFIGS_VALUE = "BridgeOtherConfigValue";
2170         final String GOOD_KEY = "GoodKey";
2171         final String GOOD_VALUE = "GoodValue";
2172         final String NO_VALUE_FOR_KEY = "NoValueForKey";
2173
2174         KeyValueBuilder<BridgeOtherConfigs> builder = new SouthboundBridgeOtherConfigsBuilder();
2175
2176         // Test Case 1:  TestOneOtherConfig
2177         // Test Type:    Positive
2178         // Description:  Create a bridge with one other_config
2179         // Expected:     A bridge is created with the single other_config specified below
2180         final String testOneOtherConfigName = "TestOneOtherConfig";
2181         testCases.add(SouthboundIT.<BridgeOtherConfigs>testCase()
2182                 .name(testOneOtherConfigName)
2183                 .input(builder.build(testOneOtherConfigName, BRIDGE_OTHER_CONFIGS_KEY, BRIDGE_OTHER_CONFIGS_VALUE))
2184                 .expectInputAsOutput()
2185                 .build());
2186
2187         // Test Case 2:  TestFiveOtherConfig
2188         // Test Type:    Positive
2189         // Description:  Create a bridge with multiple (five) other_configs
2190         // Expected:     A bridge is created with the five other_configs specified below
2191         final String testFiveOtherConfigName = "TestFiveOtherConfig";
2192         builder.reset();
2193         testCases.add(SouthboundIT.<BridgeOtherConfigs>testCase()
2194                 .name(testFiveOtherConfigName)
2195                 .input(
2196                         builder.build(testFiveOtherConfigName, BRIDGE_OTHER_CONFIGS_KEY, BRIDGE_OTHER_CONFIGS_VALUE),
2197                         builder.build(testFiveOtherConfigName, BRIDGE_OTHER_CONFIGS_KEY, BRIDGE_OTHER_CONFIGS_VALUE),
2198                         builder.build(testFiveOtherConfigName, BRIDGE_OTHER_CONFIGS_KEY, BRIDGE_OTHER_CONFIGS_VALUE),
2199                         builder.build(testFiveOtherConfigName, BRIDGE_OTHER_CONFIGS_KEY, BRIDGE_OTHER_CONFIGS_VALUE),
2200                         builder.build(testFiveOtherConfigName, BRIDGE_OTHER_CONFIGS_KEY, BRIDGE_OTHER_CONFIGS_VALUE))
2201                 .expectInputAsOutput()
2202                 .build());
2203
2204         // Test Case 3:  TestOneGoodOtherConfigOneMalformedOtherConfigValue
2205         // Test Type:    Negative
2206         // Description:
2207         //     One perfectly fine BridgeOtherConfig
2208         //        (TestOneGoodOtherConfigOneMalformedOtherConfigValue_BridgeOtherConfigKey_1,
2209         //        TestOneGoodOtherConfigOneMalformedOtherConfig_BridgeOtherConfigValue_1)
2210         //     and one malformed BridgeOtherConfig which only has key specified
2211         //        (TestOneGoodOtherConfigOneMalformedOtherConfigValue_NoValueForKey_2,
2212         //        UNSPECIFIED)
2213         // Expected:     A bridge is created without any other_config
2214         final String testOneGoodOtherConfigOneMalformedOtherConfigValueName =
2215                 "TestOneGoodOtherConfigOneMalformedOtherConfigValue";
2216         builder.reset();
2217         testCases.add(SouthboundIT.<BridgeOtherConfigs>testCase()
2218                 .name(testOneGoodOtherConfigOneMalformedOtherConfigValueName)
2219                 .input(
2220                         builder.build(testOneGoodOtherConfigOneMalformedOtherConfigValueName, GOOD_KEY, GOOD_VALUE),
2221                         builder.build(testOneGoodOtherConfigOneMalformedOtherConfigValueName, NO_VALUE_FOR_KEY, null))
2222                 .expectNoOutput()
2223                 .build());
2224
2225         return testCases;
2226     }
2227
2228     /*
2229      * @see <code>SouthboundIT.testCRUDBridgeOtherConfigs()</code>
2230      * This is helper test method to compare a test "set" of BridgeExternalIds against an expected "set"
2231      */
2232     private void assertExpectedBridgeOtherConfigsExist( List<BridgeOtherConfigs> expected,
2233                                                         List<BridgeOtherConfigs> test ) {
2234
2235         if (expected != null) {
2236             for (BridgeOtherConfigs expectedOtherConfig : expected) {
2237                 Assert.assertTrue(test.contains(expectedOtherConfig));
2238             }
2239         }
2240     }
2241
2242     /*
2243      * @see <code>SouthboundIT.generateBridgeOtherConfigsTestCases()</code> for specific test case information.
2244      */
2245     @Test
2246     public void testCRUDBridgeOtherConfigs() throws InterruptedException {
2247         final String TEST_BRIDGE_PREFIX = "CRUDBridgeOtherConfigs";
2248         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
2249         connectOvsdbNode(connectionInfo);
2250         // updateFromTestCases represent the original test case value.  updateToTestCases represent the new value after
2251         // the update has been performed.
2252         List<SouthboundTestCase<BridgeOtherConfigs>> updateFromTestCases = generateBridgeOtherConfigsTestCases();
2253         List<SouthboundTestCase<BridgeOtherConfigs>> updateToTestCases = generateBridgeOtherConfigsTestCases();
2254         for (SouthboundTestCase<BridgeOtherConfigs> updateFromTestCase : updateFromTestCases) {
2255             List<BridgeOtherConfigs> updateFromInputOtherConfigs = updateFromTestCase.inputValues;
2256             List<BridgeOtherConfigs> updateFromExpectedOtherConfigs = updateFromTestCase.expectedValues;
2257             for (SouthboundTestCase<BridgeOtherConfigs> updateToTestCase : updateToTestCases) {
2258                 String testBridgeName = String.format("%s_%s", TEST_BRIDGE_PREFIX, updateToTestCase.name);
2259                 List<BridgeOtherConfigs> updateToInputOtherConfigs = updateToTestCase.inputValues;
2260                 List<BridgeOtherConfigs> updateToExpectedOtherConfigs = updateToTestCase.expectedValues;
2261
2262                 // CREATE: Create the test bridge
2263                 boolean bridgeAdded = addBridge(connectionInfo, null,
2264                         testBridgeName, null, true, SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"),
2265                         true, null, null, null, updateFromInputOtherConfigs);
2266                 Assert.assertTrue(bridgeAdded);
2267
2268                 // READ: Read the test bridge and ensure changes are propagated to the CONFIGURATION data store,
2269                 // then repeat for OPERATIONAL data store
2270                 List<BridgeOtherConfigs> updateFromConfigurationOtherConfigs = getBridge(connectionInfo, testBridgeName,
2271                         LogicalDatastoreType.CONFIGURATION).getBridgeOtherConfigs();
2272                 assertExpectedBridgeOtherConfigsExist(updateFromExpectedOtherConfigs,
2273                         updateFromConfigurationOtherConfigs);
2274                 List<BridgeOtherConfigs> updateFromOperationalOtherConfigs = getBridge(connectionInfo, testBridgeName).getBridgeOtherConfigs();
2275                 assertExpectedBridgeOtherConfigsExist(updateFromExpectedOtherConfigs,
2276                         updateFromOperationalOtherConfigs);
2277
2278                 // UPDATE:  update the external_ids
2279                 OvsdbBridgeAugmentationBuilder bridgeAugmentationBuilder = new OvsdbBridgeAugmentationBuilder();
2280                 bridgeAugmentationBuilder.setBridgeOtherConfigs(updateToInputOtherConfigs);
2281                 InstanceIdentifier<Node> bridgeIid =
2282                         createInstanceIdentifier(connectionInfo,
2283                                 new OvsdbBridgeName(testBridgeName));
2284                 NodeBuilder bridgeNodeBuilder = new NodeBuilder();
2285                 Node bridgeNode = getBridgeNode(connectionInfo, testBridgeName);
2286                 bridgeNodeBuilder.setNodeId(bridgeNode.getNodeId());
2287                 bridgeNodeBuilder.setKey(bridgeNode.getKey());
2288                 bridgeNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class, bridgeAugmentationBuilder.build());
2289                 boolean result = mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, bridgeIid,
2290                         bridgeNodeBuilder.build());
2291                 Thread.sleep(OVSDB_UPDATE_TIMEOUT);
2292                 Assert.assertTrue(result);
2293
2294                 // READ: the test bridge and ensure changes are propagated to the CONFIGURATION data store,
2295                 // then repeat for OPERATIONAL data store
2296                 List<BridgeOtherConfigs> updateToConfigurationOtherConfigs = getBridge(connectionInfo, testBridgeName,
2297                         LogicalDatastoreType.CONFIGURATION).getBridgeOtherConfigs();
2298                 assertExpectedBridgeOtherConfigsExist(updateToExpectedOtherConfigs, updateToConfigurationOtherConfigs);
2299                 assertExpectedBridgeOtherConfigsExist(updateFromExpectedOtherConfigs,
2300                         updateToConfigurationOtherConfigs);
2301                 List<BridgeOtherConfigs> updateToOperationalOtherConfigs = getBridge(connectionInfo, testBridgeName)
2302                         .getBridgeOtherConfigs();
2303                 if (updateFromExpectedOtherConfigs != null) {
2304                     assertExpectedBridgeOtherConfigsExist(updateToExpectedOtherConfigs,
2305                             updateToOperationalOtherConfigs);
2306                     assertExpectedBridgeOtherConfigsExist(updateFromExpectedOtherConfigs,
2307                             updateToOperationalOtherConfigs);
2308                 }
2309
2310                 // DELETE
2311                 Assert.assertTrue(deleteBridge(connectionInfo, testBridgeName));
2312             }
2313         }
2314         Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
2315     }
2316
2317     /*
2318      * Generates the test cases involved in testing BridgeExternalIds.  See inline comments for descriptions of
2319      * the particular cases considered.
2320      *
2321      * The return value is a Map in the form (K,V)=(testCaseName,testCase).
2322      * - testCaseName is a String
2323      * - testCase is a Map in the form (K,V) s.t. K=(EXPECTED_VALUES_KEY|INPUT_VALUES_KEY) and V is a List of
2324      *     either corresponding INPUT bridge external ids, or EXPECTED bridge external ids
2325      *     INPUT is the List we use when calling BridgeAugmentationBuilder.setBridgeExternalIds()
2326      *     EXPECTED is the List we expect to receive after calling BridgeAugmentationBuilder.getBridgeExternalIds()
2327      */
2328     private List<SouthboundTestCase<BridgeExternalIds>> generateBridgeExternalIdsTestCases() {
2329         List<SouthboundTestCase<BridgeExternalIds>> testCases = new ArrayList<>();
2330
2331         final String BRIDGE_EXTERNAL_ID_KEY = "BridgeExternalIdKey";
2332         final String BRIDGE_EXTERNAL_ID_VALUE = "BridgeExternalIdValue";
2333         final String GOOD_KEY = "GoodKey";
2334         final String GOOD_VALUE = "GoodValue";
2335         final String NO_VALUE_FOR_KEY = "NoValueForKey";
2336
2337         KeyValueBuilder<BridgeExternalIds> builder = new SouthboundBridgeExternalIdsBuilder();
2338
2339         // Test Case 1:  TestOneExternalId
2340         // Test Type:    Positive
2341         // Description:  Create a bridge with one BridgeExternalIds
2342         // Expected:     A bridge is created with the single external_ids specified below
2343         final String testOneExternalIdName = "TestOneExternalId";
2344         testCases.add(SouthboundIT.<BridgeExternalIds>testCase()
2345                 .name(testOneExternalIdName)
2346                 .input(builder.build(testOneExternalIdName, BRIDGE_EXTERNAL_ID_KEY, BRIDGE_EXTERNAL_ID_VALUE))
2347                 .expectInputAsOutput()
2348                 .build());
2349
2350         // Test Case 2:  TestFiveExternalId
2351         // Test Type:    Positive
2352         // Description:  Create a bridge with multiple (five) BridgeExternalIds
2353         // Expected:     A bridge is created with the five external_ids specified below
2354         final String testFiveExternalIdName = "TestFiveExternalId";
2355         builder.reset();
2356         testCases.add(SouthboundIT.<BridgeExternalIds>testCase()
2357                 .name(testFiveExternalIdName)
2358                 .input(
2359                         builder.build(testFiveExternalIdName, BRIDGE_EXTERNAL_ID_KEY, BRIDGE_EXTERNAL_ID_VALUE),
2360                         builder.build(testFiveExternalIdName, BRIDGE_EXTERNAL_ID_KEY, BRIDGE_EXTERNAL_ID_VALUE),
2361                         builder.build(testFiveExternalIdName, BRIDGE_EXTERNAL_ID_KEY, BRIDGE_EXTERNAL_ID_VALUE),
2362                         builder.build(testFiveExternalIdName, BRIDGE_EXTERNAL_ID_KEY, BRIDGE_EXTERNAL_ID_VALUE),
2363                         builder.build(testFiveExternalIdName, BRIDGE_EXTERNAL_ID_KEY, BRIDGE_EXTERNAL_ID_VALUE))
2364                 .expectInputAsOutput()
2365                 .build());
2366
2367         // Test Case 3:  TestOneGoodExternalIdOneMalformedExternalIdValue
2368         // Test Type:    Negative
2369         // Description:
2370         //     One perfectly fine BridgeExternalId
2371         //        (TestOneGoodExternalIdOneMalformedExternalIdValue_BridgeExternalIdKey_1,
2372         //        TestOneGoodExternalIdOneMalformedExternalId_BridgeExternalIdValue_1)
2373         //     and one malformed BridgeExternalId which only has key specified
2374         //        (TestOneGoodExternalIdOneMalformedExternalIdValue_NoValueForKey_2,
2375         //        UNSPECIFIED)
2376         // Expected:     A bridge is created without any external_ids
2377         final String testOneGoodExternalIdOneMalformedExternalIdValueName =
2378                 "TestOneGoodExternalIdOneMalformedExternalIdValue";
2379         builder.reset();
2380         testCases.add(SouthboundIT.<BridgeExternalIds>testCase()
2381                 .name(testOneGoodExternalIdOneMalformedExternalIdValueName)
2382                 .input(
2383                         builder.build(testOneGoodExternalIdOneMalformedExternalIdValueName, GOOD_KEY, GOOD_VALUE),
2384                         builder.build(testOneGoodExternalIdOneMalformedExternalIdValueName, NO_VALUE_FOR_KEY, null))
2385                 .expectNoOutput()
2386                 .build());
2387
2388         return testCases;
2389     }
2390
2391     /*
2392      * @see <code>SouthboundIT.testCRUDBridgeExternalIds()</code>
2393      * This is helper test method to compare a test "set" of BridgeExternalIds against an expected "set"
2394      */
2395     private void assertExpectedBridgeExternalIdsExist( List<BridgeExternalIds> expected,
2396                                                        List<BridgeExternalIds> test ) {
2397
2398         if (expected != null) {
2399             for (BridgeExternalIds expectedExternalId : expected) {
2400                 Assert.assertTrue(test.contains(expectedExternalId));
2401             }
2402         }
2403     }
2404
2405     /*
2406      * @see <code>SouthboundIT.generateBridgeExternalIdsTestCases()</code> for specific test case information
2407      */
2408     @Test
2409     public void testCRUDBridgeExternalIds() throws InterruptedException {
2410         final String TEST_BRIDGE_PREFIX = "CRUDBridgeExternalIds";
2411         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portNumber);
2412         connectOvsdbNode(connectionInfo);
2413         // updateFromTestCases represent the original test case value.  updateToTestCases represent the new value after
2414         // the update has been performed.
2415         List<SouthboundTestCase<BridgeExternalIds>> updateFromTestCases = generateBridgeExternalIdsTestCases();
2416         List<SouthboundTestCase<BridgeExternalIds>> updateToTestCases = generateBridgeExternalIdsTestCases();
2417         for (SouthboundTestCase<BridgeExternalIds> updateFromTestCase : updateFromTestCases) {
2418             List<BridgeExternalIds> updateFromInputExternalIds = updateFromTestCase.inputValues;
2419             List<BridgeExternalIds> updateFromExpectedExternalIds = updateFromTestCase.expectedValues;
2420             for (SouthboundTestCase<BridgeExternalIds> updateToTestCase : updateToTestCases) {
2421                 String testBridgeName = String.format("%s_%s", TEST_BRIDGE_PREFIX, updateToTestCase.name);
2422                 List<BridgeExternalIds> updateToInputExternalIds = updateToTestCase.inputValues;
2423                 List<BridgeExternalIds> updateToExpectedExternalIds = updateToTestCase.expectedValues;
2424
2425                 // CREATE: Create the test bridge
2426                 boolean bridgeAdded = addBridge(connectionInfo, null,
2427                         testBridgeName, null, true, SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"),
2428                         true, null, updateFromInputExternalIds, null, null);
2429                 Assert.assertTrue(bridgeAdded);
2430
2431                 // READ: Read the test bridge and ensure changes are propagated to the CONFIGURATION data store,
2432                 // then repeat for OPERATIONAL data store
2433                 List<BridgeExternalIds> updateFromConfigurationExternalIds = getBridge(connectionInfo, testBridgeName,
2434                         LogicalDatastoreType.CONFIGURATION).getBridgeExternalIds();
2435                 assertExpectedBridgeExternalIdsExist(updateFromExpectedExternalIds, updateFromConfigurationExternalIds);
2436                 List<BridgeExternalIds> updateFromOperationalExternalIds = getBridge(connectionInfo, testBridgeName).getBridgeExternalIds();
2437                 assertExpectedBridgeExternalIdsExist(updateFromExpectedExternalIds, updateFromOperationalExternalIds);
2438
2439                 // UPDATE:  update the external_ids
2440                 OvsdbBridgeAugmentationBuilder bridgeAugmentationBuilder = new OvsdbBridgeAugmentationBuilder();
2441                 bridgeAugmentationBuilder.setBridgeExternalIds(updateToInputExternalIds);
2442                 InstanceIdentifier<Node> bridgeIid =
2443                         createInstanceIdentifier(connectionInfo,
2444                                 new OvsdbBridgeName(testBridgeName));
2445                 NodeBuilder bridgeNodeBuilder = new NodeBuilder();
2446                 Node bridgeNode = getBridgeNode(connectionInfo, testBridgeName);
2447                 bridgeNodeBuilder.setNodeId(bridgeNode.getNodeId());
2448                 bridgeNodeBuilder.setKey(bridgeNode.getKey());
2449                 bridgeNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class, bridgeAugmentationBuilder.build());
2450                 boolean result = mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, bridgeIid,
2451                         bridgeNodeBuilder.build());
2452                 Thread.sleep(OVSDB_UPDATE_TIMEOUT);
2453                 Assert.assertTrue(result);
2454
2455                 // READ: the test bridge and ensure changes are propagated to the CONFIGURATION data store,
2456                 // then repeat for OPERATIONAL data store
2457                 List<BridgeExternalIds> updateToConfigurationExternalIds = getBridge(connectionInfo, testBridgeName,
2458                         LogicalDatastoreType.CONFIGURATION).getBridgeExternalIds();
2459                 assertExpectedBridgeExternalIdsExist(updateToExpectedExternalIds, updateToConfigurationExternalIds);
2460                 assertExpectedBridgeExternalIdsExist(updateFromExpectedExternalIds, updateToConfigurationExternalIds);
2461                 List<BridgeExternalIds> updateToOperationalExternalIds = getBridge(connectionInfo, testBridgeName)
2462                         .getBridgeExternalIds();
2463                 if (updateFromExpectedExternalIds != null) {
2464                     assertExpectedBridgeExternalIdsExist(updateToExpectedExternalIds, updateToOperationalExternalIds);
2465                     assertExpectedBridgeExternalIdsExist(updateFromExpectedExternalIds, updateToOperationalExternalIds);
2466                 }
2467
2468                 // DELETE
2469                 Assert.assertTrue(deleteBridge(connectionInfo, testBridgeName));
2470             }
2471         }
2472         Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
2473     }
2474
2475     public static InstanceIdentifier<Node> createInstanceIdentifier(ConnectionInfo key,OvsdbBridgeName bridgeName) {
2476         return SouthboundMapper.createInstanceIdentifier(createManagedNodeId(key, bridgeName));
2477     }
2478
2479     public static NodeId createManagedNodeId(ConnectionInfo key, OvsdbBridgeName bridgeName) {
2480         return createManagedNodeId(key.getRemoteIp(), key.getRemotePort(), bridgeName);
2481     }
2482
2483     public static NodeId createManagedNodeId(IpAddress ip, PortNumber port, OvsdbBridgeName bridgeName) {
2484         return new NodeId(createNodeId(ip,port).getValue()
2485                 + "/" + SouthboundConstants.BRIDGE_URI_PREFIX + "/" + bridgeName.getValue());
2486     }
2487
2488     public static NodeId createNodeId(IpAddress ip, PortNumber port) {
2489         String uriString = SouthboundConstants.OVSDB_URI_PREFIX + "://"
2490                 + new String(ip.getValue()) + ":" + port.getValue();
2491         Uri uri = new Uri(uriString);
2492         return new NodeId(uri);
2493     }
2494
2495     public static NodeKey createNodeKey(IpAddress ip, PortNumber port) {
2496         return new NodeKey(createNodeId(ip,port));
2497     }
2498
2499     public static Node createNode(ConnectionInfo key) {
2500         NodeBuilder nodeBuilder = new NodeBuilder();
2501         nodeBuilder.setNodeId(createNodeId(key.getRemoteIp(),key.getRemotePort()));
2502         nodeBuilder.addAugmentation(OvsdbNodeAugmentation.class, createOvsdbAugmentation(key));
2503         return nodeBuilder.build();
2504     }
2505
2506     public static OvsdbNodeAugmentation createOvsdbAugmentation(ConnectionInfo key) {
2507         OvsdbNodeAugmentationBuilder ovsdbNodeBuilder = new OvsdbNodeAugmentationBuilder();
2508         ovsdbNodeBuilder.setConnectionInfo(key);
2509         return ovsdbNodeBuilder.build();
2510     }
2511
2512     public static NodeId createManagedNodeId(InstanceIdentifier<Node> iid) {
2513         NodeKey nodeKey = iid.firstKeyOf(Node.class, NodeKey.class);
2514         return nodeKey.getNodeId();
2515     }
2516
2517     /**
2518      * <p>
2519      * Representation of a southbound test case. Each test case has a name, a list of input values and a list of
2520      * expected values. The input values are provided to the augmentation builder, and the expected values are checked
2521      * against the output of the resulting augmentation.
2522      * </p>
2523      * <p>
2524      * Instances of this class are immutable.
2525      * </p>
2526      *
2527      * @param <T> The type of data used for the test case.
2528      */
2529     private static final class SouthboundTestCase<T> {
2530         private final String name;
2531         private final List<T> inputValues;
2532         private final List<T> expectedValues;
2533
2534         /**
2535          * Creates an instance of a southbound test case.
2536          *
2537          * @param name The test case's name.
2538          * @param inputValues The input values (provided as input to the underlying augmentation builder).
2539          * @param expectedValues The expected values (checked against the output of the underlying augmentation).
2540          */
2541         public SouthboundTestCase(
2542                 final String name, final List<T> inputValues, final List<T> expectedValues) {
2543             this.name = name;
2544             this.inputValues = inputValues;
2545             this.expectedValues = expectedValues;
2546         }
2547     }
2548
2549     /**
2550      * Southbound test case builder.
2551      *
2552      * @param <T> The type of data used for the test case.
2553      */
2554     private static final class SouthboundTestCaseBuilder<T> {
2555         private String name;
2556         private List<T> inputValues;
2557         private List<T> expectedValues;
2558
2559         /**
2560          * Creates a builder. Builders may be reused, the generated immutable instances are independent of the
2561          * builders. There are no default values.
2562          */
2563         public SouthboundTestCaseBuilder() {
2564             // Nothing to do
2565         }
2566
2567         /**
2568          * Sets the test case's name.
2569          *
2570          * @param name The test case's name.
2571          * @return The builder.
2572          */
2573         public SouthboundTestCaseBuilder<T> name(final String name) {
2574             this.name = name;
2575             return this;
2576         }
2577
2578         /**
2579          * Sets the input values.
2580          *
2581          * @param inputValues The input values.
2582          * @return The builder.
2583          */
2584         @SafeVarargs
2585         public final SouthboundTestCaseBuilder<T> input(final T... inputValues) {
2586             this.inputValues = Lists.newArrayList(inputValues);
2587             return this;
2588         }
2589
2590         /**
2591          * Sets the expected output values.
2592          *
2593          * @param expectedValues The expected output values.
2594          * @return The builder.
2595          */
2596         @SafeVarargs
2597         public final SouthboundTestCaseBuilder<T> expect(final T... expectedValues) {
2598             this.expectedValues = Lists.newArrayList(expectedValues);
2599             return this;
2600         }
2601
2602         /**
2603          * Indicates that the provided input values should be expected as output values.
2604          *
2605          * @return The builder.
2606          */
2607         public SouthboundTestCaseBuilder<T> expectInputAsOutput() {
2608             this.expectedValues = this.inputValues;
2609             return this;
2610         }
2611
2612         /**
2613          * Indicates that no output should be expected.
2614          *
2615          * @return The builder.
2616          */
2617         public SouthboundTestCaseBuilder<T> expectNoOutput() {
2618             this.expectedValues = null;
2619             return this;
2620         }
2621
2622         /**
2623          * Builds an immutable instance representing the test case.
2624          *
2625          * @return The test case.
2626          */
2627         @SuppressWarnings("unchecked")
2628         public SouthboundTestCase<T> build() {
2629             return new SouthboundTestCase<>(name, inputValues, expectedValues);
2630         }
2631     }
2632
2633     private static <T> SouthboundTestCaseBuilder<T> testCase() {
2634         return new SouthboundTestCaseBuilder<>();
2635     }
2636
2637     private abstract static class KeyValueBuilder<T> {
2638         private static final int COUNTER_START = 0;
2639         private int counter = COUNTER_START;
2640
2641         protected abstract Builder<T> builder();
2642
2643         protected abstract void setKey(Builder<T> builder, String key);
2644
2645         protected abstract void setValue(Builder<T> builder, String value);
2646
2647         public final T build(final String testName, final String key, final String value) {
2648             final Builder<T> builder = builder();
2649             this.counter++;
2650             if (key != null) {
2651                 setKey(builder, String.format(FORMAT_STR, testName, key, this.counter));
2652             }
2653             if (value != null) {
2654                 setValue(builder, String.format(FORMAT_STR, testName, value, this.counter));
2655             }
2656             return builder.build();
2657         }
2658
2659         public final void reset() {
2660             this.counter = COUNTER_START;
2661         }
2662     }
2663
2664     private static final class SouthboundPortExternalIdsBuilder extends KeyValueBuilder<PortExternalIds> {
2665         @Override
2666         protected Builder<PortExternalIds> builder() {
2667             return new PortExternalIdsBuilder();
2668         }
2669
2670         @Override
2671         protected void setKey(Builder<PortExternalIds> builder, String key) {
2672             ((PortExternalIdsBuilder) builder).setExternalIdKey(key);
2673         }
2674
2675         @Override
2676         protected void setValue(Builder<PortExternalIds> builder, String value) {
2677             ((PortExternalIdsBuilder) builder).setExternalIdValue(value);
2678         }
2679     }
2680
2681     private static final class SouthboundInterfaceExternalIdsBuilder extends KeyValueBuilder<InterfaceExternalIds> {
2682         @Override
2683         protected Builder<InterfaceExternalIds> builder() {
2684             return new InterfaceExternalIdsBuilder();
2685         }
2686
2687         @Override
2688         protected void setKey(Builder<InterfaceExternalIds> builder, String key) {
2689             ((InterfaceExternalIdsBuilder) builder).setExternalIdKey(key);
2690         }
2691
2692         @Override
2693         protected void setValue(Builder<InterfaceExternalIds> builder, String value) {
2694             ((InterfaceExternalIdsBuilder) builder).setExternalIdValue(value);
2695         }
2696     }
2697
2698     private static final class SouthboundOptionsBuilder extends KeyValueBuilder<Options> {
2699         @Override
2700         protected Builder<Options> builder() {
2701             return new OptionsBuilder();
2702         }
2703
2704         @Override
2705         protected void setKey(Builder<Options> builder, String key) {
2706             ((OptionsBuilder) builder).setOption(key);
2707         }
2708
2709         @Override
2710         protected void setValue(Builder<Options> builder, String value) {
2711             ((OptionsBuilder) builder).setValue(value);
2712         }
2713     }
2714
2715     private static final class SouthboundInterfaceOtherConfigsBuilder extends KeyValueBuilder<InterfaceOtherConfigs> {
2716         @Override
2717         protected Builder<InterfaceOtherConfigs> builder() {
2718             return new InterfaceOtherConfigsBuilder();
2719         }
2720
2721         @Override
2722         protected void setKey(Builder<InterfaceOtherConfigs> builder, String key) {
2723             ((InterfaceOtherConfigsBuilder) builder).setOtherConfigKey(key);
2724         }
2725
2726         @Override
2727         protected void setValue(Builder<InterfaceOtherConfigs> builder, String value) {
2728             ((InterfaceOtherConfigsBuilder) builder).setOtherConfigValue(value);
2729         }
2730     }
2731
2732     private static final class SouthboundPortOtherConfigsBuilder extends KeyValueBuilder<PortOtherConfigs> {
2733         @Override
2734         protected Builder<PortOtherConfigs> builder() {
2735             return new PortOtherConfigsBuilder();
2736         }
2737
2738         @Override
2739         protected void setKey(Builder<PortOtherConfigs> builder, String key) {
2740             ((PortOtherConfigsBuilder) builder).setOtherConfigKey(key);
2741         }
2742
2743         @Override
2744         protected void setValue(Builder<PortOtherConfigs> builder, String value) {
2745             ((PortOtherConfigsBuilder) builder).setOtherConfigValue(value);
2746         }
2747     }
2748
2749     private static final class SouthboundBridgeOtherConfigsBuilder extends KeyValueBuilder<BridgeOtherConfigs> {
2750         @Override
2751         protected Builder<BridgeOtherConfigs> builder() {
2752             return new BridgeOtherConfigsBuilder();
2753         }
2754
2755         @Override
2756         protected void setKey(Builder<BridgeOtherConfigs> builder, String key) {
2757             ((BridgeOtherConfigsBuilder) builder).setBridgeOtherConfigKey(key);
2758         }
2759
2760         @Override
2761         protected void setValue(Builder<BridgeOtherConfigs> builder, String value) {
2762             ((BridgeOtherConfigsBuilder) builder).setBridgeOtherConfigValue(value);
2763         }
2764     }
2765
2766     private static final class SouthboundBridgeExternalIdsBuilder extends KeyValueBuilder<BridgeExternalIds> {
2767         @Override
2768         protected Builder<BridgeExternalIds> builder() {
2769             return new BridgeExternalIdsBuilder();
2770         }
2771
2772         @Override
2773         protected void setKey(Builder<BridgeExternalIds> builder, String key) {
2774             ((BridgeExternalIdsBuilder) builder).setBridgeExternalIdKey(key);
2775         }
2776
2777         @Override
2778         protected void setValue(Builder<BridgeExternalIds> builder, String value) {
2779             ((BridgeExternalIdsBuilder) builder).setBridgeExternalIdValue(value);
2780         }
2781     }
2782 }