1a5f9918aSopenharmony_ci
2a5f9918aSopenharmony_ciimport sys, os, os.path, types, traceback, pprint
3a5f9918aSopenharmony_ci
4a5f9918aSopenharmony_ciDATA = 'tests/data'
5a5f9918aSopenharmony_ci
6a5f9918aSopenharmony_cidef find_test_functions(collections):
7a5f9918aSopenharmony_ci    if not isinstance(collections, list):
8a5f9918aSopenharmony_ci        collections = [collections]
9a5f9918aSopenharmony_ci    functions = []
10a5f9918aSopenharmony_ci    for collection in collections:
11a5f9918aSopenharmony_ci        if not isinstance(collection, dict):
12a5f9918aSopenharmony_ci            collection = vars(collection)
13a5f9918aSopenharmony_ci        for key in sorted(collection):
14a5f9918aSopenharmony_ci            value = collection[key]
15a5f9918aSopenharmony_ci            if isinstance(value, types.FunctionType) and hasattr(value, 'unittest'):
16a5f9918aSopenharmony_ci                functions.append(value)
17a5f9918aSopenharmony_ci    return functions
18a5f9918aSopenharmony_ci
19a5f9918aSopenharmony_cidef find_test_filenames(directory):
20a5f9918aSopenharmony_ci    filenames = {}
21a5f9918aSopenharmony_ci    for filename in os.listdir(directory):
22a5f9918aSopenharmony_ci        if os.path.isfile(os.path.join(directory, filename)):
23a5f9918aSopenharmony_ci            base, ext = os.path.splitext(filename)
24a5f9918aSopenharmony_ci            if base.endswith('-py2'):
25a5f9918aSopenharmony_ci                continue
26a5f9918aSopenharmony_ci            filenames.setdefault(base, []).append(ext)
27a5f9918aSopenharmony_ci    filenames = sorted(filenames.items())
28a5f9918aSopenharmony_ci    return filenames
29a5f9918aSopenharmony_ci
30a5f9918aSopenharmony_cidef parse_arguments(args):
31a5f9918aSopenharmony_ci    if args is None:
32a5f9918aSopenharmony_ci        args = sys.argv[1:]
33a5f9918aSopenharmony_ci    verbose = False
34a5f9918aSopenharmony_ci    if '-v' in args:
35a5f9918aSopenharmony_ci        verbose = True
36a5f9918aSopenharmony_ci        args.remove('-v')
37a5f9918aSopenharmony_ci    if '--verbose' in args:
38a5f9918aSopenharmony_ci        verbose = True
39a5f9918aSopenharmony_ci        args.remove('--verbose')
40a5f9918aSopenharmony_ci    if 'YAML_TEST_VERBOSE' in os.environ:
41a5f9918aSopenharmony_ci        verbose = True
42a5f9918aSopenharmony_ci    include_functions = []
43a5f9918aSopenharmony_ci    if args:
44a5f9918aSopenharmony_ci        include_functions.append(args.pop(0))
45a5f9918aSopenharmony_ci    if 'YAML_TEST_FUNCTIONS' in os.environ:
46a5f9918aSopenharmony_ci        include_functions.extend(os.environ['YAML_TEST_FUNCTIONS'].split())
47a5f9918aSopenharmony_ci    include_filenames = []
48a5f9918aSopenharmony_ci    include_filenames.extend(args)
49a5f9918aSopenharmony_ci    if 'YAML_TEST_FILENAMES' in os.environ:
50a5f9918aSopenharmony_ci        include_filenames.extend(os.environ['YAML_TEST_FILENAMES'].split())
51a5f9918aSopenharmony_ci    return include_functions, include_filenames, verbose
52a5f9918aSopenharmony_ci
53a5f9918aSopenharmony_cidef execute(function, filenames, verbose):
54a5f9918aSopenharmony_ci    name = function.__name__
55a5f9918aSopenharmony_ci    if verbose:
56a5f9918aSopenharmony_ci        sys.stdout.write('='*75+'\n')
57a5f9918aSopenharmony_ci        sys.stdout.write('%s(%s)...\n' % (name, ', '.join(filenames)))
58a5f9918aSopenharmony_ci    try:
59a5f9918aSopenharmony_ci        function(verbose=verbose, *filenames)
60a5f9918aSopenharmony_ci    except Exception as exc:
61a5f9918aSopenharmony_ci        info = sys.exc_info()
62a5f9918aSopenharmony_ci        if isinstance(exc, AssertionError):
63a5f9918aSopenharmony_ci            kind = 'FAILURE'
64a5f9918aSopenharmony_ci        else:
65a5f9918aSopenharmony_ci            kind = 'ERROR'
66a5f9918aSopenharmony_ci        if verbose:
67a5f9918aSopenharmony_ci            traceback.print_exc(limit=1, file=sys.stdout)
68a5f9918aSopenharmony_ci        else:
69a5f9918aSopenharmony_ci            sys.stdout.write(kind[0])
70a5f9918aSopenharmony_ci            sys.stdout.flush()
71a5f9918aSopenharmony_ci    else:
72a5f9918aSopenharmony_ci        kind = 'SUCCESS'
73a5f9918aSopenharmony_ci        info = None
74a5f9918aSopenharmony_ci        if not verbose:
75a5f9918aSopenharmony_ci            sys.stdout.write('.')
76a5f9918aSopenharmony_ci    sys.stdout.flush()
77a5f9918aSopenharmony_ci    return (name, filenames, kind, info)
78a5f9918aSopenharmony_ci
79a5f9918aSopenharmony_cidef display(results, verbose):
80a5f9918aSopenharmony_ci    if results and not verbose:
81a5f9918aSopenharmony_ci        sys.stdout.write('\n')
82a5f9918aSopenharmony_ci    total = len(results)
83a5f9918aSopenharmony_ci    failures = 0
84a5f9918aSopenharmony_ci    errors = 0
85a5f9918aSopenharmony_ci    for name, filenames, kind, info in results:
86a5f9918aSopenharmony_ci        if kind == 'SUCCESS':
87a5f9918aSopenharmony_ci            continue
88a5f9918aSopenharmony_ci        if kind == 'FAILURE':
89a5f9918aSopenharmony_ci            failures += 1
90a5f9918aSopenharmony_ci        if kind == 'ERROR':
91a5f9918aSopenharmony_ci            errors += 1
92a5f9918aSopenharmony_ci        sys.stdout.write('='*75+'\n')
93a5f9918aSopenharmony_ci        sys.stdout.write('%s(%s): %s\n' % (name, ', '.join(filenames), kind))
94a5f9918aSopenharmony_ci        if kind == 'ERROR':
95a5f9918aSopenharmony_ci            traceback.print_exception(file=sys.stdout, *info)
96a5f9918aSopenharmony_ci        else:
97a5f9918aSopenharmony_ci            sys.stdout.write('Traceback (most recent call last):\n')
98a5f9918aSopenharmony_ci            traceback.print_tb(info[2], file=sys.stdout)
99a5f9918aSopenharmony_ci            sys.stdout.write('%s: see below\n' % info[0].__name__)
100a5f9918aSopenharmony_ci            sys.stdout.write('~'*75+'\n')
101a5f9918aSopenharmony_ci            for arg in info[1].args:
102a5f9918aSopenharmony_ci                pprint.pprint(arg, stream=sys.stdout)
103a5f9918aSopenharmony_ci        for filename in filenames:
104a5f9918aSopenharmony_ci            sys.stdout.write('-'*75+'\n')
105a5f9918aSopenharmony_ci            sys.stdout.write('%s:\n' % filename)
106a5f9918aSopenharmony_ci            with open(filename, 'r', errors='replace') as file:
107a5f9918aSopenharmony_ci                data = file.read()
108a5f9918aSopenharmony_ci            sys.stdout.write(data)
109a5f9918aSopenharmony_ci            if data and data[-1] != '\n':
110a5f9918aSopenharmony_ci                sys.stdout.write('\n')
111a5f9918aSopenharmony_ci    sys.stdout.write('='*75+'\n')
112a5f9918aSopenharmony_ci    sys.stdout.write('TESTS: %s\n' % total)
113a5f9918aSopenharmony_ci    if failures:
114a5f9918aSopenharmony_ci        sys.stdout.write('FAILURES: %s\n' % failures)
115a5f9918aSopenharmony_ci    if errors:
116a5f9918aSopenharmony_ci        sys.stdout.write('ERRORS: %s\n' % errors)
117a5f9918aSopenharmony_ci    return not (failures or errors)
118a5f9918aSopenharmony_ci
119a5f9918aSopenharmony_cidef run(collections, args=None):
120a5f9918aSopenharmony_ci    test_functions = find_test_functions(collections)
121a5f9918aSopenharmony_ci    test_filenames = find_test_filenames(DATA)
122a5f9918aSopenharmony_ci    include_functions, include_filenames, verbose = parse_arguments(args)
123a5f9918aSopenharmony_ci    results = []
124a5f9918aSopenharmony_ci    for function in test_functions:
125a5f9918aSopenharmony_ci        if include_functions and function.__name__ not in include_functions:
126a5f9918aSopenharmony_ci            continue
127a5f9918aSopenharmony_ci        if function.unittest and function.unittest is not True:
128a5f9918aSopenharmony_ci            for base, exts in test_filenames:
129a5f9918aSopenharmony_ci                if include_filenames and base not in include_filenames:
130a5f9918aSopenharmony_ci                    continue
131a5f9918aSopenharmony_ci                filenames = []
132a5f9918aSopenharmony_ci                for ext in function.unittest:
133a5f9918aSopenharmony_ci                    if ext not in exts:
134a5f9918aSopenharmony_ci                        break
135a5f9918aSopenharmony_ci                    filenames.append(os.path.join(DATA, base+ext))
136a5f9918aSopenharmony_ci                else:
137a5f9918aSopenharmony_ci                    skip_exts = getattr(function, 'skip', [])
138a5f9918aSopenharmony_ci                    for skip_ext in skip_exts:
139a5f9918aSopenharmony_ci                        if skip_ext in exts:
140a5f9918aSopenharmony_ci                            break
141a5f9918aSopenharmony_ci                    else:
142a5f9918aSopenharmony_ci                        result = execute(function, filenames, verbose)
143a5f9918aSopenharmony_ci                        results.append(result)
144a5f9918aSopenharmony_ci        else:
145a5f9918aSopenharmony_ci            result = execute(function, [], verbose)
146a5f9918aSopenharmony_ci            results.append(result)
147a5f9918aSopenharmony_ci    return display(results, verbose=verbose)
148a5f9918aSopenharmony_ci
149