From: Rémi Bernon rbernon@codeweavers.com
This hashes 5 lines of source code before and after the check, to create unique identifier for each test that is more robust to moving code and modified line numbers. --- programs/winetest/main.c | 47 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-)
diff --git a/programs/winetest/main.c b/programs/winetest/main.c index 90e9bbad2eb..00a5e715c5d 100644 --- a/programs/winetest/main.c +++ b/programs/winetest/main.c @@ -36,6 +36,18 @@ #include "winetest.h" #include "resource.h"
+typedef struct +{ + ULONG Unknown[6]; + ULONG State[5]; + ULONG Count[2]; + UCHAR Buffer[64]; +} SHA_CTX; + +VOID WINAPI A_SHAInit(SHA_CTX *ctx); +VOID WINAPI A_SHAUpdate(SHA_CTX *ctx, const UCHAR *buffer, UINT size); +VOID WINAPI A_SHAFinal(SHA_CTX *ctx, PULONG result); + /* Don't submit the results if more than SKIP_LIMIT tests have been skipped */ #define SKIP_LIMIT 10
@@ -69,6 +81,7 @@ static BOOL is_wow64; static int failures; static int quiet_mode; static int junit_mode; +static int context_lines = 5;
/* filters for running only specific tests */ static char **filters; @@ -896,6 +909,36 @@ static char *strescape( const char *src, const char *end, int comment ) return dst; }
+static char *get_test_name( HMODULE module, const char *src, int num, int *size ) +{ + const char *source, *next, *line; + ULONG sha1_hash[5]; + HGLOBAL handle; + SHA_CTX ctx; + HRSRC rsrc; + + if (!(rsrc = FindResourceA( module, src, "TESTSRC" ))) return NULL; + if (!(*size = SizeofResource( module, rsrc ))) return NULL; + if (!(handle = LoadResource( module, rsrc))) return NULL; + if (!(source = LockResource( handle ))) return NULL; + + A_SHAInit( &ctx ); + for (line = next = source; line < source + *size; line = next) + { + if ((next = memchr( next, '\n', source + *size - next ))) next += 1; + else next = source + *size; + + if (--num > context_lines) continue; + A_SHAUpdate( &ctx, (BYTE *)line, next - line ); + while (line < next && (*line == ' ' || *line == '\t')) line++; + if (num <= -context_lines) break; + } + A_SHAFinal( &ctx, sha1_hash ); + + if (num > context_lines) return NULL; + return strmake( NULL, "%08x%08x%08x%08x%08x", sha1_hash[0], sha1_hash[1], sha1_hash[2], sha1_hash[3], sha1_hash[4] ); +} + static void report_test_start( struct wine_test *test, const char *subtest, const char *file ) { report( R_STEP, "Running: %s:%s", test->name, subtest ); @@ -907,6 +950,7 @@ static void report_test_done( struct wine_test *test, const char *subtest, const { if (junit_mode) { + HMODULE module = LoadLibraryExA( test->exename, NULL, LOAD_LIBRARY_AS_DATAFILE ); int total = 0, fail_total = 0, skip_total = 0, failures = 0; const char *next, *line, *ptr, *dir = strrchr( file, '/' ); float time, last_time = 0; @@ -960,7 +1004,7 @@ static void report_test_done( struct wine_test *test, const char *subtest, const if (!(ptr = strchr( line, ' ' ))) continue; ptr++;
- name = strmake( NULL, "%s:%d", src, n ); + if (!(name = get_test_name( module, src, n, &len ))) name = strmake( NULL, "%s:%d", src, n ); for (i = 0; i < ARRAY_SIZE(patterns); i++) { if (!strncmp( ptr, patterns[i].pattern, patterns[i].length )) @@ -1003,6 +1047,7 @@ static void report_test_done( struct wine_test *test, const char *subtest, const }
xprintf( " </testsuite>\n" ); + FreeLibrary( module ); } else {