oft: Move profiler setup/teardown to function

Profiler setup/teardown was done "in-situ". This was inconsistent
with the general design of 'oft'. Fix this, by moving these
operations to a seperate file.

In addition, add a '--profile-file' parameter, so that the output
file can be changed if necessary.

Signed-off-by: Stephen Finucane <stephenfinucane@hotmail.com>
diff --git a/oft b/oft
index a3756da..f6897bb 100755
--- a/oft
+++ b/oft
@@ -78,6 +78,7 @@
     "log_dir"            : None,
     "debug"              : "verbose",
     "profile"            : False,
+    "profile_file"       : "profile.out",
     "xunit"              : False,
     "xunit_dir"          : "xunit",
 
@@ -183,7 +184,8 @@
                      const="verbose", help="Shortcut for --debug=verbose")
     group.add_option("-q", "--quiet", action="store_const", dest="debug",
                      const="warning", help="Shortcut for --debug=warning")
-    group.add_option("--profile", action="store_true", help="Write Python profile to profile.out")
+    group.add_option("--profile", action="store_true", help="Enable Python profiling")
+    group.add_option("--profile-file", help="Output file for Python profiler")
     group.add_option("--xunit", action="store_true", help="Enable xUnit-formatted results")
     group.add_option("--xunit-dir", help="Output directory for xUnit-formatted results")
     parser.add_option_group(group)
@@ -252,11 +254,10 @@
     if not config["xunit"]:
         return
 
-    if config["xunit"] != None:
-        if os.path.exists(config["xunit_dir"]):
-            import shutil
-            shutil.rmtree(config["xunit_dir"])
-        os.makedirs(config["xunit_dir"])
+    if os.path.exists(config["xunit_dir"]):
+        import shutil
+        shutil.rmtree(config["xunit_dir"])
+    os.makedirs(config["xunit_dir"])
 
 def pcap_setup(config):
     """
@@ -270,6 +271,31 @@
         # start_pcap is called per-test in base_tests
         pass
 
+def profiler_setup(config):
+    """
+    Set up profiler based on config
+    """
+
+    if not config["profile"]:
+        return
+
+    import cProfile
+    profiler = cProfile.Profile()
+    profiler.enable()
+
+    return profiler
+
+def profiler_teardown(profiler):
+    """
+    Tear down profiler based on config
+    """
+
+    if not config["profile"]:
+        return
+
+    profiler.disable()
+    profiler.dump_stats(config["profile_file"])
+
 
 def load_test_modules(config):
     """
@@ -537,10 +563,7 @@
 signal.signal(signal.SIGINT, signal.SIG_DFL)
 
 if __name__ == "__main__":
-    if config["profile"]:
-        import cProfile
-        profiler = cProfile.Profile()
-        profiler.enable()
+    profiler = profiler_setup(config)
 
     # Set up the dataplane
     oftest.dataplane_instance = oftest.dataplane.DataPlane(config)
@@ -561,7 +584,8 @@
     oftest.open_logfile('main')
     if oftest.testutils.skipped_test_count > 0:
         ts = " tests"
-        if oftest.testutils.skipped_test_count == 1: ts = " test"
+        if oftest.testutils.skipped_test_count == 1:
+            ts = " test"
         logging.info("Skipped " + str(oftest.testutils.skipped_test_count) + ts)
         print("Skipped " + str(oftest.testutils.skipped_test_count) + ts)
     logging.info("*** TEST RUN END  : " + time.asctime())
@@ -570,9 +594,7 @@
     oftest.dataplane_instance.kill()
     oftest.dataplane_instance = None
 
-    if config["profile"]:
-        profiler.disable()
-        profiler.dump_stats("profile.out")
+    profiler_teardown(profiler)
 
     if result.failures or result.errors:
         # exit(1) hangs sometimes