ce39400cd7738e166ceadfeaefcef6535eeb0920
[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.when;
15 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.editConfigurationFilePut;
16 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.karafDistributionConfiguration;
17 import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.keepRuntimeFolder;
18
19 import com.google.common.collect.ImmutableBiMap;
20 import com.google.common.collect.Lists;
21 import com.google.common.collect.Maps;
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.HashMap;
29 import java.util.HashSet;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.Properties;
33 import java.util.Set;
34 import java.util.concurrent.ExecutionException;
35 import java.util.concurrent.ExecutorService;
36 import java.util.concurrent.Executors;
37 import java.util.concurrent.TimeUnit;
38
39 import javax.inject.Inject;
40
41 import org.junit.Assert;
42 import org.junit.Before;
43 import org.junit.Test;
44 import org.junit.runner.RunWith;
45 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
46 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
47 import org.opendaylight.controller.mdsal.it.base.AbstractMdsalTestBase;
48 import org.opendaylight.ovsdb.southbound.SouthboundConstants;
49 import org.opendaylight.ovsdb.southbound.SouthboundMapper;
50 import org.opendaylight.ovsdb.southbound.SouthboundProvider;
51 import org.opendaylight.ovsdb.southbound.SouthboundUtil;
52 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
53 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.PortNumber;
54 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathTypeBase;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.InterfaceTypeBase;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentation;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeAugmentationBuilder;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeName;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbBridgeProtocolBase;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbFailModeBase;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentation;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeAugmentationBuilder;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbNodeRef;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbPortInterfaceAttributes.VlanMode;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentationBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeExternalIds;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeExternalIdsBuilder;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigs;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.BridgeOtherConfigsBuilder;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntry;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ControllerEntryBuilder;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntry;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.bridge.attributes.ProtocolEntryBuilder;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfoBuilder;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.DatapathTypeEntry;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.InterfaceTypeEntryBuilder;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.OpenvswitchOtherConfigs;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIds;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceExternalIdsBuilder;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceOtherConfigs;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceOtherConfigsBuilder;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.Options;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.OptionsBuilder;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.PortExternalIds;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.PortExternalIdsBuilder;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.PortOtherConfigs;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.PortOtherConfigsBuilder;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.Trunks;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.TrunksBuilder;
94 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
95 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
96 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TpId;
97 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
98 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
99 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
100 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeBuilder;
101 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
102 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
103 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointBuilder;
104 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
105 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
106 import org.ops4j.pax.exam.Configuration;
107 import org.ops4j.pax.exam.Option;
108 import org.ops4j.pax.exam.junit.PaxExam;
109 import org.ops4j.pax.exam.karaf.options.KarafDistributionOption;
110 import org.ops4j.pax.exam.karaf.options.LogLevelOption;
111 import org.ops4j.pax.exam.options.MavenUrlReference;
112 import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
113 import org.ops4j.pax.exam.spi.reactors.PerClass;
114 import org.osgi.framework.BundleContext;
115 import org.slf4j.Logger;
116 import org.slf4j.LoggerFactory;
117
118 /**
119  * Integration tests for southbound-impl
120  *
121  * @author Sam Hague (shague@redhat.com)
122  */
123 @RunWith(PaxExam.class)
124 @ExamReactorStrategy(PerClass.class)
125 public class SouthboundIT extends AbstractMdsalTestBase {
126     private static final String EXPECTED_VALUES_KEY = "ExpectedValuesKey";
127     private static final String INPUT_VALUES_KEY = "InputValuesKey";
128     private static final String NETDEV_DP_TYPE = "netdev";
129     private static final Logger LOG = LoggerFactory.getLogger(SouthboundIT.class);
130     private static final int OVSDB_UPDATE_TIMEOUT = 1000;
131     public static final int NUM_THREADS = 4;
132     private static DataBroker dataBroker = null;
133     private static String addressStr;
134     private static String portStr;
135     private static String connectionType;
136     private static Boolean setup = false;
137     private static MdsalUtils mdsalUtils = null;
138
139     // TODO Constants copied frmo AbstractConfigTestBase, need to be removed (see TODO below)
140     private static final String PAX_EXAM_UNPACK_DIRECTORY = "target/exam";
141     private static final String KARAF_DEBUG_PORT = "5005";
142     private static final String KARAF_DEBUG_PROP = "karaf.debug";
143     private static final String KEEP_UNPACK_DIRECTORY_PROP = "karaf.keep.unpack";
144
145     @Inject
146     private BundleContext bundleContext;
147
148     @Configuration
149     public Option[] config() {
150         // TODO Figure out how to use the parent Karaf setup, then just use super.config()
151         Option[] options = new Option[] {
152                 when(Boolean.getBoolean(KARAF_DEBUG_PROP))
153                         .useOptions(KarafDistributionOption.debugConfiguration(KARAF_DEBUG_PORT, true)),
154                 karafDistributionConfiguration().frameworkUrl(getKarafDistro())
155                         .unpackDirectory(new File(PAX_EXAM_UNPACK_DIRECTORY))
156                         .useDeployFolder(false),
157                 when(Boolean.getBoolean(KEEP_UNPACK_DIRECTORY_PROP)).useOptions(keepRuntimeFolder()),
158                 // Works only if we don't specify the feature repo and name
159                 getLoggingOption()};
160         Option[] propertyOptions = getPropertiesOptions();
161         Option[] combinedOptions = new Option[options.length + propertyOptions.length];
162         System.arraycopy(options, 0, combinedOptions, 0, options.length);
163         System.arraycopy(propertyOptions, 0, combinedOptions, options.length, propertyOptions.length);
164         return combinedOptions;
165     }
166
167     @Override
168     public String getKarafDistro() {
169         return maven()
170                 .groupId("org.opendaylight.ovsdb")
171                 .artifactId("southbound-karaf")
172                 .versionAsInProject()
173                 .type("zip")
174                 .getURL();
175     }
176
177     @Override
178     public String getModuleName() {
179         return "southbound-impl";
180     }
181
182     @Override
183     public String getInstanceName() {
184         return "southbound-default";
185     }
186
187     @Override
188     public MavenUrlReference getFeatureRepo() {
189         return maven()
190                 .groupId("org.opendaylight.ovsdb")
191                 .artifactId("southbound-features")
192                 .classifier("features")
193                 .type("xml")
194                 .versionAsInProject();
195     }
196
197     @Override
198     public String getFeatureName() {
199         return "odl-ovsdb-southbound-impl-ui";
200     }
201
202     protected String usage() {
203         return "Integration Test needs a valid connection configuration as follows :\n"
204                 + "active connection : mvn -Dovsdbserver.ipaddress=x.x.x.x -Dovsdbserver.port=yyyy verify\n"
205                 + "passive connection : mvn -Dovsdbserver.connection=passive verify\n";
206     }
207
208     @Override
209     public Option getLoggingOption() {
210         return composite(
211                 editConfigurationFilePut(SouthboundITConstants.ORG_OPS4J_PAX_LOGGING_CFG,
212                         "log4j.logger.org.opendaylight.ovsdb",
213                         LogLevelOption.LogLevel.TRACE.name()),
214                 super.getLoggingOption());
215     }
216
217     private Option[] getPropertiesOptions() {
218         Properties props = new Properties(System.getProperties());
219         String addressStr = props.getProperty(SouthboundITConstants.SERVER_IPADDRESS,
220                 SouthboundITConstants.DEFAULT_SERVER_IPADDRESS);
221         String portStr = props.getProperty(SouthboundITConstants.SERVER_PORT,
222                 SouthboundITConstants.DEFAULT_SERVER_PORT);
223         String connectionType = props.getProperty(SouthboundITConstants.CONNECTION_TYPE,
224                 SouthboundITConstants.CONNECTION_TYPE_ACTIVE);
225
226         LOG.info("getPropertiesOptions: Using the following properties: mode= {}, ip:port= {}:{}",
227                 connectionType, addressStr, portStr);
228
229         Option[] options = new Option[] {
230                 editConfigurationFilePut(SouthboundITConstants.CUSTOM_PROPERTIES,
231                         SouthboundITConstants.SERVER_IPADDRESS, addressStr),
232                 editConfigurationFilePut(SouthboundITConstants.CUSTOM_PROPERTIES,
233                         SouthboundITConstants.SERVER_PORT, portStr),
234                 editConfigurationFilePut(SouthboundITConstants.CUSTOM_PROPERTIES,
235                         SouthboundITConstants.CONNECTION_TYPE, connectionType),
236         };
237         return options;
238     }
239
240     @Before
241     @Override
242     public void setup() throws InterruptedException {
243         if (setup) {
244             LOG.info("Skipping setUp, already initialized");
245             return;
246         }
247
248         try {
249             super.setup();
250         } catch (Exception e) {
251             e.printStackTrace();
252         }
253         //dataBroker = getSession().getSALService(DataBroker.class);
254         Thread.sleep(3000);
255         dataBroker = SouthboundProvider.getDb();
256         Assert.assertNotNull("db should not be null", dataBroker);
257
258         addressStr = bundleContext.getProperty(SouthboundITConstants.SERVER_IPADDRESS);
259         portStr = bundleContext.getProperty(SouthboundITConstants.SERVER_PORT);
260         connectionType = bundleContext.getProperty(SouthboundITConstants.CONNECTION_TYPE);
261
262         LOG.info("setUp: Using the following properties: mode= {}, ip:port= {}:{}",
263                 connectionType, addressStr, portStr);
264         if (connectionType.equalsIgnoreCase(SouthboundITConstants.CONNECTION_TYPE_ACTIVE)) {
265             if (addressStr == null) {
266                 fail(usage());
267             }
268         }
269
270         mdsalUtils = new MdsalUtils(dataBroker);
271         setup = true;
272     }
273
274     /**
275      * Test passive connection mode. The southbound starts in a listening mode waiting for connections on port
276      * 6640. This test will wait for incoming connections for {@link SouthboundITConstants.CONNECTION_INIT_TIMEOUT} ms.
277      *
278      * @throws InterruptedException
279      */
280     @Test
281     public void testPassiveNode() throws InterruptedException {
282         if (connectionType.equalsIgnoreCase(SouthboundITConstants.CONNECTION_TYPE_PASSIVE)) {
283             //Wait for CONNECTION_INIT_TIMEOUT for the Passive connection to be initiated by the ovsdb-server.
284             Thread.sleep(SouthboundITConstants.CONNECTION_INIT_TIMEOUT);
285         }
286     }
287
288     private ConnectionInfo getConnectionInfo(final String addressStr, final String portStr) {
289         InetAddress inetAddress = null;
290         try {
291             inetAddress = InetAddress.getByName(addressStr);
292         } catch (UnknownHostException e) {
293             fail("Could not allocate InetAddress: " + e);
294         }
295
296         IpAddress address = SouthboundMapper.createIpAddress(inetAddress);
297         PortNumber port = new PortNumber(Integer.parseInt(portStr));
298
299         LOG.info("connectionInfo: {}", new ConnectionInfoBuilder()
300                 .setRemoteIp(address)
301                 .setRemotePort(port)
302                 .build());
303         return new ConnectionInfoBuilder()
304                 .setRemoteIp(address)
305                 .setRemotePort(port)
306                 .build();
307     }
308
309     private String connectionInfoToString(final ConnectionInfo connectionInfo) {
310         return new String(connectionInfo.getRemoteIp().getValue()) + ":" + connectionInfo.getRemotePort().getValue();
311     }
312
313     @Test
314     public void testNetworkTopology() throws InterruptedException {
315         NetworkTopology networkTopology = mdsalUtils.read(LogicalDatastoreType.CONFIGURATION,
316                 InstanceIdentifier.create(NetworkTopology.class));
317         Assert.assertNotNull("NetworkTopology could not be found in " + LogicalDatastoreType.CONFIGURATION,
318                 networkTopology);
319
320         networkTopology = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL,
321                 InstanceIdentifier.create(NetworkTopology.class));
322         Assert.assertNotNull("NetworkTopology could not be found in " + LogicalDatastoreType.OPERATIONAL,
323                 networkTopology);
324     }
325
326     @Test
327     public void testOvsdbTopology() throws InterruptedException {
328         InstanceIdentifier<Topology> path = InstanceIdentifier
329                 .create(NetworkTopology.class)
330                 .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID));
331
332         Topology topology = mdsalUtils.read(LogicalDatastoreType.CONFIGURATION, path);
333         Assert.assertNotNull("Topology could not be found in " + LogicalDatastoreType.CONFIGURATION,
334                 topology);
335
336         topology = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, path);
337
338         Assert.assertNotNull("Topology could not be found in " + LogicalDatastoreType.OPERATIONAL,
339                 topology);
340     }
341
342     private boolean addOvsdbNode(final ConnectionInfo connectionInfo) throws InterruptedException {
343         InstanceIdentifier<Node> iid = createInstanceIdentifier(connectionInfo);
344         // Check that the node doesn't already exist (we don't support connecting twice)
345         Assert.assertNull("The OVSDB node has already been added",
346                 mdsalUtils.read(LogicalDatastoreType.CONFIGURATION, iid));
347         boolean result = mdsalUtils.put(LogicalDatastoreType.CONFIGURATION,
348                 iid,
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         Node node = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL,
365                 createInstanceIdentifier(connectionInfo));
366         return node;
367     }
368
369     private boolean deleteOvsdbNode(final ConnectionInfo connectionInfo) throws InterruptedException {
370         boolean result = mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION,
371                 createInstanceIdentifier(connectionInfo));
372         Thread.sleep(OVSDB_UPDATE_TIMEOUT);
373         return result;
374     }
375
376     private Node connectOvsdbNode(final ConnectionInfo connectionInfo) throws InterruptedException {
377         Assert.assertTrue(addOvsdbNode(connectionInfo));
378         Node node = getOvsdbNode(connectionInfo);
379         Assert.assertNotNull(node);
380         LOG.info("Connected to {}", connectionInfoToString(connectionInfo));
381         return node;
382     }
383
384     private boolean disconnectOvsdbNode(final ConnectionInfo connectionInfo) throws InterruptedException {
385         Assert.assertTrue(deleteOvsdbNode(connectionInfo));
386         Node node = getOvsdbNode(connectionInfo);
387         Assert.assertNull(node);
388         //Assume.assumeNotNull(node); // Using assumeNotNull because there is no assumeNull
389         LOG.info("Disconnected from {}", connectionInfoToString(connectionInfo));
390         return true;
391     }
392
393     @Test
394     public void testAddDeleteOvsdbNode() throws InterruptedException {
395         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
396         Node ovsdbNode = connectOvsdbNode(connectionInfo);
397         Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
398         //Assume.assumeTrue(disconnectOvsdbNode(connectionInfo));
399     }
400
401     @Test
402     public void testDpdkSwitch() throws InterruptedException {
403         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
404         Node ovsdbNode = connectOvsdbNode(connectionInfo);
405         List<DatapathTypeEntry> datapathTypeEntries = ovsdbNode.getAugmentation(OvsdbNodeAugmentation.class)
406                 .getDatapathTypeEntry();
407         if (datapathTypeEntries == null) {
408             LOG.info("DPDK not supported on this node.");
409         } else {
410             Class<? extends DatapathTypeBase> dpType = null;
411             String dpTypeStr = null;
412             for (DatapathTypeEntry dpTypeEntry : datapathTypeEntries) {
413                 dpType = dpTypeEntry.getDatapathType();
414                 dpTypeStr = SouthboundConstants.DATAPATH_TYPE_MAP.get(dpType);
415                 LOG.info("dp type is {}", dpTypeStr);
416                 if (dpTypeStr.equals(NETDEV_DP_TYPE)) {
417                     LOG.info("Found a DPDK node; adding a corresponding netdev device");
418                     InstanceIdentifier<Node> bridgeIid = createInstanceIdentifier(connectionInfo,
419                             new OvsdbBridgeName(SouthboundITConstants.BRIDGE_NAME));
420                     NodeId bridgeNodeId = createManagedNodeId(bridgeIid);
421                     addBridge(connectionInfo, bridgeIid, SouthboundITConstants.BRIDGE_NAME, bridgeNodeId, false, null,
422                             true, dpType, null, null, null);
423
424                     // Verify that the device is netdev
425                     OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
426                     Assert.assertNotNull(bridge);
427                     Assert.assertEquals(dpTypeStr, bridge.getDatapathType());
428
429                     // Add dpdk port
430                     final String TEST_PORT_NAME = "testDPDKPort";
431                     OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
432                             createGenericDpdkOvsdbTerminationPointAugmentationBuilder(TEST_PORT_NAME);
433                     Assert.assertTrue(addTerminationPoint(bridgeNodeId, TEST_PORT_NAME, ovsdbTerminationBuilder));
434
435                     // Verify that DPDK port was created
436                     InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
437                     Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL,
438                             terminationPointIid);
439                     Assert.assertNotNull(terminationPointNode);
440
441                     // Verify that each termination point has DPDK ifType
442                     Class<? extends InterfaceTypeBase> dpdkIfType = SouthboundConstants.OVSDB_INTERFACE_TYPE_MAP
443                             .get("dpdk");
444                     Class<? extends InterfaceTypeBase> opPort = null;
445                     List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
446                     for (TerminationPoint terminationPoint : terminationPoints) {
447                         OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation = terminationPoint
448                                 .getAugmentation(OvsdbTerminationPointAugmentation.class);
449                         if (ovsdbTerminationPointAugmentation.getName().equals(TEST_PORT_NAME)) {
450                             opPort = ovsdbTerminationPointAugmentation
451                                     .getInterfaceType();
452                             Assert.assertEquals(dpdkIfType, opPort);
453                         }
454                     }
455                     Assert.assertTrue(deleteBridge(connectionInfo));
456                     break;
457                 }
458             }
459         }
460         Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
461     }
462
463     @Test
464     public void testOvsdbNodeOvsVersion() throws InterruptedException {
465         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
466         Node ovsdbNode = connectOvsdbNode(connectionInfo);
467         OvsdbNodeAugmentation ovsdbNodeAugmentation = ovsdbNode.getAugmentation(OvsdbNodeAugmentation.class);
468         Assert.assertNotNull(ovsdbNodeAugmentation);
469         assertNotNull(ovsdbNodeAugmentation.getOvsVersion());
470         Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
471         //Assume.assumeTrue(disconnectOvsdbNode(connectionInfo));
472     }
473
474     @Test
475     public void testOpenVSwitchOtherConfig() throws InterruptedException {
476         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
477         Node ovsdbNode = connectOvsdbNode(connectionInfo);
478         OvsdbNodeAugmentation ovsdbNodeAugmentation = ovsdbNode.getAugmentation(OvsdbNodeAugmentation.class);
479         Assert.assertNotNull(ovsdbNodeAugmentation);
480         List<OpenvswitchOtherConfigs> otherConfigsList = ovsdbNodeAugmentation.getOpenvswitchOtherConfigs();
481         if (otherConfigsList != null) {
482             for (OpenvswitchOtherConfigs otherConfig : otherConfigsList) {
483                 if (otherConfig.getOtherConfigKey().equals("local_ip")) {
484                     LOG.info("local_ip: {}", otherConfig.getOtherConfigValue());
485                     break;
486                 } else {
487                     LOG.info("other_config {}:{}", otherConfig.getOtherConfigKey(), otherConfig.getOtherConfigValue());
488                 }
489             }
490         } else {
491             LOG.info("other_config is not present");
492         }
493         Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
494         //Assume.assumeTrue(disconnectOvsdbNode(connectionInfo));
495     }
496
497     @Test
498     public void testOvsdbBridgeControllerInfo() throws InterruptedException {
499         ConnectionInfo connectionInfo = getConnectionInfo(addressStr,portStr);
500         Node ovsdbNode = connectOvsdbNode(connectionInfo);
501         String controllerTarget = SouthboundUtil.getControllerTarget(ovsdbNode);
502         assertNotNull("Failed to get controller target", controllerTarget);
503         List<ControllerEntry> setControllerEntry = createControllerEntry(controllerTarget);
504         Uri setUri = new Uri(controllerTarget);
505         Assert.assertTrue(addBridge(connectionInfo, null, SouthboundITConstants.BRIDGE_NAME,null, true,
506                 SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"), true, null, null,
507                 setControllerEntry, null));
508         OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
509         Assert.assertNotNull("bridge was not found: " + SouthboundITConstants.BRIDGE_NAME,  bridge);
510         Assert.assertNotNull("ControllerEntry was not found: " + setControllerEntry.iterator().next(),
511                 bridge.getControllerEntry());
512         List<ControllerEntry> getControllerEntries = bridge.getControllerEntry();
513         for (ControllerEntry entry : getControllerEntries) {
514             if (entry.getTarget() != null) {
515                 Assert.assertEquals(setUri.toString(), entry.getTarget().toString());
516             }
517         }
518
519         Assert.assertTrue(deleteBridge(connectionInfo));
520         Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
521     }
522
523     private List<ControllerEntry> createControllerEntry(String controllerTarget) {
524         List<ControllerEntry> controllerEntriesList = new ArrayList<ControllerEntry>();
525         controllerEntriesList.add(new ControllerEntryBuilder()
526                 .setTarget(new Uri(controllerTarget))
527                 .build());
528         return controllerEntriesList;
529     }
530
531     private void setManagedBy(final OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder,
532                               final ConnectionInfo connectionInfo) {
533         InstanceIdentifier<Node> connectionNodePath = createInstanceIdentifier(connectionInfo);
534         ovsdbBridgeAugmentationBuilder.setManagedBy(new OvsdbNodeRef(connectionNodePath));
535     }
536
537     private List<ProtocolEntry> createMdsalProtocols() {
538         List<ProtocolEntry> protocolList = new ArrayList<ProtocolEntry>();
539         ImmutableBiMap<String, Class<? extends OvsdbBridgeProtocolBase>> mapper =
540                 SouthboundConstants.OVSDB_PROTOCOL_MAP.inverse();
541         protocolList.add(new ProtocolEntryBuilder().
542                 setProtocol((Class<? extends OvsdbBridgeProtocolBase>) mapper.get("OpenFlow13")).build());
543         return protocolList;
544     }
545
546     private OvsdbTerminationPointAugmentationBuilder createGenericOvsdbTerminationPointAugmentationBuilder() {
547         OvsdbTerminationPointAugmentationBuilder ovsdbTerminationPointAugmentationBuilder =
548                 new OvsdbTerminationPointAugmentationBuilder();
549         ovsdbTerminationPointAugmentationBuilder.setInterfaceType(
550                 new InterfaceTypeEntryBuilder()
551                         .setInterfaceType(
552                                 SouthboundMapper.createInterfaceType("internal"))
553                         .build().getInterfaceType());
554         return ovsdbTerminationPointAugmentationBuilder;
555     }
556
557     private OvsdbTerminationPointAugmentationBuilder createGenericDpdkOvsdbTerminationPointAugmentationBuilder(
558             final String portName) {
559         OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
560                 createGenericOvsdbTerminationPointAugmentationBuilder();
561         ovsdbTerminationBuilder.setName(portName);
562         Class<? extends InterfaceTypeBase> ifType = SouthboundConstants.OVSDB_INTERFACE_TYPE_MAP
563                 .get("dpdk");
564         ovsdbTerminationBuilder.setInterfaceType(ifType);
565         return ovsdbTerminationBuilder;
566     }
567
568     private boolean addTerminationPoint(final NodeId bridgeNodeId, final String portName,
569                                         final OvsdbTerminationPointAugmentationBuilder
570                                                 ovsdbTerminationPointAugmentationBuilder)
571             throws InterruptedException {
572
573         InstanceIdentifier<Node> portIid = SouthboundMapper.createInstanceIdentifier(bridgeNodeId);
574         NodeBuilder portNodeBuilder = new NodeBuilder();
575         NodeId portNodeId = SouthboundMapper.createManagedNodeId(portIid);
576         portNodeBuilder.setNodeId(portNodeId);
577         TerminationPointBuilder entry = new TerminationPointBuilder();
578         entry.setKey(new TerminationPointKey(new TpId(portName)));
579         entry.addAugmentation(
580                 OvsdbTerminationPointAugmentation.class,
581                 ovsdbTerminationPointAugmentationBuilder.build());
582         portNodeBuilder.setTerminationPoint(Lists.newArrayList(entry.build()));
583         boolean result = mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
584                 portIid, portNodeBuilder.build());
585         Thread.sleep(OVSDB_UPDATE_TIMEOUT);
586         return result;
587     }
588
589     /*
590      * base method for adding test bridges.  Other helper methods used to create bridges should utilize this method.
591      *
592      * @param connectionInfo
593      * @param bridgeIid if passed null, one is created
594      * @param bridgeName cannot be null
595      * @param bridgeNodeId if passed null, one is created based on <code>bridgeIid</code>
596      * @param setProtocolEntries toggles whether default protocol entries are set for the bridge
597      * @param failMode toggles whether default fail mode is set for the bridge
598      * @param setManagedBy toggles whether to setManagedBy for the bridge
599      * @param dpType if passed null, this parameter is ignored
600      * @param externalIds if passed null, this parameter is ignored
601      * @param otherConfig if passed null, this parameter is ignored
602      * @return success of bridge addition
603      * @throws InterruptedException
604      */
605     private boolean addBridge(final ConnectionInfo connectionInfo, InstanceIdentifier<Node> bridgeIid,
606                               final String bridgeName, NodeId bridgeNodeId, final boolean setProtocolEntries,
607                               final Class<? extends OvsdbFailModeBase> failMode, final boolean setManagedBy,
608                               final Class<? extends DatapathTypeBase> dpType,
609                               final List<BridgeExternalIds> externalIds,
610                               final List<ControllerEntry> controllerEntries,
611                               final List<BridgeOtherConfigs> otherConfigs) throws InterruptedException {
612
613         NodeBuilder bridgeNodeBuilder = new NodeBuilder();
614         if (bridgeIid == null) {
615             bridgeIid = createInstanceIdentifier(connectionInfo, new OvsdbBridgeName(bridgeName));
616         }
617         if (bridgeNodeId == null) {
618             bridgeNodeId = SouthboundMapper.createManagedNodeId(bridgeIid);
619         }
620         bridgeNodeBuilder.setNodeId(bridgeNodeId);
621         OvsdbBridgeAugmentationBuilder ovsdbBridgeAugmentationBuilder = new OvsdbBridgeAugmentationBuilder();
622         ovsdbBridgeAugmentationBuilder.setBridgeName(new OvsdbBridgeName(bridgeName));
623         if (setProtocolEntries) {
624             ovsdbBridgeAugmentationBuilder.setProtocolEntry(createMdsalProtocols());
625         }
626         if (failMode != null) {
627             ovsdbBridgeAugmentationBuilder.setFailMode(failMode);
628         }
629         if (setManagedBy) {
630             setManagedBy(ovsdbBridgeAugmentationBuilder, connectionInfo);
631         }
632         if (dpType != null) {
633             ovsdbBridgeAugmentationBuilder.setDatapathType(dpType);
634         }
635         if (externalIds != null) {
636             ovsdbBridgeAugmentationBuilder.setBridgeExternalIds(externalIds);
637         }
638         if (controllerEntries != null) {
639             ovsdbBridgeAugmentationBuilder.setControllerEntry(controllerEntries);
640         }
641         if (otherConfigs != null) {
642             ovsdbBridgeAugmentationBuilder.setBridgeOtherConfigs(otherConfigs);
643         }
644         bridgeNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class, ovsdbBridgeAugmentationBuilder.build());
645         LOG.debug("Built with the intent to store bridge data {}",
646                 ovsdbBridgeAugmentationBuilder.toString());
647         boolean result = mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
648                 bridgeIid, bridgeNodeBuilder.build());
649         Thread.sleep(OVSDB_UPDATE_TIMEOUT);
650         return result;
651     }
652
653     private boolean addBridge(final ConnectionInfo connectionInfo, final String bridgeName)
654             throws InterruptedException {
655
656         return addBridge(connectionInfo, null, bridgeName, null, true,
657                 SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"), true, null, null, null, null);
658     }
659
660     private OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo) {
661         return getBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME);
662     }
663
664     /**
665      * Extract the <code>store</code> type data store contents for the particular bridge identified by
666      * <code>bridgeName</code>.
667      *
668      * @param connectionInfo
669      * @param bridgeName
670      * @param store defined by the <code>LogicalDatastoreType</code> enumeration
671      * @return <code>store</code> type data store contents
672      */
673     private OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo, String bridgeName,
674                                               LogicalDatastoreType store) {
675         Node bridgeNode = getBridgeNode(connectionInfo, bridgeName, store);
676         Assert.assertNotNull(bridgeNode);
677         OvsdbBridgeAugmentation ovsdbBridgeAugmentation = bridgeNode.getAugmentation(OvsdbBridgeAugmentation.class);
678         Assert.assertNotNull(ovsdbBridgeAugmentation);
679         return ovsdbBridgeAugmentation;
680     }
681
682     /**
683      * extract the <code>LogicalDataStoreType.OPERATIONAL</code> type data store contents for the particular bridge
684      * identified by <code>bridgeName</code>
685      *
686      * @param connectionInfo
687      * @param bridgeName
688      * @see <code>SouthboundIT.getBridge(ConnectionInfo, String, LogicalDatastoreType)</code>
689      * @return <code>LogicalDatastoreType.OPERATIONAL</code> type data store contents
690      */
691     private OvsdbBridgeAugmentation getBridge(ConnectionInfo connectionInfo, String bridgeName) {
692         return getBridge(connectionInfo, bridgeName, LogicalDatastoreType.OPERATIONAL);
693     }
694
695     /**
696      * Extract the node contents from <code>store</code> type data store for the
697      * bridge identified by <code>bridgeName</code>
698      *
699      * @param connectionInfo
700      * @param bridgeName
701      * @param store defined by the <code>LogicalDatastoreType</code> enumeration
702      * @return <code>store</code> type data store contents
703      */
704     private Node getBridgeNode(ConnectionInfo connectionInfo, String bridgeName, LogicalDatastoreType store) {
705         InstanceIdentifier<Node> bridgeIid =
706                 createInstanceIdentifier(connectionInfo,
707                         new OvsdbBridgeName(bridgeName));
708         return mdsalUtils.read(store, bridgeIid);
709     }
710
711     /**
712      * Extract the node contents from <code>LogicalDataStoreType.OPERATIONAL</code> data store for the
713      * bridge identified by <code>bridgeName</code>
714      *
715      * @param connectionInfo
716      * @param bridgeName
717      * @return <code>LogicalDatastoreType.OPERATIONAL</code> type data store contents
718      */
719     private Node getBridgeNode(ConnectionInfo connectionInfo, String bridgeName) {
720         return getBridgeNode(connectionInfo, bridgeName, LogicalDatastoreType.OPERATIONAL);
721     }
722
723     private boolean deleteBridge(ConnectionInfo connectionInfo) throws InterruptedException {
724         return deleteBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME);
725     }
726
727     private boolean deleteBridge(final ConnectionInfo connectionInfo, final String bridgeName)
728             throws InterruptedException {
729
730         boolean result = mdsalUtils.delete(LogicalDatastoreType.CONFIGURATION,
731                 createInstanceIdentifier(connectionInfo,
732                         new OvsdbBridgeName(bridgeName)));
733         Thread.sleep(OVSDB_UPDATE_TIMEOUT);
734         return result;
735     }
736
737     @Test
738     public void testAddDeleteBridge() throws InterruptedException {
739         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
740         Node ovsdbNode = connectOvsdbNode(connectionInfo);
741
742         Assert.assertTrue(addBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME));
743         OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
744         Assert.assertNotNull(bridge);
745         LOG.info("bridge: {}", bridge);
746
747         Assert.assertTrue(deleteBridge(connectionInfo));
748
749         Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
750         //Assume.assumeTrue(disconnectOvsdbNode(connectionInfo));
751     }
752
753     private InstanceIdentifier<Node> getTpIid(ConnectionInfo connectionInfo, OvsdbBridgeAugmentation bridge) {
754         return createInstanceIdentifier(connectionInfo,
755                 bridge.getBridgeName());
756     }
757
758     /**
759      * Extracts the <code>TerminationPointAugmentation</code> for the <code>index</code> <code>TerminationPoint</code>
760      * on <code>bridgeName</code>
761      *
762      * @param connectionInfo
763      * @param bridgeName
764      * @param store
765      * @param index
766      * @return
767      */
768     private OvsdbTerminationPointAugmentation getOvsdbTerminationPointAugmentation(
769             ConnectionInfo connectionInfo, String bridgeName, LogicalDatastoreType store, int index ) {
770
771         List<TerminationPoint> tpList = getBridgeNode(connectionInfo, bridgeName, store).getTerminationPoint();
772         if (tpList == null) {
773             return null;
774         }
775         return ((OvsdbTerminationPointAugmentation)
776                 tpList.get(index)
777                         .getAugmentation(OvsdbTerminationPointAugmentation.class));
778     }
779
780     @Test
781     public void testCRDTerminationPointOfPort() throws InterruptedException {
782         final Long OFPORT_EXPECTED = new Long(45002);
783
784         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
785         connectOvsdbNode(connectionInfo);
786
787         // CREATE
788         Assert.assertTrue(addBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME));
789         OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
790         Assert.assertNotNull(bridge);
791         LOG.info("bridge: {}", bridge);
792         NodeId nodeId = SouthboundMapper.createManagedNodeId(createInstanceIdentifier(
793                 connectionInfo, bridge.getBridgeName()));
794         OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
795                 createGenericOvsdbTerminationPointAugmentationBuilder();
796         String portName = "testOfPort";
797         ovsdbTerminationBuilder.setName(portName);
798
799         ovsdbTerminationBuilder.setOfport(OFPORT_EXPECTED);
800         Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
801         InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
802         Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
803         Assert.assertNotNull(terminationPointNode);
804
805         // READ
806         List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
807         for (TerminationPoint terminationPoint : terminationPoints) {
808             OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
809                     terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
810             if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
811                 Long ofPort = ovsdbTerminationPointAugmentation.getOfport();
812                 // if ephemeral port 45002 is in use, ofPort is set to 1
813                 Assert.assertTrue(ofPort.equals(OFPORT_EXPECTED) || ofPort.equals(new Long(1)));
814                 LOG.info("ofPort: {}", ofPort);
815             }
816         }
817
818         // UPDATE- Not Applicable.  From the OpenVSwitch Documentation:
819         //   "A client should ideally set this column’s value in the same database transaction that it uses to create
820         //   the interface."
821
822         // DELETE
823         Assert.assertTrue(deleteBridge(connectionInfo));
824         Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
825     }
826
827     @Test
828     public void testCRDTerminationPointOfPortRequest() throws InterruptedException {
829         final Long OFPORT_EXPECTED = new Long(45008);
830         final Long OFPORT_INPUT = new Long(45008);
831
832         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
833         connectOvsdbNode(connectionInfo);
834
835         // CREATE
836         Assert.assertTrue(addBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME));
837         OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
838         Assert.assertNotNull(bridge);
839         NodeId nodeId = createManagedNodeId(createInstanceIdentifier(
840                 connectionInfo, bridge.getBridgeName()));
841         OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
842                 createGenericOvsdbTerminationPointAugmentationBuilder();
843         String portName = "testOfPortRequest";
844         ovsdbTerminationBuilder.setName(portName);
845         Integer ofPortRequestExpected = OFPORT_EXPECTED.intValue();
846         ovsdbTerminationBuilder.setOfport(OFPORT_INPUT);
847         ovsdbTerminationBuilder.setOfportRequest(ofPortRequestExpected);
848         Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
849         InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
850         Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
851         Assert.assertNotNull(terminationPointNode);
852
853         // READ
854         List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
855         for (TerminationPoint terminationPoint : terminationPoints) {
856             OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
857                     terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
858             if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
859                 Long ofPort = ovsdbTerminationPointAugmentation.getOfport();
860                 // if ephemeral port 45008 is in use, ofPort is set to 1
861                 Assert.assertTrue(ofPort.equals(OFPORT_EXPECTED) || ofPort.equals(new Long(1)));
862                 LOG.info("ofPort: {}", ofPort);
863
864                 Integer ofPortRequest = ovsdbTerminationPointAugmentation.getOfportRequest();
865                 Assert.assertTrue(ofPortRequest.equals(ofPortRequestExpected));
866                 LOG.info("ofPortRequest: {}", ofPortRequest);
867             }
868         }
869
870         // UPDATE- Not Applicable.  From the OpenVSwitch documentation:
871         //   "A client should ideally set this column’s value in the same database transaction that it uses to create
872         //   the interface. "
873
874         // DELETE
875         Assert.assertTrue(deleteBridge(connectionInfo));
876         Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
877     }
878
879     /*
880      * Generates the test cases involved in testing PortExternalIds.  See inline comments for descriptions of
881      * the particular cases considered.
882      *
883      * The return value is a Map in the form (K,V)=(testCaseName,testCase).
884      * - testCaseName is a String
885      * - testCase is a Map in the form (K,V) s.t. K=(EXPECTED_VALUES_KEY|INPUT_VALUES_KEY) and V is a List of
886      *     either corresponding INPUT port external_ids, or EXPECTED port external_ids
887      *     INPUT    is the List we use when calling
888      *              <code>TerminationPointAugmentationBuilder.setPortExternalIds()</code>
889      *     EXPECTED is the List we expect to receive after calling
890      *              <code>TerminationPointAugmentationBuilder.getPortExternalIds()</code>
891      */
892     private Map<String, Map<String, List<PortExternalIds>>> generatePortExternalIdsTestCases() {
893         Map<String, Map<String, List<PortExternalIds>>> testMap =
894                 new HashMap<String, Map<String, List<PortExternalIds>>>();
895
896         final String PORT_EXTERNAL_ID_KEY = "PortExternalIdKey";
897         final String PORT_EXTERNAL_ID_VALUE = "PortExternalIdValue";
898         final String FORMAT_STR = "%s_%s_%d";
899         final String GOOD_KEY = "GoodKey";
900         final String GOOD_VALUE = "GoodValue";
901         final String NO_VALUE_FOR_KEY = "NoValueForKey";
902         final String NO_KEY_FOR_VALUE = "NoKeyForValue";
903
904         // Test Case 1:  TestOneExternalId
905         // Test Type:    Positive
906         // Description:  Create a termination point with one PortExternalIds
907         // Expected:     A port is created with the single external_ids specified below
908         final String testOneExternalIdName = "TestOneExternalId";
909         int externalIdCounter = 0;
910         List<PortExternalIds> oneExternalId = (List<PortExternalIds>) Lists.newArrayList(
911                 (new PortExternalIdsBuilder()
912                         .setExternalIdKey(String.format(FORMAT_STR, testOneExternalIdName,
913                                 PORT_EXTERNAL_ID_KEY, ++externalIdCounter))
914                         .setExternalIdValue(String.format(FORMAT_STR, testOneExternalIdName,
915                                 PORT_EXTERNAL_ID_VALUE, externalIdCounter))
916                         .build()));
917         Map<String,List<PortExternalIds>> testCase = Maps.newHashMap();
918         testCase.put(EXPECTED_VALUES_KEY, oneExternalId);
919         testCase.put(INPUT_VALUES_KEY, oneExternalId);
920         testMap.put(testOneExternalIdName, testCase);
921
922         // Test Case 2:  TestFiveExternalId
923         // Test Type:    Positive
924         // Description:  Create a termination point with multiple (five) PortExternalIds
925         // Expected:     A port is created with the five external_ids specified below
926         final String testFiveExternalIdName = "TestFiveExternalId";
927         externalIdCounter = 0;
928         List<PortExternalIds> fiveExternalId = (List<PortExternalIds>) Lists.newArrayList(
929                 (new PortExternalIdsBuilder()
930                         .setExternalIdKey(String.format(FORMAT_STR, testFiveExternalIdName,
931                                 PORT_EXTERNAL_ID_KEY, ++externalIdCounter))
932                         .setExternalIdValue(String.format(FORMAT_STR, testFiveExternalIdName,
933                                 PORT_EXTERNAL_ID_VALUE, externalIdCounter))
934                         .build()),
935                 (new PortExternalIdsBuilder()
936                         .setExternalIdKey(String.format(FORMAT_STR, testFiveExternalIdName,
937                                 PORT_EXTERNAL_ID_KEY, ++externalIdCounter))
938                         .setExternalIdValue(String.format(FORMAT_STR, testFiveExternalIdName,
939                                 PORT_EXTERNAL_ID_VALUE, externalIdCounter))
940                         .build()),
941                 (new PortExternalIdsBuilder()
942                         .setExternalIdKey(String.format(FORMAT_STR, testFiveExternalIdName,
943                                 PORT_EXTERNAL_ID_KEY, ++externalIdCounter))
944                         .setExternalIdValue(String.format(FORMAT_STR, testFiveExternalIdName,
945                                 PORT_EXTERNAL_ID_VALUE, externalIdCounter))
946                         .build()),
947                 (new PortExternalIdsBuilder()
948                         .setExternalIdKey(String.format(FORMAT_STR, testFiveExternalIdName,
949                                 PORT_EXTERNAL_ID_KEY, ++externalIdCounter))
950                         .setExternalIdValue(String.format(FORMAT_STR, testFiveExternalIdName,
951                                 PORT_EXTERNAL_ID_VALUE, externalIdCounter))
952                         .build()),
953                 (new PortExternalIdsBuilder()
954                         .setExternalIdKey(String.format(FORMAT_STR, testFiveExternalIdName,
955                                 PORT_EXTERNAL_ID_KEY, ++externalIdCounter))
956                         .setExternalIdValue(String.format(FORMAT_STR, testFiveExternalIdName,
957                                 PORT_EXTERNAL_ID_VALUE, externalIdCounter))
958                         .build()));
959         testCase = Maps.newHashMap();
960         testCase.put(EXPECTED_VALUES_KEY, fiveExternalId);
961         testCase.put(INPUT_VALUES_KEY, fiveExternalId);
962         testMap.put(testFiveExternalIdName, testCase);
963
964         // Test Case 3:  TestOneGoodExternalIdOneMalformedExternalIdValue
965         // Test Type:    Negative
966         // Description:
967         //     One perfectly fine PortExternalId
968         //        (TestOneGoodExternalIdOneMalformedExternalIdValue_PortExternalIdKey_1,
969         //        TestOneGoodExternalIdOneMalformedExternalId_PortExternalIdValue_1)
970         //     and one malformed PortExternalId which only has key specified
971         //        (TestOneGoodExternalIdOneMalformedExternalIdValue_NoValueForKey_2,
972         //        UNSPECIFIED)
973         // Expected:     A port is created without any external_ids
974         final String testOneGoodExternalIdOneMalformedExternalIdValueName =
975                 "TestOneGoodExternalIdOneMalformedExternalIdValue";
976         externalIdCounter = 0;
977         PortExternalIds oneGood = new PortExternalIdsBuilder()
978                 .setExternalIdKey(String.format(FORMAT_STR, testOneGoodExternalIdOneMalformedExternalIdValueName,
979                         GOOD_KEY, ++externalIdCounter))
980                 .setExternalIdValue(String.format(FORMAT_STR,
981                         testOneGoodExternalIdOneMalformedExternalIdValueName,
982                         GOOD_VALUE, externalIdCounter))
983                 .build();
984         PortExternalIds oneBad = new PortExternalIdsBuilder()
985                 .setExternalIdKey(String.format(FORMAT_STR,
986                         testOneGoodExternalIdOneMalformedExternalIdValueName, NO_VALUE_FOR_KEY, ++externalIdCounter))
987                 .build();
988         List<PortExternalIds> oneGoodOneBadInput = (List<PortExternalIds>) Lists.newArrayList(
989                 oneGood, oneBad);
990         List<PortExternalIds> oneGoodOneBadExpected = null;
991         testCase = Maps.newHashMap();
992         testCase.put(INPUT_VALUES_KEY, oneGoodOneBadInput);
993         testCase.put(EXPECTED_VALUES_KEY, oneGoodOneBadExpected);
994         testMap.put(testOneGoodExternalIdOneMalformedExternalIdValueName, testCase);
995
996         // Test Case 4:  TestOneGoodExternalIdOneMalformedExternalIdKey
997         // Test Type:    Negative
998         // Description:
999         //     One perfectly fine PortExternalId
1000         //        (TestOneGoodExternalIdOneMalformedExternalIdValue_PortExternalIdKey_1,
1001         //        TestOneGoodExternalIdOneMalformedExternalId_PortExternalIdValue_1)
1002         //     and one malformed PortExternalId which only has key specified
1003         //        (UNSPECIFIED,
1004         //        TestOneGoodExternalIdOneMalformedExternalIdKey_NoKeyForValue_2)
1005         // Expected:     A port is created without any external_ids
1006         final String testOneGoodExternalIdOneMalformedExternalIdKeyName =
1007                 "TestOneGoodExternalIdOneMalformedExternalIdKey";
1008         externalIdCounter = 0;
1009         oneGood = new PortExternalIdsBuilder()
1010                 .setExternalIdKey(String.format(FORMAT_STR, testOneGoodExternalIdOneMalformedExternalIdKeyName,
1011                         GOOD_KEY, ++externalIdCounter))
1012                 .setExternalIdValue(String.format(FORMAT_STR,
1013                         testOneGoodExternalIdOneMalformedExternalIdKeyName,
1014                         GOOD_VALUE, externalIdCounter))
1015                 .build();
1016         oneBad = new PortExternalIdsBuilder()
1017                 .setExternalIdKey(String.format(FORMAT_STR,
1018                         testOneGoodExternalIdOneMalformedExternalIdKeyName, NO_KEY_FOR_VALUE, ++externalIdCounter))
1019                 .build();
1020         oneGoodOneBadInput = (List<PortExternalIds>) Lists.newArrayList(
1021                 oneGood, oneBad);
1022         oneGoodOneBadExpected = null;
1023         testCase = Maps.newHashMap();
1024         testCase.put(INPUT_VALUES_KEY, oneGoodOneBadInput);
1025         testCase.put(EXPECTED_VALUES_KEY, oneGoodOneBadExpected);
1026         testMap.put(testOneGoodExternalIdOneMalformedExternalIdKeyName, testCase);
1027
1028         return testMap;
1029     }
1030
1031     /*
1032      * @see <code>SouthboundIT.testCRUDPortExternalIds()</code>
1033      * This is helper test method to compare a test "set" of BridgeExternalIds against an expected "set"
1034      */
1035     private void assertExpectedPortExternalIdsExist( List<PortExternalIds> expected,
1036                                                      List<PortExternalIds> test ) {
1037
1038         if (expected != null) {
1039             for (PortExternalIds expectedExternalId : expected) {
1040                 Assert.assertTrue(test.contains(expectedExternalId));
1041             }
1042         }
1043     }
1044
1045     /*
1046      * Tests the CRUD operations for <code>Port</code>
1047      * <code>external_ids</code>.
1048      *
1049      * @see <code>SouthboundIT.generatePortExternalIdsTestCases()</code> for
1050      * specific test case information
1051      */
1052     @Test
1053     public void testCRUDTerminationPointPortExternalIds()
1054             throws InterruptedException, ExecutionException {
1055
1056         final String TEST_PREFIX = "CRUDTPPortExternalIds";
1057
1058         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
1059         connectOvsdbNode(connectionInfo);
1060
1061         // updateFromTestCases represent the original test case value.
1062         // updateToTestCases represent the new value after the update has been
1063         // performed.
1064         Map<String, Map<String, List<PortExternalIds>>> updateFromTestCases =
1065                 generatePortExternalIdsTestCases();
1066         Map<String, Map<String, List<PortExternalIds>>> updateToTestCases =
1067                 generatePortExternalIdsTestCases();
1068         Map<String, List<PortExternalIds>> updateFromTestCase;
1069         List<PortExternalIds> updateFromInputExternalIds;
1070         List<PortExternalIds> updateFromExpectedExternalIds;
1071         Map<String, List<PortExternalIds>> updateToTestCase;
1072         List<PortExternalIds> updateToInputExternalIds;
1073         List<PortExternalIds> updateToExpectedExternalIds;
1074         String testBridgeName;
1075         String testPortName;
1076
1077         int counter = 1;
1078         // multihreads the test using NUM_THREADS
1079         ExecutorService executor = Executors.newFixedThreadPool(NUM_THREADS);
1080         for (String updateFromTestCaseKey : updateFromTestCases.keySet()) {
1081             updateFromTestCase = updateFromTestCases.get(
1082                     updateFromTestCaseKey);
1083             updateFromInputExternalIds = updateFromTestCase.get(
1084                     INPUT_VALUES_KEY);
1085             updateFromExpectedExternalIds = updateFromTestCase.get(
1086                     EXPECTED_VALUES_KEY);
1087             for (String testCaseKey : updateToTestCases.keySet()) {
1088                 testPortName = testBridgeName = String.format("%s_%s_%d",
1089                         TEST_PREFIX, testCaseKey, counter);
1090                 counter += 1;
1091                 updateToTestCase = updateToTestCases.get(testCaseKey);
1092                 updateToInputExternalIds = updateToTestCase.get(
1093                         INPUT_VALUES_KEY);
1094                 updateToExpectedExternalIds = updateToTestCase.get(
1095                         EXPECTED_VALUES_KEY);
1096                 TestCRUDTerminationPointPortExternalIdsRunnable testRunnable =
1097                         new TestCRUDTerminationPointPortExternalIdsRunnable(
1098                                 connectionInfo, testBridgeName, testPortName,
1099                                 updateFromInputExternalIds,
1100                                 updateFromExpectedExternalIds,
1101                                 updateToInputExternalIds,
1102                                 updateToExpectedExternalIds);
1103                 executor.submit(testRunnable);
1104             }
1105         }
1106         executor.shutdown();
1107         executor.awaitTermination(5, TimeUnit.MINUTES);
1108         Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
1109     }
1110
1111     class TestCRUDTerminationPointPortExternalIdsRunnable implements Runnable {
1112         ConnectionInfo connectionInfo;
1113         String testBridgeName;
1114         String testPortName;
1115         List<PortExternalIds> updateFromInputExternalIds;
1116         List<PortExternalIds> updateFromExpectedExternalIds;
1117         List<PortExternalIds> updateToInputExternalIds;
1118         List<PortExternalIds> updateToExpectedExternalIds;
1119
1120         public TestCRUDTerminationPointPortExternalIdsRunnable(
1121                 ConnectionInfo connectionInfo,
1122                 String testBridgeName, String testPortName,
1123                 List<PortExternalIds> updateFromInputExternalIds,
1124                 List<PortExternalIds> updateFromExpectedExternalIds,
1125                 List<PortExternalIds> updateToInputExternalIds,
1126                 List<PortExternalIds> updateToExpectedExternalIds) {
1127
1128             this.connectionInfo = connectionInfo;
1129             this.testBridgeName = testBridgeName;
1130             this.testPortName = testPortName;
1131             this.updateFromInputExternalIds = updateFromInputExternalIds;
1132             this.updateFromExpectedExternalIds = updateFromExpectedExternalIds;
1133             this.updateToInputExternalIds = updateToInputExternalIds;
1134             this.updateToExpectedExternalIds = updateToExpectedExternalIds;
1135         }
1136
1137         @Override
1138         public void run() {
1139             try {
1140                 test();
1141             } catch (InterruptedException e) {
1142                 e.printStackTrace();
1143             }
1144         }
1145
1146         private void test() throws InterruptedException {
1147
1148             final int TERMINATION_POINT_TEST_INDEX = 0;
1149             // CREATE: Create the test bridge
1150             Assert.assertTrue(addBridge(connectionInfo, null,
1151                     testBridgeName, null, true,
1152                     SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"),
1153                     true, null, null, null, null));
1154             NodeId testBridgeNodeId = createManagedNodeId(createInstanceIdentifier(
1155                     connectionInfo, new OvsdbBridgeName(testBridgeName)));
1156             OvsdbTerminationPointAugmentationBuilder tpCreateAugmentationBuilder =
1157                     createGenericOvsdbTerminationPointAugmentationBuilder();
1158             tpCreateAugmentationBuilder.setName(testPortName);
1159             tpCreateAugmentationBuilder.setPortExternalIds(updateFromInputExternalIds);
1160             Assert.assertTrue(addTerminationPoint(testBridgeNodeId, testPortName, tpCreateAugmentationBuilder));
1161
1162             // READ: Read the test port and ensure changes are propagated to the CONFIGURATION data store,
1163             // then repeat for OPERATIONAL data store
1164             OvsdbTerminationPointAugmentation updateFromConfigurationTerminationPointAugmentation =
1165                     getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeName,
1166                             LogicalDatastoreType.CONFIGURATION, TERMINATION_POINT_TEST_INDEX);
1167             List<PortExternalIds> updateFromConfigurationExternalIds =
1168                     updateFromConfigurationTerminationPointAugmentation
1169                             .getPortExternalIds();
1170             assertExpectedPortExternalIdsExist(updateFromExpectedExternalIds, updateFromConfigurationExternalIds);
1171             OvsdbTerminationPointAugmentation updateFromOperationalTerminationPointAugmenation =
1172                     getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeName,
1173                             LogicalDatastoreType.OPERATIONAL, TERMINATION_POINT_TEST_INDEX);
1174             List<PortExternalIds> updateFromOperationalExternalIds = updateFromOperationalTerminationPointAugmenation
1175                     .getPortExternalIds();
1176             assertExpectedPortExternalIdsExist(updateFromExpectedExternalIds, updateFromOperationalExternalIds);
1177
1178             // UPDATE:  update the external_ids
1179             testBridgeNodeId = getBridgeNode(connectionInfo, testBridgeName).getNodeId();
1180             OvsdbTerminationPointAugmentationBuilder tpUpdateAugmentationBuilder =
1181                     new OvsdbTerminationPointAugmentationBuilder();
1182             tpUpdateAugmentationBuilder.setPortExternalIds(updateToInputExternalIds);
1183             InstanceIdentifier portIid = SouthboundMapper.createInstanceIdentifier(testBridgeNodeId);
1184             NodeBuilder portUpdateNodeBuilder = new NodeBuilder();
1185             NodeId portUpdateNodeId = createManagedNodeId(portIid);
1186             portUpdateNodeBuilder.setNodeId(portUpdateNodeId);
1187             TerminationPointBuilder tpUpdateBuilder = new TerminationPointBuilder();
1188             tpUpdateBuilder.setKey(new TerminationPointKey(new TpId(testPortName)));
1189             tpUpdateBuilder.addAugmentation(
1190                     OvsdbTerminationPointAugmentation.class,
1191                     tpUpdateAugmentationBuilder.build());
1192             portUpdateNodeBuilder.setTerminationPoint(Lists.newArrayList(tpUpdateBuilder.build()));
1193             boolean result = mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
1194                     portIid, portUpdateNodeBuilder.build());
1195             Thread.sleep(OVSDB_UPDATE_TIMEOUT);
1196             Assert.assertTrue(result);
1197
1198             // READ: the test port and ensure changes are propagated to the CONFIGURATION data store,
1199             // then repeat for OPERATIONAL data store
1200             OvsdbTerminationPointAugmentation updateToConfigurationTerminationPointAugmentation =
1201                     getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeName,
1202                             LogicalDatastoreType.CONFIGURATION, TERMINATION_POINT_TEST_INDEX);
1203             List<PortExternalIds> updateToConfigurationExternalIds = updateToConfigurationTerminationPointAugmentation
1204                     .getPortExternalIds();
1205             assertExpectedPortExternalIdsExist(updateToExpectedExternalIds, updateToConfigurationExternalIds);
1206             assertExpectedPortExternalIdsExist(updateFromExpectedExternalIds, updateToConfigurationExternalIds);
1207             OvsdbTerminationPointAugmentation updateToOperationalTerminationPointAugmentation =
1208                     getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeName,
1209                             LogicalDatastoreType.OPERATIONAL, TERMINATION_POINT_TEST_INDEX);
1210             List<PortExternalIds> updateToOperationalExternalIds =
1211                     updateToOperationalTerminationPointAugmentation.getPortExternalIds();
1212             if (updateFromExpectedExternalIds != null) {
1213                 assertExpectedPortExternalIdsExist(updateToExpectedExternalIds, updateToOperationalExternalIds);
1214                 assertExpectedPortExternalIdsExist(updateFromExpectedExternalIds, updateToOperationalExternalIds);
1215             }
1216
1217             // DELETE
1218             Assert.assertTrue(deleteBridge(connectionInfo, testBridgeName));
1219         }
1220     }
1221
1222
1223
1224     /*
1225      * Generates the test cases involved in testing InterfaceExternalIds.  See inline comments for descriptions of
1226      * the particular cases considered.
1227      *
1228      * The return value is a Map in the form (K,V)=(testCaseName,testCase).
1229      * - testCaseName is a String
1230      * - testCase is a Map in the form (K,V) s.t. K=(EXPECTED_VALUES_KEY|INPUT_VALUES_KEY) and V is a List of
1231      *     either corresponding INPUT interface external_ids, or EXPECTED interface external_ids
1232      *     INPUT    is the List we use when calling
1233      *              <code>TerminationPointAugmentationBuilder.setInterfaceExternalIds()</code>
1234      *     EXPECTED is the List we expect to receive after calling
1235      *              <code>TerminationPointAugmentationBuilder.getInterfaceExternalIds()</code>
1236      */
1237     private Map<String, Map<String, List<InterfaceExternalIds>>> generateInterfaceExternalIdsTestCases() {
1238         Map<String, Map<String, List<InterfaceExternalIds>>> testMap =
1239                 new HashMap<String, Map<String, List<InterfaceExternalIds>>>();
1240
1241         final String INTERFACE_EXTERNAL_ID_KEY = "IntExternalIdKey";
1242         final String INTERFACE_EXTERNAL_ID_VALUE = "IntExternalIdValue";
1243         final String FORMAT_STR = "%s_%s_%d";
1244         final String GOOD_KEY = "GoodKey";
1245         final String GOOD_VALUE = "GoodValue";
1246         final String NO_VALUE_FOR_KEY = "NoValueForKey";
1247         final String NO_KEY_FOR_VALUE = "NoKeyForValue";
1248
1249         // Test Case 1:  TestOneExternalId
1250         // Test Type:    Positive
1251         // Description:  Create a termination point with one InterfaceExternalIds
1252         // Expected:     A termination point is created with the single external_ids specified below
1253         final String testOneExternalIdName = "TestOneExternalId";
1254         int externalIdCounter = 0;
1255         List<InterfaceExternalIds> oneExternalId = (List<InterfaceExternalIds>) Lists.newArrayList(
1256                 (new InterfaceExternalIdsBuilder()
1257                         .setExternalIdKey(String.format(FORMAT_STR, testOneExternalIdName,
1258                                 INTERFACE_EXTERNAL_ID_KEY, ++externalIdCounter))
1259                         .setExternalIdValue(String.format(FORMAT_STR, testOneExternalIdName,
1260                                 INTERFACE_EXTERNAL_ID_VALUE, externalIdCounter))
1261                         .build()));
1262         Map<String,List<InterfaceExternalIds>> testCase = Maps.newHashMap();
1263         testCase.put(EXPECTED_VALUES_KEY, oneExternalId);
1264         testCase.put(INPUT_VALUES_KEY, oneExternalId);
1265         testMap.put(testOneExternalIdName, testCase);
1266
1267         // Test Case 2:  TestFiveExternalId
1268         // Test Type:    Positive
1269         // Description:  Create a termination point with multiple (five) InterfaceExternalIds
1270         // Expected:     A termination point is created with the five external_ids specified below
1271         final String testFiveExternalIdName = "TestFiveExternalId";
1272         externalIdCounter = 0;
1273         List<InterfaceExternalIds> fiveExternalId = (List<InterfaceExternalIds>) Lists.newArrayList(
1274                 (new InterfaceExternalIdsBuilder()
1275                         .setExternalIdKey(String.format(FORMAT_STR, testFiveExternalIdName,
1276                                 INTERFACE_EXTERNAL_ID_KEY, ++externalIdCounter))
1277                         .setExternalIdValue(String.format(FORMAT_STR, testFiveExternalIdName,
1278                                 INTERFACE_EXTERNAL_ID_VALUE, externalIdCounter))
1279                         .build()),
1280                 (new InterfaceExternalIdsBuilder()
1281                         .setExternalIdKey(String.format(FORMAT_STR, testFiveExternalIdName,
1282                                 INTERFACE_EXTERNAL_ID_KEY, ++externalIdCounter))
1283                         .setExternalIdValue(String.format(FORMAT_STR, testFiveExternalIdName,
1284                                 INTERFACE_EXTERNAL_ID_VALUE, externalIdCounter))
1285                         .build()),
1286                 (new InterfaceExternalIdsBuilder()
1287                         .setExternalIdKey(String.format(FORMAT_STR, testFiveExternalIdName,
1288                                 INTERFACE_EXTERNAL_ID_KEY, ++externalIdCounter))
1289                         .setExternalIdValue(String.format(FORMAT_STR, testFiveExternalIdName,
1290                                 INTERFACE_EXTERNAL_ID_VALUE, externalIdCounter))
1291                         .build()),
1292                 (new InterfaceExternalIdsBuilder()
1293                         .setExternalIdKey(String.format(FORMAT_STR, testFiveExternalIdName,
1294                                 INTERFACE_EXTERNAL_ID_KEY, ++externalIdCounter))
1295                         .setExternalIdValue(String.format(FORMAT_STR, testFiveExternalIdName,
1296                                 INTERFACE_EXTERNAL_ID_VALUE, externalIdCounter))
1297                         .build()),
1298                 (new InterfaceExternalIdsBuilder()
1299                         .setExternalIdKey(String.format(FORMAT_STR, testFiveExternalIdName,
1300                                 INTERFACE_EXTERNAL_ID_KEY, ++externalIdCounter))
1301                         .setExternalIdValue(String.format(FORMAT_STR, testFiveExternalIdName,
1302                                 INTERFACE_EXTERNAL_ID_VALUE, externalIdCounter))
1303                         .build()));
1304         testCase = Maps.newHashMap();
1305         testCase.put(EXPECTED_VALUES_KEY, fiveExternalId);
1306         testCase.put(INPUT_VALUES_KEY, fiveExternalId);
1307         testMap.put(testFiveExternalIdName, testCase);
1308
1309         // Test Case 3:  TestOneGoodExternalIdOneMalformedExternalIdValue
1310         // Test Type:    Negative
1311         // Description:
1312         //     One perfectly fine InterfaceExternalId
1313         //        (TestOneGoodExternalIdOneMalformedExternalIdValue_IntExternalIdKey_1,
1314         //        TestOneGoodExternalIdOneMalformedExternalId_IntExternalIdValue_1)
1315         //     and one malformed PortExternalId which only has key specified
1316         //        (TestOneGoodExternalIdOneMalformedExternalIdValue_NoValueForKey_2,
1317         //        UNSPECIFIED)
1318         // Expected:     A termination point is created without any external_ids
1319         final String testOneGoodExternalIdOneMalformedExternalIdValueName =
1320                 "TestOneGoodExternalIdOneMalformedExternalIdValue";
1321         externalIdCounter = 0;
1322         InterfaceExternalIds oneGood = new InterfaceExternalIdsBuilder()
1323                 .setExternalIdKey(String.format(FORMAT_STR, testOneGoodExternalIdOneMalformedExternalIdValueName,
1324                         GOOD_KEY, ++externalIdCounter))
1325                 .setExternalIdValue(String.format(FORMAT_STR,
1326                         testOneGoodExternalIdOneMalformedExternalIdValueName,
1327                         GOOD_VALUE, externalIdCounter))
1328                 .build();
1329         InterfaceExternalIds oneBad = new InterfaceExternalIdsBuilder()
1330                 .setExternalIdKey(String.format(FORMAT_STR,
1331                         testOneGoodExternalIdOneMalformedExternalIdValueName, NO_VALUE_FOR_KEY, ++externalIdCounter))
1332                 .build();
1333         List<InterfaceExternalIds> oneGoodOneBadInput = (List<InterfaceExternalIds>) Lists.newArrayList(
1334                 oneGood, oneBad);
1335         List<InterfaceExternalIds> oneGoodOneBadExpected = null;
1336         testCase = Maps.newHashMap();
1337         testCase.put(INPUT_VALUES_KEY, oneGoodOneBadInput);
1338         testCase.put(EXPECTED_VALUES_KEY, oneGoodOneBadExpected);
1339         testMap.put(testOneGoodExternalIdOneMalformedExternalIdValueName, testCase);
1340
1341         // Test Case 4:  TestOneGoodExternalIdOneMalformedExternalIdKey
1342         // Test Type:    Negative
1343         // Description:
1344         //     One perfectly fine InterfaceExternalId
1345         //        (TestOneGoodExternalIdOneMalformedExternalIdValue_IntExternalIdKey_1,
1346         //        TestOneGoodExternalIdOneMalformedExternalId_IntExternalIdValue_1)
1347         //     and one malformed BridgeExternalId which only has key specified
1348         //        (UNSPECIFIED,
1349         //        TestOneGoodExternalIdOneMalformedExternalIdKey_NoKeyForValue_2)
1350         // Expected:     A termination point is created without any external_ids
1351         final String testOneGoodExternalIdOneMalformedExternalIdKeyName =
1352                 "TestOneGoodExternalIdOneMalformedExternalIdKey";
1353         externalIdCounter = 0;
1354         oneGood = new InterfaceExternalIdsBuilder()
1355                 .setExternalIdKey(String.format(FORMAT_STR, testOneGoodExternalIdOneMalformedExternalIdKeyName,
1356                         GOOD_KEY, ++externalIdCounter))
1357                 .setExternalIdValue(String.format(FORMAT_STR,
1358                         testOneGoodExternalIdOneMalformedExternalIdKeyName,
1359                         GOOD_VALUE, externalIdCounter))
1360                 .build();
1361         oneBad = new InterfaceExternalIdsBuilder()
1362                 .setExternalIdKey(String.format(FORMAT_STR,
1363                         testOneGoodExternalIdOneMalformedExternalIdKeyName, NO_KEY_FOR_VALUE, ++externalIdCounter))
1364                 .build();
1365         oneGoodOneBadInput = (List<InterfaceExternalIds>) Lists.newArrayList(
1366                 oneGood, oneBad);
1367         oneGoodOneBadExpected = null;
1368         testCase = Maps.newHashMap();
1369         testCase.put(INPUT_VALUES_KEY, oneGoodOneBadInput);
1370         testCase.put(EXPECTED_VALUES_KEY, oneGoodOneBadExpected);
1371         testMap.put(testOneGoodExternalIdOneMalformedExternalIdKeyName, testCase);
1372
1373         return testMap;
1374     }
1375
1376     /*
1377      * @see <code>SouthboundIT.testCRUDInterfaceExternalIds()</code>
1378      * This is helper test method to compare a test "set" of InterfaceExternalIds against an expected "set"
1379      */
1380     private void assertExpectedInterfaceExternalIdsExist( List<InterfaceExternalIds> expected,
1381                                                           List<InterfaceExternalIds> test ) {
1382
1383         if (expected != null) {
1384             for (InterfaceExternalIds expectedExternalId : expected) {
1385                 Assert.assertTrue(test.contains(expectedExternalId));
1386             }
1387         }
1388     }
1389
1390     /*
1391      * Tests the CRUD operations for <code>Interface</code> <code>external_ids</code>.
1392      *
1393      * @see <code>SouthboundIT.generateInterfaceExternalIdsTestCases()</code> for specific test case information
1394      */
1395     @Test
1396     public void testCRUDTerminationPointInterfaceExternalIds() throws InterruptedException, ExecutionException {
1397         final String TEST_PREFIX = "CRUDTPInterfaceExternalIds";
1398         final int TERMINATION_POINT_TEST_INDEX = 0;
1399
1400         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
1401         connectOvsdbNode(connectionInfo);
1402
1403         // updateFromTestCases represent the original test case value.  updateToTestCases represent the new value after
1404         // the update has been performed.
1405         Map<String, Map<String, List<InterfaceExternalIds>>> updateFromTestCases =
1406                 generateInterfaceExternalIdsTestCases();
1407         Map<String, Map<String, List<InterfaceExternalIds>>> updateToTestCases =
1408                 generateInterfaceExternalIdsTestCases();
1409         Map<String, List<InterfaceExternalIds>> updateFromTestCase;
1410         List<InterfaceExternalIds> updateFromInputExternalIds;
1411         List<InterfaceExternalIds> updateFromExpectedExternalIds;
1412         Map<String, List<InterfaceExternalIds>> updateToTestCase;
1413         List<InterfaceExternalIds> updateToInputExternalIds;
1414         List<InterfaceExternalIds> updateToExpectedExternalIds;
1415         String testBridgeName;
1416         String testPortName;
1417
1418         int counter = 1;
1419         // multihreads the test using NUM_THREADS
1420         ExecutorService executor = Executors.newFixedThreadPool(NUM_THREADS);
1421         for (String updateFromTestCaseKey : updateFromTestCases.keySet()) {
1422             updateFromTestCase = updateFromTestCases.get(updateFromTestCaseKey);
1423             updateFromInputExternalIds = updateFromTestCase.get(INPUT_VALUES_KEY);
1424             updateFromExpectedExternalIds = updateFromTestCase.get(EXPECTED_VALUES_KEY);
1425             for (String testCaseKey : updateToTestCases.keySet()) {
1426                 testPortName = testBridgeName = String.format("%s_%s_%d", TEST_PREFIX, testCaseKey, counter);
1427                 counter += 1;
1428                 updateToTestCase = updateToTestCases.get(testCaseKey);
1429                 updateToInputExternalIds = updateToTestCase.get(INPUT_VALUES_KEY);
1430                 updateToExpectedExternalIds = updateToTestCase.get(EXPECTED_VALUES_KEY);
1431
1432                 TestCRUDTerminationPointInterfaceExternalIdsRunnable testRunnable =
1433                         new TestCRUDTerminationPointInterfaceExternalIdsRunnable(
1434                                 connectionInfo, testBridgeName, testPortName,
1435                                 updateFromInputExternalIds,
1436                                 updateFromExpectedExternalIds,
1437                                 updateToInputExternalIds,
1438                                 updateToExpectedExternalIds);
1439                 executor.submit(testRunnable);
1440             }
1441         }
1442         executor.shutdown();
1443         executor.awaitTermination(5, TimeUnit.MINUTES);
1444         Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
1445     }
1446
1447     class TestCRUDTerminationPointInterfaceExternalIdsRunnable implements Runnable {
1448
1449         ConnectionInfo connectionInfo;
1450         String testBridgeName;
1451         String testPortName;
1452         List<InterfaceExternalIds> updateFromInputExternalIds;
1453         List<InterfaceExternalIds> updateFromExpectedExternalIds;
1454         List<InterfaceExternalIds> updateToInputExternalIds;
1455         List<InterfaceExternalIds> updateToExpectedExternalIds;
1456
1457         TestCRUDTerminationPointInterfaceExternalIdsRunnable(
1458                 ConnectionInfo connectionInfo, String testBridgeName,
1459                 String testPortName,
1460                 List<InterfaceExternalIds> updateFromInputExternalIds,
1461                 List<InterfaceExternalIds> updateFromExpectedExternalIds,
1462                 List<InterfaceExternalIds> updateToInputExternalIds,
1463                 List<InterfaceExternalIds> updateToExpectedExternalIds) {
1464
1465             this.connectionInfo = connectionInfo;
1466             this.testBridgeName = testBridgeName;
1467             this.testPortName = testPortName;
1468             this.updateFromInputExternalIds = updateFromInputExternalIds;
1469             this.updateFromExpectedExternalIds = updateFromExpectedExternalIds;
1470             this.updateToInputExternalIds = updateToInputExternalIds;
1471             this.updateToExpectedExternalIds = updateToExpectedExternalIds;
1472         }
1473
1474         @Override
1475         public void run() {
1476             try {
1477                 test();
1478             } catch (InterruptedException e) {
1479                 e.printStackTrace();
1480             }
1481         }
1482
1483         public void test() throws InterruptedException {
1484
1485             final int TERMINATION_POINT_TEST_INDEX = 0;
1486             // CREATE: Create the test interface
1487             Assert.assertTrue(addBridge(connectionInfo, null,
1488                     testBridgeName, null, true, SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"),
1489                     true, null, null, null, null));
1490             NodeId testBridgeNodeId = createManagedNodeId(createInstanceIdentifier(
1491                     connectionInfo, new OvsdbBridgeName(testBridgeName)));
1492             OvsdbTerminationPointAugmentationBuilder tpCreateAugmentationBuilder =
1493                     createGenericOvsdbTerminationPointAugmentationBuilder();
1494             tpCreateAugmentationBuilder.setName(testPortName);
1495             tpCreateAugmentationBuilder.setInterfaceExternalIds(updateFromInputExternalIds);
1496             Assert.assertTrue(addTerminationPoint(testBridgeNodeId, testPortName, tpCreateAugmentationBuilder));
1497
1498             // READ: Read the test interface and ensure changes are propagated to the CONFIGURATION data store,
1499             // then repeat for OPERATIONAL data store
1500             OvsdbTerminationPointAugmentation updateFromConfigurationTerminationPointAugmentation =
1501                     getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeName,
1502                             LogicalDatastoreType.CONFIGURATION, TERMINATION_POINT_TEST_INDEX);
1503             List<InterfaceExternalIds> updateFromConfigurationExternalIds =
1504                     updateFromConfigurationTerminationPointAugmentation
1505                             .getInterfaceExternalIds();
1506             assertExpectedInterfaceExternalIdsExist(updateFromExpectedExternalIds,
1507                     updateFromConfigurationExternalIds);
1508             OvsdbTerminationPointAugmentation updateFromOperationalTerminationPointAugmenation =
1509                     getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeName,
1510                             LogicalDatastoreType.OPERATIONAL, TERMINATION_POINT_TEST_INDEX);
1511             List<InterfaceExternalIds> updateFromOperationalExternalIds =
1512                     updateFromOperationalTerminationPointAugmenation
1513                             .getInterfaceExternalIds();
1514             assertExpectedInterfaceExternalIdsExist(updateFromExpectedExternalIds,
1515                     updateFromOperationalExternalIds);
1516
1517             // UPDATE:  update the external_ids
1518             testBridgeNodeId = getBridgeNode(connectionInfo, testBridgeName).getNodeId();
1519             OvsdbTerminationPointAugmentationBuilder tpUpdateAugmentationBuilder =
1520                     new OvsdbTerminationPointAugmentationBuilder();
1521             tpUpdateAugmentationBuilder.setInterfaceExternalIds(updateToInputExternalIds);
1522             InstanceIdentifier<Node> portIid = SouthboundMapper.createInstanceIdentifier(testBridgeNodeId);
1523             NodeBuilder portUpdateNodeBuilder = new NodeBuilder();
1524             NodeId portUpdateNodeId = createManagedNodeId(portIid);
1525             portUpdateNodeBuilder.setNodeId(portUpdateNodeId);
1526             TerminationPointBuilder tpUpdateBuilder = new TerminationPointBuilder();
1527             tpUpdateBuilder.setKey(new TerminationPointKey(new TpId(testPortName)));
1528             tpUpdateBuilder.addAugmentation(
1529                     OvsdbTerminationPointAugmentation.class,
1530                     tpUpdateAugmentationBuilder.build());
1531             portUpdateNodeBuilder.setTerminationPoint(Lists.newArrayList(tpUpdateBuilder.build()));
1532             boolean result = mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
1533                     portIid, portUpdateNodeBuilder.build());
1534             Thread.sleep(OVSDB_UPDATE_TIMEOUT);
1535             Assert.assertTrue(result);
1536
1537             // READ: the test interface and ensure changes are propagated to the CONFIGURATION data store,
1538             // then repeat for OPERATIONAL data store
1539             OvsdbTerminationPointAugmentation updateToConfigurationTerminationPointAugmentation =
1540                     getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeName,
1541                             LogicalDatastoreType.CONFIGURATION, TERMINATION_POINT_TEST_INDEX);
1542             List<InterfaceExternalIds> updateToConfigurationExternalIds =
1543                     updateToConfigurationTerminationPointAugmentation
1544                     .getInterfaceExternalIds();
1545             assertExpectedInterfaceExternalIdsExist(updateToExpectedExternalIds, updateToConfigurationExternalIds);
1546             assertExpectedInterfaceExternalIdsExist(updateFromExpectedExternalIds,
1547                     updateToConfigurationExternalIds);
1548             OvsdbTerminationPointAugmentation updateToOperationalTerminationPointAugmentation =
1549                     getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeName,
1550                             LogicalDatastoreType.OPERATIONAL, TERMINATION_POINT_TEST_INDEX);
1551             List<InterfaceExternalIds> updateToOperationalExternalIds = updateToOperationalTerminationPointAugmentation
1552                     .getInterfaceExternalIds();
1553             if (updateFromExpectedExternalIds != null) {
1554                 assertExpectedInterfaceExternalIdsExist(updateToExpectedExternalIds,
1555                         updateToOperationalExternalIds);
1556                 assertExpectedInterfaceExternalIdsExist(updateFromExpectedExternalIds,
1557                         updateToOperationalExternalIds);
1558             } else {
1559                 Assert.assertNull(updateToOperationalExternalIds);
1560             }
1561
1562             // DELETE
1563             Assert.assertTrue(deleteBridge(connectionInfo, testBridgeName));
1564         }
1565     }
1566
1567     /*
1568      * Generates the test cases involved in testing TP Options.  See inline comments for descriptions of
1569      * the particular cases considered.
1570      *
1571      * The return value is a Map in the form (K,V)=(testCaseName,testCase).
1572      * - testCaseName is a String
1573      * - testCase is a Map in the form (K,V) s.t. K=(EXPECTED_VALUES_KEY|INPUT_VALUES_KEY) and V is a List of
1574      *     either corresponding INPUT TP Options, or EXPECTED TP Options
1575      *     INPUT    is the List we use when calling
1576      *              <code>TerminationPointAugmentationBuilder.setOptions()</code>
1577      *     EXPECTED is the List we expect to receive after calling
1578      *              <code>TerminationPointAugmentationBuilder.getOptions()</code>
1579      */
1580     private Map<String, Map<String, List<Options>>> generateTerminationPointOptionsTestCases() {
1581         Map<String, Map<String, List<Options>>> testMap =
1582                 new HashMap<String, Map<String, List<Options>>>();
1583
1584         final String TP_OPTIONS_KEY = "TPOptionsKey";
1585         final String TP_OPTIONS_VALUE = "TPOptionsValue";
1586         final String FORMAT_STR = "%s_%s_%d";
1587         final String GOOD_KEY = "GoodKey";
1588         final String GOOD_VALUE = "GoodValue";
1589         final String NO_VALUE_FOR_KEY = "NoValueForKey";
1590         final String NO_KEY_FOR_VALUE = "NoKeyForValue";
1591
1592         // Test Case 1:  TestOneOptions
1593         // Test Type:    Positive
1594         // Description:  Create a termination point with one Options
1595         // Expected:     A termination point is created with the single Options specified below
1596         final String testOneOptionsName = "TestOneOptions";
1597         int optionsCounter = 0;
1598         List<Options> oneOptions = (List<Options>) Lists.newArrayList(
1599                 (new OptionsBuilder()
1600                         .setOption(String.format(FORMAT_STR, testOneOptionsName,
1601                                 TP_OPTIONS_KEY, ++optionsCounter))
1602                         .setValue(String.format(FORMAT_STR, testOneOptionsName,
1603                                 TP_OPTIONS_VALUE, optionsCounter))
1604                         .build()));
1605         Map<String,List<Options>> testCase = Maps.newHashMap();
1606         testCase.put(EXPECTED_VALUES_KEY, oneOptions);
1607         testCase.put(INPUT_VALUES_KEY, oneOptions);
1608         testMap.put(testOneOptionsName, testCase);
1609
1610         // Test Case 2:  TestFiveOptions
1611         // Test Type:    Positive
1612         // Description:  Create a termination point with multiple (five) Options
1613         // Expected:     A termination point is created with the five options specified below
1614         final String testFiveOptionsName = "TestFiveOptions";
1615         optionsCounter = 0;
1616         List<Options> fiveOptions = (List<Options>) Lists.newArrayList(
1617                 (new OptionsBuilder()
1618                         .setOption(String.format(FORMAT_STR, testFiveOptionsName,
1619                                 TP_OPTIONS_KEY, ++optionsCounter))
1620                         .setValue(String.format(FORMAT_STR, testFiveOptionsName,
1621                                 TP_OPTIONS_VALUE, optionsCounter))
1622                         .build()),
1623                 (new OptionsBuilder()
1624                         .setOption(String.format(FORMAT_STR, testFiveOptionsName,
1625                                 TP_OPTIONS_KEY, ++optionsCounter))
1626                         .setValue(String.format(FORMAT_STR, testFiveOptionsName,
1627                                 TP_OPTIONS_VALUE, optionsCounter))
1628                         .build()),
1629                 (new OptionsBuilder()
1630                         .setOption(String.format(FORMAT_STR, testFiveOptionsName,
1631                                 TP_OPTIONS_KEY, ++optionsCounter))
1632                         .setValue(String.format(FORMAT_STR, testFiveOptionsName,
1633                                 TP_OPTIONS_VALUE, optionsCounter))
1634                         .build()),
1635                 (new OptionsBuilder()
1636                         .setOption(String.format(FORMAT_STR, testFiveOptionsName,
1637                                 TP_OPTIONS_KEY, ++optionsCounter))
1638                         .setValue(String.format(FORMAT_STR, testFiveOptionsName,
1639                                 TP_OPTIONS_VALUE, optionsCounter))
1640                         .build()),
1641                 (new OptionsBuilder()
1642                         .setOption(String.format(FORMAT_STR, testFiveOptionsName,
1643                                 TP_OPTIONS_KEY, ++optionsCounter))
1644                         .setValue(String.format(FORMAT_STR, testFiveOptionsName,
1645                                 TP_OPTIONS_VALUE, optionsCounter))
1646                         .build()));
1647         testCase = Maps.newHashMap();
1648         testCase.put(EXPECTED_VALUES_KEY, fiveOptions);
1649         testCase.put(INPUT_VALUES_KEY, fiveOptions);
1650         testMap.put(testFiveOptionsName, testCase);
1651
1652         // Test Case 3:  TestOneGoodOptionsOneMalformedOptionsValue
1653         // Test Type:    Negative
1654         // Description:
1655         //     One perfectly fine Options
1656         //        (TestOneGoodOptionsOneMalformedOptionsValue_OptionsKey_1,
1657         //        TestOneGoodOptionsOneMalformedOptions_OptionsValue_1)
1658         //     and one malformed Options which only has key specified
1659         //        (TestOneGoodOptionsOneMalformedOptionsValue_NoValueForKey_2,
1660         //        UNSPECIFIED)
1661         // Expected:     A termination point is created without any options
1662         final String testOneGoodOptionsOneMalformedOptionsValueName =
1663                 "TestOneGoodOptionsOneMalformedOptionsValue";
1664         optionsCounter = 0;
1665         Options oneGood = new OptionsBuilder()
1666                 .setOption(String.format(FORMAT_STR, testOneGoodOptionsOneMalformedOptionsValueName,
1667                         GOOD_KEY, ++optionsCounter))
1668                 .setValue(String.format(FORMAT_STR,
1669                         testOneGoodOptionsOneMalformedOptionsValueName,
1670                         GOOD_VALUE, optionsCounter))
1671                 .build();
1672         Options oneBad = new OptionsBuilder()
1673                 .setOption(String.format(FORMAT_STR,
1674                         testOneGoodOptionsOneMalformedOptionsValueName, NO_VALUE_FOR_KEY, ++optionsCounter))
1675                 .build();
1676         List<Options> oneGoodOneBadInput = (List<Options>) Lists.newArrayList(
1677                 oneGood, oneBad);
1678         List<Options> oneGoodOneBadExpected = null;
1679         testCase = Maps.newHashMap();
1680         testCase.put(INPUT_VALUES_KEY, oneGoodOneBadInput);
1681         testCase.put(EXPECTED_VALUES_KEY, oneGoodOneBadExpected);
1682         testMap.put(testOneGoodOptionsOneMalformedOptionsValueName, testCase);
1683
1684         // Test Case 4:  TestOneGoodOptionsOneMalformedOptionsKey
1685         // Test Type:    Negative
1686         // Description:
1687         //     One perfectly fine Options
1688         //        (TestOneGoodOptionsOneMalformedOptionsValue_OptionsKey_1,
1689         //        TestOneGoodOptionsOneMalformedOptions_OptionsValue_1)
1690         //     and one malformed Options which only has key specified
1691         //        (UNSPECIFIED,
1692         //        TestOneGoodOptionsOneMalformedOptionsKey_NoKeyForValue_2)
1693         // Expected:     A termination point is created without any options
1694         final String testOneGoodOptionsOneMalformedOptionsKeyName =
1695                 "TestOneGoodOptionsOneMalformedOptionsKey";
1696         optionsCounter = 0;
1697         oneGood = new OptionsBuilder()
1698                 .setOption(String.format(FORMAT_STR, testOneGoodOptionsOneMalformedOptionsKeyName,
1699                         GOOD_KEY, ++optionsCounter))
1700                 .setValue(String.format(FORMAT_STR,
1701                         testOneGoodOptionsOneMalformedOptionsKeyName,
1702                         GOOD_VALUE, optionsCounter))
1703                 .build();
1704         oneBad = new OptionsBuilder()
1705                 .setOption(String.format(FORMAT_STR,
1706                         testOneGoodOptionsOneMalformedOptionsKeyName, NO_KEY_FOR_VALUE, ++optionsCounter))
1707                 .build();
1708         oneGoodOneBadInput = (List<Options>) Lists.newArrayList(
1709                 oneGood, oneBad);
1710         oneGoodOneBadExpected = null;
1711         testCase = Maps.newHashMap();
1712         testCase.put(INPUT_VALUES_KEY, oneGoodOneBadInput);
1713         testCase.put(EXPECTED_VALUES_KEY, oneGoodOneBadExpected);
1714         testMap.put(testOneGoodOptionsOneMalformedOptionsKeyName, testCase);
1715
1716         return testMap;
1717     }
1718
1719     /*
1720      * @see <code>SouthboundIT.testCRUDTerminationPointOptions()</code>
1721      * This is helper test method to compare a test "set" of Options against an expected "set"
1722      */
1723     private void assertExpectedOptionsExist( List<Options> expected,
1724                                              List<Options> test ) {
1725
1726         if (expected != null) {
1727             for (Options expectedOption : expected) {
1728                 Assert.assertTrue(test.contains(expectedOption));
1729             }
1730         }
1731     }
1732
1733     /*
1734      * Tests the CRUD operations for <code>TerminationPoint</code> <code>options</code>.
1735      *
1736      * @see <code>SouthboundIT.generateTerminationPointOptions()</code> for specific test case information
1737      */
1738     @Test
1739     public void testCRUDTerminationPointOptions() throws InterruptedException {
1740         final String TEST_PREFIX = "CRUDTPOptions";
1741
1742         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
1743         connectOvsdbNode(connectionInfo);
1744
1745         // updateFromTestCases represent the original test case value.  updateToTestCases represent the new value after
1746         // the update has been performed.
1747         Map<String, Map<String, List<Options>>> updateFromTestCases =
1748                 generateTerminationPointOptionsTestCases();
1749         Map<String, Map<String, List<Options>>> updateToTestCases =
1750                 generateTerminationPointOptionsTestCases();
1751         Map<String, List<Options>> updateFromTestCase;
1752         List<Options> updateFromInputOptions;
1753         List<Options> updateFromExpectedOptions;
1754         Map<String, List<Options>> updateToTestCase;
1755         List<Options> updateToInputOptions;
1756         List<Options> updateToExpectedOptions;
1757         String testBridgeName;
1758         String testPortName;
1759
1760         int counter = 1;
1761         ExecutorService executor = Executors.newFixedThreadPool(NUM_THREADS);
1762         for (String updateFromTestCaseKey : updateFromTestCases.keySet()) {
1763             updateFromTestCase = updateFromTestCases.get(updateFromTestCaseKey);
1764             updateFromInputOptions = updateFromTestCase.get(INPUT_VALUES_KEY);
1765             updateFromExpectedOptions = updateFromTestCase.get(EXPECTED_VALUES_KEY);
1766             for (String testCaseKey : updateToTestCases.keySet()) {
1767                 testPortName = testBridgeName = String.format("%s_%s_%d", TEST_PREFIX, testCaseKey, counter);
1768                 counter += 1;
1769                 updateToTestCase = updateToTestCases.get(testCaseKey);
1770                 updateToInputOptions = updateToTestCase.get(INPUT_VALUES_KEY);
1771                 updateToExpectedOptions = updateToTestCase.get(EXPECTED_VALUES_KEY);
1772
1773                 TestCRUDTerminationPointOptionsRunnable testRunnable =
1774                         new TestCRUDTerminationPointOptionsRunnable(
1775                                 connectionInfo, testBridgeName, testPortName,
1776                                 updateFromInputOptions,
1777                                 updateFromExpectedOptions,
1778                                 updateToInputOptions,
1779                                 updateToExpectedOptions);
1780                 executor.submit(testRunnable);
1781             }
1782         }
1783         executor.shutdown();
1784         executor.awaitTermination(5, TimeUnit.MINUTES);
1785         Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
1786     }
1787
1788     class TestCRUDTerminationPointOptionsRunnable implements Runnable {
1789
1790         ConnectionInfo connectionInfo;
1791         String testBridgeName;
1792         String testPortName;
1793         List<Options> updateFromInputOptions;
1794         List<Options> updateFromExpectedOptions;
1795         List<Options> updateToInputOptions;
1796         List<Options> updateToExpectedOptions;
1797
1798         TestCRUDTerminationPointOptionsRunnable(
1799                 ConnectionInfo connectionInfo, String testBridgeName,
1800                 String testPortName,
1801                 List<Options> updateFromInputOptions,
1802                 List<Options> updateFromExpectedOptions,
1803                 List<Options> updateToInputOptions,
1804                 List<Options> updateToExpectedOptions) {
1805
1806             this.connectionInfo = connectionInfo;
1807             this.testBridgeName = testBridgeName;
1808             this.testPortName = testPortName;
1809             this.updateFromInputOptions = updateFromInputOptions;
1810             this.updateFromExpectedOptions = updateFromExpectedOptions;
1811             this.updateToInputOptions = updateToInputOptions;
1812             this.updateToExpectedOptions = updateToExpectedOptions;
1813         }
1814
1815         @Override
1816         public void run() {
1817             try {
1818                 test();
1819             } catch (InterruptedException e) {
1820                 e.printStackTrace();
1821             }
1822         }
1823
1824         public void test() throws InterruptedException {
1825             final int TERMINATION_POINT_TEST_INDEX = 0;
1826             // CREATE: Create the test interface
1827             Assert.assertTrue(addBridge(connectionInfo, null,
1828                     testBridgeName, null, true, SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"),
1829                     true, null, null, null, null));
1830             NodeId testBridgeNodeId = createManagedNodeId(createInstanceIdentifier(
1831                     connectionInfo, new OvsdbBridgeName(testBridgeName)));
1832             OvsdbTerminationPointAugmentationBuilder tpCreateAugmentationBuilder =
1833                     createGenericOvsdbTerminationPointAugmentationBuilder();
1834             tpCreateAugmentationBuilder.setName(testPortName);
1835             tpCreateAugmentationBuilder.setOptions(updateFromInputOptions);
1836             Assert.assertTrue(addTerminationPoint(testBridgeNodeId, testPortName, tpCreateAugmentationBuilder));
1837
1838             // READ: Read the test interface and ensure changes are propagated to the CONFIGURATION data store,
1839             // then repeat for OPERATIONAL data store
1840             OvsdbTerminationPointAugmentation updateFromConfigurationTerminationPointAugmentation =
1841                     getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeName,
1842                             LogicalDatastoreType.CONFIGURATION, TERMINATION_POINT_TEST_INDEX);
1843             List<Options> updateFromConfigurationOptions = updateFromConfigurationTerminationPointAugmentation
1844                     .getOptions();
1845             assertExpectedOptionsExist(updateFromExpectedOptions,
1846                     updateFromConfigurationOptions);
1847             OvsdbTerminationPointAugmentation updateFromOperationalTerminationPointAugmenation =
1848                     getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeName,
1849                             LogicalDatastoreType.OPERATIONAL, TERMINATION_POINT_TEST_INDEX);
1850             List<Options> updateFromOperationalOptions = updateFromOperationalTerminationPointAugmenation
1851                     .getOptions();
1852             assertExpectedOptionsExist(updateFromExpectedOptions,
1853                     updateFromOperationalOptions);
1854
1855             // UPDATE:  update the external_ids
1856             testBridgeNodeId = getBridgeNode(connectionInfo, testBridgeName).getNodeId();
1857             OvsdbTerminationPointAugmentationBuilder tpUpdateAugmentationBuilder =
1858                     new OvsdbTerminationPointAugmentationBuilder();
1859             tpUpdateAugmentationBuilder.setOptions(updateToInputOptions);
1860             InstanceIdentifier<Node> portIid = SouthboundMapper.createInstanceIdentifier(testBridgeNodeId);
1861             NodeBuilder portUpdateNodeBuilder = new NodeBuilder();
1862             NodeId portUpdateNodeId = createManagedNodeId(portIid);
1863             portUpdateNodeBuilder.setNodeId(portUpdateNodeId);
1864             TerminationPointBuilder tpUpdateBuilder = new TerminationPointBuilder();
1865             tpUpdateBuilder.setKey(new TerminationPointKey(new TpId(testPortName)));
1866             tpUpdateBuilder.addAugmentation(
1867                     OvsdbTerminationPointAugmentation.class,
1868                     tpUpdateAugmentationBuilder.build());
1869             portUpdateNodeBuilder.setTerminationPoint(Lists.newArrayList(tpUpdateBuilder.build()));
1870             boolean result = mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
1871                     portIid, portUpdateNodeBuilder.build());
1872             Thread.sleep(OVSDB_UPDATE_TIMEOUT);
1873             Assert.assertTrue(result);
1874
1875             // READ: the test interface and ensure changes are propagated to the CONFIGURATION data store,
1876             // then repeat for OPERATIONAL data store
1877             OvsdbTerminationPointAugmentation updateToConfigurationTerminationPointAugmentation =
1878                     getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeName,
1879                             LogicalDatastoreType.CONFIGURATION, TERMINATION_POINT_TEST_INDEX);
1880             List<Options> updateToConfigurationOptions = updateToConfigurationTerminationPointAugmentation
1881                     .getOptions();
1882             assertExpectedOptionsExist(updateToExpectedOptions, updateToConfigurationOptions);
1883             assertExpectedOptionsExist(updateFromExpectedOptions, updateToConfigurationOptions);
1884             OvsdbTerminationPointAugmentation updateToOperationalTerminationPointAugmentation =
1885                     getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeName,
1886                             LogicalDatastoreType.OPERATIONAL, TERMINATION_POINT_TEST_INDEX);
1887             List<Options> updateToOperationalOptions = updateToOperationalTerminationPointAugmentation
1888                     .getOptions();
1889             if (updateFromExpectedOptions != null) {
1890                 assertExpectedOptionsExist(updateToExpectedOptions, updateToOperationalOptions);
1891                 assertExpectedOptionsExist(updateFromExpectedOptions, updateToOperationalOptions);
1892             }
1893
1894             // DELETE
1895             Assert.assertTrue(deleteBridge(connectionInfo, testBridgeName));
1896         }
1897     }
1898
1899     /*
1900      * Generates the test cases involved in testing Interface other_configs.  See inline comments for descriptions of
1901      * the particular cases considered.
1902      *
1903      * The return value is a Map in the form (K,V)=(testCaseName,testCase).
1904      * - testCaseName is a String
1905      * - testCase is a Map in the form (K,V) s.t. K=(EXPECTED_VALUES_KEY|INPUT_VALUES_KEY) and V is a List of
1906      *     either corresponding INPUT interface other_configs, or EXPECTED interface other_configs
1907      *     INPUT    is the List we use when calling
1908      *              <code>TerminationPointAugmentationBuilder.setInterfaceOtherConfigs()</code>
1909      *     EXPECTED is the List we expect to receive after calling
1910      *              <code>TerminationPointAugmentationBuilder.getInterfaceOtherConfigs()</code>
1911      */
1912     private Map<String, Map<String, List<InterfaceOtherConfigs>>> generateInterfaceOtherConfigsTestCases() {
1913         Map<String, Map<String, List<InterfaceOtherConfigs>>> testMap =
1914                 new HashMap<String, Map<String, List<InterfaceOtherConfigs>>>();
1915
1916         final String INT_OTHER_CONFIGS_KEY = "IntOtherConfigsKey";
1917         final String INT_OTHER_CONFIGS_VALUE = "IntOtherConfigsValue";
1918         final String FORMAT_STR = "%s_%s_%d";
1919         final String GOOD_KEY = "GoodKey";
1920         final String GOOD_VALUE = "GoodValue";
1921         final String NO_VALUE_FOR_KEY = "NoValueForKey";
1922         final String NO_KEY_FOR_VALUE = "NoKeyForValue";
1923
1924         // Test Case 1:  TestOneOtherConfigs
1925         // Test Type:    Positive
1926         // Description:  Create an interface with one other_Configs
1927         // Expected:     An interface is created with the single other_configs specified below
1928         final String testOneOtherConfigsName = "TestOneInterfaceOtherConfigs";
1929         int otherConfigsCounter = 0;
1930         List<InterfaceOtherConfigs> oneOtherConfigs = (List<InterfaceOtherConfigs>) Lists.newArrayList(
1931                 (new InterfaceOtherConfigsBuilder()
1932                         .setOtherConfigKey(String.format(FORMAT_STR, testOneOtherConfigsName,
1933                                 INT_OTHER_CONFIGS_KEY, ++otherConfigsCounter))
1934                         .setOtherConfigValue(String.format(FORMAT_STR, testOneOtherConfigsName,
1935                                 INT_OTHER_CONFIGS_VALUE, otherConfigsCounter))
1936                         .build()));
1937         Map<String,List<InterfaceOtherConfigs>> testCase = Maps.newHashMap();
1938         testCase.put(EXPECTED_VALUES_KEY, oneOtherConfigs);
1939         testCase.put(INPUT_VALUES_KEY, oneOtherConfigs);
1940         testMap.put(testOneOtherConfigsName, testCase);
1941
1942         // Test Case 2:  TestFiveInterfaceOtherConfigs
1943         // Test Type:    Positive
1944         // Description:  Create a termination point with multiple (five) InterfaceOtherConfigs
1945         // Expected:     A termination point is created with the five InterfaceOtherConfigs specified below
1946         final String testFiveInterfaceOtherConfigsName = "TestFiveInterfaceOtherConfigs";
1947         otherConfigsCounter = 0;
1948         List<InterfaceOtherConfigs> fiveInterfaceOtherConfigs = (List<InterfaceOtherConfigs>) Lists.newArrayList(
1949                 (new InterfaceOtherConfigsBuilder()
1950                         .setOtherConfigKey(String.format(FORMAT_STR, testFiveInterfaceOtherConfigsName,
1951                                 INT_OTHER_CONFIGS_KEY, ++otherConfigsCounter))
1952                         .setOtherConfigValue(String.format(FORMAT_STR, testFiveInterfaceOtherConfigsName,
1953                                 INT_OTHER_CONFIGS_VALUE, otherConfigsCounter))
1954                         .build()),
1955                 (new InterfaceOtherConfigsBuilder()
1956                         .setOtherConfigKey(String.format(FORMAT_STR, testFiveInterfaceOtherConfigsName,
1957                                 INT_OTHER_CONFIGS_KEY, ++otherConfigsCounter))
1958                         .setOtherConfigValue(String.format(FORMAT_STR, testFiveInterfaceOtherConfigsName,
1959                                 INT_OTHER_CONFIGS_VALUE, otherConfigsCounter))
1960                         .build()),
1961                 (new InterfaceOtherConfigsBuilder()
1962                         .setOtherConfigKey(String.format(FORMAT_STR, testFiveInterfaceOtherConfigsName,
1963                                 INT_OTHER_CONFIGS_KEY, ++otherConfigsCounter))
1964                         .setOtherConfigValue(String.format(FORMAT_STR, testFiveInterfaceOtherConfigsName,
1965                                 INT_OTHER_CONFIGS_VALUE, otherConfigsCounter))
1966                         .build()),
1967                 (new InterfaceOtherConfigsBuilder()
1968                         .setOtherConfigKey(String.format(FORMAT_STR, testFiveInterfaceOtherConfigsName,
1969                                 INT_OTHER_CONFIGS_KEY, ++otherConfigsCounter))
1970                         .setOtherConfigValue(String.format(FORMAT_STR, testFiveInterfaceOtherConfigsName,
1971                                 INT_OTHER_CONFIGS_VALUE, otherConfigsCounter))
1972                         .build()),
1973                 (new InterfaceOtherConfigsBuilder()
1974                         .setOtherConfigKey(String.format(FORMAT_STR, testFiveInterfaceOtherConfigsName,
1975                                 INT_OTHER_CONFIGS_KEY, ++otherConfigsCounter))
1976                         .setOtherConfigValue(String.format(FORMAT_STR, testFiveInterfaceOtherConfigsName,
1977                                 INT_OTHER_CONFIGS_VALUE, otherConfigsCounter))
1978                         .build()));
1979         testCase = Maps.newHashMap();
1980         testCase.put(EXPECTED_VALUES_KEY, fiveInterfaceOtherConfigs);
1981         testCase.put(INPUT_VALUES_KEY, fiveInterfaceOtherConfigs);
1982         testMap.put(testFiveInterfaceOtherConfigsName, testCase);
1983
1984         // Test Case 3:  TestOneGoodInterfaceOtherConfigsOneMalformedInterfaceOtherConfigsValue
1985         // Test Type:    Negative
1986         // Description:
1987         //     One perfectly fine InterfaceOtherConfigs
1988         //        (TestOneGoodInterfaceOtherConfigsOneMalformedInterfaceOtherConfigsValue_InterfaceOtherConfigsKey_1,
1989         //        TestOneGoodInterfaceOtherConfigsOneMalformedInterfaceOtherConfigs_InterfaceOtherConfigsValue_1)
1990         //     and one malformed InterfaceOtherConfigs which only has key specified
1991         //        (TestOneGoodInterfaceOtherConfigsOneMalformedInterfaceOtherConfigsValue_NoValueForKey_2,
1992         //        UNSPECIFIED)
1993         // Expected:     A termination point is created without any InterfaceOtherConfigs
1994         final String testOneGoodInterfaceOtherConfigsOneMalformedInterfaceOtherConfigsValueName =
1995                 "TestOneGoodInterfaceOtherConfigsOneMalformedInterfaceOtherConfigsValue";
1996         otherConfigsCounter = 0;
1997         InterfaceOtherConfigs oneGood = new InterfaceOtherConfigsBuilder()
1998                 .setOtherConfigKey(String.format(FORMAT_STR,
1999                         testOneGoodInterfaceOtherConfigsOneMalformedInterfaceOtherConfigsValueName,
2000                         GOOD_KEY, ++otherConfigsCounter))
2001                 .setOtherConfigValue(String.format(FORMAT_STR,
2002                         testOneGoodInterfaceOtherConfigsOneMalformedInterfaceOtherConfigsValueName,
2003                         GOOD_VALUE, otherConfigsCounter))
2004                 .build();
2005         InterfaceOtherConfigs oneBad = new InterfaceOtherConfigsBuilder()
2006                 .setOtherConfigKey(String.format(FORMAT_STR,
2007                         testOneGoodInterfaceOtherConfigsOneMalformedInterfaceOtherConfigsValueName, NO_VALUE_FOR_KEY,
2008                         ++otherConfigsCounter))
2009                 .build();
2010         List<InterfaceOtherConfigs> oneGoodOneBadInput = (List<InterfaceOtherConfigs>) Lists.newArrayList(
2011                 oneGood, oneBad);
2012         List<InterfaceOtherConfigs> oneGoodOneBadExpected = null;
2013         testCase = Maps.newHashMap();
2014         testCase.put(INPUT_VALUES_KEY, oneGoodOneBadInput);
2015         testCase.put(EXPECTED_VALUES_KEY, oneGoodOneBadExpected);
2016         testMap.put(testOneGoodInterfaceOtherConfigsOneMalformedInterfaceOtherConfigsValueName, testCase);
2017
2018         // Test Case 4:  TestOneGoodInterfaceOtherConfigsOneMalformedInterfaceOtherConfigsKey
2019         // Test Type:    Negative
2020         // Description:
2021         //     One perfectly fine InterfaceOtherConfigs
2022         //        (TestOneGoodInterfaceOtherConfigsOneMalformedInterfaceOtherConfigsValue_InterfaceOtherConfigsKey_1,
2023         //        TestOneGoodInterfaceOtherConfigsOneMalformedInterfaceOtherConfigs_InterfaceOtherConfigsValue_1)
2024         //     and one malformed InterfaceOtherConfigs which only has key specified
2025         //        (UNSPECIFIED,
2026         //        TestOneGoodInterfaceOtherConfigsOneMalformedInterfaceOtherConfigsKey_NoKeyForValue_2)
2027         // Expected:     A termination point is created without any InterfaceOtherConfigs
2028         final String testOneGoodInterfaceOtherConfigsOneMalformedInterfaceOtherConfigsKeyName =
2029                 "TestOneGoodInterfaceOtherConfigsOneMalformedInterfaceOtherConfigsKey";
2030         otherConfigsCounter = 0;
2031         oneGood = new InterfaceOtherConfigsBuilder()
2032                 .setOtherConfigKey(String.format(FORMAT_STR,
2033                         testOneGoodInterfaceOtherConfigsOneMalformedInterfaceOtherConfigsKeyName,
2034                         GOOD_KEY, ++otherConfigsCounter))
2035                 .setOtherConfigValue(String.format(FORMAT_STR,
2036                         testOneGoodInterfaceOtherConfigsOneMalformedInterfaceOtherConfigsKeyName,
2037                         GOOD_VALUE, otherConfigsCounter))
2038                 .build();
2039         oneBad = new InterfaceOtherConfigsBuilder()
2040                 .setOtherConfigKey(String.format(FORMAT_STR,
2041                         testOneGoodInterfaceOtherConfigsOneMalformedInterfaceOtherConfigsKeyName, NO_KEY_FOR_VALUE,
2042                         ++otherConfigsCounter))
2043                 .build();
2044         oneGoodOneBadInput = (List<InterfaceOtherConfigs>) Lists.newArrayList(
2045                 oneGood, oneBad);
2046         oneGoodOneBadExpected = null;
2047         testCase = Maps.newHashMap();
2048         testCase.put(INPUT_VALUES_KEY, oneGoodOneBadInput);
2049         testCase.put(EXPECTED_VALUES_KEY, oneGoodOneBadExpected);
2050         testMap.put(testOneGoodInterfaceOtherConfigsOneMalformedInterfaceOtherConfigsKeyName, testCase);
2051
2052         return testMap;
2053     }
2054
2055     /*
2056      * @see <code>SouthboundIT.testCRUDInterfaceOtherConfigs()</code>
2057      * This is helper test method to compare a test "set" of Options against an expected "set"
2058      */
2059     private void assertExpectedInterfaceOtherConfigsExist( List<InterfaceOtherConfigs> expected,
2060                                                            List<InterfaceOtherConfigs> test ) {
2061
2062         if (expected != null && test != null) {
2063             for (InterfaceOtherConfigs expectedOtherConfigs : expected) {
2064                 Assert.assertTrue(test.contains(expectedOtherConfigs));
2065             }
2066         }
2067     }
2068
2069     /*
2070      * Tests the CRUD operations for <code>Interface</code> <code>other_configs</code>.
2071      *
2072      * @see <code>SouthboundIT.generateInterfaceExternalIdsTestCases()</code> for specific test case information
2073      */
2074     @Test
2075     public void testCRUDTerminationPointInterfaceOtherConfigs() throws InterruptedException {
2076         final String TEST_PREFIX = "CRUDTPInterfaceOtherConfigs";
2077
2078         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
2079         connectOvsdbNode(connectionInfo);
2080
2081         // updateFromTestCases represent the original test case value.  updateToTestCases represent the new value after
2082         // the update has been performed.
2083         Map<String, Map<String, List<InterfaceOtherConfigs>>> updateFromTestCases =
2084                 generateInterfaceOtherConfigsTestCases();
2085         Map<String, Map<String, List<InterfaceOtherConfigs>>> updateToTestCases =
2086                 generateInterfaceOtherConfigsTestCases();
2087         Map<String, List<InterfaceOtherConfigs>> updateFromTestCase;
2088         List<InterfaceOtherConfigs> updateFromInputOtherConfigs;
2089         List<InterfaceOtherConfigs> updateFromExpectedOtherConfigs;
2090         Map<String, List<InterfaceOtherConfigs>> updateToTestCase;
2091         List<InterfaceOtherConfigs> updateToInputOtherConfigs;
2092         List<InterfaceOtherConfigs> updateToExpectedOtherConfigs;
2093         String testBridgeName;
2094         String testPortName;
2095
2096         int counter = 1;
2097         ExecutorService executor = Executors.newFixedThreadPool(NUM_THREADS);
2098         for (String updateFromTestCaseKey : updateFromTestCases.keySet()) {
2099             updateFromTestCase = updateFromTestCases.get(updateFromTestCaseKey);
2100             updateFromInputOtherConfigs = updateFromTestCase.get(INPUT_VALUES_KEY);
2101             updateFromExpectedOtherConfigs = updateFromTestCase.get(EXPECTED_VALUES_KEY);
2102             for (String testCaseKey : updateToTestCases.keySet()) {
2103                 testPortName = testBridgeName = String.format("%s_%s_%d", TEST_PREFIX, testCaseKey, counter);
2104                 counter += 1;
2105                 updateToTestCase = updateToTestCases.get(testCaseKey);
2106                 updateToInputOtherConfigs = updateToTestCase.get(INPUT_VALUES_KEY);
2107                 updateToExpectedOtherConfigs = updateToTestCase.get(EXPECTED_VALUES_KEY);
2108
2109                 TestCRUDTerminationPointInterfaceOtherConfigsRunnable testRunnable =
2110                         new TestCRUDTerminationPointInterfaceOtherConfigsRunnable(
2111                                 connectionInfo, testBridgeName, testPortName,
2112                                 updateFromInputOtherConfigs,
2113                                 updateFromExpectedOtherConfigs,
2114                                 updateToInputOtherConfigs,
2115                                 updateToExpectedOtherConfigs);
2116                 executor.submit(testRunnable);
2117             }
2118         }
2119         executor.shutdown();
2120         executor.awaitTermination(5, TimeUnit.MINUTES);
2121         Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
2122     }
2123
2124     class TestCRUDTerminationPointInterfaceOtherConfigsRunnable implements Runnable {
2125
2126         ConnectionInfo connectionInfo;
2127         String testBridgeName;
2128         String testPortName;
2129         List<InterfaceOtherConfigs> updateFromInputOtherConfigs;
2130         List<InterfaceOtherConfigs> updateFromExpectedOtherConfigs;
2131         List<InterfaceOtherConfigs> updateToInputOtherConfigs;
2132         List<InterfaceOtherConfigs> updateToExpectedOtherConfigs;
2133
2134         TestCRUDTerminationPointInterfaceOtherConfigsRunnable(
2135                 ConnectionInfo connectionInfo, String testBridgeName,
2136                 String testPortName,
2137                 List<InterfaceOtherConfigs> updateFromInputOtherConfigs,
2138                 List<InterfaceOtherConfigs> updateFromExpectedOtherConfigs,
2139                 List<InterfaceOtherConfigs> updateToInputOtherConfigs,
2140                 List<InterfaceOtherConfigs> updateToExpectedOtherConfigs) {
2141
2142             this.connectionInfo = connectionInfo;
2143             this.testBridgeName = testBridgeName;
2144             this.testPortName = testPortName;
2145             this.updateFromInputOtherConfigs = updateFromInputOtherConfigs;
2146             this.updateFromExpectedOtherConfigs = updateFromExpectedOtherConfigs;
2147             this.updateToInputOtherConfigs = updateToInputOtherConfigs;
2148             this.updateToExpectedOtherConfigs = updateToExpectedOtherConfigs;
2149         }
2150
2151         @Override
2152         public void run() {
2153             try {
2154                 test();
2155             } catch (InterruptedException e) {
2156                 e.printStackTrace();
2157             }
2158         }
2159
2160         public void test() throws InterruptedException {
2161             final int TERMINATION_POINT_TEST_INDEX = 0;
2162
2163             // CREATE: Create the test interface
2164             Assert.assertTrue(addBridge(connectionInfo, null,
2165                     testBridgeName, null, true, SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"),
2166                     true, null, null, null, null));
2167             NodeId testBridgeNodeId = createManagedNodeId(createInstanceIdentifier(
2168                     connectionInfo, new OvsdbBridgeName(testBridgeName)));
2169             OvsdbTerminationPointAugmentationBuilder tpCreateAugmentationBuilder =
2170                     createGenericOvsdbTerminationPointAugmentationBuilder();
2171             tpCreateAugmentationBuilder.setName(testPortName);
2172             tpCreateAugmentationBuilder.setInterfaceOtherConfigs(updateFromInputOtherConfigs);
2173             Assert.assertTrue(addTerminationPoint(testBridgeNodeId, testPortName, tpCreateAugmentationBuilder));
2174
2175             // READ: Read the test interface and ensure changes are propagated to the CONFIGURATION data store,
2176             // then repeat for OPERATIONAL data store
2177             OvsdbTerminationPointAugmentation updateFromConfigurationTerminationPointAugmentation =
2178                     getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeName,
2179                     LogicalDatastoreType.CONFIGURATION, TERMINATION_POINT_TEST_INDEX);
2180             List<InterfaceOtherConfigs> updateFromConfigurationOtherConfigs;
2181             if (updateFromConfigurationTerminationPointAugmentation != null) {
2182                 updateFromConfigurationOtherConfigs = updateFromConfigurationTerminationPointAugmentation
2183                         .getInterfaceOtherConfigs();
2184             } else {
2185                 updateFromConfigurationOtherConfigs = null;
2186             }
2187             assertExpectedInterfaceOtherConfigsExist(updateFromExpectedOtherConfigs,
2188                     updateFromConfigurationOtherConfigs);
2189             OvsdbTerminationPointAugmentation updateFromOperationalTerminationPointAugmenation =
2190                     getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeName,
2191                             LogicalDatastoreType.OPERATIONAL, TERMINATION_POINT_TEST_INDEX);
2192             List<InterfaceOtherConfigs> updateFromOperationalOtherConfigs =
2193                     updateFromOperationalTerminationPointAugmenation.getInterfaceOtherConfigs();
2194             if (updateFromOperationalOtherConfigs != null) {
2195                 updateFromOperationalOtherConfigs = updateFromOperationalTerminationPointAugmenation
2196                         .getInterfaceOtherConfigs();
2197             } else {
2198                 updateFromOperationalOtherConfigs = null;
2199             }
2200             assertExpectedInterfaceOtherConfigsExist(updateFromExpectedOtherConfigs,
2201                     updateFromOperationalOtherConfigs);
2202
2203             // UPDATE:  update the other_configs
2204             testBridgeNodeId = getBridgeNode(connectionInfo, testBridgeName).getNodeId();
2205             OvsdbTerminationPointAugmentationBuilder tpUpdateAugmentationBuilder =
2206                     new OvsdbTerminationPointAugmentationBuilder();
2207             tpUpdateAugmentationBuilder.setInterfaceOtherConfigs(updateToInputOtherConfigs);
2208             InstanceIdentifier<Node> portIid = SouthboundMapper.createInstanceIdentifier(testBridgeNodeId);
2209             NodeBuilder portUpdateNodeBuilder = new NodeBuilder();
2210             NodeId portUpdateNodeId = createManagedNodeId(portIid);
2211             portUpdateNodeBuilder.setNodeId(portUpdateNodeId);
2212             TerminationPointBuilder tpUpdateBuilder = new TerminationPointBuilder();
2213             tpUpdateBuilder.setKey(new TerminationPointKey(new TpId(testPortName)));
2214             tpUpdateBuilder.addAugmentation(
2215                     OvsdbTerminationPointAugmentation.class,
2216                     tpUpdateAugmentationBuilder.build());
2217             portUpdateNodeBuilder.setTerminationPoint(Lists.newArrayList(tpUpdateBuilder.build()));
2218             boolean result = mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
2219                     portIid, portUpdateNodeBuilder.build());
2220             Thread.sleep(OVSDB_UPDATE_TIMEOUT);
2221             Assert.assertTrue(result);
2222
2223             // READ: the test interface and ensure changes are propagated to the CONFIGURATION data store,
2224             // then repeat for OPERATIONAL data store
2225             OvsdbTerminationPointAugmentation updateToConfigurationTerminationPointAugmentation =
2226                     getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeName,
2227                             LogicalDatastoreType.CONFIGURATION, TERMINATION_POINT_TEST_INDEX);
2228             List<InterfaceOtherConfigs> updateToConfigurationOtherConfigs =
2229                     updateToConfigurationTerminationPointAugmentation
2230                             .getInterfaceOtherConfigs();
2231             assertExpectedInterfaceOtherConfigsExist(updateToExpectedOtherConfigs,
2232                     updateToConfigurationOtherConfigs);
2233             assertExpectedInterfaceOtherConfigsExist(updateFromExpectedOtherConfigs,
2234                     updateToConfigurationOtherConfigs);
2235             OvsdbTerminationPointAugmentation updateToOperationalTerminationPointAugmentation =
2236                     getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeName,
2237                             LogicalDatastoreType.OPERATIONAL, TERMINATION_POINT_TEST_INDEX);
2238             List<InterfaceOtherConfigs> updateToOperationalOtherConfigs =
2239                     updateToOperationalTerminationPointAugmentation
2240                             .getInterfaceOtherConfigs();
2241             if (updateFromExpectedOtherConfigs != null) {
2242                 assertExpectedInterfaceOtherConfigsExist(updateToExpectedOtherConfigs,
2243                         updateToOperationalOtherConfigs);
2244                 assertExpectedInterfaceOtherConfigsExist(updateFromExpectedOtherConfigs,
2245                         updateToOperationalOtherConfigs);
2246             }
2247
2248             // DELETE
2249             Assert.assertTrue(deleteBridge(connectionInfo, testBridgeName));
2250         }
2251     }
2252
2253     /*
2254      * Generates the test cases involved in testing Port other_configs.  See inline comments for descriptions of
2255      * the particular cases considered.
2256      *
2257      * The return value is a Map in the form (K,V)=(testCaseName,testCase).
2258      * - testCaseName is a String
2259      * - testCase is a Map in the form (K,V) s.t. K=(EXPECTED_VALUES_KEY|INPUT_VALUES_KEY) and V is a List of
2260      *     either corresponding INPUT port other_configs, or EXPECTED port other_configs
2261      *     INPUT    is the List we use when calling
2262      *              <code>TerminationPointAugmentationBuilder.setPortOtherConfigs()</code>
2263      *     EXPECTED is the List we expect to receive after calling
2264      *              <code>TerminationPointAugmentationBuilder.getPortOtherConfigs()</code>
2265      */
2266     private Map<String, Map<String, List<PortOtherConfigs>>> generatePortOtherConfigsTestCases() {
2267         Map<String, Map<String, List<PortOtherConfigs>>> testMap =
2268                 new HashMap<String, Map<String, List<PortOtherConfigs>>>();
2269
2270         final String PORT_OTHER_CONFIGS_KEY = "PortOtherConfigsKey";
2271         final String PORT_OTHER_CONFIGS_VALUE = "PortOtherConfigsValue";
2272         final String FORMAT_STR = "%s_%s_%d";
2273         final String GOOD_KEY = "GoodKey";
2274         final String GOOD_VALUE = "GoodValue";
2275         final String NO_VALUE_FOR_KEY = "NoValueForKey";
2276         final String NO_KEY_FOR_VALUE = "NoKeyForValue";
2277
2278         // Test Case 1:  TestOneOtherConfigs
2279         // Test Type:    Positive
2280         // Description:  Create an port with one other_Configs
2281         // Expected:     A port is created with the single other_configs specified below
2282         final String testOneOtherConfigsName = "TestOnePortOtherConfigs";
2283         int otherConfigsCounter = 0;
2284         List<PortOtherConfigs> oneOtherConfigs = (List<PortOtherConfigs>) Lists.newArrayList(
2285                 (new PortOtherConfigsBuilder()
2286                         .setOtherConfigKey(String.format(FORMAT_STR, testOneOtherConfigsName,
2287                                 PORT_OTHER_CONFIGS_KEY, ++otherConfigsCounter))
2288                         .setOtherConfigValue(String.format(FORMAT_STR, testOneOtherConfigsName,
2289                                 PORT_OTHER_CONFIGS_VALUE, otherConfigsCounter))
2290                         .build()));
2291         Map<String,List<PortOtherConfigs>> testCase = Maps.newHashMap();
2292         testCase.put(EXPECTED_VALUES_KEY, oneOtherConfigs);
2293         testCase.put(INPUT_VALUES_KEY, oneOtherConfigs);
2294         testMap.put(testOneOtherConfigsName, testCase);
2295
2296         // Test Case 2:  TestFivePortOtherConfigs
2297         // Test Type:    Positive
2298         // Description:  Create a termination point with multiple (five) PortOtherConfigs
2299         // Expected:     A termination point is created with the five PortOtherConfigs specified below
2300         final String testFivePortOtherConfigsName = "TestFivePortOtherConfigs";
2301         otherConfigsCounter = 0;
2302         List<PortOtherConfigs> fivePortOtherConfigs = (List<PortOtherConfigs>) Lists.newArrayList(
2303                 (new PortOtherConfigsBuilder()
2304                         .setOtherConfigKey(String.format(FORMAT_STR, testFivePortOtherConfigsName,
2305                                 PORT_OTHER_CONFIGS_KEY, ++otherConfigsCounter))
2306                         .setOtherConfigValue(String.format(FORMAT_STR, testFivePortOtherConfigsName,
2307                                 PORT_OTHER_CONFIGS_VALUE, otherConfigsCounter))
2308                         .build()),
2309                 (new PortOtherConfigsBuilder()
2310                         .setOtherConfigKey(String.format(FORMAT_STR, testFivePortOtherConfigsName,
2311                                 PORT_OTHER_CONFIGS_KEY, ++otherConfigsCounter))
2312                         .setOtherConfigValue(String.format(FORMAT_STR, testFivePortOtherConfigsName,
2313                                 PORT_OTHER_CONFIGS_VALUE, otherConfigsCounter))
2314                         .build()),
2315                 (new PortOtherConfigsBuilder()
2316                         .setOtherConfigKey(String.format(FORMAT_STR, testFivePortOtherConfigsName,
2317                                 PORT_OTHER_CONFIGS_KEY, ++otherConfigsCounter))
2318                         .setOtherConfigValue(String.format(FORMAT_STR, testFivePortOtherConfigsName,
2319                                 PORT_OTHER_CONFIGS_VALUE, otherConfigsCounter))
2320                         .build()),
2321                 (new PortOtherConfigsBuilder()
2322                         .setOtherConfigKey(String.format(FORMAT_STR, testFivePortOtherConfigsName,
2323                                 PORT_OTHER_CONFIGS_KEY, ++otherConfigsCounter))
2324                         .setOtherConfigValue(String.format(FORMAT_STR, testFivePortOtherConfigsName,
2325                                 PORT_OTHER_CONFIGS_VALUE, otherConfigsCounter))
2326                         .build()),
2327                 (new PortOtherConfigsBuilder()
2328                         .setOtherConfigKey(String.format(FORMAT_STR, testFivePortOtherConfigsName,
2329                                 PORT_OTHER_CONFIGS_KEY, ++otherConfigsCounter))
2330                         .setOtherConfigValue(String.format(FORMAT_STR, testFivePortOtherConfigsName,
2331                                 PORT_OTHER_CONFIGS_VALUE, otherConfigsCounter))
2332                         .build()));
2333         testCase = Maps.newHashMap();
2334         testCase.put(EXPECTED_VALUES_KEY, fivePortOtherConfigs);
2335         testCase.put(INPUT_VALUES_KEY, fivePortOtherConfigs);
2336         testMap.put(testFivePortOtherConfigsName, testCase);
2337
2338         // Test Case 3:  TestOneGoodPortOtherConfigsOneMalformedPortOtherConfigsValue
2339         // Test Type:    Negative
2340         // Description:
2341         //     One perfectly fine PortOtherConfigs
2342         //        (TestOneGoodPortOtherConfigsOneMalformedPortOtherConfigsValue_PortOtherConfigsKey_1,
2343         //        TestOneGoodPortOtherConfigsOneMalformedPortOtherConfigs_PortOtherConfigsValue_1)
2344         //     and one malformed PortOtherConfigs which only has key specified
2345         //        (TestOneGoodPortOtherConfigsOneMalformedPortOtherConfigsValue_NoValueForKey_2,
2346         //        UNSPECIFIED)
2347         // Expected:     A termination point is created without any PortOtherConfigs
2348         final String testOneGoodPortOtherConfigsOneMalformedPortOtherConfigsValueName =
2349                 "TestOneGoodPortOtherConfigsOneMalformedPortOtherConfigsValue";
2350         otherConfigsCounter = 0;
2351         PortOtherConfigs oneGood = new PortOtherConfigsBuilder()
2352                 .setOtherConfigKey(String.format(FORMAT_STR,
2353                         testOneGoodPortOtherConfigsOneMalformedPortOtherConfigsValueName,
2354                         GOOD_KEY, ++otherConfigsCounter))
2355                 .setOtherConfigValue(String.format(FORMAT_STR,
2356                         testOneGoodPortOtherConfigsOneMalformedPortOtherConfigsValueName,
2357                         GOOD_VALUE, otherConfigsCounter))
2358                 .build();
2359         PortOtherConfigs oneBad = new PortOtherConfigsBuilder()
2360                 .setOtherConfigKey(String.format(FORMAT_STR,
2361                         testOneGoodPortOtherConfigsOneMalformedPortOtherConfigsValueName, NO_VALUE_FOR_KEY,
2362                         ++otherConfigsCounter))
2363                 .build();
2364         List<PortOtherConfigs> oneGoodOneBadInput = (List<PortOtherConfigs>) Lists.newArrayList(
2365                 oneGood, oneBad);
2366         List<PortOtherConfigs> oneGoodOneBadExpected = null;
2367         testCase = Maps.newHashMap();
2368         testCase.put(INPUT_VALUES_KEY, oneGoodOneBadInput);
2369         testCase.put(EXPECTED_VALUES_KEY, oneGoodOneBadExpected);
2370         testMap.put(testOneGoodPortOtherConfigsOneMalformedPortOtherConfigsValueName, testCase);
2371
2372         // Test Case 4:  TestOneGoodPortOtherConfigsOneMalformedPortOtherConfigsKey
2373         // Test Type:    Negative
2374         // Description:
2375         //     One perfectly fine PortOtherConfigs
2376         //        (TestOneGoodPortOtherConfigsOneMalformedPortOtherConfigsValue_PortOtherConfigsKey_1,
2377         //        TestOneGoodPortOtherConfigsOneMalformedPortOtherConfigs_PortOtherConfigsValue_1)
2378         //     and one malformed PortOtherConfigs which only has key specified
2379         //        (UNSPECIFIED,
2380         //        TestOneGoodPortOtherConfigsOneMalformedPortOtherConfigsKey_NoKeyForValue_2)
2381         // Expected:     A termination point is created without any PortOtherConfigs
2382         final String testOneGoodPortOtherConfigsOneMalformedPortOtherConfigsKeyName =
2383                 "TestOneGoodPortOtherConfigsOneMalformedPortOtherConfigsKey";
2384         otherConfigsCounter = 0;
2385         oneGood = new PortOtherConfigsBuilder()
2386                 .setOtherConfigKey(String.format(FORMAT_STR,
2387                         testOneGoodPortOtherConfigsOneMalformedPortOtherConfigsKeyName,
2388                         GOOD_KEY, ++otherConfigsCounter))
2389                 .setOtherConfigValue(String.format(FORMAT_STR,
2390                         testOneGoodPortOtherConfigsOneMalformedPortOtherConfigsKeyName,
2391                         GOOD_VALUE, otherConfigsCounter))
2392                 .build();
2393         oneBad = new PortOtherConfigsBuilder()
2394                 .setOtherConfigKey(String.format(FORMAT_STR,
2395                         testOneGoodPortOtherConfigsOneMalformedPortOtherConfigsKeyName, NO_KEY_FOR_VALUE,
2396                         ++otherConfigsCounter))
2397                 .build();
2398         oneGoodOneBadInput = (List<PortOtherConfigs>) Lists.newArrayList(
2399                 oneGood, oneBad);
2400         oneGoodOneBadExpected = null;
2401         testCase = Maps.newHashMap();
2402         testCase.put(INPUT_VALUES_KEY, oneGoodOneBadInput);
2403         testCase.put(EXPECTED_VALUES_KEY, oneGoodOneBadExpected);
2404         testMap.put(testOneGoodPortOtherConfigsOneMalformedPortOtherConfigsKeyName, testCase);
2405
2406         return testMap;
2407     }
2408
2409     /*
2410      * @see <code>SouthboundIT.testCRUDPortOtherConfigs()</code>
2411      * This is helper test method to compare a test "set" of Options against an expected "set"
2412      */
2413     private void assertExpectedPortOtherConfigsExist( List<PortOtherConfigs> expected,
2414                                                       List<PortOtherConfigs> test ) {
2415
2416         if (expected != null && test != null) {
2417             for (PortOtherConfigs expectedOtherConfigs : expected) {
2418                 Assert.assertTrue(test.contains(expectedOtherConfigs));
2419             }
2420         }
2421     }
2422
2423     /*
2424      * Tests the CRUD operations for <code>Port</code> <code>other_configs</code>.
2425      *
2426      * @see <code>SouthboundIT.generatePortExternalIdsTestCases()</code> for specific test case information
2427      */
2428     @Test
2429     public void testCRUDTerminationPointPortOtherConfigs() throws InterruptedException {
2430         final String TEST_PREFIX = "CRUDTPPortOtherConfigs";
2431
2432         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
2433         connectOvsdbNode(connectionInfo);
2434
2435         // updateFromTestCases represent the original test case value.  updateToTestCases represent the new value after
2436         // the update has been performed.
2437         Map<String, Map<String, List<PortOtherConfigs>>> updateFromTestCases =
2438                 generatePortOtherConfigsTestCases();
2439         Map<String, Map<String, List<PortOtherConfigs>>> updateToTestCases =
2440                 generatePortOtherConfigsTestCases();
2441         Map<String, List<PortOtherConfigs>> updateFromTestCase;
2442         List<PortOtherConfigs> updateFromInputOtherConfigs;
2443         List<PortOtherConfigs> updateFromExpectedOtherConfigs;
2444         Map<String, List<PortOtherConfigs>> updateToTestCase;
2445         List<PortOtherConfigs> updateToInputOtherConfigs;
2446         List<PortOtherConfigs> updateToExpectedOtherConfigs;
2447         String testBridgeName;
2448         String testPortName;
2449
2450         int counter = 1;
2451         ExecutorService executor = Executors.newFixedThreadPool(NUM_THREADS);
2452         for (String updateFromTestCaseKey : updateFromTestCases.keySet()) {
2453             updateFromTestCase = updateFromTestCases.get(updateFromTestCaseKey);
2454             updateFromInputOtherConfigs = updateFromTestCase.get(INPUT_VALUES_KEY);
2455             updateFromExpectedOtherConfigs = updateFromTestCase.get(EXPECTED_VALUES_KEY);
2456             for (String testCaseKey : updateToTestCases.keySet()) {
2457                 testPortName = testBridgeName = String.format("%s_%s_%d", TEST_PREFIX, testCaseKey, counter);
2458                 counter += 1;
2459                 updateToTestCase = updateToTestCases.get(testCaseKey);
2460                 updateToInputOtherConfigs = updateToTestCase.get(INPUT_VALUES_KEY);
2461                 updateToExpectedOtherConfigs = updateToTestCase.get(EXPECTED_VALUES_KEY);
2462
2463                 TestCRUDTerminationPointPortOtherConfigsRunnable testRunnable =
2464                         new TestCRUDTerminationPointPortOtherConfigsRunnable(
2465                                 connectionInfo, testBridgeName, testPortName,
2466                                 updateFromInputOtherConfigs,
2467                                 updateFromExpectedOtherConfigs,
2468                                 updateToInputOtherConfigs,
2469                                 updateToExpectedOtherConfigs);
2470                 executor.submit(testRunnable);
2471             }
2472         }
2473         executor.shutdown();
2474         executor.awaitTermination(5, TimeUnit.MINUTES);
2475         Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
2476     }
2477
2478     class TestCRUDTerminationPointPortOtherConfigsRunnable implements Runnable {
2479         ConnectionInfo connectionInfo;
2480         String testBridgeName;
2481         String testPortName;
2482         List<PortOtherConfigs> updateFromInputOtherConfigs;
2483         List<PortOtherConfigs> updateFromExpectedOtherConfigs;
2484         List<PortOtherConfigs> updateToInputOtherConfigs;
2485         List<PortOtherConfigs> updateToExpectedOtherConfigs;
2486
2487         TestCRUDTerminationPointPortOtherConfigsRunnable(
2488                 ConnectionInfo connectionInfo, String testBridgeName,
2489                 String testPortName,
2490                 List<PortOtherConfigs> updateFromInputOtherConfigs,
2491                 List<PortOtherConfigs> updateFromExpectedOtherConfigs,
2492                 List<PortOtherConfigs> updateToInputOtherConfigs,
2493                 List<PortOtherConfigs> updateToExpectedOtherConfigs) {
2494
2495             this.connectionInfo = connectionInfo;
2496             this.testBridgeName = testBridgeName;
2497             this.testPortName = testPortName;
2498             this.updateFromInputOtherConfigs = updateFromInputOtherConfigs;
2499             this.updateFromExpectedOtherConfigs = updateFromExpectedOtherConfigs;
2500             this.updateToInputOtherConfigs = updateToInputOtherConfigs;
2501             this.updateToExpectedOtherConfigs = updateToExpectedOtherConfigs;
2502         }
2503
2504         @Override
2505         public void run() {
2506             try {
2507                 test();
2508             } catch (InterruptedException e) {
2509                 e.printStackTrace();
2510             }
2511         }
2512
2513         public void test() throws InterruptedException {
2514             final int TERMINATION_POINT_TEST_INDEX = 0;
2515             // CREATE: Create the test port
2516             Assert.assertTrue(addBridge(connectionInfo, null,
2517                     testBridgeName, null, true, SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"),
2518                     true, null, null, null, null));
2519             NodeId testBridgeNodeId = createManagedNodeId(createInstanceIdentifier(
2520                     connectionInfo, new OvsdbBridgeName(testBridgeName)));
2521             OvsdbTerminationPointAugmentationBuilder tpCreateAugmentationBuilder =
2522                     createGenericOvsdbTerminationPointAugmentationBuilder();
2523             tpCreateAugmentationBuilder.setName(testPortName);
2524             tpCreateAugmentationBuilder.setPortOtherConfigs(updateFromInputOtherConfigs);
2525             Assert.assertTrue(addTerminationPoint(testBridgeNodeId, testPortName, tpCreateAugmentationBuilder));
2526
2527             // READ: Read the test port and ensure changes are propagated to the CONFIGURATION data store,
2528             // then repeat for OPERATIONAL data store
2529             OvsdbTerminationPointAugmentation updateFromConfigurationTerminationPointAugmentation =
2530                     getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeName,
2531                             LogicalDatastoreType.CONFIGURATION, TERMINATION_POINT_TEST_INDEX);
2532             List<PortOtherConfigs> updateFromConfigurationOtherConfigs;
2533             if (updateFromConfigurationTerminationPointAugmentation != null) {
2534                 updateFromConfigurationOtherConfigs = updateFromConfigurationTerminationPointAugmentation
2535                         .getPortOtherConfigs();
2536             } else {
2537                 updateFromConfigurationOtherConfigs = null;
2538             }
2539             assertExpectedPortOtherConfigsExist(updateFromExpectedOtherConfigs,
2540                     updateFromConfigurationOtherConfigs);
2541             OvsdbTerminationPointAugmentation updateFromOperationalTerminationPointAugmenation =
2542                     getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeName,
2543                             LogicalDatastoreType.OPERATIONAL, TERMINATION_POINT_TEST_INDEX);
2544             List<PortOtherConfigs> updateFromOperationalOtherConfigs =
2545                     updateFromOperationalTerminationPointAugmenation.getPortOtherConfigs();
2546             if (updateFromOperationalOtherConfigs != null) {
2547                 updateFromOperationalOtherConfigs = updateFromOperationalTerminationPointAugmenation
2548                         .getPortOtherConfigs();
2549             } else {
2550                 updateFromOperationalOtherConfigs = null;
2551             }
2552             assertExpectedPortOtherConfigsExist(updateFromExpectedOtherConfigs,
2553                     updateFromOperationalOtherConfigs);
2554
2555             // UPDATE:  update the other_configs
2556             testBridgeNodeId = getBridgeNode(connectionInfo, testBridgeName).getNodeId();
2557             OvsdbTerminationPointAugmentationBuilder tpUpdateAugmentationBuilder =
2558                     new OvsdbTerminationPointAugmentationBuilder();
2559             tpUpdateAugmentationBuilder.setPortOtherConfigs(updateToInputOtherConfigs);
2560             InstanceIdentifier<Node> portIid = SouthboundMapper.createInstanceIdentifier(testBridgeNodeId);
2561             NodeBuilder portUpdateNodeBuilder = new NodeBuilder();
2562             NodeId portUpdateNodeId = createManagedNodeId(portIid);
2563             portUpdateNodeBuilder.setNodeId(portUpdateNodeId);
2564             TerminationPointBuilder tpUpdateBuilder = new TerminationPointBuilder();
2565             tpUpdateBuilder.setKey(new TerminationPointKey(new TpId(testPortName)));
2566             tpUpdateBuilder.addAugmentation(
2567                     OvsdbTerminationPointAugmentation.class,
2568                     tpUpdateAugmentationBuilder.build());
2569             portUpdateNodeBuilder.setTerminationPoint(Lists.newArrayList(tpUpdateBuilder.build()));
2570             boolean result = mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
2571                     portIid, portUpdateNodeBuilder.build());
2572             Thread.sleep(OVSDB_UPDATE_TIMEOUT);
2573             Assert.assertTrue(result);
2574
2575             // READ: the test port and ensure changes are propagated to the CONFIGURATION data store,
2576             // then repeat for OPERATIONAL data store
2577             OvsdbTerminationPointAugmentation updateToConfigurationTerminationPointAugmentation =
2578                     getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeName,
2579                             LogicalDatastoreType.CONFIGURATION, TERMINATION_POINT_TEST_INDEX);
2580             List<PortOtherConfigs> updateToConfigurationOtherConfigs = updateToConfigurationTerminationPointAugmentation
2581                     .getPortOtherConfigs();
2582             assertExpectedPortOtherConfigsExist(updateToExpectedOtherConfigs,
2583                     updateToConfigurationOtherConfigs);
2584             assertExpectedPortOtherConfigsExist(updateFromExpectedOtherConfigs,
2585                     updateToConfigurationOtherConfigs);
2586             OvsdbTerminationPointAugmentation updateToOperationalTerminationPointAugmentation =
2587                     getOvsdbTerminationPointAugmentation(connectionInfo, testBridgeName,
2588                             LogicalDatastoreType.OPERATIONAL, TERMINATION_POINT_TEST_INDEX);
2589             List<PortOtherConfigs> updateToOperationalOtherConfigs = updateToOperationalTerminationPointAugmentation
2590                     .getPortOtherConfigs();
2591             if (updateFromExpectedOtherConfigs != null) {
2592                 assertExpectedPortOtherConfigsExist(updateToExpectedOtherConfigs,
2593                         updateToOperationalOtherConfigs);
2594                 assertExpectedPortOtherConfigsExist(updateFromExpectedOtherConfigs,
2595                         updateToOperationalOtherConfigs);
2596             }
2597
2598             // DELETE
2599             Assert.assertTrue(deleteBridge(connectionInfo, testBridgeName));
2600         }
2601     }
2602
2603     @Test
2604     public void testCRUDTerminationPointVlan() throws InterruptedException {
2605         final Integer CREATED_VLAN_ID = new Integer(4000);
2606         final Integer UPDATED_VLAN_ID = new Integer(4001);
2607
2608         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
2609         connectOvsdbNode(connectionInfo);
2610
2611         // CREATE
2612         Assert.assertTrue(addBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME));
2613         OvsdbBridgeAugmentation bridge = getBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME);
2614         Assert.assertNotNull(bridge);
2615         NodeId nodeId = createManagedNodeId(createInstanceIdentifier(
2616                 connectionInfo, bridge.getBridgeName()));
2617         OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
2618                 createGenericOvsdbTerminationPointAugmentationBuilder();
2619         String portName = "testTerminationPointVlanId";
2620         ovsdbTerminationBuilder.setName(portName);
2621         ovsdbTerminationBuilder.setVlanTag(new VlanId(CREATED_VLAN_ID));
2622         Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
2623         InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
2624         Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
2625         Assert.assertNotNull(terminationPointNode);
2626
2627         // READ
2628         List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
2629         OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation = null;
2630         for (TerminationPoint terminationPoint : terminationPoints) {
2631             ovsdbTerminationPointAugmentation = terminationPoint.getAugmentation(
2632                     OvsdbTerminationPointAugmentation.class);
2633             if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
2634                 VlanId actualVlanId = ovsdbTerminationPointAugmentation.getVlanTag();
2635                 Assert.assertNotNull(actualVlanId);
2636                 Integer actualVlanIdInt = actualVlanId.getValue();
2637                 Assert.assertEquals(CREATED_VLAN_ID, actualVlanIdInt);
2638             }
2639         }
2640
2641         // UPDATE
2642         NodeId testBridgeNodeId = getBridgeNode(connectionInfo, SouthboundITConstants.BRIDGE_NAME).getNodeId();
2643         OvsdbTerminationPointAugmentationBuilder tpUpdateAugmentationBuilder =
2644                 new OvsdbTerminationPointAugmentationBuilder();
2645         tpUpdateAugmentationBuilder.setVlanTag(new VlanId(UPDATED_VLAN_ID));
2646         InstanceIdentifier<Node> portIid = SouthboundMapper.createInstanceIdentifier(testBridgeNodeId);
2647         NodeBuilder portUpdateNodeBuilder = new NodeBuilder();
2648         NodeId portUpdateNodeId = createManagedNodeId(portIid);
2649         portUpdateNodeBuilder.setNodeId(portUpdateNodeId);
2650         TerminationPointBuilder tpUpdateBuilder = new TerminationPointBuilder();
2651         tpUpdateBuilder.setKey(new TerminationPointKey(new TpId(portName)));
2652         tpUpdateBuilder.addAugmentation(
2653                 OvsdbTerminationPointAugmentation.class,
2654                 tpUpdateAugmentationBuilder.build());
2655         tpUpdateBuilder.setTpId(new TpId(portName));
2656         portUpdateNodeBuilder.setTerminationPoint(Lists.newArrayList(tpUpdateBuilder.build()));
2657         boolean result = mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
2658                 portIid, portUpdateNodeBuilder.build());
2659         Assert.assertTrue(result);
2660         Thread.sleep(OVSDB_UPDATE_TIMEOUT);
2661
2662         terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
2663         terminationPoints = terminationPointNode.getTerminationPoint();
2664         for (TerminationPoint terminationPoint : terminationPoints) {
2665             ovsdbTerminationPointAugmentation = terminationPoint.getAugmentation(
2666                     OvsdbTerminationPointAugmentation.class);
2667             if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
2668                 VlanId actualVlanId = ovsdbTerminationPointAugmentation.getVlanTag();
2669                 Assert.assertNotNull(actualVlanId);
2670                 Integer actualVlanIdInt = actualVlanId.getValue();
2671                 Assert.assertEquals(UPDATED_VLAN_ID, actualVlanIdInt);
2672             }
2673         }
2674
2675         // DELETE
2676         Assert.assertTrue(deleteBridge(connectionInfo));
2677         Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
2678     }
2679
2680     @Test
2681     public void testCRUDTerminationPointVlanModes() throws InterruptedException {
2682         final VlanMode UPDATED_VLAN_MODE = VlanMode.Access;
2683         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
2684         connectOvsdbNode(connectionInfo);
2685         VlanMode []vlanModes = VlanMode.values();
2686         for (VlanMode vlanMode : vlanModes) {
2687             // CREATE
2688             Assert.assertTrue(addBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME));
2689             OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
2690             Assert.assertNotNull(bridge);
2691             NodeId nodeId = createManagedNodeId(createInstanceIdentifier(
2692                     connectionInfo, bridge.getBridgeName()));
2693             OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
2694                     createGenericOvsdbTerminationPointAugmentationBuilder();
2695             String portName = "testTerminationPointVlanMode" + vlanMode.toString();
2696             ovsdbTerminationBuilder.setName(portName);
2697             ovsdbTerminationBuilder.setVlanMode(vlanMode);
2698             Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
2699             InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
2700             Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
2701             Assert.assertNotNull(terminationPointNode);
2702
2703             // READ
2704             List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
2705             for (TerminationPoint terminationPoint : terminationPoints) {
2706                 OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
2707                         terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
2708                 if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
2709                     //test
2710                     Assert.assertTrue(ovsdbTerminationPointAugmentation.getVlanMode().equals(vlanMode));
2711                 }
2712             }
2713
2714             // UPDATE
2715             NodeId testBridgeNodeId = getBridgeNode(connectionInfo, SouthboundITConstants.BRIDGE_NAME).getNodeId();
2716             OvsdbTerminationPointAugmentationBuilder tpUpdateAugmentationBuilder =
2717                     new OvsdbTerminationPointAugmentationBuilder();
2718             tpUpdateAugmentationBuilder.setVlanMode(UPDATED_VLAN_MODE);
2719             InstanceIdentifier<Node> portIid = SouthboundMapper.createInstanceIdentifier(testBridgeNodeId);
2720             NodeBuilder portUpdateNodeBuilder = new NodeBuilder();
2721             NodeId portUpdateNodeId = createManagedNodeId(portIid);
2722             portUpdateNodeBuilder.setNodeId(portUpdateNodeId);
2723             TerminationPointBuilder tpUpdateBuilder = new TerminationPointBuilder();
2724             tpUpdateBuilder.setKey(new TerminationPointKey(new TpId(portName)));
2725             tpUpdateBuilder.addAugmentation(
2726                     OvsdbTerminationPointAugmentation.class,
2727                     tpUpdateAugmentationBuilder.build());
2728             tpUpdateBuilder.setTpId(new TpId(portName));
2729             portUpdateNodeBuilder.setTerminationPoint(Lists.newArrayList(tpUpdateBuilder.build()));
2730             boolean result = mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
2731                     portIid, portUpdateNodeBuilder.build());
2732             Assert.assertTrue(result);
2733             Thread.sleep(OVSDB_UPDATE_TIMEOUT);
2734
2735             terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
2736             terminationPoints = terminationPointNode.getTerminationPoint();
2737             for (TerminationPoint terminationPoint : terminationPoints) {
2738                 OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
2739                         terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
2740                 if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
2741                     //test
2742                     Assert.assertEquals(UPDATED_VLAN_MODE, ovsdbTerminationPointAugmentation.getVlanMode());
2743                 }
2744             }
2745
2746             // DELETE
2747             Assert.assertTrue(deleteBridge(connectionInfo));
2748         }
2749         Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
2750     }
2751
2752     private ArrayList<Set<Integer>> generateVlanSets() {
2753         ArrayList<Set<Integer>> vlanSets = new ArrayList<Set<Integer>>();
2754
2755         Set<Integer> emptySet = new HashSet<Integer>();
2756         vlanSets.add(emptySet);
2757
2758         Set<Integer> singleSet = new HashSet<Integer>();
2759         Integer single = new Integer(2222);
2760         singleSet.add(single);
2761         vlanSets.add(singleSet);
2762
2763         Set<Integer> minMaxMiddleSet = new HashSet<Integer>();
2764         Integer min = new Integer(0);
2765         minMaxMiddleSet.add(min);
2766         Integer max = new Integer(4095);
2767         minMaxMiddleSet.add(max);
2768         Integer minPlusOne = new Integer(min + 1);
2769         minMaxMiddleSet.add(minPlusOne);
2770         Integer maxMinusOne = new Integer(max - 1);
2771         minMaxMiddleSet.add(maxMinusOne);
2772         Integer middle = new Integer((max - min) / 2);
2773         minMaxMiddleSet.add(middle);
2774         vlanSets.add(minMaxMiddleSet);
2775
2776         return vlanSets;
2777     }
2778
2779     private List<Trunks> buildTrunkList(Set<Integer> trunkSet) {
2780         List<Trunks> trunkList = Lists.newArrayList();
2781         for (Integer trunk : trunkSet) {
2782             TrunksBuilder trunkBuilder = new TrunksBuilder();
2783             trunkBuilder.setTrunk(new VlanId(trunk));
2784             trunkList.add(trunkBuilder.build());
2785         }
2786         return trunkList;
2787     }
2788
2789     @Test
2790     public void testCRUDTerminationPointVlanTrunks() throws InterruptedException {
2791         final List<Trunks> UPDATED_TRUNKS = buildTrunkList(Sets.newHashSet(2011));
2792         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
2793         connectOvsdbNode(connectionInfo);
2794         Iterable<Set<Integer>> vlanSets = generateVlanSets();
2795         int testCase = 0;
2796         for (Set<Integer> vlanSet : vlanSets) {
2797             ++testCase;
2798             // CREATE
2799             Assert.assertTrue(addBridge(connectionInfo, SouthboundITConstants.BRIDGE_NAME));
2800             OvsdbBridgeAugmentation bridge = getBridge(connectionInfo);
2801             Assert.assertNotNull(bridge);
2802             NodeId nodeId = createManagedNodeId(createInstanceIdentifier(
2803                     connectionInfo, bridge.getBridgeName()));
2804             OvsdbTerminationPointAugmentationBuilder ovsdbTerminationBuilder =
2805                     createGenericOvsdbTerminationPointAugmentationBuilder();
2806             String portName = "testTerminationPointVlanTrunks" + testCase;
2807             ovsdbTerminationBuilder.setName(portName);
2808             List<Trunks> trunks = buildTrunkList(vlanSet);
2809             ovsdbTerminationBuilder.setTrunks(trunks);
2810             Assert.assertTrue(addTerminationPoint(nodeId, portName, ovsdbTerminationBuilder));
2811             InstanceIdentifier<Node> terminationPointIid = getTpIid(connectionInfo, bridge);
2812             Node terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
2813             Assert.assertNotNull(terminationPointNode);
2814
2815             // READ
2816             List<TerminationPoint> terminationPoints = terminationPointNode.getTerminationPoint();
2817             for (TerminationPoint terminationPoint : terminationPoints) {
2818                 OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
2819                         terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
2820                 if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
2821                     List<Trunks> actualTrunks = ovsdbTerminationPointAugmentation.getTrunks();
2822                     for (Trunks trunk : trunks) {
2823                         Assert.assertTrue(actualTrunks.contains(trunk));
2824                     }
2825                 }
2826             }
2827
2828
2829             // UPDATE
2830             NodeId testBridgeNodeId = getBridgeNode(connectionInfo, SouthboundITConstants.BRIDGE_NAME).getNodeId();
2831             OvsdbTerminationPointAugmentationBuilder tpUpdateAugmentationBuilder =
2832                     new OvsdbTerminationPointAugmentationBuilder();
2833             tpUpdateAugmentationBuilder.setTrunks(UPDATED_TRUNKS);
2834             InstanceIdentifier<Node> portIid = SouthboundMapper.createInstanceIdentifier(testBridgeNodeId);
2835             NodeBuilder portUpdateNodeBuilder = new NodeBuilder();
2836             NodeId portUpdateNodeId = createManagedNodeId(portIid);
2837             portUpdateNodeBuilder.setNodeId(portUpdateNodeId);
2838             TerminationPointBuilder tpUpdateBuilder = new TerminationPointBuilder();
2839             tpUpdateBuilder.setKey(new TerminationPointKey(new TpId(portName)));
2840             tpUpdateBuilder.addAugmentation(
2841                     OvsdbTerminationPointAugmentation.class,
2842                     tpUpdateAugmentationBuilder.build());
2843             tpUpdateBuilder.setTpId(new TpId(portName));
2844             portUpdateNodeBuilder.setTerminationPoint(Lists.newArrayList(tpUpdateBuilder.build()));
2845             boolean result = mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION,
2846                     portIid, portUpdateNodeBuilder.build());
2847             Assert.assertTrue(result);
2848             Thread.sleep(OVSDB_UPDATE_TIMEOUT);
2849
2850             terminationPointNode = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, terminationPointIid);
2851             terminationPoints = terminationPointNode.getTerminationPoint();
2852             for (TerminationPoint terminationPoint : terminationPoints) {
2853                 OvsdbTerminationPointAugmentation ovsdbTerminationPointAugmentation =
2854                         terminationPoint.getAugmentation(OvsdbTerminationPointAugmentation.class);
2855                 if (ovsdbTerminationPointAugmentation.getName().equals(portName)) {
2856                     //test
2857                     Assert.assertEquals(UPDATED_TRUNKS, ovsdbTerminationPointAugmentation.getTrunks());
2858                 }
2859             }
2860
2861             // DELETE
2862             Assert.assertTrue(deleteBridge(connectionInfo));
2863         }
2864         Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
2865     }
2866
2867     @Test
2868     public void testGetOvsdbNodes() throws InterruptedException {
2869         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
2870         connectOvsdbNode(connectionInfo);
2871         InstanceIdentifier<Topology> topologyPath = InstanceIdentifier
2872                 .create(NetworkTopology.class)
2873                 .child(Topology.class, new TopologyKey(SouthboundConstants.OVSDB_TOPOLOGY_ID));
2874
2875         Topology topology = mdsalUtils.read(LogicalDatastoreType.OPERATIONAL, topologyPath);
2876         InstanceIdentifier<Node> expectedNodeIid = createInstanceIdentifier(connectionInfo);
2877         NodeId expectedNodeId = expectedNodeIid.firstKeyOf(Node.class, NodeKey.class).getNodeId();
2878         Node foundNode = null;
2879         Assert.assertNotNull("Expected to find topology: " + topologyPath, topology);
2880         Assert.assertNotNull("Expected to find some nodes" + topology.getNode());
2881         LOG.info("expectedNodeId: {}, getNode: {}", expectedNodeId, topology.getNode());
2882         for (Node node : topology.getNode()) {
2883             if (node.getNodeId().getValue().equals(expectedNodeId.getValue())) {
2884                 foundNode = node;
2885                 break;
2886             }
2887         }
2888         Assert.assertNotNull("Expected to find Node: " + expectedNodeId, foundNode);
2889         Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
2890     }
2891
2892     /*
2893      * Generates the test cases involved in testing BridgeOtherConfigs.  See inline comments for descriptions of
2894      * the particular cases considered.
2895      *
2896      * The return value is a Map in the form (K,V)=(testCaseName,testCase).
2897      * - testCaseName is a String
2898      * - testCase is a Map in the form (K,V) s.t. K=(EXPECTED_VALUES_KEY|INPUT_VALUES_KEY) and V is a List of
2899      *     either corresponding INPUT bridge other_configs, or EXPECTED bridge other_configs
2900      *     INPUT is the List we use when calling BridgeAugmentationBuilder.setBridgeOtherConfigs()
2901      *     EXPECTED is the List we expect to receive after calling BridgeAugmentationBuilder.getBridgeOtherConfigs()
2902      */
2903     private Map<String, Map<String, List<BridgeOtherConfigs>>> generateBridgeOtherConfigsTestCases() {
2904         Map<String, Map<String, List<BridgeOtherConfigs>>> testMap =
2905                 new HashMap<String, Map<String, List<BridgeOtherConfigs>>>();
2906
2907         final String BRIDGE_OTHER_CONFIGS_KEY = "BridgeOtherConfigKey";
2908         final String BRIDGE_OTHER_CONFIGS_VALUE = "BridgeOtherConfigValue";
2909         final String FORMAT_STR = "%s_%s_%d";
2910         final String GOOD_KEY = "GoodKey";
2911         final String GOOD_VALUE = "GoodValue";
2912         final String NO_VALUE_FOR_KEY = "NoValueForKey";
2913         final String NO_KEY_FOR_VALUE = "NoKeyForValue";
2914
2915         // Test Case 1:  TestOneOtherConfig
2916         // Test Type:    Positive
2917         // Description:  Create a bridge with one other_config
2918         // Expected:     A bridge is created with the single other_config specified below
2919         final String testOneOtherConfigName = "TestOneOtherConfig";
2920         int otherConfigCounter = 0;
2921         List<BridgeOtherConfigs> oneOtherConfig = (List<BridgeOtherConfigs>) Lists.newArrayList(
2922                 (new BridgeOtherConfigsBuilder()
2923                         .setBridgeOtherConfigKey(String.format(FORMAT_STR, testOneOtherConfigName,
2924                                 BRIDGE_OTHER_CONFIGS_KEY, ++otherConfigCounter))
2925                         .setBridgeOtherConfigValue(String.format(FORMAT_STR, testOneOtherConfigName,
2926                                 BRIDGE_OTHER_CONFIGS_VALUE, otherConfigCounter))
2927                         .build()));
2928         Map<String,List<BridgeOtherConfigs>> testCase = Maps.newHashMap();
2929         testCase.put(EXPECTED_VALUES_KEY, oneOtherConfig);
2930         testCase.put(INPUT_VALUES_KEY, oneOtherConfig);
2931         testMap.put(testOneOtherConfigName, testCase);
2932
2933         // Test Case 2:  TestFiveOtherConfig
2934         // Test Type:    Positive
2935         // Description:  Create a bridge with multiple (five) other_configs
2936         // Expected:     A bridge is created with the five other_configs specified below
2937         final String testFiveOtherConfigName = "TestFiveOtherConfig";
2938         otherConfigCounter = 0;
2939         List<BridgeOtherConfigs> fiveOtherConfig = (List<BridgeOtherConfigs>) Lists.newArrayList(
2940                 (new BridgeOtherConfigsBuilder()
2941                         .setBridgeOtherConfigKey(String.format(FORMAT_STR, testFiveOtherConfigName,
2942                                 BRIDGE_OTHER_CONFIGS_KEY, ++otherConfigCounter))
2943                         .setBridgeOtherConfigValue(String.format(FORMAT_STR, testFiveOtherConfigName,
2944                                 BRIDGE_OTHER_CONFIGS_VALUE, otherConfigCounter))
2945                         .build()),
2946                 (new BridgeOtherConfigsBuilder()
2947                         .setBridgeOtherConfigKey(String.format(FORMAT_STR, testFiveOtherConfigName,
2948                                 BRIDGE_OTHER_CONFIGS_KEY, ++otherConfigCounter))
2949                         .setBridgeOtherConfigValue(String.format(FORMAT_STR, testFiveOtherConfigName,
2950                                 BRIDGE_OTHER_CONFIGS_VALUE, otherConfigCounter))
2951                         .build()),
2952                 (new BridgeOtherConfigsBuilder()
2953                         .setBridgeOtherConfigKey(String.format(FORMAT_STR, testFiveOtherConfigName,
2954                                 BRIDGE_OTHER_CONFIGS_KEY, ++otherConfigCounter))
2955                         .setBridgeOtherConfigValue(String.format(FORMAT_STR, testFiveOtherConfigName,
2956                                 BRIDGE_OTHER_CONFIGS_VALUE, otherConfigCounter))
2957                         .build()),
2958                 (new BridgeOtherConfigsBuilder()
2959                         .setBridgeOtherConfigKey(String.format(FORMAT_STR, testFiveOtherConfigName,
2960                                 BRIDGE_OTHER_CONFIGS_KEY, ++otherConfigCounter))
2961                         .setBridgeOtherConfigValue(String.format(FORMAT_STR, testFiveOtherConfigName,
2962                                 BRIDGE_OTHER_CONFIGS_VALUE, otherConfigCounter))
2963                         .build()),
2964                 (new BridgeOtherConfigsBuilder()
2965                         .setBridgeOtherConfigKey(String.format(FORMAT_STR, testFiveOtherConfigName,
2966                                 BRIDGE_OTHER_CONFIGS_KEY, ++otherConfigCounter))
2967                         .setBridgeOtherConfigValue(String.format(FORMAT_STR, testFiveOtherConfigName,
2968                                 BRIDGE_OTHER_CONFIGS_VALUE, otherConfigCounter))
2969                         .build()));
2970         testCase = Maps.newHashMap();
2971         testCase.put(EXPECTED_VALUES_KEY, fiveOtherConfig);
2972         testCase.put(INPUT_VALUES_KEY, fiveOtherConfig);
2973         testMap.put(testFiveOtherConfigName, testCase);
2974
2975         // Test Case 3:  TestOneGoodOtherConfigOneMalformedOtherConfigValue
2976         // Test Type:    Negative
2977         // Description:
2978         //     One perfectly fine BridgeOtherConfig
2979         //        (TestOneGoodOtherConfigOneMalformedOtherConfigValue_BridgeOtherConfigKey_1,
2980         //        TestOneGoodOtherConfigOneMalformedOtherConfig_BridgeOtherConfigValue_1)
2981         //     and one malformed BridgeOtherConfig which only has key specified
2982         //        (TestOneGoodOtherConfigOneMalformedOtherConfigValue_NoValueForKey_2,
2983         //        UNSPECIFIED)
2984         // Expected:     A bridge is created without any other_config
2985         final String testOneGoodOtherConfigOneMalformedOtherConfigValueName =
2986                 "TestOneGoodOtherConfigOneMalformedOtherConfigValue";
2987         otherConfigCounter = 0;
2988         BridgeOtherConfigs oneGood = new BridgeOtherConfigsBuilder()
2989                 .setBridgeOtherConfigKey(String.format(FORMAT_STR,
2990                         testOneGoodOtherConfigOneMalformedOtherConfigValueName, GOOD_KEY, ++otherConfigCounter))
2991                 .setBridgeOtherConfigValue(String.format(FORMAT_STR,
2992                         testOneGoodOtherConfigOneMalformedOtherConfigValueName,
2993                         GOOD_VALUE, otherConfigCounter))
2994                 .build();
2995         BridgeOtherConfigs oneBad = new BridgeOtherConfigsBuilder()
2996                 .setBridgeOtherConfigKey(String.format(FORMAT_STR,
2997                         testOneGoodOtherConfigOneMalformedOtherConfigValueName, NO_VALUE_FOR_KEY, ++otherConfigCounter))
2998                 .build();
2999         List<BridgeOtherConfigs> oneGoodOneBadInput = (List<BridgeOtherConfigs>) Lists.newArrayList(
3000                 oneGood, oneBad);
3001         List<BridgeOtherConfigs> oneGoodOneBadExpected = null;
3002         testCase = Maps.newHashMap();
3003         testCase.put(INPUT_VALUES_KEY, oneGoodOneBadInput);
3004         testCase.put(EXPECTED_VALUES_KEY, oneGoodOneBadExpected);
3005         testMap.put(testOneGoodOtherConfigOneMalformedOtherConfigValueName, testCase);
3006
3007         // Test Case 4:  TestOneGoodOtherConfigOneMalformedOtherConfigKey
3008         // Test Type:    Negative
3009         // Description:
3010         //     One perfectly fine BridgeOtherConfig
3011         //        (TestOneGoodOtherConfigOneMalformedOtherConfigValue_BridgeOtherConfigKey_1,
3012         //        TestOneGoodOtherConfigOneMalformedOtherConfig_BridgeOtherConfigValue_1)
3013         //     and one malformed BridgeOtherConfig which only has key specified
3014         //        (UNSPECIFIED,
3015         //        TestOneGoodOtherConfigOneMalformedOtherConfigKey_NoKeyForValue_2)
3016         // Expected:     A bridge is created without any other_config
3017         final String testOneGoodOtherConfigOneMalformedOtherConfigKeyName =
3018                 "TestOneGoodOtherConfigOneMalformedOtherConfigIdKey";
3019         otherConfigCounter = 0;
3020         oneGood = new BridgeOtherConfigsBuilder()
3021                 .setBridgeOtherConfigKey(String.format(FORMAT_STR, testOneGoodOtherConfigOneMalformedOtherConfigKeyName,
3022                         GOOD_KEY, ++otherConfigCounter))
3023                 .setBridgeOtherConfigValue(String.format(FORMAT_STR,
3024                         testOneGoodOtherConfigOneMalformedOtherConfigKeyName,
3025                         GOOD_VALUE, otherConfigCounter))
3026                 .build();
3027         oneBad = new BridgeOtherConfigsBuilder()
3028                 .setBridgeOtherConfigKey(String.format(FORMAT_STR,
3029                         testOneGoodOtherConfigOneMalformedOtherConfigKeyName, NO_KEY_FOR_VALUE, ++otherConfigCounter))
3030                 .build();
3031         oneGoodOneBadInput = (List<BridgeOtherConfigs>) Lists.newArrayList(
3032                 oneGood, oneBad);
3033         oneGoodOneBadExpected = null;
3034         testCase = Maps.newHashMap();
3035         testCase.put(INPUT_VALUES_KEY, oneGoodOneBadInput);
3036         testCase.put(EXPECTED_VALUES_KEY, oneGoodOneBadExpected);
3037         testMap.put(testOneGoodOtherConfigOneMalformedOtherConfigKeyName, testCase);
3038
3039         return testMap;
3040     }
3041
3042     /*
3043      * @see <code>SouthboundIT.testCRUDBridgeOtherConfigs()</code>
3044      * This is helper test method to compare a test "set" of BridgeExternalIds against an expected "set"
3045      */
3046     private void assertExpectedBridgeOtherConfigsExist( List<BridgeOtherConfigs> expected,
3047                                                         List<BridgeOtherConfigs> test ) {
3048
3049         if (expected != null) {
3050             for (BridgeOtherConfigs expectedOtherConfig : expected) {
3051                 Assert.assertTrue(test.contains(expectedOtherConfig));
3052             }
3053         }
3054     }
3055
3056     /*
3057      * @see <code>SouthboundIT.generateBridgeOtherConfigsTestCases()</code> for specific test case information.
3058      */
3059     @Test
3060     public void testCRUDBridgeOtherConfigs() throws InterruptedException {
3061         final String TEST_BRIDGE_PREFIX = "CRUDBridgeOtherConfigs";
3062         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
3063         connectOvsdbNode(connectionInfo);
3064         // updateFromTestCases represent the original test case value.  updateToTestCases represent the new value after
3065         // the update has been performed.
3066         Map<String, Map<String, List<BridgeOtherConfigs>>> updateFromTestCases = generateBridgeOtherConfigsTestCases();
3067         Map<String, Map<String, List<BridgeOtherConfigs>>> updateToTestCases = generateBridgeOtherConfigsTestCases();
3068         Map<String, List<BridgeOtherConfigs>> updateFromTestCase;
3069         Map<String, List<BridgeOtherConfigs>> updateToTestCase;
3070         List<BridgeOtherConfigs> updateFromInputOtherConfigs;
3071         List<BridgeOtherConfigs> updateFromExpectedOtherConfigs;
3072         List<BridgeOtherConfigs> updateToInputOtherConfigs;
3073         List<BridgeOtherConfigs> updateToExpectedOtherConfigs;
3074         String testBridgeName;
3075
3076         int counter = 1;
3077         ExecutorService executor = Executors.newFixedThreadPool(NUM_THREADS);
3078         for (String updateFromTestCaseKey : updateFromTestCases.keySet()) {
3079             updateFromTestCase = updateFromTestCases.get(updateFromTestCaseKey);
3080             updateFromInputOtherConfigs = updateFromTestCase.get(INPUT_VALUES_KEY);
3081             updateFromExpectedOtherConfigs = updateFromTestCase.get(EXPECTED_VALUES_KEY);
3082             for (String testCaseKey : updateToTestCases.keySet()) {
3083                 testBridgeName = String.format("%s_%s_%d", TEST_BRIDGE_PREFIX, testCaseKey, counter);
3084                 counter += 1;
3085                 updateToTestCase = updateToTestCases.get(testCaseKey);
3086                 updateToInputOtherConfigs = updateToTestCase.get(INPUT_VALUES_KEY);
3087                 updateToExpectedOtherConfigs = updateToTestCase.get(EXPECTED_VALUES_KEY);
3088
3089                 TestCRUDBridgeOtherConfigsRunnable testRunnable =
3090                         new TestCRUDBridgeOtherConfigsRunnable(
3091                                 connectionInfo, testBridgeName,
3092                                 updateFromInputOtherConfigs,
3093                                 updateFromExpectedOtherConfigs,
3094                                 updateToInputOtherConfigs,
3095                                 updateToExpectedOtherConfigs);
3096                 executor.submit(testRunnable);
3097             }
3098         }
3099         executor.shutdown();
3100         executor.awaitTermination(5, TimeUnit.MINUTES);
3101
3102         Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
3103     }
3104
3105     class TestCRUDBridgeOtherConfigsRunnable implements Runnable {
3106
3107         ConnectionInfo connectionInfo;
3108         String testBridgeName;
3109         List<BridgeOtherConfigs> updateFromInputOtherConfigs;
3110         List<BridgeOtherConfigs> updateFromExpectedOtherConfigs;
3111         List<BridgeOtherConfigs> updateToInputOtherConfigs;
3112         List<BridgeOtherConfigs> updateToExpectedOtherConfigs;
3113
3114         TestCRUDBridgeOtherConfigsRunnable(
3115                 ConnectionInfo connectionInfo, String testBridgeName,
3116                 List<BridgeOtherConfigs> updateFromInputOtherConfigs,
3117                 List<BridgeOtherConfigs> updateFromExpectedOtherConfigs,
3118                 List<BridgeOtherConfigs> updateToInputOtherConfigs,
3119                 List<BridgeOtherConfigs> updateToExpectedOtherConfigs) {
3120
3121             this.connectionInfo = connectionInfo;
3122             this.testBridgeName = testBridgeName;
3123             this.updateFromInputOtherConfigs = updateFromInputOtherConfigs;
3124             this.updateFromExpectedOtherConfigs = updateFromExpectedOtherConfigs;
3125             this.updateToInputOtherConfigs = updateToInputOtherConfigs;
3126             this.updateToExpectedOtherConfigs = updateToExpectedOtherConfigs;
3127         }
3128
3129         @Override
3130         public void run() {
3131             try {
3132                 test();
3133             } catch (InterruptedException e) {
3134                 e.printStackTrace();
3135             }
3136         }
3137
3138         public void test() throws InterruptedException {
3139             // CREATE: Create the test bridge
3140             boolean bridgeAdded = addBridge(connectionInfo, null,
3141                     testBridgeName, null, true, SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"),
3142                     true, null, null, null, updateFromInputOtherConfigs);
3143             Assert.assertTrue(bridgeAdded);
3144
3145             // READ: Read the test bridge and ensure changes are propagated to the CONFIGURATION data store,
3146             // then repeat for OPERATIONAL data store
3147             List<BridgeOtherConfigs> updateFromConfigurationOtherConfigs = getBridge(connectionInfo, testBridgeName,
3148                     LogicalDatastoreType.CONFIGURATION).getBridgeOtherConfigs();
3149             assertExpectedBridgeOtherConfigsExist(updateFromExpectedOtherConfigs,
3150                     updateFromConfigurationOtherConfigs);
3151             List<BridgeOtherConfigs> updateFromOperationalOtherConfigs = getBridge(connectionInfo, testBridgeName)
3152                     .getBridgeOtherConfigs();
3153             assertExpectedBridgeOtherConfigsExist(updateFromExpectedOtherConfigs,
3154                     updateFromOperationalOtherConfigs);
3155
3156             // UPDATE:  update the external_ids
3157             OvsdbBridgeAugmentationBuilder bridgeAugmentationBuilder = new OvsdbBridgeAugmentationBuilder();
3158             bridgeAugmentationBuilder.setBridgeOtherConfigs(updateToInputOtherConfigs);
3159             InstanceIdentifier<Node> bridgeIid =
3160                     createInstanceIdentifier(connectionInfo,
3161                             new OvsdbBridgeName(testBridgeName));
3162             NodeBuilder bridgeNodeBuilder = new NodeBuilder();
3163             Node bridgeNode = getBridgeNode(connectionInfo, testBridgeName);
3164             bridgeNodeBuilder.setNodeId(bridgeNode.getNodeId());
3165             bridgeNodeBuilder.setKey(bridgeNode.getKey());
3166             bridgeNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class, bridgeAugmentationBuilder.build());
3167             boolean result = mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, bridgeIid,
3168                     bridgeNodeBuilder.build());
3169             Thread.sleep(OVSDB_UPDATE_TIMEOUT);
3170             Assert.assertTrue(result);
3171
3172             // READ: the test bridge and ensure changes are propagated to the CONFIGURATION data store,
3173             // then repeat for OPERATIONAL data store
3174             List<BridgeOtherConfigs> updateToConfigurationOtherConfigs = getBridge(connectionInfo, testBridgeName,
3175                     LogicalDatastoreType.CONFIGURATION).getBridgeOtherConfigs();
3176             assertExpectedBridgeOtherConfigsExist(updateToExpectedOtherConfigs, updateToConfigurationOtherConfigs);
3177             assertExpectedBridgeOtherConfigsExist(updateFromExpectedOtherConfigs,
3178                     updateToConfigurationOtherConfigs);
3179             List<BridgeOtherConfigs> updateToOperationalOtherConfigs = getBridge(connectionInfo, testBridgeName)
3180                     .getBridgeOtherConfigs();
3181             if (updateFromExpectedOtherConfigs != null) {
3182                 assertExpectedBridgeOtherConfigsExist(updateToExpectedOtherConfigs,
3183                         updateToOperationalOtherConfigs);
3184                 assertExpectedBridgeOtherConfigsExist(updateFromExpectedOtherConfigs,
3185                         updateToOperationalOtherConfigs);
3186             }
3187
3188             // DELETE
3189             Assert.assertTrue(deleteBridge(connectionInfo, testBridgeName));
3190         }
3191     }
3192
3193     /*
3194      * Generates the test cases involved in testing BridgeExternalIds.  See inline comments for descriptions of
3195      * the particular cases considered.
3196      *
3197      * The return value is a Map in the form (K,V)=(testCaseName,testCase).
3198      * - testCaseName is a String
3199      * - testCase is a Map in the form (K,V) s.t. K=(EXPECTED_VALUES_KEY|INPUT_VALUES_KEY) and V is a List of
3200      *     either corresponding INPUT bridge external ids, or EXPECTED bridge external ids
3201      *     INPUT is the List we use when calling BridgeAugmentationBuilder.setBridgeExternalIds()
3202      *     EXPECTED is the List we expect to receive after calling BridgeAugmentationBuilder.getBridgeExternalIds()
3203      */
3204     private Map<String, Map<String, List<BridgeExternalIds>>> generateBridgeExternalIdsTestCases() {
3205         Map<String, Map<String, List<BridgeExternalIds>>> testMap =
3206                 new HashMap<String, Map<String, List<BridgeExternalIds>>>();
3207
3208         final String BRIDGE_EXTERNAL_ID_KEY = "BridgeExternalIdKey";
3209         final String BRIDGE_EXTERNAL_ID_VALUE = "BridgeExternalIdValue";
3210         final String FORMAT_STR = "%s_%s_%d";
3211         final String GOOD_KEY = "GoodKey";
3212         final String GOOD_VALUE = "GoodValue";
3213         final String NO_VALUE_FOR_KEY = "NoValueForKey";
3214         final String NO_KEY_FOR_VALUE = "NoKeyForValue";
3215
3216         // Test Case 1:  TestOneExternalId
3217         // Test Type:    Positive
3218         // Description:  Create a bridge with one BridgeExternalIds
3219         // Expected:     A bridge is created with the single external_ids specified below
3220         final String testOneExternalIdName = "TestOneExternalId";
3221         int externalIdCounter = 0;
3222         List<BridgeExternalIds> oneExternalId = (List<BridgeExternalIds>) Lists.newArrayList(
3223                 (new BridgeExternalIdsBuilder()
3224                         .setBridgeExternalIdKey(String.format(FORMAT_STR, testOneExternalIdName,
3225                                 BRIDGE_EXTERNAL_ID_KEY, ++externalIdCounter))
3226                         .setBridgeExternalIdValue(String.format(FORMAT_STR, testOneExternalIdName,
3227                                 BRIDGE_EXTERNAL_ID_VALUE, externalIdCounter))
3228                         .build()));
3229         Map<String,List<BridgeExternalIds>> testCase = Maps.newHashMap();
3230         testCase.put(EXPECTED_VALUES_KEY, oneExternalId);
3231         testCase.put(INPUT_VALUES_KEY, oneExternalId);
3232         testMap.put(testOneExternalIdName, testCase);
3233
3234         // Test Case 2:  TestFiveExternalId
3235         // Test Type:    Positive
3236         // Description:  Create a bridge with multiple (five) BridgeExternalIds
3237         // Expected:     A bridge is created with the five external_ids specified below
3238         final String testFiveExternalIdName = "TestFiveExternalId";
3239         externalIdCounter = 0;
3240         List<BridgeExternalIds> fiveExternalId = (List<BridgeExternalIds>) Lists.newArrayList(
3241                 (new BridgeExternalIdsBuilder()
3242                         .setBridgeExternalIdKey(String.format(FORMAT_STR, testFiveExternalIdName,
3243                                 BRIDGE_EXTERNAL_ID_KEY, ++externalIdCounter))
3244                         .setBridgeExternalIdValue(String.format(FORMAT_STR, testFiveExternalIdName,
3245                                 BRIDGE_EXTERNAL_ID_VALUE, externalIdCounter))
3246                         .build()),
3247                 (new BridgeExternalIdsBuilder()
3248                         .setBridgeExternalIdKey(String.format(FORMAT_STR, testFiveExternalIdName,
3249                                 BRIDGE_EXTERNAL_ID_KEY, ++externalIdCounter))
3250                         .setBridgeExternalIdValue(String.format(FORMAT_STR, testFiveExternalIdName,
3251                                 BRIDGE_EXTERNAL_ID_VALUE, externalIdCounter))
3252                         .build()),
3253                 (new BridgeExternalIdsBuilder()
3254                         .setBridgeExternalIdKey(String.format(FORMAT_STR, testFiveExternalIdName,
3255                                 BRIDGE_EXTERNAL_ID_KEY, ++externalIdCounter))
3256                         .setBridgeExternalIdValue(String.format(FORMAT_STR, testFiveExternalIdName,
3257                                 BRIDGE_EXTERNAL_ID_VALUE, externalIdCounter))
3258                         .build()),
3259                 (new BridgeExternalIdsBuilder()
3260                         .setBridgeExternalIdKey(String.format(FORMAT_STR, testFiveExternalIdName,
3261                                 BRIDGE_EXTERNAL_ID_KEY, ++externalIdCounter))
3262                         .setBridgeExternalIdValue(String.format(FORMAT_STR, testFiveExternalIdName,
3263                                 BRIDGE_EXTERNAL_ID_VALUE, externalIdCounter))
3264                         .build()),
3265                 (new BridgeExternalIdsBuilder()
3266                         .setBridgeExternalIdKey(String.format(FORMAT_STR, testFiveExternalIdName,
3267                                 BRIDGE_EXTERNAL_ID_KEY, ++externalIdCounter))
3268                         .setBridgeExternalIdValue(String.format(FORMAT_STR, testFiveExternalIdName,
3269                                 BRIDGE_EXTERNAL_ID_VALUE, externalIdCounter))
3270                         .build()));
3271         testCase = Maps.newHashMap();
3272         testCase.put(EXPECTED_VALUES_KEY, fiveExternalId);
3273         testCase.put(INPUT_VALUES_KEY, fiveExternalId);
3274         testMap.put(testFiveExternalIdName, testCase);
3275
3276         // Test Case 3:  TestOneGoodExternalIdOneMalformedExternalIdValue
3277         // Test Type:    Negative
3278         // Description:
3279         //     One perfectly fine BridgeExternalId
3280         //        (TestOneGoodExternalIdOneMalformedExternalIdValue_BridgeExternalIdKey_1,
3281         //        TestOneGoodExternalIdOneMalformedExternalId_BridgeExternalIdValue_1)
3282         //     and one malformed BridgeExternalId which only has key specified
3283         //        (TestOneGoodExternalIdOneMalformedExternalIdValue_NoValueForKey_2,
3284         //        UNSPECIFIED)
3285         // Expected:     A bridge is created without any external_ids
3286         final String testOneGoodExternalIdOneMalformedExternalIdValueName =
3287                 "TestOneGoodExternalIdOneMalformedExternalIdValue";
3288         externalIdCounter = 0;
3289         BridgeExternalIds oneGood = new BridgeExternalIdsBuilder()
3290                 .setBridgeExternalIdKey(String.format(FORMAT_STR, testOneGoodExternalIdOneMalformedExternalIdValueName,
3291                         GOOD_KEY, ++externalIdCounter))
3292                 .setBridgeExternalIdValue(String.format(FORMAT_STR,
3293                         testOneGoodExternalIdOneMalformedExternalIdValueName,
3294                         GOOD_VALUE, externalIdCounter))
3295                 .build();
3296         BridgeExternalIds oneBad = new BridgeExternalIdsBuilder()
3297                 .setBridgeExternalIdKey(String.format(FORMAT_STR,
3298                         testOneGoodExternalIdOneMalformedExternalIdValueName, NO_VALUE_FOR_KEY, ++externalIdCounter))
3299                 .build();
3300         List<BridgeExternalIds> oneGoodOneBadInput = (List<BridgeExternalIds>) Lists.newArrayList(
3301                 oneGood, oneBad);
3302         List<BridgeExternalIds> oneGoodOneBadExpected = null;
3303         testCase = Maps.newHashMap();
3304         testCase.put(INPUT_VALUES_KEY, oneGoodOneBadInput);
3305         testCase.put(EXPECTED_VALUES_KEY, oneGoodOneBadExpected);
3306         testMap.put(testOneGoodExternalIdOneMalformedExternalIdValueName, testCase);
3307
3308         // Test Case 4:  TestOneGoodExternalIdOneMalformedExternalIdKey
3309         // Test Type:    Negative
3310         // Description:
3311         //     One perfectly fine BridgeExternalId
3312         //        (TestOneGoodExternalIdOneMalformedExternalIdValue_BridgeExternalIdKey_1,
3313         //        TestOneGoodExternalIdOneMalformedExternalId_BridgeExternalIdValue_1)
3314         //     and one malformed BridgeExternalId which only has key specified
3315         //        (UNSPECIFIED,
3316         //        TestOneGoodExternalIdOneMalformedExternalIdKey_NoKeyForValue_2)
3317         // Expected:     A bridge is created without any external_ids
3318         final String testOneGoodExternalIdOneMalformedExternalIdKeyName =
3319                 "TestOneGoodExternalIdOneMalformedExternalIdKey";
3320         externalIdCounter = 0;
3321         oneGood = new BridgeExternalIdsBuilder()
3322                 .setBridgeExternalIdKey(String.format(FORMAT_STR, testOneGoodExternalIdOneMalformedExternalIdKeyName,
3323                         GOOD_KEY, ++externalIdCounter))
3324                 .setBridgeExternalIdValue(String.format(FORMAT_STR,
3325                         testOneGoodExternalIdOneMalformedExternalIdKeyName,
3326                         GOOD_VALUE, externalIdCounter))
3327                 .build();
3328         oneBad = new BridgeExternalIdsBuilder()
3329                 .setBridgeExternalIdKey(String.format(FORMAT_STR,
3330                         testOneGoodExternalIdOneMalformedExternalIdKeyName, NO_KEY_FOR_VALUE, ++externalIdCounter))
3331                 .build();
3332         oneGoodOneBadInput = (List<BridgeExternalIds>) Lists.newArrayList(
3333                 oneGood, oneBad);
3334         oneGoodOneBadExpected = null;
3335         testCase = Maps.newHashMap();
3336         testCase.put(INPUT_VALUES_KEY, oneGoodOneBadInput);
3337         testCase.put(EXPECTED_VALUES_KEY, oneGoodOneBadExpected);
3338         testMap.put(testOneGoodExternalIdOneMalformedExternalIdKeyName, testCase);
3339         return testMap;
3340     }
3341
3342     /*
3343      * @see <code>SouthboundIT.testCRUDBridgeExternalIds()</code>
3344      * This is helper test method to compare a test "set" of BridgeExternalIds against an expected "set"
3345      */
3346     private void assertExpectedBridgeExternalIdsExist( List<BridgeExternalIds> expected,
3347                                                        List<BridgeExternalIds> test ) {
3348
3349         if (expected != null) {
3350             for (BridgeExternalIds expectedExternalId : expected) {
3351                 Assert.assertTrue(test.contains(expectedExternalId));
3352             }
3353         }
3354     }
3355
3356     /*
3357      * @see <code>SouthboundIT.generateBridgeExternalIdsTestCases()</code> for specific test case information
3358      */
3359     @Test
3360     public void testCRUDBridgeExternalIds() throws InterruptedException {
3361         final String TEST_BRIDGE_PREFIX = "CRUDBridgeExternalIds";
3362         ConnectionInfo connectionInfo = getConnectionInfo(addressStr, portStr);
3363         connectOvsdbNode(connectionInfo);
3364         // updateFromTestCases represent the original test case value.  updateToTestCases represent the new value after
3365         // the update has been performed.
3366         Map<String, Map<String, List<BridgeExternalIds>>> updateFromTestCases = generateBridgeExternalIdsTestCases();
3367         Map<String, Map<String, List<BridgeExternalIds>>> updateToTestCases = generateBridgeExternalIdsTestCases();
3368         Map<String, List<BridgeExternalIds>> updateFromTestCase;
3369         List<BridgeExternalIds> updateFromInputExternalIds;
3370         List<BridgeExternalIds> updateFromExpectedExternalIds;
3371         Map<String, List<BridgeExternalIds>> updateToTestCase;
3372         List<BridgeExternalIds> updateToInputExternalIds;
3373         List<BridgeExternalIds> updateToExpectedExternalIds;
3374         String testBridgeName;
3375
3376         int counter = 1;
3377         ExecutorService executor = Executors.newFixedThreadPool(NUM_THREADS);
3378         for (String updateFromTestCaseKey : updateFromTestCases.keySet()) {
3379             updateFromTestCase = updateFromTestCases.get(updateFromTestCaseKey);
3380             updateFromInputExternalIds = updateFromTestCase.get(INPUT_VALUES_KEY);
3381             updateFromExpectedExternalIds = updateFromTestCase.get(EXPECTED_VALUES_KEY);
3382             for (String testCaseKey : updateToTestCases.keySet()) {
3383                 testBridgeName = String.format("%s_%s_d", TEST_BRIDGE_PREFIX, testCaseKey, counter);
3384                 counter += 1;
3385                 updateToTestCase = updateToTestCases.get(testCaseKey);
3386                 updateToInputExternalIds = updateToTestCase.get(INPUT_VALUES_KEY);
3387                 updateToExpectedExternalIds = updateToTestCase.get(EXPECTED_VALUES_KEY);
3388
3389                 TestCRUDBridgeExternalIdsRunnable testRunnable =
3390                         new TestCRUDBridgeExternalIdsRunnable(
3391                                 connectionInfo, testBridgeName,
3392                                 updateFromInputExternalIds,
3393                                 updateFromExpectedExternalIds,
3394                                 updateToInputExternalIds,
3395                                 updateToExpectedExternalIds);
3396                 executor.submit(testRunnable);
3397             }
3398         }
3399         executor.shutdown();
3400         executor.awaitTermination(5, TimeUnit.MINUTES);
3401
3402         Assert.assertTrue(disconnectOvsdbNode(connectionInfo));
3403     }
3404
3405     class TestCRUDBridgeExternalIdsRunnable implements Runnable {
3406         ConnectionInfo connectionInfo;
3407         String testBridgeName;
3408         List<BridgeExternalIds> updateFromInputExternalIds;
3409         List<BridgeExternalIds> updateFromExpectedExternalIds;
3410         List<BridgeExternalIds> updateToInputExternalIds;
3411         List<BridgeExternalIds> updateToExpectedExternalIds;
3412
3413         TestCRUDBridgeExternalIdsRunnable(
3414                 ConnectionInfo connectionInfo, String testBridgeName,
3415                 List<BridgeExternalIds> updateFromInputExternalIds,
3416                 List<BridgeExternalIds> updateFromExpectedExternalIds,
3417                 List<BridgeExternalIds> updateToInputExternalIds,
3418                 List<BridgeExternalIds> updateToExpectedExternalIds) {
3419
3420             this.connectionInfo = connectionInfo;
3421             this.testBridgeName = testBridgeName;
3422             this.updateFromInputExternalIds = updateFromInputExternalIds;
3423             this.updateFromExpectedExternalIds = updateFromExpectedExternalIds;
3424             this.updateToInputExternalIds = updateToInputExternalIds;
3425             this.updateToExpectedExternalIds = updateToExpectedExternalIds;
3426         }
3427
3428         @Override
3429         public void run() {
3430             try {
3431                 test();
3432             } catch (InterruptedException e) {
3433                 e.printStackTrace();
3434             }
3435         }
3436
3437         public void test() throws InterruptedException {
3438             // CREATE: Create the test bridge
3439             boolean bridgeAdded = addBridge(connectionInfo, null,
3440                     testBridgeName, null, true, SouthboundConstants.OVSDB_FAIL_MODE_MAP.inverse().get("secure"),
3441                     true, null, updateFromInputExternalIds, null, null);
3442             Assert.assertTrue(bridgeAdded);
3443
3444             // READ: Read the test bridge and ensure changes are propagated to the CONFIGURATION data store,
3445             // then repeat for OPERATIONAL data store
3446             List<BridgeExternalIds> updateFromConfigurationExternalIds = getBridge(connectionInfo, testBridgeName,
3447                     LogicalDatastoreType.CONFIGURATION).getBridgeExternalIds();
3448             assertExpectedBridgeExternalIdsExist(updateFromExpectedExternalIds, updateFromConfigurationExternalIds);
3449             List<BridgeExternalIds> updateFromOperationalExternalIds = getBridge(connectionInfo, testBridgeName)
3450                     .getBridgeExternalIds();
3451             assertExpectedBridgeExternalIdsExist(updateFromExpectedExternalIds, updateFromOperationalExternalIds);
3452
3453             // UPDATE:  update the external_ids
3454             OvsdbBridgeAugmentationBuilder bridgeAugmentationBuilder = new OvsdbBridgeAugmentationBuilder();
3455             bridgeAugmentationBuilder.setBridgeExternalIds(updateToInputExternalIds);
3456             InstanceIdentifier<Node> bridgeIid =
3457                     createInstanceIdentifier(connectionInfo,
3458                             new OvsdbBridgeName(testBridgeName));
3459             NodeBuilder bridgeNodeBuilder = new NodeBuilder();
3460             Node bridgeNode = getBridgeNode(connectionInfo, testBridgeName);
3461             bridgeNodeBuilder.setNodeId(bridgeNode.getNodeId());
3462             bridgeNodeBuilder.setKey(bridgeNode.getKey());
3463             bridgeNodeBuilder.addAugmentation(OvsdbBridgeAugmentation.class, bridgeAugmentationBuilder.build());
3464             boolean result = mdsalUtils.merge(LogicalDatastoreType.CONFIGURATION, bridgeIid,
3465                     bridgeNodeBuilder.build());
3466             Thread.sleep(OVSDB_UPDATE_TIMEOUT);
3467             Assert.assertTrue(result);
3468
3469             // READ: the test bridge and ensure changes are propagated to the CONFIGURATION data store,
3470             // then repeat for OPERATIONAL data store
3471             List<BridgeExternalIds> updateToConfigurationExternalIds = getBridge(connectionInfo, testBridgeName,
3472                     LogicalDatastoreType.CONFIGURATION).getBridgeExternalIds();
3473             assertExpectedBridgeExternalIdsExist(updateToExpectedExternalIds, updateToConfigurationExternalIds);
3474             assertExpectedBridgeExternalIdsExist(updateFromExpectedExternalIds, updateToConfigurationExternalIds);
3475             List<BridgeExternalIds> updateToOperationalExternalIds = getBridge(connectionInfo, testBridgeName)
3476                     .getBridgeExternalIds();
3477             if (updateFromExpectedExternalIds != null) {
3478                 assertExpectedBridgeExternalIdsExist(updateToExpectedExternalIds, updateToOperationalExternalIds);
3479                 assertExpectedBridgeExternalIdsExist(updateFromExpectedExternalIds, updateToOperationalExternalIds);
3480             }
3481
3482             // DELETE
3483             Assert.assertTrue(deleteBridge(connectionInfo, testBridgeName));
3484         }
3485     }
3486
3487     public static InstanceIdentifier<Node> createInstanceIdentifier(ConnectionInfo key,OvsdbBridgeName bridgeName) {
3488         return SouthboundMapper.createInstanceIdentifier(createManagedNodeId(key, bridgeName));
3489     }
3490
3491     public static NodeId createManagedNodeId(ConnectionInfo key, OvsdbBridgeName bridgeName) {
3492         return createManagedNodeId(key.getRemoteIp(),key.getRemotePort(),bridgeName);
3493     }
3494
3495     public static NodeId createManagedNodeId(IpAddress ip, PortNumber port, OvsdbBridgeName bridgeName) {
3496         return new NodeId(createNodeId(ip,port).getValue()
3497                 + "/" + SouthboundConstants.BRIDGE_URI_PREFIX + "/" + bridgeName.getValue());
3498     }
3499
3500     public static NodeId createNodeId(IpAddress ip, PortNumber port) {
3501         String uriString = SouthboundConstants.OVSDB_URI_PREFIX + "://"
3502                 + new String(ip.getValue()) + ":" + port.getValue();
3503         Uri uri = new Uri(uriString);
3504         NodeId nodeId = new NodeId(uri);
3505         return nodeId;
3506     }
3507
3508     public static NodeKey createNodeKey(IpAddress ip, PortNumber port) {
3509         return new NodeKey(createNodeId(ip,port));
3510     }
3511
3512     public static Node createNode(ConnectionInfo key) {
3513         NodeBuilder nodeBuilder = new NodeBuilder();
3514         nodeBuilder.setNodeId(createNodeId(key.getRemoteIp(),key.getRemotePort()));
3515         nodeBuilder.addAugmentation(OvsdbNodeAugmentation.class, createOvsdbAugmentation(key));
3516         return nodeBuilder.build();
3517     }
3518
3519     public static OvsdbNodeAugmentation createOvsdbAugmentation(ConnectionInfo key) {
3520         OvsdbNodeAugmentationBuilder ovsdbNodeBuilder = new OvsdbNodeAugmentationBuilder();
3521         ovsdbNodeBuilder.setConnectionInfo(key);
3522         return ovsdbNodeBuilder.build();
3523     }
3524
3525     public static NodeId createManagedNodeId(InstanceIdentifier<Node> iid) {
3526         NodeKey nodeKey = iid.firstKeyOf(Node.class, NodeKey.class);
3527         return nodeKey.getNodeId();
3528     }
3529 }