25
25
import re
26
26
import logging
27
27
28
+ # Formatting. Default colors to empty strings.
29
+ BOLD , BLUE , RED , GREY = ("" , "" ), ("" , "" ), ("" , "" ), ("" , "" )
30
+ TICK = "✓ "
31
+ CROSS = "✖ "
32
+ CIRCLE = "○ "
33
+ if os .name == 'posix' :
34
+ # primitive formatting on supported
35
+ # terminal via ANSI escape sequences:
36
+ BOLD = ('\033 [0m' , '\033 [1m' )
37
+ BLUE = ('\033 [0m' , '\033 [0;34m' )
38
+ RED = ('\033 [0m' , '\033 [0;31m' )
39
+ GREY = ('\033 [0m' , '\033 [1;30m' )
40
+
28
41
TEST_EXIT_PASSED = 0
29
42
TEST_EXIT_SKIPPED = 77
30
43
@@ -231,11 +244,6 @@ def main():
231
244
run_tests (test_list , config ["environment" ]["SRCDIR" ], config ["environment" ]["BUILDDIR" ], config ["environment" ]["EXEEXT" ], args .jobs , args .coverage , passon_args )
232
245
233
246
def run_tests (test_list , src_dir , build_dir , exeext , jobs = 1 , enable_coverage = False , args = []):
234
- BOLD = ("" ,"" )
235
- if os .name == 'posix' :
236
- # primitive formatting on supported
237
- # terminal via ANSI escape sequences:
238
- BOLD = ('\033 [0m' , '\033 [1m' )
239
247
240
248
#Set env vars
241
249
if "BITCOIND" not in os .environ :
@@ -258,42 +266,55 @@ def run_tests(test_list, src_dir, build_dir, exeext, jobs=1, enable_coverage=Fal
258
266
subprocess .check_output ([tests_dir + 'create_cache.py' ] + flags )
259
267
260
268
#Run Tests
261
- all_passed = True
262
- time_sum = 0
263
- time0 = time .time ()
264
-
265
269
job_queue = TestHandler (jobs , tests_dir , test_list , flags )
270
+ time0 = time .time ()
271
+ test_results = []
266
272
267
273
max_len_name = len (max (test_list , key = len ))
268
- results = " \n " + BOLD [ 1 ] + "%s | %s | %s \n \n " % ( "TEST" . ljust ( max_len_name ), "STATUS " , "DURATION" ) + BOLD [ 0 ]
274
+
269
275
for _ in range (len (test_list )):
270
- (name , stdout , stderr , status , duration ) = job_queue .get_next ()
271
- all_passed = all_passed and status != "Failed"
272
- time_sum += duration
273
-
274
- if status == "Passed" :
275
- logging .debug ("\n %s%s%s passed, Duration: %s s" % (BOLD [1 ], name , BOLD [0 ], duration ))
276
- elif status == "Skipped" :
277
- logging .debug ("\n %s%s%s skipped" % (BOLD [1 ], name , BOLD [0 ]))
276
+ test_result , stdout , stderr = job_queue .get_next ()
277
+ test_results .append (test_result )
278
+
279
+ if test_result .status == "Passed" :
280
+ logging .debug ("\n %s%s%s passed, Duration: %s s" % (BOLD [1 ], test_result .name , BOLD [0 ], test_result .time ))
281
+ elif test_result .status == "Skipped" :
282
+ logging .debug ("\n %s%s%s skipped" % (BOLD [1 ], test_result .name , BOLD [0 ]))
278
283
else :
279
- print ("\n %s%s%s failed, Duration: %s s\n " % (BOLD [1 ], name , BOLD [0 ], duration ))
284
+ print ("\n %s%s%s failed, Duration: %s s\n " % (BOLD [1 ], test_result . name , BOLD [0 ], test_result . time ))
280
285
print (BOLD [1 ] + 'stdout:\n ' + BOLD [0 ] + stdout + '\n ' )
281
286
print (BOLD [1 ] + 'stderr:\n ' + BOLD [0 ] + stderr + '\n ' )
282
287
283
- results += "%s | %s | %s s\n " % (name .ljust (max_len_name ), status .ljust (7 ), duration )
284
-
285
- results += BOLD [1 ] + "\n %s | %s | %s s (accumulated)" % ("ALL" .ljust (max_len_name ), str (all_passed ).ljust (7 ), time_sum ) + BOLD [0 ]
286
- print (results )
287
- print ("\n Runtime: %s s" % (int (time .time () - time0 )))
288
+ print_results (test_results , max_len_name , (int (time .time () - time0 )))
288
289
289
290
if coverage :
290
291
coverage .report_rpc_coverage ()
291
292
292
293
logging .debug ("Cleaning up coverage data" )
293
294
coverage .cleanup ()
294
295
296
+ all_passed = all (map (lambda test_result : test_result .status == "Passed" , test_results ))
297
+
295
298
sys .exit (not all_passed )
296
299
300
+ def print_results (test_results , max_len_name , runtime ):
301
+ results = "\n " + BOLD [1 ] + "%s | %s | %s\n \n " % ("TEST" .ljust (max_len_name ), "STATUS " , "DURATION" ) + BOLD [0 ]
302
+
303
+ test_results .sort (key = lambda result : result .name .lower ())
304
+ all_passed = True
305
+ time_sum = 0
306
+
307
+ for test_result in test_results :
308
+ all_passed = all_passed and test_result .status != "Failed"
309
+ time_sum += test_result .time
310
+ test_result .padding = max_len_name
311
+ results += str (test_result )
312
+
313
+ status = TICK + "Passed" if all_passed else CROSS + "Failed"
314
+ results += BOLD [1 ] + "\n %s | %s | %s s (accumulated) \n " % ("ALL" .ljust (max_len_name ), status .ljust (9 ), time_sum ) + BOLD [0 ]
315
+ results += "Runtime: %s s\n " % (runtime )
316
+ print (results )
317
+
297
318
class TestHandler :
298
319
"""
299
320
Trigger the testscrips passed in via the list.
@@ -348,9 +369,31 @@ def get_next(self):
348
369
status = "Failed"
349
370
self .num_running -= 1
350
371
self .jobs .remove (j )
351
- return name , stdout , stderr , status , int (time .time () - time0 )
372
+
373
+ return TestResult (name , status , int (time .time () - time0 )), stdout , stderr
352
374
print ('.' , end = '' , flush = True )
353
375
376
+ class TestResult ():
377
+ def __init__ (self , name , status , time ):
378
+ self .name = name
379
+ self .status = status
380
+ self .time = time
381
+ self .padding = 0
382
+
383
+ def __repr__ (self ):
384
+ if self .status == "Passed" :
385
+ color = BLUE
386
+ glyph = TICK
387
+ elif self .status == "Failed" :
388
+ color = RED
389
+ glyph = CROSS
390
+ elif self .status == "Skipped" :
391
+ color = GREY
392
+ glyph = CIRCLE
393
+
394
+ return color [1 ] + "%s | %s%s | %s s\n " % (self .name .ljust (self .padding ), glyph , self .status .ljust (7 ), self .time ) + color [0 ]
395
+
396
+
354
397
def check_script_list (src_dir ):
355
398
"""Check scripts directory.
356
399
0 commit comments