1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

Rework the readline test to be more robust.

- Capture that the child is started by initial log line.
- More robust handling of child status reaping.
- Direct exit without sucess mesage if `#readline` receives input.
This commit is contained in:
Samuel Williams 2021-08-09 09:40:13 +12:00
parent 3a8cadcf8f
commit 48c43f7783
Notes: git 2021-08-09 08:41:25 +09:00

View file

@ -8,6 +8,8 @@ module BasetestReadline
INPUTRC = "INPUTRC" INPUTRC = "INPUTRC"
SAVED_ENV = %w[COLUMNS LINES] SAVED_ENV = %w[COLUMNS LINES]
TIMEOUT = 8
def setup def setup
@saved_env = ENV.values_at(*SAVED_ENV) @saved_env = ENV.values_at(*SAVED_ENV)
@inputrc, ENV[INPUTRC] = ENV[INPUTRC], IO::NULL @inputrc, ENV[INPUTRC] = ENV[INPUTRC], IO::NULL
@ -449,7 +451,7 @@ module BasetestReadline
w << "\cr\u3042\u3093" w << "\cr\u3042\u3093"
w.reopen(IO::NULL) w.reopen(IO::NULL)
assert_equal("\u3046\u3093", Readline.readline("", true), bug6602) assert_equal("\u3046\u3093", Readline.readline("", true), bug6602)
Timeout.timeout(2) do Timeout.timeout(TIMEOUT) do
assert_equal("\u3042\u3093", Readline.readline("", true), bug6602) assert_equal("\u3042\u3093", Readline.readline("", true), bug6602)
end end
assert_equal(nil, Readline.readline("", true), bug6602) assert_equal(nil, Readline.readline("", true), bug6602)
@ -482,6 +484,7 @@ module BasetestReadline
code = <<-"end;" code = <<-"end;"
require 'readline' require 'readline'
require 'helper' require 'helper'
puts "Readline::VERSION is \#{Readline::VERSION}."
#{ #{
if defined?(TestReadline) && self.class == TestReadline if defined?(TestReadline) && self.class == TestReadline
"use_ext_readline" "use_ext_readline"
@ -496,6 +499,7 @@ module BasetestReadline
p :INT p :INT
} }
Readline.readline('input> ') Readline.readline('input> ')
exit!(0) # Cause the process to exit immediately.
}.value }.value
rescue Interrupt rescue Interrupt
puts 'FAILED' puts 'FAILED'
@ -503,59 +507,52 @@ module BasetestReadline
end end
puts 'SUCCEEDED' puts 'SUCCEEDED'
end; end;
f = Tempfile.new("interrupt_in_other_thread")
path = f.path script = Tempfile.new("interrupt_in_other_thread")
f.write code script.write code
f.close script.close
f.open
asserted = false log = String.new
current_dir = File.expand_path("..", __FILE__)
log, status = EnvUtil.invoke_ruby(["-I#{current_dir}", path], "", true, :merge_to_stdout) do |_in, _out, _, pid| EnvUtil.invoke_ruby(["-I#{__dir__}", script.path], "", true, :merge_to_stdout) do |_in, _out, _, pid|
begin Timeout.timeout(TIMEOUT) do
Timeout.timeout(4) do while c = _out.read(1)
log = String.new("Readline::VERSION is #{Readline::VERSION}.\n") log << c if c
while c = _out.read(1) break if log.include?('input>')
log << c if c end
break if log.include?('input>') Process.kill(:INT, pid)
sleep 0.1
while c = _out.read(1)
log << c if c
break if log.include?('INT')
end
begin
_in.write "\n"
rescue Errno::EPIPE
# The "write" will fail if Reline crashed by SIGINT.
end
while c = _out.read(1)
log << c if c
if log.include?('FAILED')
assert false, "Should handle SIGINT correctly but raised interrupt.\nLog: #{log}\n----"
end end
Process.kill(:INT, pid) if log.include?('SUCCEEDED')
sleep 0.1 assert false, "Should handle SIGINT correctly but exited successfully.\nLog: #{log}\n----"
while c = _out.read(1)
log << c if c
break if log.include?('INT')
end
begin
_in.write "\n"
rescue Errno::EPIPE
# The "write" will fail if Reline crashed by SIGINT.
end
while c = _out.read(1)
log << c if c
if log.include?('FAILED')
assert false, "Should handle SIGINT correctly but failed."
asserted = true
end
if log.include?('SUCCEEDED')
assert true, "Should handle SIGINT correctly but failed."
asserted = true
end
end end
end end
rescue Timeout::Error => e rescue Timeout::Error
assert false, "Timed out to handle SIGINT.\nLog: #{log}\nBacktrace:\n#{e.full_message(highlight: false)}\n----" assert false, "Timed out to handle SIGINT!\nLog: #{log}\n----"
asserted = true
end end
[log, Process.wait2(pid)[1]] ensure
end status = Process.wait2(pid).last
unless asserted assert status.success?, "Unknown failure with exit status #{status}\nLog: #{log}\n----"
assert false, "Unknown failure with exit status #{status}\nLog: #{log}\n----"
end end
assert log.include?('INT'), "Interrupt was handled correctly."
ensure ensure
f.close! if f script&.close!
end end
def test_setting_quoting_detection_proc def test_setting_quoting_detection_proc
return unless Readline.respond_to?(:quoting_detection_proc=) return unless Readline.respond_to?(:quoting_detection_proc=)