Run all unittests in their own process so as to provide isolation.

Signed-off-by: Jeremy Orlow <jorlow@google.com>



git-svn-id: http://test.kernel.org/svn/autotest/trunk@1909 592f7852-d20e-0410-864c-8624ca9c26a4
diff --git a/unittest_suite.py b/unittest_suite.py
index 6429997..dfdb7f2 100644
--- a/unittest_suite.py
+++ b/unittest_suite.py
@@ -3,21 +3,54 @@
 import os, sys, unittest
 import common
 
+
+LONG_TESTS = set((
+    'monitor_db_unittest.py',
+    'barrier_unittest.py',
+    'migrate_unittest.py', 
+    'frontend_unittest.py',
+    ))
+
+
 root = os.path.abspath(os.path.dirname(__file__))
-suites = unittest.TestSuite()
-def lister(dummy, dirname, files):
+modules = []
+
+def lister(short, dirname, files):
     for f in files:
         if f.endswith('_unittest.py'):
+            if short and f in LONG_TESTS:
+                continue
             temp = os.path.join(dirname, f).strip('.py')
             mod_name = ['autotest_lib'] + temp[len(root)+1:].split('/')
-            mod = common.setup_modules.import_module(mod_name[-1],
-                                                     '.'.join(mod_name[:-1]))
-            try:
-                loader = unittest.defaultTestLoader
-                suite = loader.loadTestsFromModule(mod)
-                suites.addTest(suite)
-            except Exception, err:
-                print "module %s failed to load: %s" % (mod_name, err)
+            modules.append(mod_name)
+
+
+def run_test(mod_name):
+    mod = common.setup_modules.import_module(mod_name[-1],
+                                             '.'.join(mod_name[:-1]))
+    test = unittest.defaultTestLoader.loadTestsFromModule(mod)
+    suite = unittest.TestSuite(test)
+    runner = unittest.TextTestRunner(verbosity=2)
+    result = runner.run(suite)
+    return (result.errors, result.failures)
+
+
+def run_tests(start, short=False):
+    os.path.walk(start, lister, short)
+
+    errors = []
+    for module in modules:
+        pid = os.fork()
+        if pid == 0:
+            errors, failures = run_test(module)
+            if errors or failures:
+                os._exit(1)
+            os._exit(0)
+
+        _, status = os.waitpid(pid, 0)
+        if status != 0:
+            errors.append('.'.join(module))
+    return errors
 
 
 if __name__ == "__main__":
@@ -25,6 +58,13 @@
         start = os.path.join(root, sys.argv[1])
     else:
         start = root
-    os.path.walk(start, lister, None)
-    runner = unittest.TextTestRunner(verbosity=2)
-    runner.run(suites)
+
+    errors = run_tests(start)
+    if errors:
+        print "%d tests resulted in an error/failure:" % len(errors)
+        for error in errors:
+            print "\t%s" % error
+        sys.exit(1)
+    else:
+        print "All passed!"
+        sys.exit(0)