62
62
CSV_RESULTS_NAME = "{}.csv" .format (_BASE_NAME )
63
63
HTML_RESULTS_NAME = "{}.html" .format (_BASE_NAME )
64
64
65
+ HR = "" .join (['-' for _ in range (120 )])
65
66
66
67
PTRN_ERROR = re .compile (r'^(?P<error>[A-Z][a-z][a-zA-Z]+):(?P<message>.*)$' )
67
- PTRN_UNITTEST = re .compile (r'^#### running: graalpython/lib-python/3/test/(?P<unittest>.*)$' )
68
+ PTRN_UNITTEST = re .compile (r'^#### running: graalpython/lib-python/3/test/(?P<unittest>[\w.]+).*$' , re . DOTALL )
68
69
PTRN_NUM_TESTS = re .compile (r'^Ran (?P<num_tests>\d+) test.*$' )
69
70
PTRN_FAILED = re .compile (
70
71
r'^FAILED \((failures=(?P<failures>\d+))?(, )?(errors=(?P<errors>\d+))?(, )?(skipped=(?P<skipped>\d+))?\)$' )
71
72
PTRN_OK = re .compile (
72
73
r'^OK \((failures=(?P<failures>\d+))?(, )?(errors=(?P<errors>\d+))?(, )?(skipped=(?P<skipped>\d+))?\)$' )
73
74
PTRN_JAVA_EXCEPTION = re .compile (r'^(?P<exception>com\.oracle\.[^:]*):(?P<message>.*)' )
74
75
PTRN_MODULE_NOT_FOUND = re .compile (r'.*ModuleNotFound: \'(?P<module>.*)\'\..*' , re .DOTALL )
75
-
76
+ PTRN_IMPORT_ERROR = re . compile ( r".*cannot import name \'(?P<module>.*)\'.*" , re . DOTALL )
76
77
77
78
# ----------------------------------------------------------------------------------------------------------------------
78
79
#
@@ -126,8 +127,11 @@ def scp(results_file_path, destination_path, destination_name=None):
126
127
return _run_cmd (cmd )[0 ]
127
128
128
129
129
- def _run_unittest (test_path ):
130
- cmd = ["mx" , "python3" , "--python.CatchAllExceptions=true" , test_path , "-v" ]
130
+ def _run_unittest (test_path , with_cpython = False ):
131
+ if with_cpython :
132
+ cmd = ["python3" , test_path , "-v" ]
133
+ else :
134
+ cmd = ["mx" , "python3" , "--python.CatchAllExceptions=true" , test_path , "-v" ]
131
135
success , output = _run_cmd (cmd )
132
136
output = '''
133
137
##############################################################
@@ -139,7 +143,7 @@ def _run_unittest(test_path):
139
143
TIMEOUT = 60 * 20 # 20 mins per unittest wait time max ...
140
144
141
145
142
- def run_unittests (unittests , timeout ):
146
+ def run_unittests (unittests , timeout , with_cpython = False ):
143
147
assert isinstance (unittests , (list , tuple ))
144
148
num_unittests = len (unittests )
145
149
log ("[EXEC] running {} unittests ... " , num_unittests )
@@ -148,7 +152,7 @@ def run_unittests(unittests, timeout):
148
152
149
153
pool = Pool ()
150
154
for ut in unittests :
151
- results .append (pool .apply_async (_run_unittest , args = (ut , )))
155
+ results .append (pool .apply_async (_run_unittest , args = (ut , with_cpython )))
152
156
pool .close ()
153
157
154
158
log ("[INFO] collect results ... " )
@@ -163,11 +167,12 @@ def run_unittests(unittests, timeout):
163
167
timed_out .append (unittests [i ])
164
168
log ("[PROGRESS] {} / {}: \t {}%" , i + 1 , num_unittests , int (((i + 1 ) * 100.0 ) / num_unittests ))
165
169
166
- log ("" .join (['-' for i in range (120 )]))
167
- for t in timed_out :
168
- log ("[TIMEOUT] skipped: {}" , t )
169
- log ("" .join (['-' for i in range (120 )]))
170
- log ("[STATS] processed {} out of {} unitttests" , num_unittests - len (timed_out ), num_unittests )
170
+ if timed_out :
171
+ log (HR )
172
+ for t in timed_out :
173
+ log ("[TIMEOUT] skipped: {}" , t )
174
+ log (HR )
175
+ log ("[STATS] processed {} out of {} unittests" , num_unittests - len (timed_out ), num_unittests )
171
176
pool .terminate ()
172
177
pool .join ()
173
178
return out
@@ -279,11 +284,14 @@ def process_output(output_lines):
279
284
# python error processing
280
285
#
281
286
# ----------------------------------------------------------------------------------------------------------------------
282
- def process_errors (unittests , error_messages , error = None , msg_processor = None ):
287
+ def process_errors (unittests , error_messages , err = None , msg_processor = None ):
288
+ if isinstance (err , str ):
289
+ err = {err ,}
290
+
283
291
def _err_filter (item ):
284
- if not error :
292
+ if not err :
285
293
return True
286
- return item [0 ] == error
294
+ return item [0 ] in err
287
295
288
296
def _processor (msg ):
289
297
if not msg_processor :
@@ -304,6 +312,11 @@ def get_missing_module(msg):
304
312
return match .group ('module' ) if match else None
305
313
306
314
315
+ def get_cannot_import_module (msg ):
316
+ match = re .match (PTRN_IMPORT_ERROR , msg )
317
+ return match .group ('module' ) if match else None
318
+
319
+
307
320
# ----------------------------------------------------------------------------------------------------------------------
308
321
#
309
322
# csv reporting
@@ -317,6 +330,11 @@ class Col(object):
317
330
NUM_SKIPPED = 'num_skipped'
318
331
NUM_PASSES = 'num_passes'
319
332
PYTHON_ERRORS = 'python_errors'
333
+ CPY_NUM_TESTS = 'cpy_num_tests'
334
+ CPY_NUM_FAILS = 'cpy_num_fails'
335
+ CPY_NUM_ERRORS = 'cpy_num_errors'
336
+ CPY_NUM_SKIPPED = 'cpy_num_skipped'
337
+ CPY_NUM_PASSES = 'cpy_num_passes'
320
338
321
339
322
340
CSV_HEADER = [
@@ -326,6 +344,11 @@ class Col(object):
326
344
Col .NUM_ERRORS ,
327
345
Col .NUM_SKIPPED ,
328
346
Col .NUM_PASSES ,
347
+ Col .CPY_NUM_TESTS ,
348
+ Col .CPY_NUM_FAILS ,
349
+ Col .CPY_NUM_ERRORS ,
350
+ Col .CPY_NUM_SKIPPED ,
351
+ Col .CPY_NUM_PASSES ,
329
352
Col .PYTHON_ERRORS
330
353
]
331
354
@@ -350,7 +373,7 @@ def save_as_txt(report_path, results):
350
373
return output
351
374
352
375
353
- def save_as_csv (report_path , unittests , error_messages , java_exceptions , stats ):
376
+ def save_as_csv (report_path , unittests , error_messages , java_exceptions , stats , cpy_stats = None ):
354
377
rows = []
355
378
with open (report_path , 'w' ) as CSV :
356
379
totals = {
@@ -365,18 +388,27 @@ def save_as_csv(report_path, unittests, error_messages, java_exceptions, stats):
365
388
366
389
for unittest in unittests :
367
390
unittest_stats = stats [unittest ]
391
+ cpy_unittest_stats = cpy_stats [unittest ] if cpy_stats else None
368
392
unittest_errmsg = error_messages [unittest ]
369
393
if not unittest_errmsg :
370
394
unittest_errmsg = java_exceptions [unittest ]
371
395
372
396
rows .append ({
373
397
Col .UNITTEST : unittest ,
398
+ # graalpython stats
374
399
Col .NUM_TESTS : unittest_stats .num_tests ,
375
400
Col .NUM_FAILS : unittest_stats .num_fails ,
376
401
Col .NUM_ERRORS : unittest_stats .num_errors ,
377
402
Col .NUM_SKIPPED : unittest_stats .num_skipped ,
378
403
Col .NUM_PASSES : unittest_stats .num_passes ,
379
- Col .PYTHON_ERRORS : dumps (list (unittest_errmsg ))
404
+ # cpython stats
405
+ Col .CPY_NUM_TESTS : cpy_unittest_stats .num_tests if cpy_unittest_stats else None ,
406
+ Col .CPY_NUM_FAILS : cpy_unittest_stats .num_fails if cpy_unittest_stats else None ,
407
+ Col .CPY_NUM_ERRORS : cpy_unittest_stats .num_errors if cpy_unittest_stats else None ,
408
+ Col .CPY_NUM_SKIPPED : cpy_unittest_stats .num_skipped if cpy_unittest_stats else None ,
409
+ Col .CPY_NUM_PASSES : cpy_unittest_stats .num_passes if cpy_unittest_stats else None ,
410
+ # errors
411
+ Col .PYTHON_ERRORS : dumps (list (unittest_errmsg )),
380
412
})
381
413
382
414
# update totals that ran in some way
@@ -499,7 +531,7 @@ def save_as_csv(report_path, unittests, error_messages, java_exceptions, stats):
499
531
'''
500
532
501
533
502
- def save_as_html (report_name , rows , totals , missing_modules , java_issues , current_date ):
534
+ def save_as_html (report_name , rows , totals , missing_modules , cannot_import_modules , java_issues , current_date ):
503
535
def grid (* components ):
504
536
def _fmt (cmp ):
505
537
if isinstance (cmp , tuple ):
@@ -601,6 +633,11 @@ def format_val(row, k):
601
633
for cnt , name in sorted (((cnt , name ) for name , cnt in missing_modules .items ()), reverse = True )
602
634
])
603
635
636
+ cannot_import_modules_info = ul ('modules which could not be imported' , [
637
+ '<b>{}</b> <span class="text-muted">could not be imported by {} unittests</span>' .format (name , cnt )
638
+ for cnt , name in sorted (((cnt , name ) for name , cnt in cannot_import_modules .items ()), reverse = True )
639
+ ])
640
+
604
641
java_issues_info = ul ('Java issues' , [
605
642
'<b>{}</b> <span class="text-muted">caused by {} unittests</span>' .format (name , cnt )
606
643
for cnt , name in sorted (((cnt , name ) for name , cnt in java_issues .items ()), reverse = True )
@@ -619,7 +656,10 @@ def format_val(row, k):
619
656
620
657
table_stats = table ('stats' , CSV_HEADER , rows )
621
658
622
- content = ' <br> ' .join ([total_stats_info , table_stats , missing_modules_info , java_issues_info ])
659
+ content = ' <br> ' .join ([total_stats_info , table_stats ,
660
+ missing_modules_info ,
661
+ cannot_import_modules_info ,
662
+ java_issues_info ])
623
663
624
664
report = HTML_TEMPLATE .format (
625
665
title = 'GraalPython Unittests Stats' ,
@@ -679,24 +719,37 @@ def _fmt(t):
679
719
skip_tests = set ([_fmt (test ) for test in flags .skip_tests .split ("," )]) if flags .skip_tests else None
680
720
unittests = get_unittests (flags .tests_path , limit = flags .limit , skip_tests = skip_tests )
681
721
682
- results = run_unittests (unittests , flags .timeout )
722
+ # get cpython stats
723
+ log (HR )
724
+ log ("[INFO] get cpython stats" )
725
+ cpy_results = run_unittests (unittests , 60 * 5 , with_cpython = True )
726
+ cpy_stats = process_output ('\n ' .join (cpy_results ))[- 1 ]
727
+
728
+ # get graalpython stats
729
+ log (HR )
730
+ log ("[INFO] get graalpython stats" )
731
+ results = run_unittests (unittests , flags .timeout , with_cpython = False )
683
732
txt_report_path = file_name (TXT_RESULTS_NAME , current_date )
684
733
output = save_as_txt (txt_report_path , results )
685
734
686
735
unittests , error_messages , java_exceptions , stats = process_output (output )
687
736
688
737
csv_report_path = file_name (CSV_RESULTS_NAME , current_date )
689
- rows , totals = save_as_csv (csv_report_path , unittests , error_messages , java_exceptions , stats )
738
+ rows , totals = save_as_csv (csv_report_path , unittests , error_messages , java_exceptions , stats , cpy_stats = cpy_stats )
690
739
691
- missing_modules = process_errors (unittests , error_messages , error = 'ModuleNotFoundError' ,
740
+ missing_modules = process_errors (unittests , error_messages , 'ModuleNotFoundError' ,
692
741
msg_processor = get_missing_module )
693
742
log ("[MISSING MODULES] \n {}" , pformat (dict (missing_modules )))
694
743
744
+ cannot_import_modules = process_errors (unittests , error_messages , err = 'ImportError' ,
745
+ msg_processor = get_cannot_import_module )
746
+ log ("[CANNOT IMPORT MODULES] \n {}" , pformat (dict (cannot_import_modules )))
747
+
695
748
java_issues = process_errors (unittests , java_exceptions )
696
749
log ("[JAVA ISSUES] \n {}" , pformat (dict (java_issues )))
697
750
698
751
html_report_path = file_name (HTML_RESULTS_NAME , current_date )
699
- save_as_html (html_report_path , rows , totals , missing_modules , java_issues , current_date )
752
+ save_as_html (html_report_path , rows , totals , missing_modules , cannot_import_modules , java_issues , current_date )
700
753
701
754
if flags .path :
702
755
log ("[SAVE] saving results to {} ... " , flags .path )
0 commit comments