[ROSTESTS] Implement automatic test discovery

This uses the START_TEST macro to create test entries in a ".test" section in the binary.
This commit is contained in:
Timo Kreuzer
2026-02-25 17:14:30 +02:00
parent 104d889c7a
commit 151c67ebfc
4 changed files with 55 additions and 0 deletions

View File

@@ -88,6 +88,7 @@ typedef unsigned int u32;
typedef COMPILER_DEPENDENT_UINT64 u64;
#endif
#ifndef __REACTOS__
/*
* Map low I/O functions for MS. This allows us to disable MS language
* extensions for maximum portability.
@@ -101,6 +102,7 @@ typedef COMPILER_DEPENDENT_UINT64 u64;
#define mkdir _mkdir
#define fileno _fileno
#define isatty _isatty
#endif // __REACTOS__
#if _MSC_VER <= 1200 /* Versions below VC++ 6 */
#define vsnprintf _vsnprintf

View File

@@ -1,6 +1,10 @@
start_module_group(rostests)
if(NOT MSVC)
add_link_options("-Wl,-T,${CMAKE_CURRENT_SOURCE_DIR}/test-section.lds")
endif()
add_definitions(-DHAVE_APITEST)
if(MSVC_IDE)

View File

@@ -0,0 +1,11 @@
/* Make sure the .test section is kept and sorted */
SECTIONS
{
.test BLOCK(__section_alignment__) :
{
___test_start__ = . ;
KEEP (*(SORT(.test$*)))
___test_end__ = . ;
}
}
INSERT BEFORE .reloc; /* .reloc is always at the end */

View File

@@ -586,7 +586,12 @@ struct test
void (*func)(void);
};
#ifdef __REACTOS__
extern const struct test winetest_testlist_start[];
const struct test* winetest_testlist = &winetest_testlist_start[1];
#else
extern const struct test winetest_testlist[];
#endif
/* debug level */
int winetest_debug = 1;
@@ -1018,8 +1023,41 @@ extern void winetest_end_nocount(void);
#define GetNTVersion() ((GetMajorNTVersion() << 8) | GetMinorNTVersion())
#define __REACTOS__WinVer_lt(Ver) ((GetNTVersion() < (Ver)))
#ifndef STANDALONE
struct test
{
const char *name;
void (*func)(void);
};
#endif
/* Section allocation helper for automatic test registration */
#if defined(_MSC_VER)
#pragma section(".test$A",long,read)
#define _TESTALLOC(x) __declspec(allocate(x))
#define _PRAGMA_SECTION(x, y, z) __pragma(section(x, y, z))
#define _TESTKEEP(x) const void* keep_##x = &x;
#elif defined(__GNUC__)
#define _TESTALLOC(x) __attribute__((used, section(x)))
#define _PRAGMA_SECTION(x, y, z)
#define _TESTKEEP(x)
#else
#error Your compiler is not supported.
#endif
#undef START_TEST
#define START_TEST(name) \
EXTERN_C void func_##name(void); \
_PRAGMA_SECTION(_CRT_STRINGIZE(.test$B##name), long, read); \
_TESTALLOC(_CRT_STRINGIZE(.test$B##name)) const struct test winetest_testentry_##name = { #name, func_##name }; \
_TESTKEEP(winetest_testentry_##name) \
EXTERN_C void func_##name(void)
#ifdef STANDALONE
_TESTALLOC(".test$A") const struct test winetest_testlist_start[] = { { "", 0 } };
#define winetest_testlist winetest_testlist_dummy
LONG winetest_get_successes(void)
{
return winetest_successes;