@@ -2455,12 +2455,101 @@ static int test_mp_pack_unpack(void)
2455
2455
#define ONLY_PUBLIC_API_C
2456
2456
#endif
2457
2457
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
+
2458
2550
static int unit_tests (int argc , char * * argv )
2459
2551
{
2460
- static const struct {
2461
- const char * name ;
2462
- int (* fn )(void );
2463
- } test [] = {
2552
+ static const struct test_fn test [] = {
2464
2553
#define T0 (n ) { #n , test_##n }
2465
2554
#define T1 (n , o ) { #n, MP_HAS(o) ? test_##n : NULL }
2466
2555
#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)
2522
2611
#undef T2
2523
2612
#undef T1
2524
2613
};
2614
+ struct thread_info test_threads [sizeof (test )/sizeof (test [0 ])], * res ;
2525
2615
unsigned long i , ok , fail , nop ;
2526
2616
uint64_t t ;
2527
2617
int j ;
2528
-
2529
2618
ok = fail = nop = 0 ;
2530
2619
2531
2620
t = (uint64_t )time (NULL );
2532
2621
printf ("SEED: 0x%" PRIx64 "\n\n" , t );
2533
2622
s_mp_rand_jenkins_init (t );
2534
2623
mp_rand_source (s_mp_rand_jenkins );
2535
2624
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
+
2536
2638
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
+ }
2541
2646
}
2647
+ if (j == argc ) continue ;
2542
2648
}
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 ;
2544
2655
}
2545
2656
printf ("TEST %s\n" , test [i ].name );
2657
+
2546
2658
if (test [i ].fn == NULL ) {
2547
2659
nop ++ ;
2548
2660
printf ("NOP %s\n\n" , test [i ].name );
2549
- } else if (test [ i ]. fn () == EXIT_SUCCESS ) {
2661
+ } else if (j == EXIT_SUCCESS ) {
2550
2662
ok ++ ;
2551
2663
printf ("\n" );
2552
2664
} else {
@@ -2556,8 +2668,12 @@ static int unit_tests(int argc, char **argv)
2556
2668
}
2557
2669
fprintf (fail ?stderr :stdout , "Tests OK/NOP/FAIL: %lu/%lu/%lu\n" , ok , nop , fail );
2558
2670
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 ;
2561
2677
}
2562
2678
2563
2679
int main (int argc , char * * argv )
0 commit comments