blob: 5c1ce598899488891714c25650277dbcd4ab6e6b [file] [log] [blame]
Neels Hofmeyrdae3d3c2017-03-28 12:16:58 +02001#!/usr/bin/env python3
2
3import os
4import sys
5import subprocess
6import time
7import difflib
8import argparse
Neels Hofmeyr3531a192017-03-28 14:30:28 +02009import re
Neels Hofmeyrdae3d3c2017-03-28 12:16:58 +020010
11parser = argparse.ArgumentParser()
12parser.add_argument('testdir_or_test', nargs='*',
13 help='subdir name or test script name')
14parser.add_argument('-u', '--update', action='store_true',
15 help='Update test expecations instead of verifying them')
16args = parser.parse_args()
17
18def run_test(path):
19 print(path)
20 p = subprocess.Popen(path, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
21 o,e = p.communicate()
22 while True:
23 retval = p.poll()
24 if retval is not None:
25 break;
26 p.kill()
27 time.sleep(.1)
28 return retval, o.decode('utf-8'), e.decode('utf-8')
29
30def udiff(expect, got, expect_path):
31 expect = expect.splitlines(1)
32 got = got.splitlines(1)
33 for line in difflib.unified_diff(expect, got,
34 fromfile=expect_path, tofile='got'):
35 sys.stderr.write(line)
36 if not line.endswith('\n'):
37 sys.stderr.write('[no-newline]\n')
38
39def verify_output(got, expect_file, update=False):
40 if os.path.isfile(expect_file):
Neels Hofmeyr3531a192017-03-28 14:30:28 +020041 ign_file = expect_file + '.ign'
42 if os.path.isfile(ign_file):
43 with open(ign_file, 'r') as f:
44 ign_rules = f.readlines()
45 for ign_rule in ign_rules:
46 if not ign_rule:
47 continue
48 if '\t' in ign_rule:
49 ign_rule, repl = ign_rule.split('\t')
50 repl = repl.strip()
51 else:
52 repl = '*'
53 ir = re.compile(ign_rule)
54 got = repl.join(ir.split(got))
55
Neels Hofmeyrdae3d3c2017-03-28 12:16:58 +020056 if update:
57 with open(expect_file, 'w') as f:
58 f.write(got)
59 return True
60
61 with open(expect_file, 'r') as f:
62 expect = f.read()
Neels Hofmeyr3531a192017-03-28 14:30:28 +020063
Neels Hofmeyrdae3d3c2017-03-28 12:16:58 +020064 if expect != got:
65 udiff(expect, got, expect_file)
66 sys.stderr.write('output mismatch: %r\n'
67 % os.path.basename(expect_file))
68 return False
69 return True
70
71
72script_dir = sys.path[0]
73
74tests = []
75for f in os.listdir(script_dir):
76 file_path = os.path.join(script_dir, f)
77 if not os.path.isfile(file_path):
78 continue
79
80 if not (file_path.endswith('_test.py') or file_path.endswith('_test.sh')):
81 continue
82 tests.append(file_path)
83
84ran = []
85errors = []
86
87for test in sorted(tests):
88
89 if args.testdir_or_test:
90 if not any([t in test for t in args.testdir_or_test]):
91 continue
92
93 ran.append(test)
94
95 success = True
96
97 name, ext = os.path.splitext(test)
98 ok_file = name + '.ok'
99 err_file = name + '.err'
100
101 rc, out, err = run_test(test)
102
103 if rc != 0:
104 sys.stderr.write('%r: returned %d\n' % (os.path.basename(test), rc))
105 success = False
106
107 if not verify_output(out, ok_file, args.update):
108 success = False
109 if not verify_output(err, err_file, args.update):
110 success = False
111
112 if not success:
Neels Hofmeyr3531a192017-03-28 14:30:28 +0200113 sys.stderr.write('\nTest failed: %r\n\n' % os.path.basename(test))
Neels Hofmeyrdae3d3c2017-03-28 12:16:58 +0200114 errors.append(test)
115
116if errors:
117 print('%d of %d TESTS FAILED:\n %s' % (len(errors), len(ran), '\n '.join(errors)))
118 exit(1)
119
120print('%d tests ok' % len(ran))
121exit(0)
122
123# vim: expandtab tabstop=4 shiftwidth=4