@@ -25,7 +25,7 @@ use std::sync::OnceLock;
2525use pyo3:: prelude:: * ;
2626use pyo3:: types:: PyAny ;
2727
28- use recorder_errors:: { bug, enverr, usage, ErrorCode , RecorderResult } ;
28+ use recorder_errors:: { bug, enverr, target , usage, ErrorCode , RecorderResult } ;
2929use runtime_tracing:: NonStreamingTraceWriter ;
3030use runtime_tracing:: { Line , TraceEventsFileFormat , TraceWriter } ;
3131
@@ -97,6 +97,8 @@ impl FailureStage {
9797enum FailureMode {
9898 Stage ( FailureStage ) ,
9999 SuppressEvents ,
100+ TargetArgs ,
101+ Panic ,
100102}
101103
102104#[ cfg( feature = "integration-test" ) ]
@@ -116,26 +118,46 @@ fn configured_failure_mode() -> Option<FailureMode> {
116118 "line" => Some ( FailureMode :: Stage ( FailureStage :: Line ) ) ,
117119 "finish" => Some ( FailureMode :: Stage ( FailureStage :: Finish ) ) ,
118120 "suppress-events" | "suppress_events" | "suppress" => Some ( FailureMode :: SuppressEvents ) ,
121+ "target" | "target-args" | "target_args" => Some ( FailureMode :: TargetArgs ) ,
122+ "panic" | "panic-callback" | "panic_callback" => Some ( FailureMode :: Panic ) ,
119123 _ => None ,
120124 } )
121125 } )
122126}
123127
124128#[ cfg( feature = "integration-test" ) ]
125129fn should_inject_failure ( stage : FailureStage ) -> bool {
126- match configured_failure_mode ( ) {
127- Some ( FailureMode :: Stage ( mode) ) if mode == stage => {
128- !FAILURE_TRIGGERED . swap ( true , Ordering :: SeqCst )
129- }
130- _ => false ,
131- }
130+ matches ! ( configured_failure_mode( ) , Some ( FailureMode :: Stage ( mode) ) if mode == stage)
131+ && mark_failure_triggered ( )
132132}
133133
134134#[ cfg( not( feature = "integration-test" ) ) ]
135135fn should_inject_failure ( _stage : FailureStage ) -> bool {
136136 false
137137}
138138
139+ #[ cfg( feature = "integration-test" ) ]
140+ fn should_inject_target_error ( ) -> bool {
141+ matches ! ( configured_failure_mode( ) , Some ( FailureMode :: TargetArgs ) )
142+ && mark_failure_triggered ( )
143+ }
144+
145+ #[ cfg( not( feature = "integration-test" ) ) ]
146+ fn should_inject_target_error ( ) -> bool {
147+ false
148+ }
149+
150+ #[ cfg( feature = "integration-test" ) ]
151+ fn should_panic_in_callback ( ) -> bool {
152+ matches ! ( configured_failure_mode( ) , Some ( FailureMode :: Panic ) ) && mark_failure_triggered ( )
153+ }
154+
155+ #[ cfg( not( feature = "integration-test" ) ) ]
156+ #[ allow( dead_code) ]
157+ fn should_panic_in_callback ( ) -> bool {
158+ false
159+ }
160+
139161#[ cfg( feature = "integration-test" ) ]
140162fn suppress_events ( ) -> bool {
141163 matches ! ( configured_failure_mode( ) , Some ( FailureMode :: SuppressEvents ) )
@@ -146,6 +168,17 @@ fn suppress_events() -> bool {
146168 false
147169}
148170
171+ #[ cfg( feature = "integration-test" ) ]
172+ fn mark_failure_triggered ( ) -> bool {
173+ !FAILURE_TRIGGERED . swap ( true , Ordering :: SeqCst )
174+ }
175+
176+ #[ cfg( not( feature = "integration-test" ) ) ]
177+ #[ allow( dead_code) ]
178+ fn mark_failure_triggered ( ) -> bool {
179+ false
180+ }
181+
149182#[ cfg( feature = "integration-test" ) ]
150183fn injected_failure_err ( stage : FailureStage ) -> PyErr {
151184 let err = bug ! (
@@ -340,6 +373,16 @@ impl Tracer for RuntimeTracer {
340373 return Err ( injected_failure_err ( FailureStage :: PyStart ) ) ;
341374 }
342375
376+ if should_inject_target_error ( ) {
377+ return Err ( ffi:: map_recorder_error (
378+ target ! (
379+ ErrorCode :: TraceIncomplete ,
380+ "test-injected target error from capture_call_arguments"
381+ )
382+ . with_context ( "injection_stage" , "capture_call_arguments" ) ,
383+ ) ) ;
384+ }
385+
343386 log_event ( py, code, "on_py_start" , None ) ;
344387
345388 if let Ok ( fid) = self . ensure_function_id ( py, code) {
@@ -381,6 +424,13 @@ impl Tracer for RuntimeTracer {
381424 return Err ( injected_failure_err ( FailureStage :: Line ) ) ;
382425 }
383426
427+ #[ cfg( feature = "integration-test" ) ]
428+ {
429+ if should_panic_in_callback ( ) {
430+ panic ! ( "test-injected panic in on_line" ) ;
431+ }
432+ }
433+
384434 log_event ( py, code, "on_line" , Some ( lineno) ) ;
385435
386436 if let Ok ( filename) = code. filename ( py) {
0 commit comments