diff --git a/test/allcalls.h b/test/allcalls.h index 3ec24eb6..f1dbf98a 100644 --- a/test/allcalls.h +++ b/test/allcalls.h @@ -4,9 +4,7 @@ allcallsCase(uiMain, /* no arguments */) allcallsCase(uiQuit, /* no arguments */) -#ifdef allcallsIncludeQueueMain -allcallsCase(uiQueueMain, NULL, NULL) -#endif +// uiQueueMain() is defined in all files explicitly since it isn't instantiated for all possible allcalls tests allcallsCase(uiControlType, /* no arguments */) @@ -17,4 +15,3 @@ allcallsCase(uiNewControl, 0, NULL) allcallsCase(uiControlFree, NULL) allcallsCase(uiControlSetParent, NULL, NULL) allcallsCase(uiControlImplData, NULL) -allcallsCase(uiControlOnFree, /* no arguments */) diff --git a/test/meson.build b/test/meson.build index 38e58716..2669fc17 100644 --- a/test/meson.build +++ b/test/meson.build @@ -3,7 +3,10 @@ # Using files() is the cleanest way to ensure the python script below gets the right filenames regardless of how meson sandboxes the command it's running. libui_test_sources = files([ 'initmain.c', -# 'noinitwrongthread.c', + 'noinitwrongthread.c', +]) +libui_allcalls_headers = files([ + 'allcalls.h', ]) libui_test_sources_without_cases = [ @@ -46,7 +49,7 @@ libui_testlist_py = files(['testlist.py']) libui_testlist_h = custom_target( 'testlist.h', - input: libui_test_sources, + input: libui_test_sources + libui_allcalls_headers, output: ['testlist.h'], command: [python, libui_testlist_py, 'header', '@OUTPUT@', '@INPUT@']) libui_testlist_c = custom_target( @@ -63,7 +66,7 @@ libui_testparent = executable('testparent', libui_test_sources + libui_test_sour gui_app: false, install: false) -runresult = run_command(python, libui_testlist_py + ['list'] + libui_test_sources) +runresult = run_command(python, libui_testlist_py + ['list'] + libui_test_sources + libui_allcalls_headers) if runresult.returncode() != 0 error('testlist.py failed; cannot compute list of test cases. Exit code @0@; stderr:\n@1@'.format(runresult.returncode(), runresult.stderr())) endif diff --git a/test/noinitwrongthread.c b/test/noinitwrongthread.c index 44640b23..d26d833c 100644 --- a/test/noinitwrongthread.c +++ b/test/noinitwrongthread.c @@ -1,35 +1,52 @@ // 28 may 2019 #include "test.h" -#define allcallsCaseFuncName(f) allcallsCaseFunc ## f -#define allcallsCase(f, ...) static void allcallsCaseFuncName(f)(void) { f(__VA_ARGS__); } -#define allcallsIncludeQueueMain + if match is not None: + f = match.group(1) + casenames.append('TestCallOnWrongThreadIsProgrammerError_' + f) + +// TODO rename to FunctionsFailBeforeInit? +#define allcallsCase(f, ...) \ + TestNoInit(CallBeforeInitIsProgrammerError_ ## f) \ + { \ + void *ctx; \ + ctx = beginCheckProgrammerError("atteTODOmpt to call " #f "() before uiInit()"); \ + f(__VA_ARGS__); \ + endCheckProgrammerError(ctx); \ + } #include "allcalls.h" -#undef allcallsIncludeQueueMain #undef allcallsCase -static const struct checkErrorCase beforeInitCases[] = { -#define allcallsCase(f, ...) { #f "()", allcallsCaseFuncName(f), "attempt to call " #f "() before uiInit()" }, -#define allcallsIncludeQueueMain -#include "allcalls.h" -#undef allcallsIncludeQueueMain -#undef allcallsCase - { NULL, NULL, NULL }, -}; - -TestNoInit(FunctionsFailBeforeInit) +TestNoInit(CallBeforeInitIsProgrammerError_uiQueueMain) { - checkProgrammerErrors(beforeInitCases); + void *ctx; + + ctx = beginCheckProgrammerError("atteTODOmpt to call uiQueueMain() before uiInit()"); + uiQueueMain(NULL, NULL); + endCheckProgrammerError(ctx); } -static const struct checkErrorCase wrongThreadCases[] = { -#define allcallsCase(f, ...) { #f "()", allcallsCaseFuncName(f), "attempt to call " #f "() on a thread other than the GUI thread" }, +// TODO rename to FunctionsFailOnWrongThread? +#define allcallsCase(f, ...) \ + static void threadTest ## f(void *data) \ + { \ + f(__VA_ARGS__); \ + } \ + Test(CallOnWrongThreadIsProgrammerError_ ## f) \ + { \ + threadThread *thread; \ + threadSysError err; \ + void *ctx; \ + ctx = beginCheckProgrammerError("atteTODOmpt to call " #f "() on a thread other than the GUI thread"); \ + err = threadNewThread(threadTest ## f, NULL, &thread); \ + if (err != 0) \ + TestFatalf("error creating thread: " threadSysErrorFmt, threadSysErrorFmtArg(err)); \ + err = threadThreadWaitAndFree(thread); \ + if (err != 0) \ + TestFatalf("error waiting for thread to finish: " threadSysErrorFmt, threadSysErrorFmtArg(err)); \ + endCheckProgrammerError(ctx); \ + } #include "allcalls.h" #undef allcallsCase - { NULL, NULL, NULL }, -}; -Test(FunctionsFailOnWrongThread) -{ - checkProgrammerErrorsInThread(wrongThreadCases); -} +// no uiQueueMain() test for the wrong thread; it's supposed to be callable from any thread diff --git a/test/testlist.py b/test/testlist.py index 1f3fb4f0..6895ced4 100644 --- a/test/testlist.py +++ b/test/testlist.py @@ -128,7 +128,8 @@ def usage(): sys.exit(1) def main(): - r = re.compile('^(?:Test|TestNoInit)\(([A-Za-z0-9_]+)\)$') + rTest = re.compile('^(?:Test|TestNoInit)\(([A-Za-z0-9_]+)\)$') + rAllCalls = re.compile('^(?:allcallsCase)\(([A-Za-z0-9_]+),') if len(sys.argv) < 2: usage() @@ -151,9 +152,15 @@ def main(): casenames = [] for line in fileinput.input(files = files): - match = r.match(line) + match = rTest.match(line) if match is not None: casenames.append(match.group(1)) + match = rAllCalls.match(line) + if match is not None: + f = match.group(1) + # noinitwrongthread.c + casenames.append('TestCallBeforeInitIsProgrammerError_' + f) + casenames.append('TestCallOnWrongThreadIsProgrammerError_' + f) cmd.run(sorted(casenames)) main()