Changeset: 24beb19de861 for MonetDB URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=24beb19de861 Added Files: testing/helpers.py Modified Files: testing/Mtest.py.in Branch: mtest Log Message:
build test ctx helper object diffs (200 lines): diff --git a/testing/Mtest.py.in b/testing/Mtest.py.in --- a/testing/Mtest.py.in +++ b/testing/Mtest.py.in @@ -1820,7 +1820,7 @@ def RunSQLLogicTest(env, Test, TestOut, database=env['TSTDB']) except Exception as e: exit_code = F_SOCK - msg = "Connection failure" + msg = "Connection refused" print(e, file=f) else: sql.drop() @@ -1833,7 +1833,8 @@ def RunSQLLogicTest(env, Test, TestOut, except BrokenPipeError as e: # server timeout print(e, file=f) - msg = 'timeout' + exit_code = F_SOCK + msg = "Broken pipe" sql.close() is_dirty = os.path.getsize(TestErr) > 0 # clean up if all okay @@ -2269,7 +2270,6 @@ def SetExecEnv(exe,verbose) : THISFILE = os.path.basename(sys.argv[0]) THISPATH = os.path.realpath(os.path.dirname(sys.argv[0])) -dftIGNORE = r'^\(| \|\)#' TSTDBG = str(2+8) TSTTHREADS = "0" dftTSTPREF = "mTests" diff --git a/testing/helpers.py b/testing/helpers.py new file mode 100644 --- /dev/null +++ b/testing/helpers.py @@ -0,0 +1,165 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# Copyright 1997 - July 2008 CWI, August 2008 - 2020 MonetDB B.V. + +import os, sys +import re + + +def get_tests_from_all_file(fpath:str): + res = [] + with open(fpath, 'r') as f: + for l in f: + r = l.strip() + # ignore comments + if r and r[0] != '#': + # break cond from file name + if '?' in r: + cond, test = r.split('?') + cond = cond.strip() + test = test.strip() + else: + cond = None + test = r.strip() + res.append((cond, test)) + return res + +def process_test_dir(dir_path:str, ctx={}, **kwargs): + """ + Adds statistics and tests info to ctx + """ + real_dir_path = os.path.realpath(dir_path) + folder = {'realpath': real_dir_path} + allf = os.path.join(real_dir_path, 'All') + tests = get_tests_from_all_file(allf) if os.path.isfile(allf) else [] + test_names = kwargs.get('test_names') + if test_names: + # ensure all test name exist in All file + test_names_in_all = [x[1] for x in tests] + for tn in test_names: + if tn not in test_names_in_all: + raise ValueError('ERROR: {} does not appear to be valid test name. Check {}/All'.format(tn, dir_path)) + tests = [(None, test_name) for test_name in test_names] + tests_out = [] + for cond, test_name in tests: + test_path = os.path.join(real_dir_path, test_name) + test = { + 'test_name': test_name, + 'test_path': test_path, + 'cond': cond} + lookup = ( + # EXT CALL SERVER + ('.py', 'python', ''), + ('.MAL.py', 'python', 'MAL'), + ('.SQL.py', 'python', 'SQL'), + ('.malC', 'mal', 'MAL'), + ('.sql', 'sql', 'SQL'), + ('.test', 'sqltest','SQL'), + ('.R', 'R', 'SQL'), + ('.rb', 'ruby', 'SQL'), + ) + # does this test require other tests? + # if so they should exist in the same folder + if os.path.isfile(test_path + '.reqtests'): + reqtests = [] + missing_reqtests = [] + with open(test_path + '.reqtests', 'r') as f: + for l in f: + reqtests.append(l.strip()) + test['reqtests'] = reqtests + for r in reqtests: + rp = os.path.join(real_dir_path, test_name) + for ext, _, _ in lookup: + if os.path.isfile(rp + ext) \ + or os.path.isfile(rp + ext + 'src') \ + or os.path.isfile(rp + ext + 'in'): + break + else: + missing_reqtests.append(r) + test['missing_reqtests'] = missing_reqtests + # TODO .timeout and .nomito + for ext, call, server in lookup: + if os.path.isfile(test_path + ext): + test['ext'] = ext + test['call'] = call + test['server'] = server + break + if os.path.isfile(test_path + ext + '.src'): + test['ext'] = ext + '.src' + test['call'] = call + test['server'] = server + test['is_link'] = True + break + if os.path.isfile(test_path + ext + '.in'): + test['ext'] = ext + '.in' + test['call'] = call + test['server'] = server + test['is_input'] = True + break + else: + print("WARNING: test name {} declared but not found under {}".format(test_name, dir_path)) + if (kwargs.get('sqllogic') is True) and (test.get('ext') == '.sql'): + # assuming those sql scripts have being converted to sqllogic, so skip + pass + else: + tests_out.append(test) + folder['test_count'] = len(tests_out) + folder['tests'] = tests_out + ctx['test_folders'].append(folder) + ctx['test_count'] += len(tests_out) + return ctx + +def process_dir(dir_path: str, ctx={}, **kwargs): + print('-->', dir_path) + if os.path.basename(os.path.realpath(dir_path)) == 'Tests': + return process_test_dir(dir_path, ctx, **kwargs) + onlydirs = [d for d in os.listdir(dir_path) if os.path.isdir(os.path.join(dir_path, d))] + # temporary rule here when sqllogictest and Tests folders are siblings, then assuming .sql + # tests under Tests folder were converted to .test under sqllogictest/Tests + rgx = re.compile('Tests|sqllogictest') + filtered = list(filter(lambda x: rgx.search(x), onlydirs)) + found_siblings = len(filtered) == 2 + for d in onlydirs: + dir_ = os.path.join(dir_path, d) + if d == 'Tests' and found_siblings: + process_dir(dir_, ctx, **kwargs, sqllogic=True) + else: + process_dir(dir_, ctx, **kwargs) + +def build_work_ctx(*args): + """ + builds testing context + args: + single directory, or list of directories, or directory followed by list of tests within it + return: + ctx object + """ + ctx = {'test_folders': [], 'test_count': 0} + if len(args) == 0: + return ctx + if len(args) == 1 and os.path.isdir(args[0]): + process_dir(args[0], ctx) + return ctx + is_all_dir = True + for n in args: + if not os.path.isdir(n): + is_all_dir = False + break + if is_all_dir: + for d in args: + process_dir(d, ctx) + return ctx + # check for first arg being dir, following being valid test files within that directory + dir_path = os.path.realpath(args[0]) if os.path.isdir(args[0]) else None + if dir_path and os.path.basename(dir_path) == 'Tests': + process_test_dir(dir_path, ctx, test_names=args[1:]) + else: + raise ValueError('ERROR: {} is not a valid Tests directory'.format(args[0])) + return ctx + +if __name__ == '__main__': + ctx = build_work_ctx(*sys.argv[1:]) + import json + print(json.dumps(ctx, indent=4)) _______________________________________________ checkin-list mailing list checkin-list@monetdb.org https://www.monetdb.org/mailman/listinfo/checkin-list