1212
1313max_retries = 5
1414
15+
1516class SimTestWorkflow (TrickWorkflow ):
1617 def __init__ (self , quiet , trick_top_level , cpus , config_file , trick_dir = None ):
1718 self .cpus = cpus
@@ -41,72 +42,107 @@ def __init__(self, quiet, trick_top_level, cpus, config_file, trick_dir=None):
4142 cpus = self .cpus ,
4243 quiet = quiet ,
4344 )
44- def run ( self ):
45- build_jobs = self .get_jobs (kind = 'build' )
46-
47- # This is awful but I can't think of another way around it
48- # SIM_test_varserver has 2 tests that should return the code for SIGUSR1, the number is different on Mac vs Linux
49- # so it can't be hardcoded in the input yml file. Maybe this is a case having a label on a run would be cleaner?
50- import signal
51- run_names = ["Run test/SIM_test_varserv RUN_test/err1_test.py" , "Run test/SIM_test_varserv RUN_test/err2_test.py" ]
52- for job in [job for job in self .get_jobs (kind = 'run' ) if job .name in run_names ]:
53- job ._expected_exit_status = signal .SIGUSR1 .value
54-
55- # Several test sims have runs that require ordering via phases:
56- # - SIM_stls dumps a checkpoint that is then read in and checked by a subsequent run
57- # - SIM_checkpoint_data_recording dumps checkpoints that are read by subsequent runs
58- # - SIM_test_varserver has 3 runs that cannot be concurrent
59- # - SIM_mc_generation generates runs and then runs them
60- phases = [- 1 , 0 , 1 , 2 , 3 ]
61-
62- analysis_jobs = self .get_jobs (kind = 'analyze' )
63- if self .platform == "darwin" :
64- for job in build_jobs :
65- if job .name == "Build test/SIM_trickified_shared" :
66- print ("REMOVING JOB: " + job .name )
67- build_jobs .remove (job )
68- builds_status = self .execute_jobs (build_jobs , max_concurrent = self .cpus , header = 'Executing all sim builds.' )
69-
70- jobs = build_jobs
71-
72- run_status = 0
73- for phase in phases :
74- run_jobs = self .get_jobs (kind = 'run' , phase = phase )
45+
46+ def run (self ):
47+ build_jobs = self .get_jobs (kind = "build" )
48+
49+ # This is awful but I can't think of another way around it
50+ # SIM_test_varserver has 2 tests that should return the code for SIGUSR1, the number is different on Mac vs Linux
51+ # so it can't be hardcoded in the input yml file. Maybe this is a case having a label on a run would be cleaner?
52+ import signal
53+
54+ run_names = [
55+ "Run test/SIM_test_varserv RUN_test/err1_test.py" ,
56+ "Run test/SIM_test_varserv RUN_test/err2_test.py" ,
57+ ]
58+ for job in [job for job in self .get_jobs (kind = "run" ) if job .name in run_names ]:
59+ job ._expected_exit_status = signal .SIGUSR1 .value
60+
61+ # Several test sims have runs that require ordering via phases:
62+ # - SIM_stls dumps a checkpoint that is then read in and checked by a subsequent run
63+ # - SIM_checkpoint_data_recording dumps checkpoints that are read by subsequent runs
64+ # - SIM_test_varserver has 3 runs that cannot be concurrent
65+ # - SIM_mc_generation generates runs and then runs them
66+ phases = [- 1 , 0 , 1 , 2 , 3 ]
67+
68+ analysis_jobs = self .get_jobs (kind = "analyze" )
7569 if self .platform == "darwin" :
76- for job in run_jobs :
77- if job .name == "Run test/SIM_trickified_shared RUN_test/unit_test.py" :
78- print ("REMOVING JOB: " + job .name )
79- run_jobs .remove (job )
80- this_status = self .execute_jobs (run_jobs , max_concurrent = self .cpus , header = "Executing phase " + str (phase ) + " runs." , job_timeout = 1000 )
81- run_status = run_status or this_status
82- jobs += run_jobs
83-
84- comparison_result = self .compare ()
85- analysis_status = self .execute_jobs (analysis_jobs , max_concurrent = self .cpus , header = 'Executing all analysis.' )
86-
87- self .report () # Print Verbose report
88- self .status_summary () # Print a Succinct summary
89-
90- # Dump failing logs
91- for job in jobs :
92- if job .get_status () == Job .Status .FAILED or job .get_status () == Job .Status .TIMEOUT :
93- print ("*" * 120 )
94- if job .get_status () == Job .Status .FAILED :
95- header = "Failing job: " + job .name
96- else :
97- header = "Timed out job: " + job .name
98-
99- numspaces = int ((120 - 20 - len (header ))/ 2 - 2 )
100- print ("*" * 10 , " " * numspaces , header , " " * numspaces , "*" * 10 ,)
101- print ("*" * 120 )
102- print (Path (job .log_file ).read_text ())
103- print ("*" * 120 , "\n \n \n " )
104-
105- return (builds_status or run_status or len (self .config_errors ) > 0 or comparison_result or analysis_status )
70+ for job in build_jobs :
71+ if job .name == "Build test/SIM_trickified_shared" :
72+ print ("REMOVING JOB: " + job .name )
73+ build_jobs .remove (job )
74+ builds_status = self .execute_jobs (
75+ build_jobs , max_concurrent = self .cpus , header = "Executing all sim builds."
76+ )
77+
78+ jobs = build_jobs
79+
80+ run_status = 0
81+ for phase in phases :
82+ run_jobs = self .get_jobs (kind = "run" , phase = phase )
83+ if self .platform == "darwin" :
84+ for job in run_jobs :
85+ if (
86+ job .name
87+ == "Run test/SIM_trickified_shared RUN_test/unit_test.py"
88+ ):
89+ print ("REMOVING JOB: " + job .name )
90+ run_jobs .remove (job )
91+ this_status = self .execute_jobs (
92+ run_jobs ,
93+ max_concurrent = self .cpus ,
94+ header = "Executing phase " + str (phase ) + " runs." ,
95+ job_timeout = 1000 ,
96+ )
97+ run_status = run_status or this_status
98+ jobs += run_jobs
99+
100+ comparison_result = self .compare ()
101+ analysis_status = self .execute_jobs (
102+ analysis_jobs , max_concurrent = self .cpus , header = "Executing all analysis."
103+ )
104+
105+ self .report () # Print Verbose report
106+ self .status_summary () # Print a Succinct summary
107+
108+ # Dump failing logs
109+ for job in jobs :
110+ if (
111+ job .get_status () == Job .Status .FAILED
112+ or job .get_status () == Job .Status .TIMEOUT
113+ ):
114+ print ("*" * 120 )
115+ if job .get_status () == Job .Status .FAILED :
116+ header = "Failing job: " + job .name
117+ else :
118+ header = "Timed out job: " + job .name
119+
120+ numspaces = int ((120 - 20 - len (header )) / 2 - 2 )
121+ print (
122+ "*" * 10 ,
123+ " " * numspaces ,
124+ header ,
125+ " " * numspaces ,
126+ "*" * 10 ,
127+ )
128+ print ("*" * 120 )
129+ print (Path (job .log_file ).read_text ())
130+ print ("*" * 120 , "\n \n \n " )
131+
132+ return (
133+ builds_status
134+ or run_status
135+ or len (self .config_errors ) > 0
136+ or comparison_result
137+ or analysis_status
138+ )
139+
106140
107141if __name__ == "__main__" :
108- parser = argparse .ArgumentParser (description = 'Build, run, and compare all test sims for Trick' ,
109- formatter_class = argparse .ArgumentDefaultsHelpFormatter )
142+ parser = argparse .ArgumentParser (
143+ description = "Build, run, and compare all test sims for Trick" ,
144+ formatter_class = argparse .ArgumentDefaultsHelpFormatter ,
145+ )
110146 parser .add_argument (
111147 "--trick_top_level" ,
112148 type = str ,
@@ -122,14 +158,27 @@ def run( self ):
122158 "behavior, where sims and the Trick install share one tree)." ,
123159 default = None ,
124160 )
125- parser .add_argument ( "--quiet" , action = "store_true" , help = "Suppress progress bars (automatically set to True if environment variable CI is present)." )
126- parser .add_argument ( "--cpus" , type = int , default = (os .cpu_count () if os .cpu_count () is not None else 8 ),
127- help = "Number of cpus to use for testing. For builds this number is used for MAKEFLAGS *and* number of "
128- "concurrent builds (cpus^2). For sim runs this controls the maximum number of simultaneous runs." )
129- parser .add_argument ( "--config_file" , type = str , help = "Run configuration file to use, relative to trick_top_level" , default = "test_sims.yml" )
161+ parser .add_argument (
162+ "--quiet" ,
163+ action = "store_true" ,
164+ help = "Suppress progress bars (automatically set to True if environment variable CI is present)." ,
165+ )
166+ parser .add_argument (
167+ "--cpus" ,
168+ type = int ,
169+ default = (os .cpu_count () if os .cpu_count () is not None else 8 ),
170+ help = "Number of cpus to use for testing. For builds this number is used for MAKEFLAGS *and* number of "
171+ "concurrent builds (cpus^2). For sim runs this controls the maximum number of simultaneous runs." ,
172+ )
173+ parser .add_argument (
174+ "--config_file" ,
175+ type = str ,
176+ help = "Run configuration file to use, relative to trick_top_level" ,
177+ default = "test_sims.yml" ,
178+ )
130179
131180 myargs = parser .parse_args ()
132- should_be_quiet = myargs .quiet or os .getenv ('CI' ) is not None
181+ should_be_quiet = myargs .quiet or os .getenv ("CI" ) is not None
133182 sys .exit (
134183 SimTestWorkflow (
135184 quiet = should_be_quiet ,
0 commit comments