66require "process/metrics"
77# Load ProcessStatus backend so we can compare General (Linux) vs General::ProcessStatus.
88require "process/metrics/general/process_status"
9+ require_relative "../../../fixtures/process/metrics/a_stable_process"
910
1011describe Process ::Metrics ::General do
1112 with "Linux backend matches ProcessStatus backend" do
13+ include_context Process ::Metrics ::AStableProcess
14+
1215 def assert_backends_match ( linux_capture , process_status_capture )
1316 expect ( linux_capture . keys . sort ) . to be == process_status_capture . keys . sort
1417
@@ -22,6 +25,7 @@ def assert_backends_match(linux_capture, process_status_capture)
2225 expect ( linux_process . process_group_id ) . to be == process_status_process . process_group_id
2326
2427 # VSZ and RSS differ because ps excludes device mappings while /proc/stat includes them.
28+ # With a stable controlled process, RSS should be more consistent between measurements.
2529 expect ( linux_process . virtual_size ) . to be_within ( 10.0 ) . percent_of ( process_status_process . virtual_size )
2630 expect ( linux_process . resident_size ) . to be_within ( 10.0 ) . percent_of ( process_status_process . resident_size )
2731
@@ -34,24 +38,67 @@ def assert_backends_match(linux_capture, process_status_capture)
3438 it "single pid capture matches" do
3539 skip "Linux with ProcessStatus required" unless RUBY_PLATFORM . include? ( "linux" ) && Process ::Metrics ::General ::ProcessStatus . supported?
3640
37- pid = Process . pid
38- linux_capture = Process ::Metrics ::General . capture ( pid : pid , memory : false )
39- process_status_capture = Process ::Metrics ::General ::ProcessStatus . capture ( pid : pid , memory : false )
41+ # Stabilize the child process before taking measurements
42+ @child . write_message ( action : "stabilize" )
43+ @child . wait_for_message ( "stabilized" )
44+
45+ linux_capture = Process ::Metrics ::General . capture ( pid : @pid , memory : false )
46+ process_status_capture = Process ::Metrics ::General ::ProcessStatus . capture ( pid : @pid , memory : false )
4047 assert_backends_match ( linux_capture , process_status_capture )
4148 end
4249
4350 it "pid and ppid capture matches" do
4451 skip "Linux with ProcessStatus required" unless RUBY_PLATFORM . include? ( "linux" ) && Process ::Metrics ::General ::ProcessStatus . supported?
4552
46- child_pid = Process . spawn ( "sleep 10" )
47- begin
48- linux_capture = Process ::Metrics ::General . capture ( pid : child_pid , ppid : child_pid , memory : false )
49- process_status_capture = Process ::Metrics ::General ::ProcessStatus . capture ( pid : child_pid , ppid : child_pid , memory : false )
50- assert_backends_match ( linux_capture , process_status_capture )
51- ensure
52- Process . kill ( :TERM , child_pid )
53- Process . wait ( child_pid )
53+ # Stabilize the child process before taking measurements
54+ @child . write_message ( action : "stabilize" )
55+ @child . wait_for_message ( "stabilized" )
56+
57+ linux_capture = Process ::Metrics ::General . capture ( pid : @pid , ppid : @pid , memory : false )
58+ process_status_capture = Process ::Metrics ::General ::ProcessStatus . capture ( pid : @pid , ppid : @pid , memory : false )
59+ assert_backends_match ( linux_capture , process_status_capture )
60+ end
61+
62+ it "captures child processes by ppid" do
63+ skip "Linux with ProcessStatus required" unless RUBY_PLATFORM . include? ( "linux" ) && Process ::Metrics ::General ::ProcessStatus . supported?
64+
65+ # Fork 2 child processes
66+ @child . write_message ( action : "fork" )
67+ response1 = @child . wait_for_message ( "forked" )
68+
69+ @child . write_message ( action : "fork" )
70+ response2 = @child . wait_for_message ( "forked" )
71+
72+ child_pids = [ response1 [ :child_pid ] , response2 [ :child_pid ] ]
73+
74+ # Stabilize before measuring
75+ @child . write_message ( action : "stabilize" )
76+ @child . wait_for_message ( "stabilized" )
77+
78+ # Capture using ppid - should get parent + both children
79+ linux_capture = Process ::Metrics ::General . capture ( ppid : @pid , memory : false )
80+ process_status_capture = Process ::Metrics ::General ::ProcessStatus . capture ( ppid : @pid , memory : false )
81+
82+ # Should have captured 3 processes: parent + 2 children
83+ expect ( linux_capture . size ) . to be == 3
84+ expect ( process_status_capture . size ) . to be == 3
85+
86+ # Verify parent is included
87+ expect ( linux_capture . keys ) . to be ( :include? , @pid )
88+ expect ( process_status_capture . keys ) . to be ( :include? , @pid )
89+
90+ # Verify both children are included
91+ child_pids . each do |child_pid |
92+ expect ( linux_capture . keys ) . to be ( :include? , child_pid )
93+ expect ( process_status_capture . keys ) . to be ( :include? , child_pid )
94+
95+ # Verify parent-child relationship
96+ expect ( linux_capture [ child_pid ] . parent_process_id ) . to be == @pid
97+ expect ( process_status_capture [ child_pid ] . parent_process_id ) . to be == @pid
5498 end
99+
100+ # Compare all processes
101+ assert_backends_match ( linux_capture , process_status_capture )
55102 end
56103 end
57104end
0 commit comments