Unit tests for the OpenFlow controller class

Change-Id: I14a6e2810ec15edfccb309ab94dabe96670f4026
diff --git a/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/Controller.java b/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/Controller.java
index 69c0616..d9848be 100644
--- a/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/Controller.java
+++ b/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/Controller.java
@@ -94,7 +94,7 @@
     protected String tsLocation;
     protected char[] ksPwd;
     protected char[] tsPwd;
-    private SSLEngine serverSSLEngine;
+    protected SSLEngine serverSSLEngine;
 
     // Perf. related configuration
     protected static final int SEND_BUFFER_SIZE = 4 * 1024 * 1024;
diff --git a/openflow/ctl/src/test/java/org/onosproject/openflow/DriverAdapter.java b/openflow/ctl/src/test/java/org/onosproject/openflow/DriverAdapter.java
new file mode 100644
index 0000000..57becf9
--- /dev/null
+++ b/openflow/ctl/src/test/java/org/onosproject/openflow/DriverAdapter.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.openflow;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.onosproject.net.driver.Behaviour;
+import org.onosproject.net.driver.Driver;
+import org.onosproject.net.driver.DriverData;
+import org.onosproject.net.driver.DriverHandler;
+import org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver;
+
+/**
+ * Created by ray on 11/4/15.
+ */
+public class DriverAdapter implements Driver {
+    @Override
+    public String name() {
+        return null;
+    }
+
+    @Override
+    public Driver parent() {
+        return null;
+    }
+
+    @Override
+    public String manufacturer() {
+        return null;
+    }
+
+    @Override
+    public String hwVersion() {
+        return null;
+    }
+
+    @Override
+    public String swVersion() {
+        return null;
+    }
+
+    @Override
+    public Set<Class<? extends Behaviour>> behaviours() {
+        return null;
+    }
+
+    @Override
+    public Class<? extends Behaviour> implementation(Class<? extends Behaviour> behaviour) {
+        return null;
+    }
+
+    @Override
+    public boolean hasBehaviour(Class<? extends Behaviour> behaviourClass) {
+        return true;
+    }
+
+    @Override
+    public <T extends Behaviour> T createBehaviour(DriverData data, Class<T> behaviourClass) {
+        return null;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends Behaviour> T createBehaviour(DriverHandler handler, Class<T> behaviourClass) {
+        if (behaviourClass == OpenFlowSwitchDriver.class) {
+            return (T) new OpenflowSwitchDriverAdapter();
+        }
+        return null;
+    }
+
+    @Override
+    public Map<String, String> properties() {
+        return null;
+    }
+
+    @Override
+    public Driver merge(Driver other) {
+        return null;
+    }
+
+    @Override
+    public Set<String> keys() {
+        return null;
+    }
+
+    @Override
+    public String value(String key) {
+        return null;
+    }
+}
diff --git a/openflow/ctl/src/test/java/org/onosproject/openflow/DriverServiceAdapter.java b/openflow/ctl/src/test/java/org/onosproject/openflow/DriverServiceAdapter.java
new file mode 100644
index 0000000..25596ad
--- /dev/null
+++ b/openflow/ctl/src/test/java/org/onosproject/openflow/DriverServiceAdapter.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.openflow;
+
+import java.util.Set;
+
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.driver.Behaviour;
+import org.onosproject.net.driver.Driver;
+import org.onosproject.net.driver.DriverHandler;
+import org.onosproject.net.driver.DriverService;
+
+/**
+ * Created by ray on 11/4/15.
+ */
+public class DriverServiceAdapter implements DriverService {
+    @Override
+    public Set<Driver> getDrivers() {
+        return null;
+    }
+
+    @Override
+    public Set<Driver> getDrivers(Class<? extends Behaviour> withBehaviour) {
+        return null;
+    }
+
+    @Override
+    public Driver getDriver(String mfr, String hw, String sw) {
+        return null;
+    }
+
+    @Override
+    public Driver getDriver(DeviceId deviceId) {
+        return null;
+    }
+
+    @Override
+    public DriverHandler createHandler(DeviceId deviceId, String... credentials) {
+        return null;
+    }
+
+    @Override
+    public Driver getDriver(String driverName) {
+        return null;
+    }
+}
diff --git a/openflow/ctl/src/test/java/org/onosproject/openflow/OFDescStatsReplyAdapter.java b/openflow/ctl/src/test/java/org/onosproject/openflow/OFDescStatsReplyAdapter.java
new file mode 100644
index 0000000..1e86641
--- /dev/null
+++ b/openflow/ctl/src/test/java/org/onosproject/openflow/OFDescStatsReplyAdapter.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.openflow;
+
+import java.util.Set;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
+import org.projectfloodlight.openflow.protocol.OFStatsReplyFlags;
+import org.projectfloodlight.openflow.protocol.OFStatsType;
+import org.projectfloodlight.openflow.protocol.OFType;
+import org.projectfloodlight.openflow.protocol.OFVersion;
+
+import com.google.common.hash.PrimitiveSink;
+
+/**
+ * Created by ray on 11/4/15.
+ */
+public class OFDescStatsReplyAdapter implements OFDescStatsReply {
+    @Override
+    public OFVersion getVersion() {
+        return null;
+    }
+
+    @Override
+    public OFType getType() {
+        return null;
+    }
+
+    @Override
+    public long getXid() {
+        return 0;
+    }
+
+    @Override
+    public OFStatsType getStatsType() {
+        return null;
+    }
+
+    @Override
+    public Set<OFStatsReplyFlags> getFlags() {
+        return null;
+    }
+
+    @Override
+    public String getMfrDesc() {
+        return null;
+    }
+
+    @Override
+    public String getHwDesc() {
+        return null;
+    }
+
+    @Override
+    public String getSwDesc() {
+        return null;
+    }
+
+    @Override
+    public String getSerialNum() {
+        return null;
+    }
+
+    @Override
+    public String getDpDesc() {
+        return null;
+    }
+
+    @Override
+    public void writeTo(ChannelBuffer channelBuffer) {
+
+    }
+
+    @Override
+    public Builder createBuilder() {
+        return null;
+    }
+
+    @Override
+    public void putTo(PrimitiveSink sink) {
+
+    }
+}
diff --git a/openflow/ctl/src/test/java/org/onosproject/openflow/OpenflowSwitchDriverAdapter.java b/openflow/ctl/src/test/java/org/onosproject/openflow/OpenflowSwitchDriverAdapter.java
new file mode 100644
index 0000000..25ea641
--- /dev/null
+++ b/openflow/ctl/src/test/java/org/onosproject/openflow/OpenflowSwitchDriverAdapter.java
@@ -0,0 +1,299 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.openflow;
+
+import java.util.List;
+
+import org.jboss.netty.channel.Channel;
+import org.onosproject.net.Device;
+import org.onosproject.net.driver.DriverData;
+import org.onosproject.net.driver.DriverHandler;
+import org.onosproject.openflow.controller.Dpid;
+import org.onosproject.openflow.controller.RoleState;
+import org.onosproject.openflow.controller.driver.OpenFlowAgent;
+import org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver;
+import org.onosproject.openflow.controller.driver.RoleHandler;
+import org.onosproject.openflow.controller.driver.SwitchStateException;
+import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
+import org.projectfloodlight.openflow.protocol.OFErrorMsg;
+import org.projectfloodlight.openflow.protocol.OFFactories;
+import org.projectfloodlight.openflow.protocol.OFFactory;
+import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
+import org.projectfloodlight.openflow.protocol.OFMessage;
+import org.projectfloodlight.openflow.protocol.OFPortDesc;
+import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply;
+import org.projectfloodlight.openflow.protocol.OFVersion;
+
+/**
+ * Testing adapter for the OpenFlow switch driver class.
+ */
+public class OpenflowSwitchDriverAdapter implements OpenFlowSwitchDriver {
+    @Override
+    public void setAgent(OpenFlowAgent agent) {
+
+    }
+
+    @Override
+    public void setRoleHandler(RoleHandler roleHandler) {
+
+    }
+
+    @Override
+    public void reassertRole() {
+
+    }
+
+    @Override
+    public boolean handleRoleError(OFErrorMsg error) {
+        return false;
+    }
+
+    @Override
+    public void handleNiciraRole(OFMessage m) throws SwitchStateException {
+
+    }
+
+    @Override
+    public void handleRole(OFMessage m) throws SwitchStateException {
+
+    }
+
+    @Override
+    public boolean connectSwitch() {
+        return false;
+    }
+
+    @Override
+    public boolean activateMasterSwitch() {
+        return false;
+    }
+
+    @Override
+    public boolean activateEqualSwitch() {
+        return false;
+    }
+
+    @Override
+    public void transitionToEqualSwitch() {
+
+    }
+
+    @Override
+    public void transitionToMasterSwitch() {
+
+    }
+
+    @Override
+    public void removeConnectedSwitch() {
+
+    }
+
+    @Override
+    public void setPortDescReply(OFPortDescStatsReply portDescReply) {
+
+    }
+
+    @Override
+    public void setPortDescReplies(List<OFPortDescStatsReply> portDescReplies) {
+
+    }
+
+    @Override
+    public void setFeaturesReply(OFFeaturesReply featuresReply) {
+
+    }
+
+    @Override
+    public void setSwitchDescription(OFDescStatsReply desc) {
+
+    }
+
+    @Override
+    public int getNextTransactionId() {
+        return 0;
+    }
+
+    @Override
+    public void setOFVersion(OFVersion ofV) {
+
+    }
+
+    @Override
+    public void setTableFull(boolean full) {
+
+    }
+
+    @Override
+    public void setChannel(Channel channel) {
+
+    }
+
+    @Override
+    public void setConnected(boolean connected) {
+
+    }
+
+    @Override
+    public void init(Dpid dpid, OFDescStatsReply desc, OFVersion ofv) {
+
+    }
+
+    @Override
+    public Boolean supportNxRole() {
+        return true;
+    }
+
+    @Override
+    public void startDriverHandshake() {
+
+    }
+
+    @Override
+    public boolean isDriverHandshakeComplete() {
+        return false;
+    }
+
+    @Override
+    public void processDriverHandshakeMessage(OFMessage m) {
+
+    }
+
+    @Override
+    public void sendRoleRequest(OFMessage message) {
+
+    }
+
+    @Override
+    public void sendHandshakeMessage(OFMessage message) {
+
+    }
+
+    @Override
+    public DriverHandler handler() {
+        return null;
+    }
+
+    @Override
+    public void setHandler(DriverHandler handler) {
+
+    }
+
+    @Override
+    public DriverData data() {
+        return null;
+    }
+
+    @Override
+    public void setData(DriverData data) {
+
+    }
+
+    @Override
+    public void sendMsg(OFMessage msg) {
+
+    }
+
+    @Override
+    public void sendMsg(List<OFMessage> msgs) {
+
+    }
+
+    @Override
+    public void handleMessage(OFMessage fromSwitch) {
+
+    }
+
+    @Override
+    public void setRole(RoleState role) {
+
+    }
+
+    @Override
+    public RoleState getRole() {
+        return null;
+    }
+
+    @Override
+    public List<OFPortDesc> getPorts() {
+        return null;
+    }
+
+    @Override
+    public OFFactory factory() {
+        // return what-ever triggers requestPending = true
+        return OFFactories.getFactory(OFVersion.OF_10);
+    }
+
+    @Override
+    public String getStringId() {
+        return "100";
+    }
+
+    @Override
+    public long getId() {
+        return 0;
+    }
+
+    @Override
+    public String manufacturerDescription() {
+        return null;
+    }
+
+    @Override
+    public String datapathDescription() {
+        return null;
+    }
+
+    @Override
+    public String hardwareDescription() {
+        return null;
+    }
+
+    @Override
+    public String softwareDescription() {
+        return null;
+    }
+
+    @Override
+    public String serialNumber() {
+        return null;
+    }
+
+    @Override
+    public boolean isConnected() {
+        return false;
+    }
+
+    @Override
+    public void disconnectSwitch() {
+
+    }
+
+    @Override
+    public void returnRoleReply(RoleState requested, RoleState response) {
+
+    }
+
+    @Override
+    public Device.Type deviceType() {
+        return Device.Type.SWITCH;
+    }
+
+    @Override
+    public String channelId() {
+        return null;
+    }
+}
diff --git a/openflow/ctl/src/test/java/org/onosproject/openflow/controller/impl/ControllerTest.java b/openflow/ctl/src/test/java/org/onosproject/openflow/controller/impl/ControllerTest.java
new file mode 100644
index 0000000..3ff3bde
--- /dev/null
+++ b/openflow/ctl/src/test/java/org/onosproject/openflow/controller/impl/ControllerTest.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.openflow.controller.impl;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.stream.IntStream;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.junit.TestTools;
+import org.onlab.util.ItemNotFoundException;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.driver.Driver;
+import org.onosproject.openflow.DriverAdapter;
+import org.onosproject.openflow.DriverServiceAdapter;
+import org.onosproject.openflow.OFDescStatsReplyAdapter;
+import org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver;
+import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.io.Files;
+
+import static com.google.common.io.ByteStreams.toByteArray;
+import static com.google.common.io.Files.write;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.hasItem;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.lessThan;
+import static org.hamcrest.Matchers.not;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.hamcrest.Matchers.nullValue;
+
+/**
+ * Unit tests for the OpenFlow controller class.
+ */
+public class ControllerTest {
+
+    Controller controller;
+    protected static final Logger log = LoggerFactory.getLogger(ControllerTest.class);
+
+    static final File TEST_DIR = Files.createTempDir();
+
+    /*
+     * Writes the necessary file for the tests in the temporary directory
+     */
+    static File stageTestResource(String name) throws IOException {
+        File file = new File(TEST_DIR, name);
+        byte[] bytes = toByteArray(ControllerTest.class.getResourceAsStream(name));
+        write(bytes, file);
+        return file;
+    }
+
+    class MockDriverService extends DriverServiceAdapter {
+        static final int NO_SUCH_DRIVER_ID = 1;
+        static final int ITEM_NOT_FOUND_DRIVER_ID = 2;
+        static final int DRIVER_EXISTS_ID = 3;
+
+        static final String BASE_DRIVER_NAME = "of:000000000000000";
+
+        static final String NO_SUCH_DRIVER = BASE_DRIVER_NAME
+                + NO_SUCH_DRIVER_ID;
+        static final String ITEM_NOT_FOUND_DRIVER = BASE_DRIVER_NAME
+                + ITEM_NOT_FOUND_DRIVER_ID;
+        static final String DRIVER_EXISTS = BASE_DRIVER_NAME
+                + DRIVER_EXISTS_ID;
+
+        @Override
+        public Driver getDriver(DeviceId deviceId) {
+            switch (deviceId.toString()) {
+                case NO_SUCH_DRIVER:
+                    return null;
+                case ITEM_NOT_FOUND_DRIVER:
+                    throw new ItemNotFoundException();
+                case DRIVER_EXISTS:
+                    return new DriverAdapter();
+                default:
+                    throw new AssertionError();
+            }
+        }
+    }
+
+    /**
+     * Creates and initializes a new controller.
+     */
+    @Before
+    public void setUp() {
+        controller = new Controller();
+        Dictionary<String, String> properties = new Hashtable<>();
+        properties.put("openflowPorts",
+                       Integer.toString(TestTools.findAvailablePort(0)));
+        controller.setConfigParams(properties);
+    }
+
+    /**
+     * Tests fetching a driver that does not exist.
+     */
+    @Test
+    public void switchInstanceNotFoundTest() {
+        controller.start(null, new MockDriverService());
+        OpenFlowSwitchDriver driver =
+                controller.getOFSwitchInstance(MockDriverService.NO_SUCH_DRIVER_ID,
+                                               null,
+                                               null);
+        assertThat(driver, nullValue());
+        controller.stop();
+    }
+
+    /**
+     * Tests fetching a driver that throws an ItemNotFoundException.
+     */
+    @Test
+    public void switchItemNotFoundTest() {
+        controller.start(null, new MockDriverService());
+        OFDescStatsReply stats =
+                new OFDescStatsReplyAdapter();
+        OpenFlowSwitchDriver driver =
+                controller.getOFSwitchInstance(MockDriverService.ITEM_NOT_FOUND_DRIVER_ID,
+                                               stats,
+                                               null);
+        assertThat(driver, nullValue());
+        controller.stop();
+    }
+
+    /**
+     * Tests fetching a driver that throws an ItemNotFoundException.
+     */
+    @Test
+    public void driverExistsTest() {
+        controller.start(null, new MockDriverService());
+        OFDescStatsReply stats =
+                new OFDescStatsReplyAdapter();
+        OpenFlowSwitchDriver driver =
+                controller.getOFSwitchInstance(MockDriverService.DRIVER_EXISTS_ID,
+                                               stats,
+                                               null);
+        assertThat(driver, notNullValue());
+        controller.stop();
+    }
+
+    /**
+     * Tests configuring the controller.
+     */
+    @Test
+    public void testConfiguration() {
+        Dictionary<String, String> properties = new Hashtable<>();
+        properties.put("openflowPorts", "1,2,3,4,5");
+        properties.put("workerThreads", "5");
+
+        controller.setConfigParams(properties);
+        IntStream.rangeClosed(1, 5)
+                .forEach(i -> assertThat(controller.openFlowPorts, hasItem(i)));
+        assertThat(controller.workerThreads, is(5));
+    }
+
+    /**
+     * Tests the SSL/TLS methods in the controller.
+     */
+    @Test
+    public void testSsl() throws IOException {
+        File keystore = stageTestResource("ControllerTestKeystore.jks");
+        String keystoreName = keystore.getAbsolutePath();
+
+        System.setProperty("enableOFTLS", Boolean.toString(Boolean.TRUE));
+        System.setProperty("javax.net.ssl.keyStore", keystoreName);
+        System.setProperty("javax.net.ssl.trustStore", keystoreName);
+        System.setProperty("javax.net.ssl.keyStorePassword", "password");
+        System.setProperty("javax.net.ssl.trustStorePassword", "password");
+        Dictionary<String, String> properties = new Hashtable<>();
+        properties.put("openflowPorts",
+                       Integer.toString(TestTools.findAvailablePort(0)));
+        properties.put("workerThreads", "0");
+
+        controller.setConfigParams(properties);
+        controller.start(null, new MockDriverService());
+
+        assertThat(controller.serverSSLEngine, notNullValue());
+
+        controller.stop();
+        boolean removed = keystore.delete();
+        if (!removed) {
+            log.warn("Could not remove temporary file");
+        }
+    }
+
+    /**
+     * Tests controll utility health methods.
+     */
+    @Test
+    public void testHealth() {
+        Map<String, Long> memory = controller.getMemory();
+        assertThat(memory.size(), is(2));
+        assertThat(memory.get("total"), is(not(0)));
+        assertThat(memory.get("free"), is(not(0)));
+
+        long startTime = controller.getSystemStartTime();
+        assertThat(startTime, lessThan(System.currentTimeMillis()));
+
+        long upTime = controller.getSystemUptime();
+        assertThat(upTime, lessThan(30L * 1000));
+    }
+}
diff --git a/openflow/ctl/src/test/java/org/onosproject/openflow/controller/impl/RoleManagerTest.java b/openflow/ctl/src/test/java/org/onosproject/openflow/controller/impl/RoleManagerTest.java
index 0a71a40..4b59438 100644
--- a/openflow/ctl/src/test/java/org/onosproject/openflow/controller/impl/RoleManagerTest.java
+++ b/openflow/ctl/src/test/java/org/onosproject/openflow/controller/impl/RoleManagerTest.java
@@ -15,35 +15,21 @@
  */
 package org.onosproject.openflow.controller.impl;
 
-import org.jboss.netty.channel.Channel;
+import java.io.IOException;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
-import org.onosproject.net.Device;
-import org.onosproject.net.driver.DriverData;
-import org.onosproject.net.driver.DriverHandler;
-import org.onosproject.openflow.controller.Dpid;
+import org.onosproject.openflow.OpenflowSwitchDriverAdapter;
 import org.onosproject.openflow.controller.RoleState;
-import org.onosproject.openflow.controller.driver.OpenFlowAgent;
 import org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver;
-import org.onosproject.openflow.controller.driver.RoleHandler;
 import org.onosproject.openflow.controller.driver.RoleRecvStatus;
 import org.onosproject.openflow.controller.driver.RoleReplyInfo;
 import org.onosproject.openflow.controller.driver.SwitchStateException;
 import org.projectfloodlight.openflow.protocol.OFDescStatsReply;
-import org.projectfloodlight.openflow.protocol.OFErrorMsg;
-import org.projectfloodlight.openflow.protocol.OFFactories;
-import org.projectfloodlight.openflow.protocol.OFFactory;
 import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
-import org.projectfloodlight.openflow.protocol.OFMessage;
-import org.projectfloodlight.openflow.protocol.OFPortDesc;
-import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply;
-import org.projectfloodlight.openflow.protocol.OFVersion;
 import org.projectfloodlight.openflow.types.U64;
 
-import java.io.IOException;
-import java.util.List;
-
 import static org.junit.Assert.assertEquals;
 import static org.onosproject.openflow.controller.RoleState.MASTER;
 import static org.onosproject.openflow.controller.RoleState.SLAVE;
@@ -103,25 +89,12 @@
         }
     }
 
-    private class TestSwitchDriver implements OpenFlowSwitchDriver {
+    private class TestSwitchDriver extends OpenflowSwitchDriverAdapter {
 
         RoleState failed = null;
         RoleState current = null;
 
         @Override
-        public void sendMsg(OFMessage msg) {
-        }
-
-        @Override
-        public void sendMsg(List<OFMessage> msgs) {
-        }
-
-
-        @Override
-        public void handleMessage(OFMessage fromSwitch) {
-        }
-
-        @Override
         public void setRole(RoleState role) {
             current = role;
         }
@@ -132,143 +105,6 @@
         }
 
         @Override
-        public List<OFPortDesc> getPorts() {
-            return null;
-        }
-
-        @Override
-        public OFFactory factory() {
-            // return what-ever triggers requestPending = true
-            return OFFactories.getFactory(OFVersion.OF_10);
-        }
-
-        @Override
-        public String getStringId() {
-            return "100";
-        }
-
-        @Override
-        public long getId() {
-            return 0;
-        }
-
-        @Override
-        public String manufacturerDescription() {
-            return null;
-        }
-
-        @Override
-        public String datapathDescription() {
-            return null;
-        }
-
-        @Override
-        public String hardwareDescription() {
-            return null;
-        }
-
-        @Override
-        public String softwareDescription() {
-            return null;
-        }
-
-        @Override
-        public String serialNumber() {
-            return null;
-        }
-
-        @Override
-        public void disconnectSwitch() {
-        }
-
-        @Override
-        public Device.Type deviceType() {
-            return Device.Type.SWITCH;
-        }
-
-        @Override
-        public void setAgent(OpenFlowAgent agent) {
-        }
-
-        @Override
-        public void setRoleHandler(RoleHandler roleHandler) {
-        }
-
-        @Override
-        public void reassertRole() {
-        }
-
-        @Override
-        public boolean handleRoleError(OFErrorMsg error) {
-            return false;
-        }
-
-        @Override
-        public void handleNiciraRole(OFMessage m) throws SwitchStateException {
-        }
-
-        @Override
-        public void handleRole(OFMessage m) throws SwitchStateException {
-        }
-
-        @Override
-        public void startDriverHandshake() {
-        }
-
-        @Override
-        public boolean isDriverHandshakeComplete() {
-            return false;
-        }
-
-        @Override
-        public void processDriverHandshakeMessage(OFMessage m) {
-        }
-
-        @Override
-        public void sendRoleRequest(OFMessage message) {
-
-        }
-
-        @Override
-        public void sendHandshakeMessage(OFMessage message) {
-        }
-
-        @Override
-        public boolean connectSwitch() {
-            return false;
-        }
-
-        @Override
-        public boolean activateMasterSwitch() {
-            return false;
-        }
-
-        @Override
-        public boolean activateEqualSwitch() {
-            return false;
-        }
-
-        @Override
-        public void transitionToEqualSwitch() {
-        }
-
-        @Override
-        public void transitionToMasterSwitch() {
-        }
-
-        @Override
-        public void removeConnectedSwitch() {
-        }
-
-        @Override
-        public void setPortDescReply(OFPortDescStatsReply portDescReply) {
-        }
-
-        @Override
-        public void setPortDescReplies(List<OFPortDescStatsReply> portDescReplies) {
-        }
-
-        @Override
         public void setFeaturesReply(OFFeaturesReply featuresReply) {
         }
 
@@ -282,37 +118,6 @@
         }
 
         @Override
-        public Boolean supportNxRole() {
-            return true;
-        }
-
-        @Override
-        public void setOFVersion(OFVersion ofV) {
-        }
-
-        @Override
-        public void setTableFull(boolean full) {
-        }
-
-        @Override
-        public void setChannel(Channel channel) {
-        }
-
-        @Override
-        public void setConnected(boolean connected) {
-        }
-
-        @Override
-        public void init(Dpid dpid, OFDescStatsReply desc, OFVersion ofv) {
-
-        }
-
-        @Override
-        public boolean isConnected() {
-            return false;
-        }
-
-        @Override
         public void returnRoleReply(RoleState requested, RoleState response) {
             failed = requested;
         }
@@ -321,25 +126,5 @@
         public String channelId() {
             return "1.2.3.4:1";
         }
-
-        @Override
-        public DriverHandler handler() {
-            return null;
-        }
-
-        @Override
-        public void setHandler(DriverHandler handler) {
-
-        }
-
-        @Override
-        public DriverData data() {
-            return null;
-        }
-
-        @Override
-        public void setData(DriverData data) {
-
-        }
     }
 }
diff --git a/utils/junit/src/main/java/org/onlab/junit/TestTools.java b/utils/junit/src/main/java/org/onlab/junit/TestTools.java
index e2fcefc..40e8686 100644
--- a/utils/junit/src/main/java/org/onlab/junit/TestTools.java
+++ b/utils/junit/src/main/java/org/onlab/junit/TestTools.java
@@ -20,6 +20,7 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.net.ServerSocket;
 import java.util.List;
 import java.util.Random;
 
@@ -207,4 +208,20 @@
         }
     }
 
+    /*
+     * Finds an available port that a test can bind to.
+     */
+    public static int findAvailablePort(int defaultPort) {
+        try {
+            ServerSocket socket = new ServerSocket(0);
+            socket.setReuseAddress(true);
+            int port = socket.getLocalPort();
+            socket.close();
+            return port;
+        } catch (IOException ex) {
+            return defaultPort;
+        }
+    }
+
+
 }
diff --git a/utils/junit/src/main/resources/org/onosproject/openflow/controller/impl/ControllerTestKeystore.jks b/utils/junit/src/main/resources/org/onosproject/openflow/controller/impl/ControllerTestKeystore.jks
new file mode 100644
index 0000000..ba750519
--- /dev/null
+++ b/utils/junit/src/main/resources/org/onosproject/openflow/controller/impl/ControllerTestKeystore.jks
Binary files differ