debugger-xml 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|