unittest_suite.py revision ef1edafb2cee0a06805476cd3d78557ad5935310
1#!/usr/bin/python -u
2
3import os, sys, unittest, optparse
4import common
5from autotest_lib.utils import parallel
6
7
8root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
9
10parser = optparse.OptionParser()
11parser.add_option("-r", action="store", type="string", dest="start",
12                  default='',
13                  help="root directory to start running unittests")
14parser.add_option("--full", action="store_true", dest="full", default=False,
15                  help="whether to run the shortened version of the test")
16parser.add_option("--debug", action="store_true", dest="debug", default=False,
17                  help="run in debug mode")
18
19
20LONG_TESTS = set((
21    'monitor_db_unittest.py',
22    'barrier_unittest.py',
23    'migrate_unittest.py',
24    'frontend_unittest.py',
25    'client_compilation_unittest.py',
26    'csv_encoder_unittest.py',
27    'rpc_interface_unittest.py',
28    'logging_manager_test.py',
29    ))
30
31modules = []
32
33
34def lister(full, dirname, files):
35    if not os.path.exists(os.path.join(dirname, '__init__.py')):
36        return
37    for f in files:
38        if f.endswith('_unittest.py') or f.endswith('_test.py'):
39            if not full and f in LONG_TESTS:
40                continue
41            temp = os.path.join(dirname, f).strip('.py')
42            mod_name = ['autotest_lib'] + temp[len(root)+1:].split('/')
43            modules.append(mod_name)
44
45
46def run_test(mod_name):
47    if not options.debug:
48        parallel.redirect_io()
49
50    print "Running %s" % '.'.join(mod_name)
51    mod = common.setup_modules.import_module(mod_name[-1],
52                                             '.'.join(mod_name[:-1]))
53    test = unittest.defaultTestLoader.loadTestsFromModule(mod)
54    suite = unittest.TestSuite(test)
55    runner = unittest.TextTestRunner(verbosity=2)
56    result = runner.run(suite)
57    if result.errors or result.failures:
58        raise Exception("%s failed" % '.'.join(mod_name))
59
60
61def run_tests(start, full=False):
62    os.path.walk(start, lister, full)
63
64    functions = {}
65    for module in modules:
66        # Create a function that'll test a particular module.  module=module
67        # is a hack to force python to evaluate the params now.  We then
68        # rename the function to make error reporting nicer.
69        run_module = lambda module=module: run_test(module)
70        name = '.'.join(module)
71        run_module.__name__ = name
72        functions[run_module] = set()
73
74    try:
75        dargs = {}
76        if options.debug:
77            dargs['max_simultaneous_procs'] = 1
78        pe = parallel.ParallelExecute(functions, **dargs)
79        pe.run_until_completion()
80    except parallel.ParallelError, err:
81        return err.errors
82    return []
83
84
85def main():
86    global options, args
87    options, args = parser.parse_args()
88    if args:
89        parser.error('Unexpected argument(s): %s' % args)
90        parser.print_help()
91        sys.exit(1)
92
93    # Strip the arguments off the command line, so that the unit tests do not
94    # see them.
95    sys.argv = [sys.argv[0]]
96
97    errors = run_tests(os.path.join(root, options.start), options.full)
98    if errors:
99        print "%d tests resulted in an error/failure:" % len(errors)
100        for error in errors:
101            print "\t%s" % error
102        sys.exit(1)
103    else:
104        print "All passed!"
105        sys.exit(0)
106
107if __name__ == "__main__":
108    main()
109