Test refresh_line hook

This commit is contained in:
Sami Samhuri 2026-02-03 04:17:09 -08:00
parent 2b78487c74
commit 35fc514a14
No known key found for this signature in database
2 changed files with 27 additions and 4 deletions

View file

@ -10,9 +10,10 @@ module Shell
attr_reader :logger
def initialize(logger: nil)
def initialize(logger: nil, refresh_line: nil)
@jobs_by_pid = {}
@logger = logger || Logger.instance
@refresh_line = refresh_line || -> { Readline.refresh_line }
end
def exec_command(cmd, args, background: false)
@ -67,7 +68,11 @@ module Shell
def trap_sigchld
# handler for SIGCHLD when a child's state changes
Signal.trap("CHLD") do |_signo|
pid = Process.waitpid(-1, Process::WNOHANG)
pid = begin
Process.waitpid(-1, Process::WNOHANG)
rescue Errno::ECHILD
nil
end
if pid.nil?
# no-op
elsif (job = @jobs_by_pid[pid])
@ -79,7 +84,7 @@ module Shell
else
warn "\n#{yellow("[WARN]")} No job found for child with PID #{pid}"
end
Readline.refresh_line
@refresh_line.call
end
end

View file

@ -1,5 +1,9 @@
require "minitest/autorun"
require "etc"
require "timeout"
$LOAD_PATH.unshift(File.expand_path("..", __dir__))
require_relative "../shell/job_control"
require_relative "../shell/logger"
class ShellTest < Minitest::Test
TRIVIAL_SHELL_SCRIPT = "#!/bin/sh\ntrue".freeze
@ -151,7 +155,21 @@ class ShellTest < Minitest::Test
end
def test_refreshes_readline_after_bg_execution
skip "unimplemented"
called = false
job_control = Shell::JobControl.new(
logger: Shell::Logger.instance,
refresh_line: -> { called = true }
)
previous = job_control.trap_sigchld
begin
job_control.exec_command("echo", ["hello"], background: true)
Timeout.timeout(2) do
sleep 0.01 until called
end
assert called
ensure
Signal.trap("CHLD", previous)
end
end
#########################