aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStan Lo <stan001212@gmail.com>2023-08-02 19:33:38 +0100
committergit <svn-admin@ruby-lang.org>2023-08-02 18:33:43 +0000
commit8ecd300e1e51f9e56bf22a8c4fb64ef475612914 (patch)
tree0796319cf792cd3290be9dbee93b38df1211fa2a
parentdc54574adefe798702cc93457655da40f4939669 (diff)
downloadruby-8ecd300e1e51f9e56bf22a8c4fb64ef475612914.tar.gz
[ruby/irb] Extract integration testing helpers out of debug command
tests (https://github.com/ruby/irb/pull/660) The ability to run a test case in a subprocess is useful for testing many other features, like nested IRB sessions. So I think it's worth extracting them into a new test case class. https://github.com/ruby/irb/commit/73b7a895f8
-rw-r--r--test/irb/helper.rb110
-rw-r--r--test/irb/test_debug_cmd.rb106
2 files changed, 113 insertions, 103 deletions
diff --git a/test/irb/helper.rb b/test/irb/helper.rb
index 55f9e083eb..44dd41bd1b 100644
--- a/test/irb/helper.rb
+++ b/test/irb/helper.rb
@@ -7,6 +7,11 @@ begin
rescue LoadError # ruby/ruby defines helpers differently
end
+begin
+ require "pty"
+rescue LoadError # some platforms don't support PTY
+end
+
module IRB
class InputMethod; end
end
@@ -73,4 +78,109 @@ module TestIRB
}
end
end
+
+ class IntegrationTestCase
+ LIB = File.expand_path("../../lib", __dir__)
+ TIMEOUT_SEC = 3
+
+ def setup
+ unless defined?(PTY)
+ omit "Integration tests require PTY."
+ end
+ end
+
+ def run_ruby_file(&block)
+ cmd = [EnvUtil.rubybin, "-I", LIB, @ruby_file.to_path]
+ tmp_dir = Dir.mktmpdir
+
+ @commands = []
+ lines = []
+
+ yield
+
+ PTY.spawn(integration_envs.merge("TERM" => "dumb"), *cmd) do |read, write, pid|
+ Timeout.timeout(TIMEOUT_SEC) do
+ while line = safe_gets(read)
+ lines << line
+
+ # means the breakpoint is triggered
+ if line.match?(/binding\.irb/)
+ while command = @commands.shift
+ write.puts(command)
+ end
+ end
+ end
+ end
+ ensure
+ read.close
+ write.close
+ kill_safely(pid)
+ end
+
+ lines.join
+ rescue Timeout::Error
+ message = <<~MSG
+ Test timedout.
+
+ #{'=' * 30} OUTPUT #{'=' * 30}
+ #{lines.map { |l| " #{l}" }.join}
+ #{'=' * 27} END OF OUTPUT #{'=' * 27}
+ MSG
+ assert_block(message) { false }
+ ensure
+ File.unlink(@ruby_file) if @ruby_file
+ FileUtils.remove_entry tmp_dir
+ end
+
+ # read.gets could raise exceptions on some platforms
+ # https://github.com/ruby/ruby/blob/master/ext/pty/pty.c#L721-L728
+ def safe_gets(read)
+ read.gets
+ rescue Errno::EIO
+ nil
+ end
+
+ def kill_safely pid
+ return if wait_pid pid, TIMEOUT_SEC
+
+ Process.kill :TERM, pid
+ return if wait_pid pid, 0.2
+
+ Process.kill :KILL, pid
+ Process.waitpid(pid)
+ rescue Errno::EPERM, Errno::ESRCH
+ end
+
+ def wait_pid pid, sec
+ total_sec = 0.0
+ wait_sec = 0.001 # 1ms
+
+ while total_sec < sec
+ if Process.waitpid(pid, Process::WNOHANG) == pid
+ return true
+ end
+ sleep wait_sec
+ total_sec += wait_sec
+ wait_sec *= 2
+ end
+
+ false
+ rescue Errno::ECHILD
+ true
+ end
+
+ def type(command)
+ @commands << command
+ end
+
+ def write_ruby(program)
+ @ruby_file = Tempfile.create(%w{irb- .rb})
+ @ruby_file.write(program)
+ @ruby_file.close
+ end
+
+ def integration_envs
+ {}
+ end
+ end
end
diff --git a/test/irb/test_debug_cmd.rb b/test/irb/test_debug_cmd.rb
index 3bc00638dd..aa0321b66f 100644
--- a/test/irb/test_debug_cmd.rb
+++ b/test/irb/test_debug_cmd.rb
@@ -1,24 +1,12 @@
# frozen_string_literal: true
-begin
- require "pty"
-rescue LoadError
- return
-end
-
require "tempfile"
require "tmpdir"
require_relative "helper"
module TestIRB
- LIB = File.expand_path("../../lib", __dir__)
-
- class DebugCommandTestCase < TestCase
- IRB_AND_DEBUGGER_OPTIONS = {
- "NO_COLOR" => "true", "RUBY_DEBUG_HISTORY_FILE" => ''
- }
-
+ class DebugCommandTest < IntegrationTestCase
def setup
if ruby_core?
omit "This test works only under ruby/irb"
@@ -204,96 +192,8 @@ module TestIRB
private
- TIMEOUT_SEC = 3
-
- def run_ruby_file(&block)
- cmd = [EnvUtil.rubybin, "-I", LIB, @ruby_file.to_path]
- tmp_dir = Dir.mktmpdir
-
- @commands = []
- lines = []
-
- yield
-
- PTY.spawn(IRB_AND_DEBUGGER_OPTIONS.merge("TERM" => "dumb"), *cmd) do |read, write, pid|
- Timeout.timeout(TIMEOUT_SEC) do
- while line = safe_gets(read)
- lines << line
-
- # means the breakpoint is triggered
- if line.match?(/binding\.irb/)
- while command = @commands.shift
- write.puts(command)
- end
- end
- end
- end
- ensure
- read.close
- write.close
- kill_safely(pid)
- end
-
- lines.join
- rescue Timeout::Error
- message = <<~MSG
- Test timedout.
-
- #{'=' * 30} OUTPUT #{'=' * 30}
- #{lines.map { |l| " #{l}" }.join}
- #{'=' * 27} END OF OUTPUT #{'=' * 27}
- MSG
- assert_block(message) { false }
- ensure
- File.unlink(@ruby_file) if @ruby_file
- FileUtils.remove_entry tmp_dir
- end
-
- # read.gets could raise exceptions on some platforms
- # https://github.com/ruby/ruby/blob/master/ext/pty/pty.c#L729-L736
- def safe_gets(read)
- read.gets
- rescue Errno::EIO
- nil
- end
-
- def kill_safely pid
- return if wait_pid pid, TIMEOUT_SEC
-
- Process.kill :TERM, pid
- return if wait_pid pid, 0.2
-
- Process.kill :KILL, pid
- Process.waitpid(pid)
- rescue Errno::EPERM, Errno::ESRCH
- end
-
- def wait_pid pid, sec
- total_sec = 0.0
- wait_sec = 0.001 # 1ms
-
- while total_sec < sec
- if Process.waitpid(pid, Process::WNOHANG) == pid
- return true
- end
- sleep wait_sec
- total_sec += wait_sec
- wait_sec *= 2
- end
-
- false
- rescue Errno::ECHILD
- true
- end
-
- def type(command)
- @commands << command
- end
-
- def write_ruby(program)
- @ruby_file = Tempfile.create(%w{irb- .rb})
- @ruby_file.write(program)
- @ruby_file.close
+ def integration_envs
+ { "NO_COLOR" => "true", "RUBY_DEBUG_HISTORY_FILE" => '' }
end
end
end