1212def pytest_addoption (parser ):
1313 parser .addoption ("--log" , type = str , help = 'Log file path' , default = None )
1414 parser .addoption ("--output" , type = str , help = "Output file path." , default = None )
15- parser .addoption ("--data-dir" , type = str , help = "Data directory." , default = None )
15+ parser .addoption ("--data-dir" , type = str , help = "Data directory." , default = os . getenv ( 'HAIL_BENCHMARK_DIR' ) )
1616 parser .addoption ('--iterations' , type = int , help = 'override number of iterations for all benchmarks' , default = None )
1717 parser .addoption ('--cores' , type = int , help = 'Number of cores to use.' , default = 1 )
1818 parser .addoption (
@@ -23,36 +23,36 @@ def pytest_addoption(parser):
2323 const = 'cpu' ,
2424 default = None ,
2525 )
26- parser .addoption ('--profiler-path' , type = str , help = 'path to aysnc profiler' , default = None )
26+ parser .addoption (
27+ '--max-duration' ,
28+ type = int ,
29+ help = 'Maximum permitted duration for any benchmark trial in seconds, not to be confused with pytest-timeout' ,
30+ default = 200 ,
31+ )
32+ parser .addoption ('--max-failures' , type = int , help = 'Stop benchmarking item after this many failures' , default = 3 )
33+ parser .addoption (
34+ '--profiler-path' , type = str , help = 'path to aysnc profiler' , default = os .getenv ('ASYNC_PROFILER_HOME' )
35+ )
2736 parser .addoption ('--profiler-fmt' , choices = ['html' , 'flame' , 'jfr' ], help = 'Choose profiler output.' , default = 'html' )
2837
2938
30- def run_config_from_pytest_config (pytest_config ):
31- return type (
32- 'RunConfig' ,
33- (object ,),
34- {
35- ** {
36- flag : pytest_config .getoption (flag ) or default
37- for flag , default in [
38- ('log' , None ),
39- ('output' , None ),
40- ('cores' , 1 ),
41- ('data_dir' , os .getenv ('HAIL_BENCHMARK_DIR' )),
42- ('iterations' , None ),
43- ('profile' , None ),
44- ('profiler_path' , os .getenv ('ASYNC_PROFILER_HOME' )),
45- ('profiler_fmt' , None ),
46- ]
47- },
48- 'verbose' : pytest_config .getoption ('verbose' ) > 0 ,
49- 'quiet' : pytest_config .getoption ('verbose' ) < 0 ,
50- 'timeout' : int (pytest_config .getoption ('timeout' ) or 1800 ),
51- },
39+ @pytest .hookimpl
40+ def pytest_configure (config ):
41+ init_logging (file = config .getoption ('log' ))
42+
43+
44+ @pytest .hookimpl (tryfirst = True )
45+ def pytest_collection_modifyitems (config , items ):
46+ max_duration = config .getoption ('max_duration' )
47+
48+ xfail = pytest .mark .xfail (
49+ raises = TimeoutError ,
50+ reason = f'Runtime exceeds maximum permitted duration of { max_duration } s' ,
5251 )
5352
53+ for item in items :
54+ if (xtimeout := item .get_closest_marker ('xtimeout' )) is None :
55+ continue
5456
55- @pytest .hookimpl
56- def pytest_configure (config ):
57- config .run_config = run_config_from_pytest_config (config )
58- init_logging (file = config .run_config .log )
57+ if len (xtimeout .args ) == 0 or (len (xtimeout .args ) == 1 and xtimeout .args [0 ] >= max_duration ):
58+ item .add_marker (xfail )
0 commit comments