crt: tests: add helper library libtest.a This static library contains helper functions for use by test programs; it is linked into every test program. Signed-off-by: Kirill Makurin <maiddaisuki@outlook.com> Signed-off-by: LIU Hao <lh_mouse@126.com>
diff --git a/mingw-w64-crt/testcases/Makefile.am b/mingw-w64-crt/testcases/Makefile.am index 1bf8f5a..0b6336e 100644 --- a/mingw-w64-crt/testcases/Makefile.am +++ b/mingw-w64-crt/testcases/Makefile.am
@@ -4,6 +4,21 @@ AM_CFLAGS=@ADD_C_CXX_WARNING_FLAGS@ @ADD_C_ONLY_WARNING_FLAGS@ $(TEST_CFLAGS) -Wno-missing-prototypes AM_CXXFLAGS=@ADD_C_CXX_WARNING_FLAGS@ @ADD_CXX_ONLY_WARNING_FLAGS@ $(TEST_CFLAGS) +# Link all test programs against libtest.a; for targets with their own +# target-specifc *_LDADD variable, make sure to add $(LDADD). +LDADD = $(builddir)/libtest.a + +check_LIBRARIES = \ + libtest.a + +# libtest.a is a static library containing helper function for use by tests +# programs. +# +# When you write a new test, please include libtest.h and add a call to +# mingw_test_init() function upon entry to main(). +libtest_a_SOURCES = \ + libtest.c libtest.h + # Used by t_safe_flush libprocdetach.dll: libprocdetach.o $(LINK) -shared libprocdetach.o -o libprocdetach.dll @@ -165,7 +180,7 @@ t_intrinc_CFLAGS = -std=c99 $(AM_CFLAGS) # Link t_safe_flush against libprocdetach.dll -t_safe_flush_LDADD = libprocdetach.dll +t_safe_flush_LDADD = libprocdetach.dll $(LDADD) # Compile t_tls_ansi in C89 mode t_tls_ansi_CFLAGS = -std=c89 $(AM_CFLAGS) @@ -174,7 +189,7 @@ t_tls_c11_CFLAGS = -std=c11 $(AM_CFLAGS) # Link t_winmain against gdi32.dll -t_winmain_LDADD = -lgdi32 +t_winmain_LDADD = -lgdi32 $(LDADD) if ENABLE_TESTS_UNICODE # The following tests require compiler support for -municode option @@ -188,8 +203,6 @@ t__wstat_all_CFLAGS = -municode $(AM_CFLAGS) endif -check_LIBRARIES = - check_PROGRAMS = \ $(testcase_compile_only) \ $(testcase_progs)
diff --git a/mingw-w64-crt/testcases/libtest.c b/mingw-w64-crt/testcases/libtest.c new file mode 100644 index 0000000..9d39c40 --- /dev/null +++ b/mingw-w64-crt/testcases/libtest.c
@@ -0,0 +1,113 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ + +#ifdef NDEBUG +#undef NDEBUG +#endif + +#include <assert.h> +#include <crtdbg.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <wchar.h> + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +#include "libtest.h" + +/** + * Invalid parameter handler. + */ +__attribute__ ((__noreturn__)) +static void __cdecl mingw_test_invalid_parameter_handler ( + const wchar_t *expression, + const wchar_t *function, + const wchar_t *file, + unsigned int line, + uintptr_t pReserved +) { + fprintf(stderr, "Invalid parameter: %ls", expression); + /* Additional arguments are non-NULL only for debug CRT DLLs */ + if (function) + fprintf(stderr, ", function %ls", function); + if (file) + fprintf(stderr, ", file %ls", file); + if (line) + fprintf(stderr, ", line %d", line); + fprintf(stderr, "\n"); + (void)pReserved; + /* Ensure that this handler does not return, as the whole handler replaces calling of Dr. Watson */ + abort (); +} + +static int __cdecl mingw_test_fini (void) { + _CrtCheckMemory (); + _CrtDumpMemoryLeaks (); + + return EXIT_SUCCESS; +} + +void mingw_test_init (void) { + UINT oldErrorMode = SetErrorMode (0); + SetErrorMode (oldErrorMode | SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX); + + /** + * msvcr80.dll and later attempt to set multibyte code page to active + * ANSI code page during initialization. + * + * If active ANSI code page is 65001 (UTF-8), _setmbcp will fail + * and set `errno` to EINVAL. + * + * Some tests may assume `errno` to be set to zero when entering main. + */ + errno = 0; + + /* Set CRT _invalid_parameter() output to CRT stderr and call abort (the default is to just call Dr. Watson) */ + _set_invalid_parameter_handler (mingw_test_invalid_parameter_handler); + + /** + * Disable buffering. + * This ensures that all output is written to log files. + */ + setvbuf (stdout, NULL, _IONBF, 0); + setvbuf (stderr, NULL, _IONBF, 0); + +#if __MSVCRT_VERSION__ >= 0x0800 + /** + * Make `abort` as silent as possible. + */ + _set_abort_behavior (0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT); +#endif + +#if __MSVCRT_VERSION__ >= 0x0400 + /** + * We don't want failed assertions to pop-up a message box. + */ + assert (_set_error_mode (_OUT_TO_STDERR) != -1); +#endif + + /** + * Redirect `_CRT_WARN` debug messages to `stderr`. + */ + assert (_CrtSetReportMode (_CRT_WARN, _CRTDBG_MODE_DEBUG | _CRTDBG_MODE_FILE) != -1); + assert (_CrtSetReportFile (_CRT_WARN, _CRTDBG_FILE_STDERR) != _CRTDBG_HFILE_ERROR); + + /** + * Redirect `_CRT_ERROR` debug messages to `stderr`. + */ + assert (_CrtSetReportMode (_CRT_ERROR, _CRTDBG_MODE_DEBUG | _CRTDBG_MODE_FILE) != -1); + assert (_CrtSetReportFile (_CRT_ERROR, _CRTDBG_FILE_STDERR) != _CRTDBG_HFILE_ERROR); + + /** + * Redirect `_CRT_ASSERT` debug messages to `stderr`. + */ + assert (_CrtSetReportMode (_CRT_ASSERT, _CRTDBG_MODE_DEBUG | _CRTDBG_MODE_FILE) != -1); + assert (_CrtSetReportFile (_CRT_ASSERT, _CRTDBG_FILE_STDERR) != _CRTDBG_HFILE_ERROR); + + _onexit (mingw_test_fini); +}
diff --git a/mingw-w64-crt/testcases/libtest.h b/mingw-w64-crt/testcases/libtest.h new file mode 100644 index 0000000..18a612b --- /dev/null +++ b/mingw-w64-crt/testcases/libtest.h
@@ -0,0 +1,37 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ + +#ifndef __MINGW_LIBTEST_H +#define __MINGW_LIBTEST_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * This function should be called at the beginning of every test program. + * + * Currently, this function: + * + * 1. Calls `SetErrorMode` + * 2. Sets `errno` to zero, so that tests can assume it to be zero upon entry + * to main() + * 3. Sets invalid parameter handler which terminates the process by calling + * `abort` (instead of default behavior to invoke Dr. Watson) + * 4. Disables buffering on `stdout` and `stderr` to ensure that all output + * is written to log files + * 5. Calls `_set_abort_behavior` so that `abort` does not pop up a message box + * and does not invoke Dr. Watson + * 6. Calls `_set_error_mode` so that `abort` and failed `assert` does not + * pop up a message box + */ +void mingw_test_init (void); + +#ifdef __cplusplus +} +#endif + +#endif /* __MINGW_LIBTEST_H */