36
36
# SOFTWARE.
37
37
38
38
import csv
39
+ import gzip
39
40
import os
40
41
import re
41
42
import subprocess
55
56
PATH_UNITTESTS = "graalpython/lib-python/3/test/"
56
57
57
58
_BASE_NAME = "unittests"
58
- TXT_RESULTS_NAME = "{}.txt" .format (_BASE_NAME )
59
+ TXT_RESULTS_NAME = "{}.txt.gz " .format (_BASE_NAME )
59
60
CSV_RESULTS_NAME = "{}.csv" .format (_BASE_NAME )
60
61
HTML_RESULTS_NAME = "{}.html" .format (_BASE_NAME )
61
62
65
66
PTRN_NUM_TESTS = re .compile (r'^Ran (?P<num_tests>\d+) test.*$' )
66
67
PTRN_NUM_ERRORS = re .compile (
67
68
r'^FAILED \((failures=(?P<failures>\d+))?(, )?(errors=(?P<errors>\d+))?(, )?(skipped=(?P<skipped>\d+))?\)$' )
69
+ PTRN_JAVA_EXCEPTION = re .compile (r'^(?P<exception>com\.oracle\.[^:]*):(?P<message>.*)' )
70
+ PTRN_MODULE_NOT_FOUND = re .compile (r'.*ModuleNotFound: \'(?P<module>.*)\'\..*' , re .DOTALL )
68
71
69
72
70
73
# ----------------------------------------------------------------------------------------------------------------------
@@ -82,7 +85,7 @@ def debug(msg, *args, **kwargs):
82
85
83
86
84
87
def file_name (name , current_date_time ):
85
- idx = name .rindex ('.' )
88
+ idx = name .index ('.' )
86
89
if idx > 0 :
87
90
return '{}-{}{}' .format (name [:idx ], current_date_time , name [idx :])
88
91
return '{}-{}' .format (name , current_date_time )
@@ -131,14 +134,17 @@ def _run_unittest(test_path):
131
134
132
135
def run_unittests (unittests ):
133
136
assert isinstance (unittests , (list , tuple ))
134
- log ("[EXEC] running {} unittests ... " .format (len (unittests )))
137
+ num_unittests = len (unittests )
138
+ log ("[EXEC] running {} unittests ... " , num_unittests )
135
139
results = []
140
+
136
141
pool = Pool ()
137
142
for ut in unittests :
138
- results .append (pool .apply_async (_run_unittest , args = (ut ,)))
143
+ results .append (pool .apply_async (_run_unittest , args = (ut , )))
139
144
pool .close ()
140
145
pool .join ()
141
- return [r .get ()[1 ] for r in results ]
146
+
147
+ return [res .get ()[1 ] for res in results ]
142
148
143
149
144
150
def get_unittests (base_tests_path , limit = None , sort = True ):
@@ -180,6 +186,7 @@ def process_output(output_lines):
180
186
181
187
unittests = []
182
188
error_messages = defaultdict (set )
189
+ java_exceptions = defaultdict (set )
183
190
stats = defaultdict (StatEntry )
184
191
185
192
for line in output_lines :
@@ -194,6 +201,12 @@ def process_output(output_lines):
194
201
error_messages [unittests [- 1 ]].add ((match .group ('error' ), match .group ('message' )))
195
202
continue
196
203
204
+ # extract java exceptions
205
+ match = re .match (PTRN_JAVA_EXCEPTION , line )
206
+ if match :
207
+ java_exceptions [unittests [- 1 ]].add ((match .group ('exception' ), match .group ('message' )))
208
+ continue
209
+
197
210
# stats
198
211
if line .strip () == 'OK' :
199
212
stats [unittests [- 1 ]].all_ok ()
@@ -216,27 +229,34 @@ def process_output(output_lines):
216
229
stats [unittests [- 1 ]].num_errors = int (errs ) if errs else 0
217
230
stats [unittests [- 1 ]].num_skipped = int (skipped ) if skipped else 0
218
231
219
- return unittests , error_messages , stats
232
+ return unittests , error_messages , java_exceptions , stats
220
233
221
234
222
235
# ----------------------------------------------------------------------------------------------------------------------
223
236
#
224
237
# python error processing
225
238
#
226
239
# ----------------------------------------------------------------------------------------------------------------------
227
- def process_errors (unittests , error_messages , error , msg_processor ):
240
+ def process_errors (unittests , error_messages , error = None , msg_processor = None ):
241
+ def _err_filter (item ):
242
+ if not error :
243
+ return True
244
+ return item [0 ] == error
245
+
246
+ def _processor (msg ):
247
+ if not msg_processor :
248
+ return msg
249
+ return msg_processor (msg )
250
+
228
251
missing_modules = defaultdict (lambda : 0 )
229
252
for ut in unittests :
230
253
errors = error_messages [ut ]
231
- for name in map (msg_processor , (msg for err , msg in errors if err == error )):
254
+ for name in map (_processor , (msg for err , msg in filter ( _err_filter , errors ) )):
232
255
missing_modules [name ] = missing_modules [name ] + 1
233
256
234
257
return missing_modules
235
258
236
259
237
- PTRN_MODULE_NOT_FOUND = re .compile (r'.*ModuleNotFound: \'(?P<module>.*)\'\..*' , re .DOTALL )
238
-
239
-
240
260
def get_missing_module (msg ):
241
261
match = re .match (PTRN_MODULE_NOT_FOUND , msg )
242
262
return match .group ('module' ) if match else None
@@ -282,13 +302,13 @@ class Stat(object):
282
302
283
303
284
304
def save_as_txt (report_path , results ):
285
- with open (report_path , 'w ' ) as TXT :
305
+ with gzip . open (report_path , 'wb ' ) as TXT :
286
306
output = '\n ' .join (results )
287
- TXT .write (output )
307
+ TXT .write (bytes ( output , 'utf-8' ) )
288
308
return output
289
309
290
310
291
- def save_as_csv (report_path , unittests , error_messages , stats , current_date ):
311
+ def save_as_csv (report_path , unittests , error_messages , java_exceptions , stats ):
292
312
rows = []
293
313
with open (report_path , 'w' ) as CSV :
294
314
totals = {
@@ -304,6 +324,9 @@ def save_as_csv(report_path, unittests, error_messages, stats, current_date):
304
324
for unittest in unittests :
305
325
unittest_stats = stats [unittest ]
306
326
unittest_errmsg = error_messages [unittest ]
327
+ if not unittest_errmsg :
328
+ unittest_errmsg = java_exceptions [unittest ]
329
+
307
330
rows .append ({
308
331
Col .UNITTEST : unittest ,
309
332
Col .NUM_TESTS : unittest_stats .num_tests ,
@@ -434,7 +457,7 @@ def save_as_csv(report_path, unittests, error_messages, stats, current_date):
434
457
'''
435
458
436
459
437
- def save_as_html (report_name , rows , totals , missing_modules , current_date ):
460
+ def save_as_html (report_name , rows , totals , missing_modules , java_issues , current_date ):
438
461
def grid (* components ):
439
462
def _fmt (cmp ):
440
463
if isinstance (cmp , tuple ):
@@ -536,6 +559,11 @@ def format_val(row, k):
536
559
for cnt , name in sorted (((cnt , name ) for name , cnt in missing_modules .items ()), reverse = True )
537
560
])
538
561
562
+ java_issues_info = ul ('Java issues' , [
563
+ '<b>{}</b> <span class="text-muted">caused by {} unittests</span>' .format (name , cnt )
564
+ for cnt , name in sorted (((cnt , name ) for name , cnt in java_issues .items ()), reverse = True )
565
+ ])
566
+
539
567
total_stats_info = ul ("<b>Summary</b>" , [
540
568
grid ('<b># total</b> unittests: {}' .format (totals [Stat .UT_TOTAL ])),
541
569
grid ((progress_bar (totals [Stat .UT_PERCENT_RUNS ], color = "info" ), 3 ),
@@ -549,7 +577,7 @@ def format_val(row, k):
549
577
550
578
table_stats = table ('stats' , CSV_HEADER , rows )
551
579
552
- content = ' <br> ' .join ([total_stats_info , table_stats , missing_modules_info ])
580
+ content = ' <br> ' .join ([total_stats_info , table_stats , missing_modules_info , java_issues_info ])
553
581
554
582
report = HTML_TEMPLATE .format (
555
583
title = 'GraalPython Unittests Stats' ,
@@ -608,16 +636,20 @@ def _fmt(t):
608
636
txt_report_path = file_name (TXT_RESULTS_NAME , current_date )
609
637
output = save_as_txt (txt_report_path , results )
610
638
611
- unittests , error_messages , stats = process_output (output )
639
+ unittests , error_messages , java_exceptions , stats = process_output (output )
612
640
613
641
csv_report_path = file_name (CSV_RESULTS_NAME , current_date )
614
- rows , totals = save_as_csv (csv_report_path , unittests , error_messages , stats , current_date )
642
+ rows , totals = save_as_csv (csv_report_path , unittests , error_messages , java_exceptions , stats )
615
643
616
- missing_modules = process_errors (unittests , error_messages , 'ModuleNotFoundError' , get_missing_module )
644
+ missing_modules = process_errors (unittests , error_messages , error = 'ModuleNotFoundError' ,
645
+ msg_processor = get_missing_module )
617
646
log ("[MISSING MODULES] \n {}" , pformat (dict (missing_modules )))
618
647
648
+ java_issues = process_errors (unittests , java_exceptions )
649
+ log ("[JAVA ISSUES] \n {}" , pformat (dict (java_issues )))
650
+
619
651
html_report_path = file_name (HTML_RESULTS_NAME , current_date )
620
- save_as_html (html_report_path , rows , totals , missing_modules , current_date )
652
+ save_as_html (html_report_path , rows , totals , missing_modules , java_issues , current_date )
621
653
622
654
if flags .path :
623
655
log ("[SAVE] saving results to {} ... " , flags .path )
0 commit comments