1from __future__ import print_function
2from glob import glob
3import sys
4import os
5import os.path
6import subprocess
7import optparse
8
9VALGRIND_CMD = 'valgrind --tool=memcheck --leak-check=yes --undef-value-errors=yes'
10
11class TestProxy(object):
12    def __init__( self, test_exe_path, use_valgrind=False ):
13        self.test_exe_path = os.path.normpath( os.path.abspath( test_exe_path ) )
14        self.use_valgrind = use_valgrind
15
16    def run( self, options ):
17        if self.use_valgrind:
18            cmd = VALGRIND_CMD.split()
19        else:
20            cmd = []
21        cmd.extend( [self.test_exe_path, '--test-auto'] + options )
22        process = subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT )
23        stdout = process.communicate()[0]
24        if process.returncode:
25            return False, stdout
26        return True, stdout
27
28def runAllTests( exe_path, use_valgrind=False ):
29    test_proxy = TestProxy( exe_path, use_valgrind=use_valgrind )
30    status, test_names = test_proxy.run( ['--list-tests'] )
31    if not status:
32        print("Failed to obtain unit tests list:\n" + test_names, file=sys.stderr)
33        return 1
34    test_names = [name.strip() for name in test_names.strip().split('\n')]
35    failures = []
36    for name in test_names:
37        print('TESTING %s:' % name, end=' ')
38        succeed, result = test_proxy.run( ['--test', name] )
39        if succeed:
40            print('OK')
41        else:
42            failures.append( (name, result) )
43            print('FAILED')
44    failed_count = len(failures)
45    pass_count = len(test_names) - failed_count
46    if failed_count:
47        print()
48        for name, result in failures:
49            print(result)
50        print('%d/%d tests passed (%d failure(s))' % (
51            pass_count, len(test_names), failed_count))
52        return 1
53    else:
54        print('All %d tests passed' % len(test_names))
55        return 0
56
57def main():
58    from optparse import OptionParser
59    parser = OptionParser( usage="%prog [options] <path to test_lib_json.exe>" )
60    parser.add_option("--valgrind",
61                  action="store_true", dest="valgrind", default=False,
62                  help="run all the tests using valgrind to detect memory leaks")
63    parser.enable_interspersed_args()
64    options, args = parser.parse_args()
65
66    if len(args) != 1:
67        parser.error( 'Must provides at least path to test_lib_json executable.' )
68        sys.exit( 1 )
69
70    exit_code = runAllTests( args[0], use_valgrind=options.valgrind )
71    sys.exit( exit_code )
72
73if __name__ == '__main__':
74    main()
75