@@ -491,6 +491,7 @@ enum ARG_KEYS {
491
491
ARG_TEST_NAME_GLOB_DENYLIST = 'd' ,
492
492
ARG_NUM_WORKERS = 'j' ,
493
493
ARG_DEBUG = -1 ,
494
+ ARG_TIMING = -2 ,
494
495
};
495
496
496
497
static const struct argp_option opts [] = {
@@ -516,6 +517,8 @@ static const struct argp_option opts[] = {
516
517
"Number of workers to run in parallel, default to number of cpus." },
517
518
{ "debug" , ARG_DEBUG , NULL , 0 ,
518
519
"print extra debug information for test_progs." },
520
+ { "timing" , ARG_TIMING , NULL , 0 ,
521
+ "track and print timing information for each test." },
519
522
{},
520
523
};
521
524
@@ -696,6 +699,9 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state)
696
699
case ARG_DEBUG :
697
700
env -> debug = true;
698
701
break ;
702
+ case ARG_TIMING :
703
+ env -> timing = true;
704
+ break ;
699
705
case ARGP_KEY_ARG :
700
706
argp_usage (state );
701
707
break ;
@@ -848,6 +854,7 @@ struct test_result {
848
854
int error_cnt ;
849
855
int skip_cnt ;
850
856
int sub_succ_cnt ;
857
+ __u32 duration_ms ;
851
858
852
859
size_t log_cnt ;
853
860
char * log_buf ;
@@ -905,9 +912,29 @@ static int recv_message(int sock, struct msg *msg)
905
912
return ret ;
906
913
}
907
914
908
- static void run_one_test (int test_num )
915
+ static __u32 timespec_diff_ms (struct timespec start , struct timespec end )
916
+ {
917
+ struct timespec temp ;
918
+
919
+ if ((end .tv_nsec - start .tv_nsec ) < 0 ) {
920
+ temp .tv_sec = end .tv_sec - start .tv_sec - 1 ;
921
+ temp .tv_nsec = 1000000000 + end .tv_nsec - start .tv_nsec ;
922
+ } else {
923
+ temp .tv_sec = end .tv_sec - start .tv_sec ;
924
+ temp .tv_nsec = end .tv_nsec - start .tv_nsec ;
925
+ }
926
+ return (temp .tv_sec * 1000 ) + (temp .tv_nsec / 1000000 );
927
+ }
928
+
929
+
930
+ static double run_one_test (int test_num )
909
931
{
910
932
struct prog_test_def * test = & prog_test_defs [test_num ];
933
+ struct timespec start = {}, end = {};
934
+ __u32 duration_ms = 0 ;
935
+
936
+ if (env .timing )
937
+ clock_gettime (CLOCK_MONOTONIC , & start );
911
938
912
939
env .test = test ;
913
940
@@ -928,6 +955,13 @@ static void run_one_test(int test_num)
928
955
restore_netns ();
929
956
if (test -> need_cgroup_cleanup )
930
957
cleanup_cgroup_environment ();
958
+
959
+ if (env .timing ) {
960
+ clock_gettime (CLOCK_MONOTONIC , & end );
961
+ duration_ms = timespec_diff_ms (start , end );
962
+ }
963
+
964
+ return duration_ms ;
931
965
}
932
966
933
967
struct dispatch_data {
@@ -999,6 +1033,7 @@ static void *dispatch_thread(void *ctx)
999
1033
result -> error_cnt = msg_test_done .test_done .error_cnt ;
1000
1034
result -> skip_cnt = msg_test_done .test_done .skip_cnt ;
1001
1035
result -> sub_succ_cnt = msg_test_done .test_done .sub_succ_cnt ;
1036
+ result -> duration_ms = msg_test_done .test_done .duration_ms ;
1002
1037
1003
1038
/* collect all logs */
1004
1039
if (msg_test_done .test_done .have_log ) {
@@ -1023,6 +1058,8 @@ static void *dispatch_thread(void *ctx)
1023
1058
}
1024
1059
/* output log */
1025
1060
{
1061
+ char buf [255 ] = {};
1062
+
1026
1063
pthread_mutex_lock (& stdout_output_lock );
1027
1064
1028
1065
if (result -> log_cnt ) {
@@ -1032,9 +1069,15 @@ static void *dispatch_thread(void *ctx)
1032
1069
fprintf (stdout , "\n" );
1033
1070
}
1034
1071
1035
- fprintf (stdout , "#%d %s:%s\n" ,
1072
+ if (env .timing ) {
1073
+ snprintf (buf , sizeof (buf ), " (%u ms)" , result -> duration_ms );
1074
+ buf [sizeof (buf ) - 1 ] = '\0' ;
1075
+ }
1076
+
1077
+ fprintf (stdout , "#%d %s:%s%s\n" ,
1036
1078
test -> test_num , test -> test_name ,
1037
- result -> error_cnt ? "FAIL" : (result -> skip_cnt ? "SKIP" : "OK" ));
1079
+ result -> error_cnt ? "FAIL" : (result -> skip_cnt ? "SKIP" : "OK" ),
1080
+ buf );
1038
1081
1039
1082
pthread_mutex_unlock (& stdout_output_lock );
1040
1083
}
@@ -1092,6 +1135,57 @@ static void print_all_error_logs(void)
1092
1135
}
1093
1136
}
1094
1137
1138
+ struct item {
1139
+ int id ;
1140
+ __u32 duration_ms ;
1141
+ };
1142
+
1143
+ static int rcompitem (const void * a , const void * b )
1144
+ {
1145
+ __u32 val_a = ((struct item * )a )-> duration_ms ;
1146
+ __u32 val_b = ((struct item * )b )-> duration_ms ;
1147
+
1148
+ if (val_a > val_b )
1149
+ return -1 ;
1150
+ if (val_a < val_b )
1151
+ return 1 ;
1152
+ return 0 ;
1153
+ }
1154
+
1155
+ static void print_slow_tests (void )
1156
+ {
1157
+ int i ;
1158
+ struct item items [ARRAY_SIZE (prog_test_defs )] = {};
1159
+
1160
+ for (i = 0 ; i < prog_test_cnt ; i ++ ) {
1161
+ struct prog_test_def * test = & prog_test_defs [i ];
1162
+ struct test_result * result = & test_results [i ];
1163
+
1164
+ if (!test -> tested || !result -> duration_ms )
1165
+ continue ;
1166
+
1167
+ items [i ].id = i ;
1168
+ items [i ].duration_ms = result -> duration_ms ;
1169
+ }
1170
+ qsort (& items [0 ], ARRAY_SIZE (items ), sizeof (items [0 ]), rcompitem );
1171
+
1172
+ fprintf (stdout , "\nTop 10 Slowest tests:\n" );
1173
+
1174
+ for (i = 0 ; i < 10 ; i ++ ) {
1175
+ struct item * v = & items [i ];
1176
+ struct prog_test_def * test ;
1177
+
1178
+ if (!v -> duration_ms )
1179
+ break ;
1180
+
1181
+ test = & prog_test_defs [v -> id ];
1182
+ fprintf (stdout , "#%d %s: %u ms%s\n" ,
1183
+ test -> test_num , test -> test_name , v -> duration_ms ,
1184
+ test -> run_serial_test != NULL ? " (serial)" : "" );
1185
+ }
1186
+ }
1187
+
1188
+
1095
1189
static int server_main (void )
1096
1190
{
1097
1191
pthread_t * dispatcher_threads ;
@@ -1149,13 +1243,15 @@ static int server_main(void)
1149
1243
for (int i = 0 ; i < prog_test_cnt ; i ++ ) {
1150
1244
struct prog_test_def * test = & prog_test_defs [i ];
1151
1245
struct test_result * result = & test_results [i ];
1246
+ char buf [255 ] = {};
1247
+ __u32 duration_ms = 0 ;
1152
1248
1153
1249
if (!test -> should_run || !test -> run_serial_test )
1154
1250
continue ;
1155
1251
1156
1252
stdio_hijack ();
1157
1253
1158
- run_one_test (i );
1254
+ duration_ms = run_one_test (i );
1159
1255
1160
1256
stdio_restore ();
1161
1257
if (env .log_buf ) {
@@ -1168,13 +1264,20 @@ static int server_main(void)
1168
1264
}
1169
1265
restore_netns ();
1170
1266
1171
- fprintf (stdout , "#%d %s:%s\n" ,
1267
+ if (env .timing ) {
1268
+ snprintf (buf , sizeof (buf ), " (%u ms)" , duration_ms );
1269
+ buf [sizeof (buf ) - 1 ] = '\0' ;
1270
+ }
1271
+
1272
+ fprintf (stdout , "#%d %s:%s%s\n" ,
1172
1273
test -> test_num , test -> test_name ,
1173
- test -> error_cnt ? "FAIL" : (test -> skip_cnt ? "SKIP" : "OK" ));
1274
+ test -> error_cnt ? "FAIL" : (test -> skip_cnt ? "SKIP" : "OK" ),
1275
+ buf );
1174
1276
1175
1277
result -> error_cnt = test -> error_cnt ;
1176
1278
result -> skip_cnt = test -> skip_cnt ;
1177
1279
result -> sub_succ_cnt = test -> sub_succ_cnt ;
1280
+ result -> duration_ms = duration_ms ;
1178
1281
}
1179
1282
1180
1283
/* generate summary */
@@ -1200,6 +1303,9 @@ static int server_main(void)
1200
1303
1201
1304
print_all_error_logs ();
1202
1305
1306
+ if (env .timing )
1307
+ print_slow_tests ();
1308
+
1203
1309
fprintf (stdout , "Summary: %d/%d PASSED, %d SKIPPED, %d FAILED\n" ,
1204
1310
env .succ_cnt , env .sub_succ_cnt , env .skip_cnt , env .fail_cnt );
1205
1311
@@ -1236,6 +1342,7 @@ static int worker_main(int sock)
1236
1342
int test_to_run ;
1237
1343
struct prog_test_def * test ;
1238
1344
struct msg msg_done ;
1345
+ __u32 duration_ms = 0 ;
1239
1346
1240
1347
test_to_run = msg .do_test .test_num ;
1241
1348
test = & prog_test_defs [test_to_run ];
@@ -1248,7 +1355,7 @@ static int worker_main(int sock)
1248
1355
1249
1356
stdio_hijack ();
1250
1357
1251
- run_one_test (test_to_run );
1358
+ duration_ms = run_one_test (test_to_run );
1252
1359
1253
1360
stdio_restore ();
1254
1361
@@ -1258,6 +1365,7 @@ static int worker_main(int sock)
1258
1365
msg_done .test_done .error_cnt = test -> error_cnt ;
1259
1366
msg_done .test_done .skip_cnt = test -> skip_cnt ;
1260
1367
msg_done .test_done .sub_succ_cnt = test -> sub_succ_cnt ;
1368
+ msg_done .test_done .duration_ms = duration_ms ;
1261
1369
msg_done .test_done .have_log = false;
1262
1370
1263
1371
if (env .verbosity > VERBOSE_NONE || test -> force_log || test -> error_cnt ) {
@@ -1486,6 +1594,9 @@ int main(int argc, char **argv)
1486
1594
1487
1595
print_all_error_logs ();
1488
1596
1597
+ if (env .timing )
1598
+ print_slow_tests ();
1599
+
1489
1600
fprintf (stdout , "Summary: %d/%d PASSED, %d SKIPPED, %d FAILED\n" ,
1490
1601
env .succ_cnt , env .sub_succ_cnt , env .skip_cnt , env .fail_cnt );
1491
1602
0 commit comments