[ruby/irb] Add commands to start and use the debugger
(https://github.com/ruby/irb/pull/449) * Seamlessly integrate a few debug commands * Improve the break command support * Utilize skip_src option if available * Add step and delete commands * Write end-to-end tests for each debugger command * Add documentation * Add backtrace, info, catch commands https://github.com/ruby/irb/commit/976100c1c2
This commit is contained in:
parent
65e31402ae
commit
c9fbc779a6
@ -96,6 +96,8 @@ require_relative "irb/easter-egg"
|
|||||||
# * Show the source code around binding.irb again.
|
# * Show the source code around binding.irb again.
|
||||||
# * debug
|
# * debug
|
||||||
# * Start the debugger of debug.gem.
|
# * Start the debugger of debug.gem.
|
||||||
|
# * break, delete, next, step, continue, finish, backtrace, info, catch
|
||||||
|
# * Start the debugger of debug.gem and run the command on it.
|
||||||
#
|
#
|
||||||
# == Configuration
|
# == Configuration
|
||||||
#
|
#
|
||||||
@ -470,10 +472,6 @@ module IRB
|
|||||||
def initialize(workspace = nil, input_method = nil)
|
def initialize(workspace = nil, input_method = nil)
|
||||||
@context = Context.new(self, workspace, input_method)
|
@context = Context.new(self, workspace, input_method)
|
||||||
@context.main.extend ExtendCommandBundle
|
@context.main.extend ExtendCommandBundle
|
||||||
@context.command_aliases.each do |alias_name, cmd_name|
|
|
||||||
next if @context.symbol_alias(alias_name)
|
|
||||||
@context.main.install_alias_method(alias_name, cmd_name)
|
|
||||||
end
|
|
||||||
@signal_status = :IN_IRB
|
@signal_status = :IN_IRB
|
||||||
@scanner = RubyLex.new
|
@scanner = RubyLex.new
|
||||||
end
|
end
|
||||||
|
21
lib/irb/cmd/backtrace.rb
Normal file
21
lib/irb/cmd/backtrace.rb
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require_relative "debug"
|
||||||
|
|
||||||
|
module IRB
|
||||||
|
# :stopdoc:
|
||||||
|
|
||||||
|
module ExtendCommand
|
||||||
|
class Backtrace < Debug
|
||||||
|
def self.transform_args(args)
|
||||||
|
args&.dump
|
||||||
|
end
|
||||||
|
|
||||||
|
def execute(*args)
|
||||||
|
super(pre_cmds: ["backtrace", *args].join(" "))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# :startdoc:
|
||||||
|
end
|
21
lib/irb/cmd/break.rb
Normal file
21
lib/irb/cmd/break.rb
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require_relative "debug"
|
||||||
|
|
||||||
|
module IRB
|
||||||
|
# :stopdoc:
|
||||||
|
|
||||||
|
module ExtendCommand
|
||||||
|
class Break < Debug
|
||||||
|
def self.transform_args(args)
|
||||||
|
args&.dump
|
||||||
|
end
|
||||||
|
|
||||||
|
def execute(args = nil)
|
||||||
|
super(pre_cmds: "break #{args}")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# :startdoc:
|
||||||
|
end
|
21
lib/irb/cmd/catch.rb
Normal file
21
lib/irb/cmd/catch.rb
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require_relative "debug"
|
||||||
|
|
||||||
|
module IRB
|
||||||
|
# :stopdoc:
|
||||||
|
|
||||||
|
module ExtendCommand
|
||||||
|
class Catch < Debug
|
||||||
|
def self.transform_args(args)
|
||||||
|
args&.dump
|
||||||
|
end
|
||||||
|
|
||||||
|
def execute(*args)
|
||||||
|
super(pre_cmds: ["catch", *args].join(" "))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# :startdoc:
|
||||||
|
end
|
17
lib/irb/cmd/continue.rb
Normal file
17
lib/irb/cmd/continue.rb
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require_relative "debug"
|
||||||
|
|
||||||
|
module IRB
|
||||||
|
# :stopdoc:
|
||||||
|
|
||||||
|
module ExtendCommand
|
||||||
|
class Continue < Debug
|
||||||
|
def execute(*args)
|
||||||
|
super(do_cmds: ["continue", *args].join(" "))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# :startdoc:
|
||||||
|
end
|
@ -11,7 +11,7 @@ module IRB
|
|||||||
].map { |file| /\A#{Regexp.escape(file)}:\d+:in `irb'\z/ }
|
].map { |file| /\A#{Regexp.escape(file)}:\d+:in `irb'\z/ }
|
||||||
IRB_DIR = File.expand_path('..', __dir__)
|
IRB_DIR = File.expand_path('..', __dir__)
|
||||||
|
|
||||||
def execute(*args)
|
def execute(pre_cmds: nil, do_cmds: nil)
|
||||||
unless binding_irb?
|
unless binding_irb?
|
||||||
puts "`debug` command is only available when IRB is started with binding.irb"
|
puts "`debug` command is only available when IRB is started with binding.irb"
|
||||||
return
|
return
|
||||||
@ -25,11 +25,19 @@ module IRB
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
options = { oneshot: true, hook_call: false }
|
||||||
|
if pre_cmds || do_cmds
|
||||||
|
options[:command] = ['irb', pre_cmds, do_cmds]
|
||||||
|
end
|
||||||
|
if DEBUGGER__::LineBreakpoint.instance_method(:initialize).parameters.include?([:key, :skip_src])
|
||||||
|
options[:skip_src] = true
|
||||||
|
end
|
||||||
|
|
||||||
# To make debugger commands like `next` or `continue` work without asking
|
# To make debugger commands like `next` or `continue` work without asking
|
||||||
# the user to quit IRB after that, we need to exit IRB first and then hit
|
# the user to quit IRB after that, we need to exit IRB first and then hit
|
||||||
# a TracePoint on #debug_break.
|
# a TracePoint on #debug_break.
|
||||||
file, lineno = IRB::Irb.instance_method(:debug_break).source_location
|
file, lineno = IRB::Irb.instance_method(:debug_break).source_location
|
||||||
DEBUGGER__::SESSION.add_line_breakpoint(file, lineno + 1, oneshot: true, hook_call: false)
|
DEBUGGER__::SESSION.add_line_breakpoint(file, lineno + 1, **options)
|
||||||
# exit current Irb#run call
|
# exit current Irb#run call
|
||||||
throw :IRB_EXIT
|
throw :IRB_EXIT
|
||||||
end
|
end
|
||||||
|
17
lib/irb/cmd/delete.rb
Normal file
17
lib/irb/cmd/delete.rb
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require_relative "debug"
|
||||||
|
|
||||||
|
module IRB
|
||||||
|
# :stopdoc:
|
||||||
|
|
||||||
|
module ExtendCommand
|
||||||
|
class Delete < Debug
|
||||||
|
def execute(*args)
|
||||||
|
super(pre_cmds: ["delete", *args].join(" "))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# :startdoc:
|
||||||
|
end
|
17
lib/irb/cmd/finish.rb
Normal file
17
lib/irb/cmd/finish.rb
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require_relative "debug"
|
||||||
|
|
||||||
|
module IRB
|
||||||
|
# :stopdoc:
|
||||||
|
|
||||||
|
module ExtendCommand
|
||||||
|
class Finish < Debug
|
||||||
|
def execute(*args)
|
||||||
|
super(do_cmds: ["finish", *args].join(" "))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# :startdoc:
|
||||||
|
end
|
@ -1,31 +1,18 @@
|
|||||||
# frozen_string_literal: false
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_relative "nop"
|
require_relative "debug"
|
||||||
|
|
||||||
module IRB
|
module IRB
|
||||||
# :stopdoc:
|
# :stopdoc:
|
||||||
|
|
||||||
module ExtendCommand
|
module ExtendCommand
|
||||||
class Info < Nop
|
class Info < Debug
|
||||||
def execute
|
def self.transform_args(args)
|
||||||
Class.new {
|
args&.dump
|
||||||
def inspect
|
end
|
||||||
str = "Ruby version: #{RUBY_VERSION}\n"
|
|
||||||
str += "IRB version: #{IRB.version}\n"
|
def execute(*args)
|
||||||
str += "InputMethod: #{IRB.CurrentContext.io.inspect}\n"
|
super(pre_cmds: ["info", *args].join(" "))
|
||||||
str += ".irbrc path: #{IRB.rc_file}\n" if File.exist?(IRB.rc_file)
|
|
||||||
str += "RUBY_PLATFORM: #{RUBY_PLATFORM}\n"
|
|
||||||
str += "LANG env: #{ENV["LANG"]}\n" if ENV["LANG"] && !ENV["LANG"].empty?
|
|
||||||
str += "LC_ALL env: #{ENV["LC_ALL"]}\n" if ENV["LC_ALL"] && !ENV["LC_ALL"].empty?
|
|
||||||
str += "East Asian Ambiguous Width: #{Reline.ambiguous_width.inspect}\n"
|
|
||||||
if RbConfig::CONFIG['host_os'] =~ /mswin|msys|mingw|cygwin|bccwin|wince|emc/
|
|
||||||
codepage = `chcp`.b.sub(/.*: (\d+)\n/, '\1')
|
|
||||||
str += "Code page: #{codepage}\n"
|
|
||||||
end
|
|
||||||
str
|
|
||||||
end
|
|
||||||
alias_method :to_s, :inspect
|
|
||||||
}.new
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
34
lib/irb/cmd/irb_info.rb
Normal file
34
lib/irb/cmd/irb_info.rb
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
# frozen_string_literal: false
|
||||||
|
|
||||||
|
require_relative "nop"
|
||||||
|
|
||||||
|
module IRB
|
||||||
|
# :stopdoc:
|
||||||
|
|
||||||
|
module ExtendCommand
|
||||||
|
class IrbInfo < Nop
|
||||||
|
def execute
|
||||||
|
Class.new {
|
||||||
|
def inspect
|
||||||
|
str = "Ruby version: #{RUBY_VERSION}\n"
|
||||||
|
str += "IRB version: #{IRB.version}\n"
|
||||||
|
str += "InputMethod: #{IRB.CurrentContext.io.inspect}\n"
|
||||||
|
str += ".irbrc path: #{IRB.rc_file}\n" if File.exist?(IRB.rc_file)
|
||||||
|
str += "RUBY_PLATFORM: #{RUBY_PLATFORM}\n"
|
||||||
|
str += "LANG env: #{ENV["LANG"]}\n" if ENV["LANG"] && !ENV["LANG"].empty?
|
||||||
|
str += "LC_ALL env: #{ENV["LC_ALL"]}\n" if ENV["LC_ALL"] && !ENV["LC_ALL"].empty?
|
||||||
|
str += "East Asian Ambiguous Width: #{Reline.ambiguous_width.inspect}\n"
|
||||||
|
if RbConfig::CONFIG['host_os'] =~ /mswin|msys|mingw|cygwin|bccwin|wince|emc/
|
||||||
|
codepage = `chcp`.b.sub(/.*: (\d+)\n/, '\1')
|
||||||
|
str += "Code page: #{codepage}\n"
|
||||||
|
end
|
||||||
|
str
|
||||||
|
end
|
||||||
|
alias_method :to_s, :inspect
|
||||||
|
}.new
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# :startdoc:
|
||||||
|
end
|
17
lib/irb/cmd/next.rb
Normal file
17
lib/irb/cmd/next.rb
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require_relative "debug"
|
||||||
|
|
||||||
|
module IRB
|
||||||
|
# :stopdoc:
|
||||||
|
|
||||||
|
module ExtendCommand
|
||||||
|
class Next < Debug
|
||||||
|
def execute(*args)
|
||||||
|
super(do_cmds: ["next", *args].join(" "))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# :startdoc:
|
||||||
|
end
|
18
lib/irb/cmd/step.rb
Normal file
18
lib/irb/cmd/step.rb
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require_relative "debug"
|
||||||
|
|
||||||
|
module IRB
|
||||||
|
# :stopdoc:
|
||||||
|
|
||||||
|
module ExtendCommand
|
||||||
|
class Step < Debug
|
||||||
|
def execute(*args)
|
||||||
|
# Run `next` first to move out of binding.irb
|
||||||
|
super(pre_cmds: "next", do_cmds: ["step", *args].join(" "))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# :startdoc:
|
||||||
|
end
|
@ -486,9 +486,9 @@ module IRB
|
|||||||
@workspace.local_variable_set(:_, exception)
|
@workspace.local_variable_set(:_, exception)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Transform a non-identifier alias (ex: @, $)
|
# Transform a non-identifier alias (@, $) or keywords (next, break)
|
||||||
command, args = line.split(/\s/, 2)
|
command, args = line.split(/\s/, 2)
|
||||||
if original = symbol_alias(command)
|
if original = command_aliases[command.to_sym]
|
||||||
line = line.gsub(/\A#{Regexp.escape(command)}/, original.to_s)
|
line = line.gsub(/\A#{Regexp.escape(command)}/, original.to_s)
|
||||||
command = original
|
command = original
|
||||||
end
|
end
|
||||||
@ -545,10 +545,16 @@ module IRB
|
|||||||
workspace.binding.local_variables
|
workspace.binding.local_variables
|
||||||
end
|
end
|
||||||
|
|
||||||
# Return a command name if it's aliased from the argument and it's not an identifier.
|
# Return true if it's aliased from the argument and it's not an identifier.
|
||||||
def symbol_alias(command)
|
def symbol_alias?(command)
|
||||||
return nil if command.match?(/\A\w+\z/)
|
return nil if command.match?(/\A\w+\z/)
|
||||||
command_aliases[command.to_sym]
|
command_aliases.key?(command.to_sym)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Return true if the command supports transforming args
|
||||||
|
def transform_args?(command)
|
||||||
|
command = command_aliases.fetch(command.to_sym, command)
|
||||||
|
ExtendCommandBundle.load_command(command)&.respond_to?(:transform_args)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -124,13 +124,48 @@ module IRB # :nodoc:
|
|||||||
:irb_edit, :Edit, "cmd/edit",
|
:irb_edit, :Edit, "cmd/edit",
|
||||||
[:edit, NO_OVERRIDE],
|
[:edit, NO_OVERRIDE],
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
:irb_break, :Break, "cmd/break",
|
||||||
|
],
|
||||||
|
[
|
||||||
|
:irb_catch, :Catch, "cmd/catch",
|
||||||
|
],
|
||||||
|
[
|
||||||
|
:irb_next, :Next, "cmd/next",
|
||||||
|
],
|
||||||
|
[
|
||||||
|
:irb_delete, :Delete, "cmd/delete",
|
||||||
|
[:delete, NO_OVERRIDE],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
:irb_step, :Step, "cmd/step",
|
||||||
|
[:step, NO_OVERRIDE],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
:irb_continue, :Continue, "cmd/continue",
|
||||||
|
[:continue, NO_OVERRIDE],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
:irb_finish, :Finish, "cmd/finish",
|
||||||
|
[:finish, NO_OVERRIDE],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
:irb_backtrace, :Backtrace, "cmd/backtrace",
|
||||||
|
[:backtrace, NO_OVERRIDE],
|
||||||
|
[:bt, NO_OVERRIDE],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
:irb_debug_info, :Info, "cmd/info",
|
||||||
|
[:info, NO_OVERRIDE],
|
||||||
|
],
|
||||||
|
|
||||||
[
|
[
|
||||||
:irb_help, :Help, "cmd/help",
|
:irb_help, :Help, "cmd/help",
|
||||||
[:help, NO_OVERRIDE],
|
[:help, NO_OVERRIDE],
|
||||||
],
|
],
|
||||||
|
|
||||||
[
|
[
|
||||||
:irb_info, :Info, "cmd/info"
|
:irb_info, :IrbInfo, "cmd/irb_info"
|
||||||
],
|
],
|
||||||
|
|
||||||
[
|
[
|
||||||
|
@ -160,8 +160,13 @@ module IRB # :nodoc:
|
|||||||
@CONF[:AT_EXIT] = []
|
@CONF[:AT_EXIT] = []
|
||||||
|
|
||||||
@CONF[:COMMAND_ALIASES] = {
|
@CONF[:COMMAND_ALIASES] = {
|
||||||
|
# Symbol aliases
|
||||||
:'$' => :show_source,
|
:'$' => :show_source,
|
||||||
:'@' => :whereami,
|
:'@' => :whereami,
|
||||||
|
# Keyword aliases
|
||||||
|
:break => :irb_break,
|
||||||
|
:catch => :irb_catch,
|
||||||
|
:next => :irb_next,
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -65,9 +65,9 @@ class RubyLex
|
|||||||
false
|
false
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
# Accept any single-line input starting with a non-identifier alias (ex: @, $)
|
# Accept any single-line input for symbol aliases or commands that transform args
|
||||||
command = code.split(/\s/, 2).first
|
command = code.split(/\s/, 2).first
|
||||||
if context.symbol_alias(command)
|
if context.symbol_alias?(command) || context.transform_args?(command)
|
||||||
next true
|
next true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -17,6 +17,8 @@ begin
|
|||||||
@irbrc_backup = ENV['IRBRC']
|
@irbrc_backup = ENV['IRBRC']
|
||||||
@irbrc_file = ENV['IRBRC'] = File.join(@tmpdir, 'temporaty_irbrc')
|
@irbrc_file = ENV['IRBRC'] = File.join(@tmpdir, 'temporaty_irbrc')
|
||||||
File.unlink(@irbrc_file) if File.exist?(@irbrc_file)
|
File.unlink(@irbrc_file) if File.exist?(@irbrc_file)
|
||||||
|
@ruby_file = File.join(@tmpdir, 'ruby_file.rb')
|
||||||
|
File.unlink(@ruby_file) if File.exist?(@ruby_file)
|
||||||
end
|
end
|
||||||
|
|
||||||
def teardown
|
def teardown
|
||||||
@ -235,11 +237,234 @@ begin
|
|||||||
EOC
|
EOC
|
||||||
end
|
end
|
||||||
|
|
||||||
private def write_irbrc(content)
|
def test_debug
|
||||||
|
write_ruby <<~'RUBY'
|
||||||
|
puts "start IRB"
|
||||||
|
binding.irb
|
||||||
|
puts "Hello"
|
||||||
|
RUBY
|
||||||
|
start_terminal(25, 80, %W{ruby -I#{@pwd}/lib #{@ruby_file}}, startup_message: 'start IRB')
|
||||||
|
write("debug\n")
|
||||||
|
write("next\n")
|
||||||
|
close
|
||||||
|
assert_include_screen(<<~EOC)
|
||||||
|
(rdbg) next # command
|
||||||
|
[1, 3] in #{@ruby_file}
|
||||||
|
1| puts "start IRB"
|
||||||
|
2| binding.irb
|
||||||
|
=> 3| puts "Hello"
|
||||||
|
EOC
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_break
|
||||||
|
write_ruby <<~'RUBY'
|
||||||
|
puts "start IRB"
|
||||||
|
binding.irb
|
||||||
|
puts "Hello"
|
||||||
|
puts "World"
|
||||||
|
RUBY
|
||||||
|
start_terminal(25, 80, %W{ruby -I#{@pwd}/lib #{@ruby_file}}, startup_message: 'start IRB')
|
||||||
|
write("break 3\n")
|
||||||
|
write("continue\n")
|
||||||
|
close
|
||||||
|
assert_include_screen(<<~EOC)
|
||||||
|
(rdbg:irb) break 3
|
||||||
|
#0 BP - Line #{@ruby_file}:3 (line)
|
||||||
|
EOC
|
||||||
|
assert_include_screen(<<~EOC)
|
||||||
|
(rdbg) continue # command
|
||||||
|
[1, 4] in #{@ruby_file}
|
||||||
|
1| puts "start IRB"
|
||||||
|
2| binding.irb
|
||||||
|
=> 3| puts "Hello"
|
||||||
|
4| puts "World"
|
||||||
|
=>#0 <main> at #{@ruby_file}:3
|
||||||
|
|
||||||
|
Stop by #0 BP - Line #{@ruby_file}:3 (line)
|
||||||
|
EOC
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_delete
|
||||||
|
write_ruby <<~'RUBY'
|
||||||
|
puts "start IRB"
|
||||||
|
binding.irb
|
||||||
|
puts "Hello"
|
||||||
|
binding.irb
|
||||||
|
puts "World"
|
||||||
|
RUBY
|
||||||
|
start_terminal(25, 80, %W{ruby -I#{@pwd}/lib #{@ruby_file}}, startup_message: 'start IRB')
|
||||||
|
write("break 5\n")
|
||||||
|
write("continue\n")
|
||||||
|
write("delete 0\n")
|
||||||
|
close
|
||||||
|
assert_include_screen(<<~EOC)
|
||||||
|
(rdbg:irb) delete 0
|
||||||
|
deleted: #0 BP - Line #{@ruby_file}:5 (line)
|
||||||
|
EOC
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_next
|
||||||
|
write_ruby <<~'RUBY'
|
||||||
|
puts "start IRB"
|
||||||
|
binding.irb
|
||||||
|
puts "Hello"
|
||||||
|
puts "World"
|
||||||
|
RUBY
|
||||||
|
start_terminal(25, 80, %W{ruby -I#{@pwd}/lib #{@ruby_file}}, startup_message: 'start IRB')
|
||||||
|
write("next\n")
|
||||||
|
close
|
||||||
|
assert_include_screen(<<~EOC)
|
||||||
|
(rdbg:irb) next
|
||||||
|
[1, 4] in #{@ruby_file}
|
||||||
|
1| puts "start IRB"
|
||||||
|
2| binding.irb
|
||||||
|
=> 3| puts "Hello"
|
||||||
|
4| puts "World"
|
||||||
|
=>#0 <main> at #{@ruby_file}:3
|
||||||
|
EOC
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_step
|
||||||
|
write_ruby <<~'RUBY'
|
||||||
|
puts "start IRB"
|
||||||
|
def foo
|
||||||
|
puts "Hello"
|
||||||
|
end
|
||||||
|
binding.irb
|
||||||
|
foo
|
||||||
|
puts "World"
|
||||||
|
RUBY
|
||||||
|
start_terminal(25, 80, %W{ruby -I#{@pwd}/lib #{@ruby_file}}, startup_message: 'start IRB')
|
||||||
|
write("step\n")
|
||||||
|
close
|
||||||
|
assert_include_screen(<<~EOC)
|
||||||
|
(rdbg:irb) step
|
||||||
|
[1, 7] in #{@ruby_file}
|
||||||
|
1| puts "start IRB"
|
||||||
|
2| def foo
|
||||||
|
=> 3| puts "Hello"
|
||||||
|
4| end
|
||||||
|
5| binding.irb
|
||||||
|
EOC
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_continue
|
||||||
|
write_ruby <<~'RUBY'
|
||||||
|
puts "start IRB"
|
||||||
|
binding.irb
|
||||||
|
puts "Hello"
|
||||||
|
binding.irb
|
||||||
|
puts "World"
|
||||||
|
RUBY
|
||||||
|
start_terminal(25, 80, %W{ruby -I#{@pwd}/lib #{@ruby_file}}, startup_message: 'start IRB')
|
||||||
|
write("continue\n")
|
||||||
|
close
|
||||||
|
assert_include_screen(<<~EOC)
|
||||||
|
(rdbg:irb) continue
|
||||||
|
Hello
|
||||||
|
|
||||||
|
From: #{@ruby_file} @ line 4 :
|
||||||
|
|
||||||
|
1: puts "start IRB"
|
||||||
|
2: binding.irb
|
||||||
|
3: puts "Hello"
|
||||||
|
=> 4: binding.irb
|
||||||
|
5: puts "World"
|
||||||
|
EOC
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_finish
|
||||||
|
write_ruby <<~'RUBY'
|
||||||
|
puts "start IRB"
|
||||||
|
def foo
|
||||||
|
binding.irb
|
||||||
|
puts "Hello"
|
||||||
|
end
|
||||||
|
foo
|
||||||
|
puts "World"
|
||||||
|
RUBY
|
||||||
|
start_terminal(25, 80, %W{ruby -I#{@pwd}/lib #{@ruby_file}}, startup_message: 'start IRB')
|
||||||
|
write("finish\n")
|
||||||
|
close
|
||||||
|
assert_include_screen(<<~EOC)
|
||||||
|
(rdbg:irb) finish
|
||||||
|
Hello
|
||||||
|
[1, 7] in #{@ruby_file}
|
||||||
|
1| puts "start IRB"
|
||||||
|
2| def foo
|
||||||
|
3| binding.irb
|
||||||
|
4| puts "Hello"
|
||||||
|
=> 5| end
|
||||||
|
6| foo
|
||||||
|
EOC
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_backtrace
|
||||||
|
write_ruby <<~'RUBY'
|
||||||
|
puts "start IRB"
|
||||||
|
def foo
|
||||||
|
binding.irb
|
||||||
|
end
|
||||||
|
foo
|
||||||
|
RUBY
|
||||||
|
start_terminal(25, 80, %W{ruby -I#{@pwd}/lib #{@ruby_file}}, startup_message: 'start IRB')
|
||||||
|
write("backtrace\n")
|
||||||
|
close
|
||||||
|
assert_include_screen(<<~EOC)
|
||||||
|
(rdbg:irb) backtrace
|
||||||
|
=>#0 Object#foo at #{@ruby_file}:3
|
||||||
|
#1 <main> at #{@ruby_file}:5
|
||||||
|
EOC
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_info
|
||||||
|
write_ruby <<~'RUBY'
|
||||||
|
puts "start IRB"
|
||||||
|
a = 1
|
||||||
|
binding.irb
|
||||||
|
RUBY
|
||||||
|
start_terminal(25, 80, %W{ruby -I#{@pwd}/lib #{@ruby_file}}, startup_message: 'start IRB')
|
||||||
|
write("info\n")
|
||||||
|
close
|
||||||
|
assert_include_screen(<<~EOC)
|
||||||
|
(rdbg:irb) info
|
||||||
|
%self = main
|
||||||
|
a = 1
|
||||||
|
EOC
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_catch
|
||||||
|
write_ruby <<~'RUBY'
|
||||||
|
puts "start IRB"
|
||||||
|
binding.irb
|
||||||
|
raise NotImplementedError
|
||||||
|
RUBY
|
||||||
|
start_terminal(25, 80, %W{ruby -I#{@pwd}/lib #{@ruby_file}}, startup_message: 'start IRB')
|
||||||
|
write("catch NotImplementedError\n")
|
||||||
|
write("continue\n")
|
||||||
|
close
|
||||||
|
assert_include_screen(<<~EOC)
|
||||||
|
Stop by #0 BP - Catch "NotImplementedError"
|
||||||
|
EOC
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def assert_include_screen(expected)
|
||||||
|
assert_include(result.join("\n"), expected)
|
||||||
|
end
|
||||||
|
|
||||||
|
def write_irbrc(content)
|
||||||
File.open(@irbrc_file, 'w') do |f|
|
File.open(@irbrc_file, 'w') do |f|
|
||||||
f.write content
|
f.write content
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def write_ruby(content)
|
||||||
|
File.open(@ruby_file, 'w') do |f|
|
||||||
|
f.write content
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
rescue LoadError, NameError
|
rescue LoadError, NameError
|
||||||
# On Ruby repository, this test suit doesn't run because Ruby repo doesn't
|
# On Ruby repository, this test suit doesn't run because Ruby repo doesn't
|
||||||
|
Loading…
x
Reference in New Issue
Block a user