@@ -40,7 +40,9 @@ groups() ->
4040 duplicates ]},
4141 {trace , [single_pid ,
4242 single_pid_with_msg ,
43- msg_after_traced_call ]},
43+ msg_after_traced_call ,
44+ new_children_first ,
45+ new_children_all ]},
4446 {range , [ranges ,
4547 ranges_max_depth ,
4648 range ,
@@ -200,6 +202,68 @@ msg_after_traced_call(_Config) ->
200202 # tr {index = 3 , event = send , pid = Pid , data = {ok , 1 }, info = {Self , true }},
201203 # tr {index = 4 , event = recv , pid = Pid , data = stop }] = tr :select ().
202204
205+ new_children_first (_Config ) ->
206+ % % Start a parent process before tracing
207+ Parent = self (),
208+ ParentPid = spawn_link (fun () -> spawner_loop (Parent ) end ),
209+ receive {spawner_ready , ParentPid } -> ok end ,
210+
211+ % % Trace only the parent with new_children => first
212+ MFA = {? MODULE , traced_child_fun , 1 },
213+ tr :trace (#{modules => [MFA ], pids => [ParentPid ], new_children => first }),
214+
215+ % % Spawn two children from the parent - only the first should be traced
216+ ParentPid ! {spawn_child , 1 },
217+ Child1 = receive {child_spawned , Ch1 , 1 } -> Ch1 end ,
218+ ParentPid ! {spawn_child , 2 },
219+ Child2 = receive {child_spawned , Ch2 , 2 } -> Ch2 end ,
220+
221+ % % Wait for traces - only 2 traces from the first child (call + return)
222+ wait_for_traces (2 ),
223+ tr :stop_tracing (),
224+
225+ % % Clean up
226+ ParentPid ! stop ,
227+
228+ % % Verify only the first child's traces are collected
229+ [# tr {index = 1 , event = call , mfa = MFA , pid = Child1 , data = [1 ]},
230+ # tr {index = 2 , event = return , mfa = MFA , pid = Child1 , data = 1 }] = tr :select (),
231+
232+ % % Verify Child2 is different from Child1
233+ ? assertNotEqual (Child1 , Child2 ).
234+
235+ new_children_all (_Config ) ->
236+ % % Start a parent process before tracing
237+ Parent = self (),
238+ ParentPid = spawn_link (fun () -> spawner_loop (Parent ) end ),
239+ receive {spawner_ready , ParentPid } -> ok end ,
240+
241+ % % Trace only the parent with new_children => all
242+ MFA = {? MODULE , traced_child_fun , 1 },
243+ tr :trace (#{modules => [MFA ], pids => [ParentPid ], new_children => all }),
244+
245+ % % Spawn two children from the parent - both should be traced
246+ ParentPid ! {spawn_child , 1 },
247+ Child1 = receive {child_spawned , Ch1 , 1 } -> Ch1 end ,
248+ ParentPid ! {spawn_child , 2 },
249+ Child2 = receive {child_spawned , Ch2 , 2 } -> Ch2 end ,
250+
251+ % % Wait for traces - 4 traces total (2 from each child)
252+ wait_for_traces (4 ),
253+ tr :stop_tracing (),
254+
255+ % % Clean up
256+ ParentPid ! stop ,
257+
258+ % % Verify both children's traces are collected
259+ [# tr {index = 1 , event = call , mfa = MFA , pid = Child1 , data = [1 ]},
260+ # tr {index = 2 , event = return , mfa = MFA , pid = Child1 , data = 1 },
261+ # tr {index = 3 , event = call , mfa = MFA , pid = Child2 , data = [2 ]},
262+ # tr {index = 4 , event = return , mfa = MFA , pid = Child2 , data = 2 }] = tr :select (),
263+
264+ % % Verify Child2 is different from Child1
265+ ? assertNotEqual (Child1 , Child2 ).
266+
203267ranges (_Config ) ->
204268 Traces = trace_fib3 (),
205269
@@ -835,3 +899,24 @@ log(#{msg := {Format, Args}, level := Level}, #{config := Pid}) ->
835899 Pid ! {Level , lists :flatten (io_lib :format (Format , Args ))};
836900log (_Event , _Config ) ->
837901 ok .
902+
903+ % % Helper for new_children tests
904+ spawner_loop (Parent ) ->
905+ Parent ! {spawner_ready , self ()},
906+ spawner_loop_ready (Parent ).
907+
908+ spawner_loop_ready (Parent ) ->
909+ receive
910+ {spawn_child , Id } ->
911+ Child = spawn_link (fun () ->
912+ ? MODULE :traced_child_fun (Id ),
913+ receive after infinity -> ok end
914+ end ),
915+ Parent ! {child_spawned , Child , Id },
916+ spawner_loop_ready (Parent );
917+ stop ->
918+ ok
919+ end .
920+
921+ traced_child_fun (N ) ->
922+ N .
0 commit comments