33#
44# SPDX-License-Identifier: BSD-3-Clause
55
6- import datetime
76import inspect
87import json
98import os
109import re
1110import socket
1211import sys
12+ import time
1313import traceback
14- from pathlib import Path
1514
1615import reframe
1716import reframe .core .config as config
3231 AsynchronousExecutionPolicy )
3332from reframe .frontend .loader import RegressionCheckLoader
3433from reframe .frontend .printer import PrettyPrinter
35- from reframe .utility import get_next_runreport_index
3634
3735
3836def format_check (check , detailed ):
@@ -72,6 +70,22 @@ def list_checks(checks, printer, detailed=False):
7270 printer .info ('\n Found %d check(s).' % len (checks ))
7371
7472
73+ def generate_report_filename (filepatt ):
74+ if not '{sessionid}' in filepatt :
75+ return filepatt
76+
77+ search_patt = os .path .basename (filepatt ).replace ('{sessionid}' , r'(\d+)' )
78+ new_id = - 1
79+ for filename in os .listdir (os .path .dirname (filepatt )):
80+ match = re .match (search_patt , filename )
81+ if match :
82+ found_id = int (match .group (1 ))
83+ new_id = max (found_id , new_id )
84+
85+ new_id += 1
86+ return filepatt .format (sessionid = new_id )
87+
88+
7589def main ():
7690 # Setup command line options
7791 argparser = argparse .ArgumentParser ()
@@ -140,8 +154,10 @@ def main():
140154 envvar = 'RFM_SAVE_LOG_FILES' , configvar = 'general/save_log_files'
141155 )
142156 output_options .add_argument (
143- '--runreport-name' , action = 'store' , metavar = 'NAME' ,
144- help = "Do not overwrite runreport.json" ,
157+ '--report-file' , action = 'store' , metavar = 'FILE' ,
158+ help = "Store JSON run report in FILE" ,
159+ envvar = 'RFM_REPORT_FILE' ,
160+ configvar = 'general/report_file'
145161 )
146162
147163 # Check discovery options
@@ -516,32 +532,33 @@ def print_infoline(param, value):
516532 param = param + ':'
517533 printer .info (f" { param .ljust (18 )} { value } " )
518534
519- reframe_info = {
535+ session_info = {
536+ 'cmdline' : ' ' .join (sys .argv ),
537+ 'config_file' : rt .site_config .filename ,
538+ 'data_version' : '1.0' ,
539+ 'hostname' : socket .gethostname (),
540+ 'prefix_output' : rt .output_prefix ,
541+ 'prefix_stage' : rt .stage_prefix ,
542+ 'user' : os_ext .osuser (),
520543 'version' : os_ext .reframe_version (),
521- 'command' : repr (' ' .join (sys .argv )),
522- 'user' : f"{ os_ext .osuser () or '<unknown>' } " ,
523- 'host' : socket .gethostname (),
524- 'working_directory' : repr (os .getcwd ()),
525- 'check_search_path' : f"{ ':' .join (loader .load_path )!r} " ,
526- 'recursive_search_path' : loader .recurse ,
527- 'settings_file' : site_config .filename ,
528- 'stage_prefix' : repr (rt .stage_prefix ),
529- 'output_prefix' : repr (rt .output_prefix ),
544+ 'workdir' : os .getcwd (),
530545 }
531546
532547 # Print command line
533548 printer .info (f"[ReFrame Setup]" )
534- print_infoline ('version' , reframe_info ['version' ])
535- print_infoline ('command' , reframe_info ['command' ])
536- print_infoline ('launched by' ,
537- f"{ reframe_info ['user' ]} @{ reframe_info ['host' ]} " )
538- print_infoline ('working directory' , reframe_info ['working_directory' ])
539- print_infoline ('settings file' , f"{ reframe_info ['settings_file' ]!r} " )
549+ print_infoline ('version' , session_info ['version' ])
550+ print_infoline ('command' , session_info ['cmdline' ])
551+ print_infoline (
552+ f"launched by" ,
553+ f"{ session_info ['user' ] or '<unknown>' } @{ session_info ['hostname' ]} "
554+ )
555+ print_infoline ('working directory' , repr (session_info ['workdir' ]))
556+ print_infoline ('settings file' , f"{ session_info ['config_file' ]!r} " )
540557 print_infoline ('check search path' ,
541- f"{ '(R) ' if reframe_info [ 'recursive_search_path' ] else '' } "
542- f"{ reframe_info [ 'check_search_path' ] !r} " )
543- print_infoline ('stage directory' , reframe_info [ 'stage_prefix' ] )
544- print_infoline ('output directory' , reframe_info [ 'output_prefix' ] )
558+ f"{ '(R) ' if loader . recurse else '' } "
559+ f"{ ':' . join ( loader . load_path ) !r} " )
560+ print_infoline ('stage directory' , repr ( session_info [ 'prefix_stage' ]) )
561+ print_infoline ('output directory' , repr ( session_info [ 'prefix_output' ]) )
545562 printer .info ('' )
546563 try :
547564 # Locate and load checks
@@ -716,13 +733,19 @@ def print_infoline(param, value):
716733 max_retries ) from None
717734 runner = Runner (exec_policy , printer , max_retries )
718735 try :
719- reframe_info ['start_time' ] = (
720- datetime .datetime .today ().strftime ('%c %Z' ))
736+ time_start = time .time ()
737+ session_info ['time_start' ] = time .strftime (
738+ '%FT%T%z' , time .localtime (time_start ),
739+ )
721740 runner .runall (testcases )
722741 finally :
742+ time_end = time .time ()
743+ session_info ['time_end' ] = time .strftime (
744+ '%FT%T%z' , time .localtime (time_end )
745+ )
746+ session_info ['time_elapsed' ] = time_end - time_start
747+
723748 # Print a retry report if we did any retries
724- reframe_info ['end_time' ] = (
725- datetime .datetime .today ().strftime ('%c %Z' ))
726749 if runner .stats .failures (run = 0 ):
727750 printer .info (runner .stats .retry_report ())
728751
@@ -736,23 +759,30 @@ def print_infoline(param, value):
736759 if options .performance_report :
737760 printer .info (runner .stats .performance_report ())
738761
739- if options .runreport_name :
740- runreport_file = options .runreport_name
741- else :
742- runreport_dir = os .path .join (Path .home (), '.local/reframe' )
743- runreport_id = get_next_runreport_index (runreport_dir )
744- runreport_name = f'runreport-{ runreport_id } .json'
745- Path (runreport_dir ).mkdir (parents = True , exist_ok = True )
746- runreport_file = os .path .join (runreport_dir ,
747- runreport_name )
748-
762+ # Generate the report for this session
763+ report_file = os .path .normpath (
764+ os_ext .expandvars (rt .get_option ('general/0/report_file' ))
765+ )
766+ os .makedirs (os .path .dirname (report_file ), exist_ok = True )
767+
768+ # Build final report JSON
769+ run_stats = runner .stats .json ()
770+ session_info .update ({
771+ 'num_cases' : run_stats [0 ]['num_cases' ],
772+ 'num_failures' : run_stats [- 1 ]['num_failures' ]
773+ })
774+ json_report = {
775+ 'session_info' : session_info ,
776+ 'runs' : run_stats
777+ }
778+ report_file = generate_report_filename (report_file )
749779 try :
750- with open (runreport_file , 'w' ) as fp :
751- json .dump (runner . stats . json ( reframe_info , force = True ),
752- fp , indent = 4 )
753- except OSError :
754- printer . error ( f'invalid path : { runreport_file } ' )
755- sys . exit ( 1 )
780+ with open (report_file , 'w' ) as fp :
781+ json .dump (json_report , fp , indent = 2 )
782+ except OSError as e :
783+ printer . warning (
784+ f'failed to generate report in { report_file !r } : { e } '
785+ )
756786
757787 else :
758788 printer .error ("No action specified. Please specify `-l'/`-L' for "
0 commit comments