2424)
2525
2626
27+ def _parse_bool_env (name ):
28+ raw = os .getenv (name )
29+ if raw is None :
30+ return None
31+ value = raw .strip ().lower ()
32+ if value in ("1" , "true" , "yes" , "on" ):
33+ return True
34+ if value in ("0" , "false" , "no" , "off" ):
35+ return False
36+ return None
37+
38+
39+ _fail_on_unmasked_env = _parse_bool_env ("ACTS_SEQUENCER_FAIL_ON_UNMASKED_FPE" )
40+ _requires_fail_on_unmasked = pytest .mark .skipif (
41+ _fail_on_unmasked_env is False ,
42+ reason = "requires failOnUnmaskedFpe=true, but env override disables it" ,
43+ )
44+ _requires_no_fail_on_unmasked = pytest .mark .skipif (
45+ _fail_on_unmasked_env is True ,
46+ reason = "requires failOnUnmaskedFpe=false, but env override enables it" ,
47+ )
48+
49+
2750_names = {
2851 acts .examples .FpeType .FLTDIV : "DivByZero" ,
2952 acts .examples .FpeType .FLTOVF : "Overflow" ,
@@ -83,14 +106,6 @@ def disable_log_threshold():
83106 yield
84107 acts .logging .setFailureThreshold (prev )
85108
86-
87- @pytest .fixture (autouse = True )
88- def force_fail_on_unmasked_fpe (monkeypatch ):
89- # These tests assert raise/no-raise behavior based on unmasked FPE policy.
90- # Keep them deterministic even when CI sets a global override.
91- monkeypatch .setenv ("ACTS_SEQUENCER_FAIL_ON_UNMASKED_FPE" , "1" )
92-
93-
94109def test_notrackfpe ():
95110 s = acts .examples .Sequencer (
96111 events = 3 * 100 ,
@@ -111,6 +126,7 @@ def fpe_type(request):
111126 yield request .param
112127
113128
129+ @_requires_fail_on_unmasked
114130def test_fpe_single_fail_at_end (fpe_type ):
115131 s = acts .examples .Sequencer (
116132 events = 10 ,
@@ -134,6 +150,7 @@ def test_fpe_single_fail_at_end(fpe_type):
134150 assert res .count (x ) == (s .config .events if x == fpe_type else 0 )
135151
136152
153+ @_requires_no_fail_on_unmasked
137154def test_fpe_single_no_fail_at_end (fpe_type ):
138155 s = acts .examples .Sequencer (
139156 events = 10 ,
@@ -156,6 +173,7 @@ def test_fpe_single_no_fail_at_end(fpe_type):
156173 assert res .count (x ) == (s .config .events if x == fpe_type else 0 )
157174
158175
176+ @_requires_fail_on_unmasked
159177def test_fpe_single_fail_immediately (fpe_type ):
160178 s = acts .examples .Sequencer (
161179 events = 10 ,
@@ -199,6 +217,7 @@ def execute(self, context):
199217 s .run ()
200218
201219
220+ @_requires_fail_on_unmasked
202221def test_fpe_rearm (fpe_type ):
203222 trigger = getattr (acts .examples .FpeMonitor , f"_trigger_{ _names [fpe_type ].lower ()} " )
204223
@@ -232,6 +251,7 @@ def execute(self, context):
232251 sys .platform == "darwin" ,
233252 reason = "Source-location FPE masking is not stable on macOS backtraces" ,
234253)
254+ @_requires_fail_on_unmasked
235255def test_fpe_masking_single (fpe_type ):
236256 trigger = getattr (acts .examples .FpeMonitor , f"_trigger_{ _names [fpe_type ].lower ()} " )
237257
@@ -314,6 +334,7 @@ def test_fpe_context(fpe_type):
314334 print (fpe .result )
315335
316336
337+ @_requires_fail_on_unmasked
317338def test_buffer_sufficient ():
318339 s = acts .examples .Sequencer (
319340 events = 10000 ,
0 commit comments