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