7
7
#include <string.h>
8
8
9
9
/* defined in test_progs.h */
10
- struct test_env env = {
11
- .test_num_selector = -1 ,
12
- };
10
+ struct test_env env ;
13
11
int error_cnt , pass_cnt ;
14
12
15
13
struct prog_test_def {
@@ -20,8 +18,82 @@ struct prog_test_def {
20
18
int pass_cnt ;
21
19
int error_cnt ;
22
20
bool tested ;
21
+
22
+ const char * subtest_name ;
23
+ int subtest_num ;
24
+
25
+ /* store counts before subtest started */
26
+ int old_pass_cnt ;
27
+ int old_error_cnt ;
23
28
};
24
29
30
+ static bool should_run (struct test_selector * sel , int num , const char * name )
31
+ {
32
+ if (sel -> name && sel -> name [0 ] && !strstr (name , sel -> name ))
33
+ return false;
34
+
35
+ if (!sel -> num_set )
36
+ return true;
37
+
38
+ return num < sel -> num_set_len && sel -> num_set [num ];
39
+ }
40
+
41
+ static void dump_test_log (const struct prog_test_def * test , bool failed )
42
+ {
43
+ if (env .verbose || test -> force_log || failed ) {
44
+ if (env .log_cnt ) {
45
+ fprintf (stdout , "%s" , env .log_buf );
46
+ if (env .log_buf [env .log_cnt - 1 ] != '\n' )
47
+ fprintf (stdout , "\n" );
48
+ }
49
+ env .log_cnt = 0 ;
50
+ }
51
+ }
52
+
53
+ void test__end_subtest ()
54
+ {
55
+ struct prog_test_def * test = env .test ;
56
+ int sub_error_cnt = error_cnt - test -> old_error_cnt ;
57
+
58
+ if (sub_error_cnt )
59
+ env .fail_cnt ++ ;
60
+ else
61
+ env .sub_succ_cnt ++ ;
62
+
63
+ dump_test_log (test , sub_error_cnt );
64
+
65
+ printf ("#%d/%d %s:%s\n" ,
66
+ test -> test_num , test -> subtest_num ,
67
+ test -> subtest_name , sub_error_cnt ? "FAIL" : "OK" );
68
+ }
69
+
70
+ bool test__start_subtest (const char * name )
71
+ {
72
+ struct prog_test_def * test = env .test ;
73
+
74
+ if (test -> subtest_name ) {
75
+ test__end_subtest ();
76
+ test -> subtest_name = NULL ;
77
+ }
78
+
79
+ test -> subtest_num ++ ;
80
+
81
+ if (!name || !name [0 ]) {
82
+ fprintf (stderr , "Subtest #%d didn't provide sub-test name!\n" ,
83
+ test -> subtest_num );
84
+ return false;
85
+ }
86
+
87
+ if (!should_run (& env .subtest_selector , test -> subtest_num , name ))
88
+ return false;
89
+
90
+ test -> subtest_name = name ;
91
+ env .test -> old_pass_cnt = pass_cnt ;
92
+ env .test -> old_error_cnt = error_cnt ;
93
+
94
+ return true;
95
+ }
96
+
25
97
void test__force_log () {
26
98
env .test -> force_log = true;
27
99
}
@@ -281,24 +353,103 @@ static int libbpf_print_fn(enum libbpf_print_level level,
281
353
return 0 ;
282
354
}
283
355
356
+ int parse_num_list (const char * s , struct test_selector * sel )
357
+ {
358
+ int i , set_len = 0 , num , start = 0 , end = -1 ;
359
+ bool * set = NULL , * tmp , parsing_end = false;
360
+ char * next ;
361
+
362
+ while (s [0 ]) {
363
+ errno = 0 ;
364
+ num = strtol (s , & next , 10 );
365
+ if (errno )
366
+ return - errno ;
367
+
368
+ if (parsing_end )
369
+ end = num ;
370
+ else
371
+ start = num ;
372
+
373
+ if (!parsing_end && * next == '-' ) {
374
+ s = next + 1 ;
375
+ parsing_end = true;
376
+ continue ;
377
+ } else if (* next == ',' ) {
378
+ parsing_end = false;
379
+ s = next + 1 ;
380
+ end = num ;
381
+ } else if (* next == '\0' ) {
382
+ parsing_end = false;
383
+ s = next ;
384
+ end = num ;
385
+ } else {
386
+ return - EINVAL ;
387
+ }
388
+
389
+ if (start > end )
390
+ return - EINVAL ;
391
+
392
+ if (end + 1 > set_len ) {
393
+ set_len = end + 1 ;
394
+ tmp = realloc (set , set_len );
395
+ if (!tmp ) {
396
+ free (set );
397
+ return - ENOMEM ;
398
+ }
399
+ set = tmp ;
400
+ }
401
+ for (i = start ; i <= end ; i ++ ) {
402
+ set [i ] = true;
403
+ }
404
+
405
+ }
406
+
407
+ if (!set )
408
+ return - EINVAL ;
409
+
410
+ sel -> num_set = set ;
411
+ sel -> num_set_len = set_len ;
412
+
413
+ return 0 ;
414
+ }
415
+
284
416
static error_t parse_arg (int key , char * arg , struct argp_state * state )
285
417
{
286
418
struct test_env * env = state -> input ;
287
419
288
420
switch (key ) {
289
421
case ARG_TEST_NUM : {
290
- int test_num ;
422
+ char * subtest_str = strchr ( arg , '/' ) ;
291
423
292
- errno = 0 ;
293
- test_num = strtol (arg , NULL , 10 );
294
- if (errno )
295
- return - errno ;
296
- env -> test_num_selector = test_num ;
424
+ if (subtest_str ) {
425
+ * subtest_str = '\0' ;
426
+ if (parse_num_list (subtest_str + 1 ,
427
+ & env -> subtest_selector )) {
428
+ fprintf (stderr ,
429
+ "Failed to parse subtest numbers.\n" );
430
+ return - EINVAL ;
431
+ }
432
+ }
433
+ if (parse_num_list (arg , & env -> test_selector )) {
434
+ fprintf (stderr , "Failed to parse test numbers.\n" );
435
+ return - EINVAL ;
436
+ }
297
437
break ;
298
438
}
299
- case ARG_TEST_NAME :
300
- env -> test_name_selector = arg ;
439
+ case ARG_TEST_NAME : {
440
+ char * subtest_str = strchr (arg , '/' );
441
+
442
+ if (subtest_str ) {
443
+ * subtest_str = '\0' ;
444
+ env -> subtest_selector .name = strdup (subtest_str + 1 );
445
+ if (!env -> subtest_selector .name )
446
+ return - ENOMEM ;
447
+ }
448
+ env -> test_selector .name = strdup (arg );
449
+ if (!env -> test_selector .name )
450
+ return - ENOMEM ;
301
451
break ;
452
+ }
302
453
case ARG_VERIFIER_STATS :
303
454
env -> verifier_stats = true;
304
455
break ;
@@ -353,14 +504,15 @@ int main(int argc, char **argv)
353
504
env .test = test ;
354
505
test -> test_num = i + 1 ;
355
506
356
- if (env .test_num_selector >= 0 &&
357
- test -> test_num != env .test_num_selector )
358
- continue ;
359
- if (env .test_name_selector &&
360
- !strstr (test -> test_name , env .test_name_selector ))
507
+ if (!should_run (& env .test_selector ,
508
+ test -> test_num , test -> test_name ))
361
509
continue ;
362
510
363
511
test -> run_test ();
512
+ /* ensure last sub-test is finalized properly */
513
+ if (test -> subtest_name )
514
+ test__end_subtest ();
515
+
364
516
test -> tested = true;
365
517
test -> pass_cnt = pass_cnt - old_pass_cnt ;
366
518
test -> error_cnt = error_cnt - old_error_cnt ;
@@ -369,21 +521,17 @@ int main(int argc, char **argv)
369
521
else
370
522
env .succ_cnt ++ ;
371
523
372
- if (env .verbose || test -> force_log || test -> error_cnt ) {
373
- if (env .log_cnt ) {
374
- fprintf (stdout , "%s" , env .log_buf );
375
- if (env .log_buf [env .log_cnt - 1 ] != '\n' )
376
- fprintf (stdout , "\n" );
377
- }
378
- }
379
- env .log_cnt = 0 ;
524
+ dump_test_log (test , test -> error_cnt );
380
525
381
526
printf ("#%d %s:%s\n" , test -> test_num , test -> test_name ,
382
527
test -> error_cnt ? "FAIL" : "OK" );
383
528
}
384
- printf ("Summary: %d PASSED, %d FAILED\n" , env .succ_cnt , env .fail_cnt );
529
+ printf ("Summary: %d/%d PASSED, %d FAILED\n" ,
530
+ env .succ_cnt , env .sub_succ_cnt , env .fail_cnt );
385
531
386
532
free (env .log_buf );
533
+ free (env .test_selector .num_set );
534
+ free (env .subtest_selector .num_set );
387
535
388
536
return error_cnt ? EXIT_FAILURE : EXIT_SUCCESS ;
389
537
}
0 commit comments