@@ -2455,12 +2455,101 @@ static int test_mp_pack_unpack(void)
24552455#define ONLY_PUBLIC_API_C
24562456#endif
24572457
2458+ #if !defined(LTM_TEST_MULTITHREAD )
2459+ #define SINGLE_THREADED_C
2460+ typedef uintptr_t thread_id_t ;
2461+ #else
2462+ #define MULTI_THREADED_C
2463+ #if !defined(_WIN32 )
2464+ #define MULTI_THREADED_PTHREAD_C
2465+ #include <pthread.h>
2466+ typedef pthread_t thread_id_t ;
2467+ #else
2468+ #define MULTI_THREADED_MSVC_C
2469+
2470+ #ifndef _WIN32_WINNT
2471+ #define _WIN32_WINNT 0x0501
2472+ #endif
2473+ #ifndef WINVER
2474+ #define WINVER 0x0501
2475+ #endif
2476+
2477+ #define WIN32_LEAN_AND_MEAN
2478+ #include <windows.h>
2479+ typedef HANDLE thread_id_t ;
2480+ #endif
2481+ #endif
2482+
2483+ #if !defined(MULTI_THREADED_PTHREAD_C )
2484+ extern int pthread_create (thread_id_t * , const void * , void * (* )(void * ), void * );
2485+ extern int pthread_join (thread_id_t , void * * );
2486+ #endif
2487+
2488+ #if !defined(MULTI_THREADED_MSVC_C )
2489+ extern thread_id_t CreateThread (void * , size_t , unsigned long (* )(void * ), void * , unsigned long , void * );
2490+ extern unsigned long WaitForSingleObject (thread_id_t hHandle , unsigned long dwMilliseconds );
2491+ #define INFINITE ((unsigned long)-1)
2492+ #endif
2493+
2494+ struct test_fn {
2495+ const char * name ;
2496+ int (* fn )(void );
2497+ };
2498+
2499+ struct thread_info {
2500+ thread_id_t thread_id ;
2501+ const struct test_fn * t ;
2502+ int ret ;
2503+ };
2504+
2505+ static void run (struct thread_info * tinfo )
2506+ {
2507+ tinfo -> ret = tinfo -> t -> fn ();
2508+
2509+ if (mp_warray_free () == -2 )
2510+ tinfo -> ret = EXIT_FAILURE ;
2511+ }
2512+
2513+ static void * run_pthread (void * arg )
2514+ {
2515+ run (arg );
2516+
2517+ return arg ;
2518+ }
2519+
2520+ static unsigned long run_msvc (void * arg )
2521+ {
2522+ run (arg );
2523+
2524+ return 0 ;
2525+ }
2526+
2527+ static int thread_start (struct thread_info * info )
2528+ {
2529+ if (MP_HAS (MULTI_THREADED_PTHREAD ))
2530+ return pthread_create (& info -> thread_id , NULL , run_pthread , info );
2531+ if (MP_HAS (MULTI_THREADED_MSVC )) {
2532+ info -> thread_id = CreateThread (NULL , 0 , run_msvc , info , 0 , NULL );
2533+ return info -> thread_id == (thread_id_t )NULL ? -1 : 0 ;
2534+ }
2535+ return -1 ;
2536+ }
2537+
2538+ static int thread_join (struct thread_info * info , struct thread_info * * res )
2539+ {
2540+ if (MP_HAS (MULTI_THREADED_PTHREAD ))
2541+ return pthread_join (info -> thread_id , (void * * )res );
2542+ if (MP_HAS (MULTI_THREADED_MSVC )) {
2543+ WaitForSingleObject (info -> thread_id , INFINITE );
2544+ * res = info ;
2545+ return 0 ;
2546+ }
2547+ return -1 ;
2548+ }
2549+
24582550static int unit_tests (int argc , char * * argv )
24592551{
2460- static const struct {
2461- const char * name ;
2462- int (* fn )(void );
2463- } test [] = {
2552+ static const struct test_fn test [] = {
24642553#define T0 (n ) { #n , test_##n }
24652554#define T1 (n , o ) { #n, MP_HAS(o) ? test_##n : NULL }
24662555#define T2 (n , o1 , o2 ) { #n, (MP_HAS(o1) && MP_HAS(o2)) ? test_##n : NULL }
@@ -2522,31 +2611,54 @@ static int unit_tests(int argc, char **argv)
25222611#undef T2
25232612#undef T1
25242613 };
2614+ struct thread_info test_threads [sizeof (test )/sizeof (test [0 ])], * res ;
25252615 unsigned long i , ok , fail , nop ;
25262616 uint64_t t ;
25272617 int j ;
2528-
25292618 ok = fail = nop = 0 ;
25302619
25312620 t = (uint64_t )time (NULL );
25322621 printf ("SEED: 0x%" PRIx64 "\n\n" , t );
25332622 s_mp_rand_jenkins_init (t );
25342623 mp_rand_source (s_mp_rand_jenkins );
25352624
2625+ if (MP_HAS (MP_SMALL_STACK_SIZE )) {
2626+ printf ("Small-stack enabled\n\n" );
2627+ }
2628+
2629+ if (MP_HAS (MULTI_THREADED )) {
2630+ printf ("Multi-threading enabled\n\n" );
2631+ /* we ignore the fact that jenkins is not thread safe */
2632+ for (i = 0 ; i < (sizeof (test ) / sizeof (test [0 ])); ++ i ) {
2633+ test_threads [i ].t = & test [i ];
2634+ EXPECT (thread_start (& test_threads [i ]) == 0 );
2635+ }
2636+ }
2637+
25362638 for (i = 0 ; i < (sizeof (test ) / sizeof (test [0 ])); ++ i ) {
2537- if (argc > 1 ) {
2538- for (j = 1 ; j < argc ; ++ j ) {
2539- if (strstr (test [i ].name , argv [j ]) != NULL ) {
2540- break ;
2639+ j = -1 ;
2640+ if (MP_HAS (SINGLE_THREADED )) {
2641+ if (argc > 1 ) {
2642+ for (j = 1 ; j < argc ; ++ j ) {
2643+ if (strstr (test [i ].name , argv [j ]) != NULL ) {
2644+ break ;
2645+ }
25412646 }
2647+ if (j == argc ) continue ;
25422648 }
2543- if (j == argc ) continue ;
2649+
2650+ if (test [i ].fn )
2651+ j = test [i ].fn ();
2652+ } else if (MP_HAS (MULTI_THREADED )) {
2653+ EXPECT (thread_join (& test_threads [i ], & res ) == 0 );
2654+ j = res -> ret ;
25442655 }
25452656 printf ("TEST %s\n" , test [i ].name );
2657+
25462658 if (test [i ].fn == NULL ) {
25472659 nop ++ ;
25482660 printf ("NOP %s\n\n" , test [i ].name );
2549- } else if (test [ i ]. fn () == EXIT_SUCCESS ) {
2661+ } else if (j == EXIT_SUCCESS ) {
25502662 ok ++ ;
25512663 printf ("\n" );
25522664 } else {
@@ -2556,8 +2668,12 @@ static int unit_tests(int argc, char **argv)
25562668 }
25572669 fprintf (fail ?stderr :stdout , "Tests OK/NOP/FAIL: %lu/%lu/%lu\n" , ok , nop , fail );
25582670
2559- if (fail != 0 ) return EXIT_FAILURE ;
2560- else return EXIT_SUCCESS ;
2671+ EXPECT (mp_warray_free () != -2 );
2672+
2673+ if (fail == 0 )
2674+ return EXIT_SUCCESS ;
2675+ LBL_ERR :
2676+ return EXIT_FAILURE ;
25612677}
25622678
25632679int main (int argc , char * * argv )
0 commit comments