debugger-xml 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +20 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +24 -0
- data/Rakefile +10 -0
- data/bin/rdebug-ide +90 -0
- data/debugger-xml.gemspec +25 -0
- data/lib/debugger/printers/texts/xml.yml +121 -0
- data/lib/debugger/printers/xml.rb +195 -0
- data/lib/debugger/xml.rb +3 -0
- data/lib/debugger/xml/extensions/commands/edit.rb +13 -0
- data/lib/debugger/xml/extensions/commands/frame.rb +14 -0
- data/lib/debugger/xml/extensions/commands/help.rb +13 -0
- data/lib/debugger/xml/extensions/commands/info.rb +13 -0
- data/lib/debugger/xml/extensions/commands/irb.rb +13 -0
- data/lib/debugger/xml/extensions/commands/kill.rb +13 -0
- data/lib/debugger/xml/extensions/commands/tmate.rb +13 -0
- data/lib/debugger/xml/extensions/commands/trace.rb +13 -0
- data/lib/debugger/xml/extensions/commands/variables.rb +16 -0
- data/lib/debugger/xml/extensions/debugger.rb +28 -0
- data/lib/debugger/xml/extensions/processor.rb +9 -0
- data/lib/debugger/xml/ide_processor.rb +149 -0
- data/lib/debugger/xml/interface.rb +65 -0
- data/lib/debugger/xml/version.rb +5 -0
- data/test/breakpoints_test.rb +190 -0
- data/test/conditions_test.rb +32 -0
- data/test/continue_test.rb +12 -0
- data/test/display_test.rb +25 -0
- data/test/edit_test.rb +12 -0
- data/test/eval_test.rb +20 -0
- data/test/examples/breakpoint1.rb +15 -0
- data/test/examples/breakpoint2.rb +7 -0
- data/test/examples/conditions.rb +4 -0
- data/test/examples/continue.rb +4 -0
- data/test/examples/display.rb +5 -0
- data/test/examples/edit.rb +3 -0
- data/test/examples/eval.rb +4 -0
- data/test/examples/frame.rb +31 -0
- data/test/examples/help.rb +2 -0
- data/test/examples/info.rb +48 -0
- data/test/examples/irb.rb +6 -0
- data/test/examples/jump.rb +14 -0
- data/test/examples/kill.rb +2 -0
- data/test/examples/method.rb +15 -0
- data/test/examples/reload.rb +6 -0
- data/test/examples/restart.rb +6 -0
- data/test/examples/set.rb +3 -0
- data/test/examples/stepping.rb +21 -0
- data/test/examples/thread.rb +32 -0
- data/test/examples/tmate.rb +10 -0
- data/test/examples/trace.rb +7 -0
- data/test/examples/variables.rb +26 -0
- data/test/examples/variables_xml.rb +31 -0
- data/test/frame_test.rb +29 -0
- data/test/help_test.rb +13 -0
- data/test/ide_control_command_processor_test.rb +62 -0
- data/test/ide_processor_test.rb +118 -0
- data/test/info_test.rb +12 -0
- data/test/irb_test.rb +12 -0
- data/test/jump_test.rb +22 -0
- data/test/kill_test.rb +13 -0
- data/test/method_test.rb +36 -0
- data/test/printers/xml_test.rb +193 -0
- data/test/reload_test.rb +14 -0
- data/test/restart_test.rb +50 -0
- data/test/set_test.rb +12 -0
- data/test/stepping_test.rb +15 -0
- data/test/test_helper.rb +6 -0
- data/test/thread_test.rb +20 -0
- data/test/tmate_test.rb +15 -0
- data/test/trace_test.rb +12 -0
- data/test/variables_test.rb +84 -0
- metadata +253 -0
data/lib/debugger/xml.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
module Debugger
|
2
|
+
class Edit < Command
|
3
|
+
|
4
|
+
def execute_with_xml(*args)
|
5
|
+
errmsg(pr("general.errors.unsupported", cmd: 'edit')) && return if Debugger.printer.type == "xml"
|
6
|
+
execute_without_xml(*args)
|
7
|
+
end
|
8
|
+
|
9
|
+
alias_method :execute_without_xml, :execute
|
10
|
+
alias_method :execute, :execute_with_xml
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Debugger
|
2
|
+
module FrameFunctions
|
3
|
+
|
4
|
+
# Mark should be 'true' or 'false', as a String
|
5
|
+
def get_pr_arguments_with_xml(mark, *args)
|
6
|
+
get_pr_arguments_without_xml((!!mark).to_s, *args)
|
7
|
+
end
|
8
|
+
|
9
|
+
alias_method :get_pr_arguments_without_xml, :get_pr_arguments
|
10
|
+
alias_method :get_pr_arguments, :get_pr_arguments_with_xml
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Debugger
|
2
|
+
class HelpCommand < Command
|
3
|
+
|
4
|
+
def execute_with_xml(*args)
|
5
|
+
errmsg(pr("general.errors.unsupported", cmd: 'help')) && return if Debugger.printer.type == "xml"
|
6
|
+
execute_without_xml(*args)
|
7
|
+
end
|
8
|
+
|
9
|
+
alias_method :execute_without_xml, :execute
|
10
|
+
alias_method :execute, :execute_with_xml
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Debugger
|
2
|
+
class InfoCommand < Command
|
3
|
+
|
4
|
+
def execute_with_xml(*args)
|
5
|
+
errmsg(pr("general.errors.unsupported", cmd: 'info')) && return if Debugger.printer.type == "xml"
|
6
|
+
execute_without_xml(*args)
|
7
|
+
end
|
8
|
+
|
9
|
+
alias_method :execute_without_xml, :execute
|
10
|
+
alias_method :execute, :execute_with_xml
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Debugger
|
2
|
+
class IRBCommand < Command
|
3
|
+
|
4
|
+
def execute_with_xml(*args)
|
5
|
+
errmsg(pr("general.errors.unsupported", cmd: 'irb')) && return if Debugger.printer.type == "xml"
|
6
|
+
execute_without_xml(*args)
|
7
|
+
end
|
8
|
+
|
9
|
+
alias_method :execute_without_xml, :execute
|
10
|
+
alias_method :execute, :execute_with_xml
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Debugger
|
2
|
+
class KillCommand < Command
|
3
|
+
|
4
|
+
def execute_with_xml(*args)
|
5
|
+
errmsg(pr("general.errors.unsupported", cmd: 'kill')) && return if Debugger.printer.type == "xml"
|
6
|
+
execute_without_xml(*args)
|
7
|
+
end
|
8
|
+
|
9
|
+
alias_method :execute_without_xml, :execute
|
10
|
+
alias_method :execute, :execute_with_xml
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Debugger
|
2
|
+
class TextMateCommand < Command
|
3
|
+
|
4
|
+
def execute_with_xml(*args)
|
5
|
+
errmsg(pr("general.errors.unsupported", cmd: 'tmate')) && return if Debugger.printer.type == "xml"
|
6
|
+
execute_without_xml(*args)
|
7
|
+
end
|
8
|
+
|
9
|
+
alias_method :execute_without_xml, :execute
|
10
|
+
alias_method :execute, :execute_with_xml
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Debugger
|
2
|
+
class TraceCommand < Command
|
3
|
+
|
4
|
+
def execute_with_xml(*args)
|
5
|
+
errmsg(pr("general.errors.unsupported", cmd: 'trace')) && return if Debugger.printer.type == "xml"
|
6
|
+
execute_without_xml(*args)
|
7
|
+
end
|
8
|
+
|
9
|
+
alias_method :execute_without_xml, :execute
|
10
|
+
alias_method :execute, :execute_with_xml
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Debugger
|
2
|
+
class VarInstanceCommand < Command
|
3
|
+
|
4
|
+
def execute_with_xml(*args)
|
5
|
+
if Debugger.printer.type == "xml"
|
6
|
+
print Debugger.printer.print_instance_variables(get_obj(@match))
|
7
|
+
else
|
8
|
+
execute_without_xml(*args)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
alias_method :execute_without_xml, :execute
|
13
|
+
alias_method :execute, :execute_with_xml
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Debugger
|
2
|
+
class << self
|
3
|
+
attr_accessor :wait_for_start
|
4
|
+
|
5
|
+
def start_remote_ide(host, port)
|
6
|
+
return if @control_thread
|
7
|
+
@mutex = Mutex.new
|
8
|
+
@proceed = ConditionVariable.new
|
9
|
+
start
|
10
|
+
@control_thread = DebugThread.new do
|
11
|
+
server = TCPServer.new(host, port)
|
12
|
+
while (session = server.accept)
|
13
|
+
interface = IdeInterface.new(session)
|
14
|
+
processor = IdeControlCommandProcessor.new(interface)
|
15
|
+
self.handler = IdeProcessor.new(interface)
|
16
|
+
processor.process_commands
|
17
|
+
end
|
18
|
+
end
|
19
|
+
@mutex.synchronize { @proceed.wait(@mutex) } if wait_for_start
|
20
|
+
end
|
21
|
+
|
22
|
+
def proceed
|
23
|
+
return unless @mutex
|
24
|
+
@mutex.synchronize { @proceed.signal }
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
require 'ruby-debug/processor'
|
2
|
+
|
3
|
+
module Debugger
|
4
|
+
module Xml
|
5
|
+
|
6
|
+
class IdeProcessor < Processor
|
7
|
+
attr_reader :context, :file, :line, :display
|
8
|
+
def initialize(interface)
|
9
|
+
@mutex = Mutex.new
|
10
|
+
@interface = interface
|
11
|
+
@display = []
|
12
|
+
end
|
13
|
+
|
14
|
+
def at_breakpoint(context, breakpoint)
|
15
|
+
raise "@last_breakpoint supposed to be nil. is #{@last_breakpoint}" if @last_breakpoint
|
16
|
+
# at_breakpoint is immediately followed by #at_line event. So postpone breakpoint printing until #at_line.
|
17
|
+
@last_breakpoint = breakpoint
|
18
|
+
end
|
19
|
+
protect :at_breakpoint
|
20
|
+
|
21
|
+
# TODO: Catching exceptions doesn't work so far, need to fix
|
22
|
+
def at_catchpoint(context, excpt)
|
23
|
+
end
|
24
|
+
|
25
|
+
# We don't have tracing for IDE
|
26
|
+
def at_tracing(*args)
|
27
|
+
end
|
28
|
+
|
29
|
+
def at_line(context, file, line)
|
30
|
+
if context.nil? || context.stop_reason == :step
|
31
|
+
print_file_line(context, file, line)
|
32
|
+
end
|
33
|
+
line_event(context, file, line)
|
34
|
+
end
|
35
|
+
protect :at_line
|
36
|
+
|
37
|
+
def at_return(context, file, line)
|
38
|
+
print_file_line(context, file, line)
|
39
|
+
context.stop_frame = -1
|
40
|
+
line_event(context, file, line)
|
41
|
+
end
|
42
|
+
|
43
|
+
def at_line?
|
44
|
+
!!@line
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def print_file_line(context, file, line)
|
50
|
+
print(
|
51
|
+
Debugger.printer.print(
|
52
|
+
"stop.suspend",
|
53
|
+
file: CommandProcessor.canonic_file(file), line_number: line, line: Debugger.line_at(file, line),
|
54
|
+
thnum: context && context.thnum, frames: context && context.stack_size
|
55
|
+
)
|
56
|
+
)
|
57
|
+
end
|
58
|
+
|
59
|
+
def line_event(context, file, line)
|
60
|
+
@line = line
|
61
|
+
@file = file
|
62
|
+
@context = context
|
63
|
+
if @last_breakpoint
|
64
|
+
# followed after #at_breakpoint in the same thread. Print breakpoint
|
65
|
+
# now when @line, @file and @context are correctly set to prevent race
|
66
|
+
# condition with `control thread'.
|
67
|
+
n = Debugger.breakpoints.index(@last_breakpoint) + 1
|
68
|
+
print pr("breakpoints.stop_at_breakpoint",
|
69
|
+
id: n, file: @file, line: @line, thread_id: Debugger.current_context.thnum
|
70
|
+
)
|
71
|
+
end
|
72
|
+
if @context && @context.thread.is_a?(Debugger::DebugThread)
|
73
|
+
raise pr("thread.errors.debug_trace", thread: @context.thread)
|
74
|
+
end
|
75
|
+
# will be resumed by commands like `step', `next', `continue', `finish'
|
76
|
+
# from `control thread'
|
77
|
+
Thread.stop
|
78
|
+
ensure
|
79
|
+
@line = nil
|
80
|
+
@file = nil
|
81
|
+
@context = nil
|
82
|
+
@last_breakpoint = nil
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
class IdeControlCommandProcessor < Processor
|
87
|
+
|
88
|
+
def initialize(interface)
|
89
|
+
@interface = interface
|
90
|
+
end
|
91
|
+
|
92
|
+
def process_commands
|
93
|
+
control_command_classes = Command.commands.select(&:allow_in_control)
|
94
|
+
state = ControlCommandProcessor::State.new(@interface, control_command_classes)
|
95
|
+
control_commands = control_command_classes.map { |cmd| cmd.new(state) }
|
96
|
+
|
97
|
+
while input = @interface.read_command
|
98
|
+
split_commands(input).each do |cmd|
|
99
|
+
catch(:debug_error) do
|
100
|
+
if matched_cmd = control_commands.find { |c| c.match(cmd) }
|
101
|
+
matched_cmd.execute
|
102
|
+
else
|
103
|
+
process_context_commands(cmd)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
rescue IOError, Errno::EPIPE
|
109
|
+
rescue Exception
|
110
|
+
print "INTERNAL ERROR!!! #{$!}\n" rescue nil
|
111
|
+
print $!.backtrace.map{|l| "\t#{l}"}.join("\n") rescue nil
|
112
|
+
ensure
|
113
|
+
@interface.close
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
|
118
|
+
def process_context_commands(input)
|
119
|
+
unless Debugger.handler.at_line?
|
120
|
+
errmsg pr("base.errors.no_suspended_thread", input: input)
|
121
|
+
return
|
122
|
+
end
|
123
|
+
event_command_classes = Command.commands.select(&:event)
|
124
|
+
state = CommandProcessor::State.new do |s|
|
125
|
+
s.context = Debugger.handler.context
|
126
|
+
s.file = Debugger.handler.file
|
127
|
+
s.line = Debugger.handler.line
|
128
|
+
s.binding = Debugger.handler.context.frame_binding(0)
|
129
|
+
s.interface = @interface
|
130
|
+
s.commands = event_command_classes
|
131
|
+
end
|
132
|
+
event_commands = event_command_classes.map { |cls| cls.new(state) }
|
133
|
+
catch(:debug_error) do
|
134
|
+
if cmd = event_commands.find { |c| c.match(input) }
|
135
|
+
if state.context.dead? && cmd.class.need_context
|
136
|
+
print pr("base.errors.command_unavailable")
|
137
|
+
else
|
138
|
+
cmd.execute
|
139
|
+
end
|
140
|
+
else
|
141
|
+
print pr("base.errors.unknown_command", input: input)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
state.context.thread.run if state.proceed?
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
end
|
149
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module Debugger
|
2
|
+
module Xml
|
3
|
+
class IdeInterface < Interface # :nodoc:
|
4
|
+
attr_accessor :command_queue
|
5
|
+
attr_accessor :histfile
|
6
|
+
attr_accessor :history_save
|
7
|
+
attr_accessor :history_length
|
8
|
+
attr_accessor :restart_file
|
9
|
+
|
10
|
+
def initialize(socket)
|
11
|
+
@command_queue = []
|
12
|
+
@socket = socket
|
13
|
+
@history_save = false
|
14
|
+
@history_length = 256
|
15
|
+
@histfile = ''
|
16
|
+
@restart_file = nil
|
17
|
+
end
|
18
|
+
|
19
|
+
def close
|
20
|
+
@socket.close
|
21
|
+
rescue Exception
|
22
|
+
end
|
23
|
+
|
24
|
+
def print_debug(msg)
|
25
|
+
STDOUT.puts(msg)
|
26
|
+
end
|
27
|
+
|
28
|
+
def errmsg(*args)
|
29
|
+
print(*args)
|
30
|
+
end
|
31
|
+
|
32
|
+
def confirm(prompt)
|
33
|
+
true
|
34
|
+
end
|
35
|
+
|
36
|
+
def finalize
|
37
|
+
close
|
38
|
+
end
|
39
|
+
|
40
|
+
# Workaround for JRuby issue http://jira.codehaus.org/browse/JRUBY-2063
|
41
|
+
def non_blocking_gets
|
42
|
+
loop do
|
43
|
+
result, _, _ = IO.select([@socket], nil, nil, 0.2)
|
44
|
+
next unless result
|
45
|
+
return result[0].gets
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def read_command(*args)
|
50
|
+
result = non_blocking_gets
|
51
|
+
raise IOError unless result
|
52
|
+
result.chomp
|
53
|
+
end
|
54
|
+
|
55
|
+
def readline_support?
|
56
|
+
false
|
57
|
+
end
|
58
|
+
|
59
|
+
def print(*args)
|
60
|
+
@socket.printf(*escape_input(args))
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,190 @@
|
|
1
|
+
require_relative 'test_helper'
|
2
|
+
|
3
|
+
describe "Breakpoints" do
|
4
|
+
include TestDsl
|
5
|
+
temporary_change_method_value(Debugger, :printer, Printers::Xml.new)
|
6
|
+
|
7
|
+
describe "setting breakpoint in the current file" do
|
8
|
+
it "must return right response" do
|
9
|
+
enter 'break 10'
|
10
|
+
id = nil
|
11
|
+
debug_file('breakpoint1') { id = breakpoint.id }
|
12
|
+
check_output_includes "<breakpointAdded no=\"#{id}\" location=\"#{fullpath('breakpoint1')}:10\"/>"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "setting breakpoint to unexisted line" do
|
17
|
+
it "must show an error" do
|
18
|
+
enter 'break 100'
|
19
|
+
debug_file("breakpoint1")
|
20
|
+
check_output_includes "<error>There are only 15 lines in file 'breakpoint1.rb'</error>", interface.error_queue
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
describe "shows a message when stopping at breakpoint" do
|
26
|
+
temporary_change_hash_value(Debugger::Command.settings, :basename, false)
|
27
|
+
|
28
|
+
it "must show a message with full filename" do
|
29
|
+
enter 'break 14', 'cont'
|
30
|
+
debug_file("breakpoint1")
|
31
|
+
check_output_includes "<breakpoint file=\"#{fullpath('breakpoint1')}\" line=\"14\" threadId=\"1\"/>"
|
32
|
+
end
|
33
|
+
|
34
|
+
it "must show a message with basename" do
|
35
|
+
enter 'set basename', 'break 14', 'cont'
|
36
|
+
debug_file("breakpoint1")
|
37
|
+
check_output_includes "<breakpoint file=\"breakpoint1.rb\" line=\"14\" threadId=\"1\"/>"
|
38
|
+
end
|
39
|
+
|
40
|
+
it "must not show <suspended>" do
|
41
|
+
enter 'break 14', 'cont'
|
42
|
+
debug_file("breakpoint1")
|
43
|
+
check_output_doesnt_include /<suspended[^>]+line="14"/
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "set breakpoint in a file when setting breakpoint to unexisted file" do
|
48
|
+
before do
|
49
|
+
enter "break asf:324"
|
50
|
+
debug_file("breakpoint1")
|
51
|
+
end
|
52
|
+
|
53
|
+
it "must show an error" do
|
54
|
+
check_output_includes "<error>No source file named asf</error>", interface.error_queue
|
55
|
+
end
|
56
|
+
|
57
|
+
it "must ask about setting breakpoint anyway" do
|
58
|
+
check_output_includes "<confirmation>Set breakpoint anyway?</confirmation>", interface.confirm_queue
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "set breakpoint to a method" do
|
63
|
+
describe "set breakpoint to an instance method" do
|
64
|
+
it "must output show in xml" do
|
65
|
+
enter 'break A#b', 'cont'
|
66
|
+
id = nil
|
67
|
+
debug_file("breakpoint1") { id = breakpoint.id }
|
68
|
+
check_output_includes "<breakpointAdded no=\"#{id}\" method=\"A::b\"/>"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "set breakpoint to unexisted class" do
|
73
|
+
it "must show an error" do
|
74
|
+
enter "break B.a"
|
75
|
+
debug_file("breakpoint1")
|
76
|
+
check_output_includes "<error>Unknown class B</error>", interface.error_queue
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe "set breakpoint to an invalid location" do
|
82
|
+
it "must show an error" do
|
83
|
+
enter "break foo"
|
84
|
+
debug_file("breakpoint1")
|
85
|
+
check_output_includes '<error>Invalid breakpoint location: foo</error>', interface.error_queue
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
describe "disabling a breakpoint" do
|
91
|
+
it "must show success message" do
|
92
|
+
enter "break 14", ->{"disable #{breakpoint.id}"}, "break 15"
|
93
|
+
id = nil
|
94
|
+
debug_file("breakpoint1") { id = breakpoint.id }
|
95
|
+
check_output_includes "<breakpointDisabled bp_id=\"#{id}\"/>"
|
96
|
+
end
|
97
|
+
|
98
|
+
describe "errors" do
|
99
|
+
it "must show an error if syntax is incorrect" do
|
100
|
+
enter "disable"
|
101
|
+
debug_file("breakpoint1")
|
102
|
+
check_output_includes(
|
103
|
+
"<error>'disable' must be followed 'display', 'breakpoints' or breakpoint numbers</error>",
|
104
|
+
interface.error_queue
|
105
|
+
)
|
106
|
+
end
|
107
|
+
|
108
|
+
it "must show an error if no breakpoints is set" do
|
109
|
+
enter "disable 1"
|
110
|
+
debug_file("breakpoint1")
|
111
|
+
check_output_includes '<error>No breakpoints have been set</error>', interface.error_queue
|
112
|
+
end
|
113
|
+
|
114
|
+
it "must show an error if not a number is provided as an argument to 'disable' command" do
|
115
|
+
enter "break 14", "disable foo"
|
116
|
+
debug_file("breakpoint1")
|
117
|
+
check_output_includes "<error>Disable breakpoints argument 'foo' needs to be a number</error>"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
describe "enabling a breakpoint" do
|
123
|
+
it "must show success message" do
|
124
|
+
enter "break 14", ->{"enable #{breakpoint.id}"}, "break 15"
|
125
|
+
id = nil
|
126
|
+
debug_file("breakpoint1") { id = breakpoint.id }
|
127
|
+
check_output_includes "<breakpointEnabled bp_id=\"#{id}\"/>"
|
128
|
+
end
|
129
|
+
|
130
|
+
it "must show an error if syntax is incorrect" do
|
131
|
+
enter "enable"
|
132
|
+
debug_file("breakpoint1")
|
133
|
+
check_output_includes(
|
134
|
+
"<error>'enable' must be followed 'display', 'breakpoints' or breakpoint numbers</error>",
|
135
|
+
interface.error_queue
|
136
|
+
)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
describe "deleting a breakpoint" do
|
141
|
+
it "must show a success message" do
|
142
|
+
breakpoint_id = nil
|
143
|
+
enter "break 14", ->{breakpoint_id = breakpoint.id; "delete #{breakpoint_id}"}, "break 15"
|
144
|
+
debug_file("breakpoint1")
|
145
|
+
check_output_includes "<breakpointDeleted no=\"#{breakpoint_id}\"/>"
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
describe "Conditional breakpoints" do
|
150
|
+
it "must show an error when conditional syntax is wrong" do
|
151
|
+
enter "break 14 ifa b == 3", "break 15", "cont"
|
152
|
+
debug_file("breakpoint1") { state.line.must_equal 15 }
|
153
|
+
check_output_includes(
|
154
|
+
"<error>Expecting 'if' in breakpoint condition; got: ifa b == 3</error>",
|
155
|
+
interface.error_queue
|
156
|
+
)
|
157
|
+
end
|
158
|
+
|
159
|
+
describe "enabling with wrong conditional syntax" do
|
160
|
+
it "must show an error" do
|
161
|
+
enter(
|
162
|
+
"break 14",
|
163
|
+
->{"disable #{breakpoint.id}"},
|
164
|
+
->{"cond #{breakpoint.id} b -=( 3"},
|
165
|
+
->{"enable #{breakpoint.id}"}
|
166
|
+
)
|
167
|
+
debug_file("breakpoint1")
|
168
|
+
check_output_includes(
|
169
|
+
"<error>Expression 'b -=( 3' syntactically incorrect; breakpoint remains disabled</error>",
|
170
|
+
interface.error_queue
|
171
|
+
)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
it "must show an error if no file or line is specified" do
|
176
|
+
enter "break ifa b == 3", "break 15", "cont"
|
177
|
+
debug_file("breakpoint1") { state.line.must_equal 15 }
|
178
|
+
check_output_includes "<error>Invalid breakpoint location: ifa b == 3</error>", interface.error_queue
|
179
|
+
end
|
180
|
+
|
181
|
+
it "must show an error if expression syntax is invalid" do
|
182
|
+
enter "break if b -=) 3", "break 15", "cont"
|
183
|
+
debug_file("breakpoint1") { state.line.must_equal 15 }
|
184
|
+
check_output_includes(
|
185
|
+
"<error>Expression 'b -=) 3' syntactically incorrect; breakpoint disabled</error>",
|
186
|
+
interface.error_queue
|
187
|
+
)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|