byebug 2.3.1 → 2.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -0
- data/README.md +3 -11
- data/Rakefile +10 -3
- data/bin/byebug +16 -2
- data/byebug.gemspec +1 -0
- data/ext/byebug/byebug.c +0 -54
- data/ext/byebug/byebug.h +3 -4
- data/ext/byebug/extconf.rb +1 -1
- data/lib/byebug.rb +15 -42
- data/lib/byebug/command.rb +12 -28
- data/lib/byebug/commands/breakpoints.rb +2 -0
- data/lib/byebug/commands/catchpoint.rb +1 -1
- data/lib/byebug/commands/condition.rb +1 -0
- data/lib/byebug/commands/display.rb +6 -0
- data/lib/byebug/commands/frame.rb +10 -3
- data/lib/byebug/commands/info.rb +5 -3
- data/lib/byebug/commands/reload.rb +1 -0
- data/lib/byebug/commands/set.rb +5 -1
- data/lib/byebug/commands/threads.rb +5 -4
- data/lib/byebug/commands/trace.rb +5 -5
- data/lib/byebug/context.rb +3 -3
- data/lib/byebug/interface.rb +3 -187
- data/lib/byebug/interfaces/local_interface.rb +88 -0
- data/lib/byebug/interfaces/remote_interface.rb +55 -0
- data/lib/byebug/interfaces/script_interface.rb +45 -0
- data/lib/byebug/processor.rb +15 -13
- data/lib/byebug/version.rb +1 -1
- data/test/breakpoints_test.rb +23 -25
- data/test/conditions_test.rb +6 -8
- data/test/continue_test.rb +4 -6
- data/test/debugger_alias_test.rb +5 -0
- data/test/display_test.rb +9 -11
- data/test/edit_test.rb +0 -2
- data/test/eval_test.rb +1 -3
- data/test/finish_test.rb +12 -12
- data/test/frame_test.rb +38 -40
- data/test/help_test.rb +1 -3
- data/test/info_test.rb +12 -14
- data/test/kill_test.rb +0 -2
- data/test/list_test.rb +1 -3
- data/test/method_test.rb +0 -2
- data/test/post_mortem_test.rb +77 -96
- data/test/quit_test.rb +0 -2
- data/test/reload_test.rb +0 -2
- data/test/repl_test.rb +3 -5
- data/test/restart_test.rb +0 -2
- data/test/save_test.rb +1 -3
- data/test/set_test.rb +3 -5
- data/test/show_test.rb +0 -2
- data/test/source_test.rb +0 -2
- data/test/stepping_test.rb +17 -19
- data/test/support/test_dsl.rb +21 -13
- data/test/test_helper.rb +23 -1
- data/test/thread_test.rb +19 -21
- data/test/trace_test.rb +12 -14
- data/test/variables_test.rb +6 -6
- metadata +22 -3
@@ -0,0 +1,45 @@
|
|
1
|
+
module Byebug
|
2
|
+
class ScriptInterface < Interface
|
3
|
+
attr_accessor :command_queue, :history_length, :history_save, :histfile
|
4
|
+
attr_accessor :restart_file
|
5
|
+
|
6
|
+
def initialize(file, out, verbose=false)
|
7
|
+
super()
|
8
|
+
@command_queue = []
|
9
|
+
@file = file.respond_to?(:gets) ? file : open(file)
|
10
|
+
@out = out
|
11
|
+
@verbose = verbose
|
12
|
+
@history_save = false
|
13
|
+
@history_length = 256
|
14
|
+
@histfile = ''
|
15
|
+
end
|
16
|
+
|
17
|
+
def finalize
|
18
|
+
end
|
19
|
+
|
20
|
+
def read_command(prompt)
|
21
|
+
while result = @file.gets
|
22
|
+
puts "# #{result}" if @verbose
|
23
|
+
next if result =~ /^\s*#/
|
24
|
+
next if result.strip.empty?
|
25
|
+
return result.chomp
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def readline_support?
|
30
|
+
false
|
31
|
+
end
|
32
|
+
|
33
|
+
def confirm(prompt)
|
34
|
+
'y'
|
35
|
+
end
|
36
|
+
|
37
|
+
def print(*args)
|
38
|
+
@out.printf(*args)
|
39
|
+
end
|
40
|
+
|
41
|
+
def close
|
42
|
+
@file.close
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/byebug/processor.rb
CHANGED
@@ -58,7 +58,7 @@ module Byebug
|
|
58
58
|
|
59
59
|
def self.protect(mname)
|
60
60
|
alias_method "__#{mname}", mname
|
61
|
-
module_eval
|
61
|
+
module_eval <<-END, __FILE__, __LINE__+1
|
62
62
|
def #{mname}(*args)
|
63
63
|
@mutex.synchronize do
|
64
64
|
return unless @interface
|
@@ -72,7 +72,7 @@ module Byebug
|
|
72
72
|
print "INTERNAL ERROR!!! #\{$!\}\n" rescue nil
|
73
73
|
print $!.backtrace.map{|l| "\t#\{l\}"}.join("\n") rescue nil
|
74
74
|
end
|
75
|
-
|
75
|
+
END
|
76
76
|
end
|
77
77
|
|
78
78
|
def at_breakpoint(context, breakpoint)
|
@@ -87,7 +87,6 @@ module Byebug
|
|
87
87
|
file = CommandProcessor.canonic_file(context.frame_file(0))
|
88
88
|
line = context.frame_line(0)
|
89
89
|
print "Catchpoint at %s:%d: `%s' (%s)\n", file, line, excpt, excpt.class
|
90
|
-
print_backtrace
|
91
90
|
end
|
92
91
|
protect :at_catchpoint
|
93
92
|
|
@@ -129,24 +128,22 @@ module Byebug
|
|
129
128
|
# @return List of commands acceptable to run bound to the current state
|
130
129
|
#
|
131
130
|
def always_run(context, file, line, run_level)
|
132
|
-
|
131
|
+
cmds = Command.commands
|
133
132
|
|
134
133
|
# Remove some commands in post-mortem
|
135
|
-
|
136
|
-
cmd.allow_in_post_mortem
|
137
|
-
end if context.dead?
|
134
|
+
cmds = cmds.find_all { |cmd| cmd.allow_in_post_mortem } if context.dead?
|
138
135
|
|
139
|
-
state = State.new(
|
136
|
+
state = State.new(cmds, context, @display, file, @interface, line)
|
140
137
|
|
141
138
|
# Change default when in irb or code included in command line
|
142
139
|
Command.settings[:autolist] = 0 if ['(irb)', '-e'].include?(file)
|
143
140
|
|
144
141
|
# Bind commands to the current state.
|
145
|
-
commands =
|
142
|
+
commands = cmds.map { |cmd| cmd.new(state) }
|
143
|
+
|
144
|
+
commands.select { |cmd| cmd.class.always_run >= run_level }
|
145
|
+
.each { |cmd| cmd.execute }
|
146
146
|
|
147
|
-
commands.select do |cmd|
|
148
|
-
cmd.class.always_run >= run_level
|
149
|
-
end.each {|cmd| cmd.execute}
|
150
147
|
return state, commands
|
151
148
|
end
|
152
149
|
|
@@ -175,7 +172,12 @@ module Byebug
|
|
175
172
|
#
|
176
173
|
def process_commands(context, file, line)
|
177
174
|
state, commands = always_run(context, file, line, 1)
|
178
|
-
|
175
|
+
|
176
|
+
if Command.settings[:testing]
|
177
|
+
Thread.current.thread_variable_set('state', state)
|
178
|
+
else
|
179
|
+
Thread.current.thread_variable_set('state', nil)
|
180
|
+
end
|
179
181
|
|
180
182
|
preloop(commands, context)
|
181
183
|
print state.location if Command.settings[:autolist] == 0
|
data/lib/byebug/version.rb
CHANGED
data/test/breakpoints_test.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require_relative 'test_helper'
|
2
|
-
|
3
1
|
class BreakpointExample
|
4
2
|
def self.a(num)
|
5
3
|
4
|
@@ -93,12 +91,12 @@ class TestBreakpoints < TestDsl::TestCase
|
|
93
91
|
describe 'stopping at breakpoint' do
|
94
92
|
it 'must stop at the correct line' do
|
95
93
|
enter 'break 5', 'cont'
|
96
|
-
debug_file('breakpoint') {
|
94
|
+
debug_file('breakpoint') { state.line.must_equal 5 }
|
97
95
|
end
|
98
96
|
|
99
97
|
it 'must stop at the correct file' do
|
100
98
|
enter 'break 5', 'cont'
|
101
|
-
debug_file('breakpoint') {
|
99
|
+
debug_file('breakpoint') { state.file.must_equal @tst_file }
|
102
100
|
end
|
103
101
|
|
104
102
|
describe 'show a message' do
|
@@ -151,14 +149,14 @@ class TestBreakpoints < TestDsl::TestCase
|
|
151
149
|
|
152
150
|
describe 'set breakpoint in a file' do
|
153
151
|
describe 'successfully' do
|
154
|
-
before { enter "break #{__FILE__}:
|
152
|
+
before { enter "break #{__FILE__}:3", 'cont' }
|
155
153
|
|
156
154
|
it 'must stop at the correct line' do
|
157
|
-
debug_file('breakpoint') {
|
155
|
+
debug_file('breakpoint') { state.line.must_equal 3 }
|
158
156
|
end
|
159
157
|
|
160
158
|
it 'must stop at the correct file' do
|
161
|
-
debug_file('breakpoint') {
|
159
|
+
debug_file('breakpoint') { state.file.must_equal __FILE__ }
|
162
160
|
end
|
163
161
|
end
|
164
162
|
|
@@ -184,11 +182,11 @@ class TestBreakpoints < TestDsl::TestCase
|
|
184
182
|
before { enter 'break BreakpointExample#b', 'cont' }
|
185
183
|
|
186
184
|
it 'must stop at the correct line' do
|
187
|
-
debug_file('breakpoint') {
|
185
|
+
debug_file('breakpoint') { state.line.must_equal 5 }
|
188
186
|
end
|
189
187
|
|
190
188
|
it 'must stop at the correct file' do
|
191
|
-
debug_file('breakpoint') {
|
189
|
+
debug_file('breakpoint') { state.file.must_equal __FILE__ }
|
192
190
|
end
|
193
191
|
end
|
194
192
|
|
@@ -196,11 +194,11 @@ class TestBreakpoints < TestDsl::TestCase
|
|
196
194
|
before { enter 'break BreakpointExample.a', 'cont' }
|
197
195
|
|
198
196
|
it 'must stop at the correct line' do
|
199
|
-
debug_file('breakpoint') {
|
197
|
+
debug_file('breakpoint') { state.line.must_equal 2 }
|
200
198
|
end
|
201
199
|
|
202
200
|
it 'must stop at the correct file' do
|
203
|
-
debug_file('breakpoint') {
|
201
|
+
debug_file('breakpoint') { state.file.must_equal __FILE__ }
|
204
202
|
end
|
205
203
|
end
|
206
204
|
|
@@ -240,7 +238,7 @@ class TestBreakpoints < TestDsl::TestCase
|
|
240
238
|
|
241
239
|
it 'must not stop on the disabled breakpoint' do
|
242
240
|
enter 'cont'
|
243
|
-
debug_file('breakpoint') {
|
241
|
+
debug_file('breakpoint') { state.line.must_equal 6 }
|
244
242
|
end
|
245
243
|
end
|
246
244
|
|
@@ -259,7 +257,7 @@ class TestBreakpoints < TestDsl::TestCase
|
|
259
257
|
enter 'cont'
|
260
258
|
debug_file('breakpoint')
|
261
259
|
# Obscure assert to check for program termination
|
262
|
-
|
260
|
+
state.proceed.must_equal true
|
263
261
|
end
|
264
262
|
end
|
265
263
|
|
@@ -313,7 +311,7 @@ class TestBreakpoints < TestDsl::TestCase
|
|
313
311
|
|
314
312
|
it 'must stop on the enabled breakpoint' do
|
315
313
|
enter 'cont'
|
316
|
-
debug_file('breakpoint') {
|
314
|
+
debug_file('breakpoint') { state.line.must_equal 5 }
|
317
315
|
end
|
318
316
|
end
|
319
317
|
|
@@ -330,12 +328,12 @@ class TestBreakpoints < TestDsl::TestCase
|
|
330
328
|
|
331
329
|
it 'must stop on the first breakpoint' do
|
332
330
|
enter 'cont'
|
333
|
-
debug_file('breakpoint') {
|
331
|
+
debug_file('breakpoint') { state.line.must_equal 5 }
|
334
332
|
end
|
335
333
|
|
336
334
|
it 'must stop on the last breakpoint' do
|
337
335
|
enter 'cont', 'cont'
|
338
|
-
debug_file('breakpoint') {
|
336
|
+
debug_file('breakpoint') { state.line.must_equal 6 }
|
339
337
|
end
|
340
338
|
end
|
341
339
|
|
@@ -351,7 +349,7 @@ class TestBreakpoints < TestDsl::TestCase
|
|
351
349
|
|
352
350
|
it 'must stop only on the enabled breakpoint' do
|
353
351
|
enter 'cont'
|
354
|
-
debug_file('breakpoint') {
|
352
|
+
debug_file('breakpoint') { state.line.must_equal 6 }
|
355
353
|
end
|
356
354
|
end
|
357
355
|
end
|
@@ -377,24 +375,24 @@ class TestBreakpoints < TestDsl::TestCase
|
|
377
375
|
|
378
376
|
it 'must not stop on the disabled breakpoint' do
|
379
377
|
enter 'cont'
|
380
|
-
debug_file('breakpoint') {
|
378
|
+
debug_file('breakpoint') { state.line.must_equal 6 }
|
381
379
|
end
|
382
380
|
end
|
383
381
|
|
384
382
|
describe 'Conditional breakpoints' do
|
385
383
|
it 'must stop if the condition is true' do
|
386
384
|
enter 'break 5 if z == 5', 'break 6', 'cont'
|
387
|
-
debug_file('breakpoint') {
|
385
|
+
debug_file('breakpoint') { state.line.must_equal 5 }
|
388
386
|
end
|
389
387
|
|
390
388
|
it 'must skip if the condition is false' do
|
391
389
|
enter 'break 5 if z == 3', 'break 6', 'cont'
|
392
|
-
debug_file('breakpoint') {
|
390
|
+
debug_file('breakpoint') { state.line.must_equal 6 }
|
393
391
|
end
|
394
392
|
|
395
393
|
it 'must show an error when conditional syntax is wrong' do
|
396
394
|
enter 'break 5 ifa z == 3', 'break 6', 'cont'
|
397
|
-
debug_file('breakpoint') {
|
395
|
+
debug_file('breakpoint') { state.line.must_equal 6 }
|
398
396
|
check_error_includes \
|
399
397
|
'Expecting "if" in breakpoint condition; got: ifa z == 3.'
|
400
398
|
end
|
@@ -419,13 +417,13 @@ class TestBreakpoints < TestDsl::TestCase
|
|
419
417
|
|
420
418
|
it 'must show an error if no file or line is specified' do
|
421
419
|
enter 'break ifa z == 3', 'break 6', 'cont'
|
422
|
-
debug_file('breakpoint') {
|
420
|
+
debug_file('breakpoint') { state.line.must_equal 6 }
|
423
421
|
check_error_includes 'Invalid breakpoint location: ifa z == 3.'
|
424
422
|
end
|
425
423
|
|
426
424
|
it 'must show an error if expression syntax is invalid' do
|
427
425
|
enter 'break if z -=) 3', 'break 6', 'cont'
|
428
|
-
debug_file('breakpoint') {
|
426
|
+
debug_file('breakpoint') { state.line.must_equal 6 }
|
429
427
|
check_error_includes \
|
430
428
|
'Expression "z -=) 3" syntactically incorrect; breakpoint disabled.'
|
431
429
|
end
|
@@ -434,13 +432,13 @@ class TestBreakpoints < TestDsl::TestCase
|
|
434
432
|
describe 'Stopping through `byebug` keyword' do
|
435
433
|
describe 'when not the last instruction of a method' do
|
436
434
|
it 'must stop in the next line' do
|
437
|
-
debug_file('breakpoint') {
|
435
|
+
debug_file('breakpoint') { state.line.must_equal 4 }
|
438
436
|
end
|
439
437
|
end
|
440
438
|
|
441
439
|
describe 'when last instruction of a method' do
|
442
440
|
it 'must stop right before returning from the frame' do
|
443
|
-
debug_file('breakpoint_deep') {
|
441
|
+
debug_file('breakpoint_deep') { state.line.must_equal 25 }
|
444
442
|
end
|
445
443
|
end
|
446
444
|
end
|
data/test/conditions_test.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require_relative 'test_helper'
|
2
|
-
|
3
1
|
class TestConditions < TestDsl::TestCase
|
4
2
|
|
5
3
|
describe 'setting condition' do
|
@@ -14,11 +12,11 @@ class TestConditions < TestDsl::TestCase
|
|
14
12
|
end
|
15
13
|
|
16
14
|
it 'must stop at the breakpoint if condition is true' do
|
17
|
-
debug_file('conditions') {
|
15
|
+
debug_file('conditions') { state.line.must_equal 3 }
|
18
16
|
end
|
19
17
|
|
20
18
|
it 'must work with full command name too' do
|
21
|
-
debug_file('conditions') {
|
19
|
+
debug_file('conditions') { state.line.must_equal 3 }
|
22
20
|
end
|
23
21
|
end
|
24
22
|
|
@@ -27,7 +25,7 @@ class TestConditions < TestDsl::TestCase
|
|
27
25
|
|
28
26
|
it 'must not stop at the breakpoint if condition is false' do
|
29
27
|
enter ->{ "cond #{Byebug.breakpoints.first.id} b == 3" }, 'cont'
|
30
|
-
debug_file('conditions') {
|
28
|
+
debug_file('conditions') { state.line.must_equal 4 }
|
31
29
|
end
|
32
30
|
|
33
31
|
it 'must assign expression to breakpoint in spite of incorrect syntax' do
|
@@ -38,7 +36,7 @@ class TestConditions < TestDsl::TestCase
|
|
38
36
|
|
39
37
|
it 'must ignore the condition if when incorrect syntax' do
|
40
38
|
enter ->{ "cond #{Byebug.breakpoints.first.id} b ==" }, 'cont'
|
41
|
-
debug_file('conditions') {
|
39
|
+
debug_file('conditions') { state.line.must_equal 4 }
|
42
40
|
end
|
43
41
|
end
|
44
42
|
end
|
@@ -52,7 +50,7 @@ class TestConditions < TestDsl::TestCase
|
|
52
50
|
end
|
53
51
|
|
54
52
|
it 'must unconditionally stop on the breakpoint' do
|
55
|
-
debug_file('conditions') {
|
53
|
+
debug_file('conditions') { state.line.must_equal 3 }
|
56
54
|
end
|
57
55
|
end
|
58
56
|
|
@@ -65,7 +63,7 @@ class TestConditions < TestDsl::TestCase
|
|
65
63
|
|
66
64
|
it 'must not set breakpoint condition if breakpoint id is incorrect' do
|
67
65
|
enter 'break 3', 'cond 8 b == 3', 'cont'
|
68
|
-
debug_file('conditions') {
|
66
|
+
debug_file('conditions') { state.line.must_equal 3 }
|
69
67
|
end
|
70
68
|
end
|
71
69
|
end
|
data/test/continue_test.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require_relative 'test_helper'
|
2
|
-
|
3
1
|
class ContinueExample
|
4
2
|
def self.a(num)
|
5
3
|
num + 4
|
@@ -11,24 +9,24 @@ class TestContinue < TestDsl::TestCase
|
|
11
9
|
describe "successful" do
|
12
10
|
it "must continue up to breakpoint if no line specified" do
|
13
11
|
enter 'break 4', 'continue'
|
14
|
-
debug_file('continue') {
|
12
|
+
debug_file('continue') { state.line.must_equal 4 }
|
15
13
|
end
|
16
14
|
|
17
15
|
it "must work in abbreviated mode too" do
|
18
16
|
enter 'break 4', 'cont'
|
19
|
-
debug_file('continue') {
|
17
|
+
debug_file('continue') { state.line.must_equal 4 }
|
20
18
|
end
|
21
19
|
|
22
20
|
it "must continue up to specified line" do
|
23
21
|
enter 'cont 4'
|
24
|
-
debug_file('continue') {
|
22
|
+
debug_file('continue') { state.line.must_equal 4 }
|
25
23
|
end
|
26
24
|
end
|
27
25
|
|
28
26
|
describe "unsuccessful" do
|
29
27
|
it "must ignore the command if specified line is not valid" do
|
30
28
|
enter 'cont 123'
|
31
|
-
debug_file('continue') {
|
29
|
+
debug_file('continue') { state.line.must_equal 3 }
|
32
30
|
end
|
33
31
|
|
34
32
|
it "must show error if specified line is not valid" do
|
data/test/display_test.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require_relative 'test_helper'
|
2
|
-
|
3
1
|
class TestDisplay < TestDsl::TestCase
|
4
2
|
|
5
3
|
it 'must show expressions' do
|
@@ -16,7 +14,7 @@ class TestDisplay < TestDsl::TestCase
|
|
16
14
|
|
17
15
|
it 'must save displayed expressions' do
|
18
16
|
enter 'display d + 1'
|
19
|
-
debug_file('display') {
|
17
|
+
debug_file('display') { state.display.must_equal [[true, 'd + 1']] }
|
20
18
|
end
|
21
19
|
|
22
20
|
it 'displays all expressions available' do
|
@@ -46,8 +44,8 @@ class TestDisplay < TestDsl::TestCase
|
|
46
44
|
end
|
47
45
|
|
48
46
|
it 'must set all expressions saved to "false"' do
|
49
|
-
debug_file('display') {
|
50
|
-
|
47
|
+
debug_file('display') { state.display.must_equal [[false, 'abc'],
|
48
|
+
[false, 'd']] }
|
51
49
|
end
|
52
50
|
|
53
51
|
it 'must not show any output' do
|
@@ -60,8 +58,8 @@ class TestDisplay < TestDsl::TestCase
|
|
60
58
|
let(:confirm_response) { 'n' }
|
61
59
|
|
62
60
|
it 'must set all expressions saved to "false"' do
|
63
|
-
debug_file('display') {
|
64
|
-
|
61
|
+
debug_file('display') { state.display.must_equal [[true, 'abc'],
|
62
|
+
[true, 'd']] }
|
65
63
|
end
|
66
64
|
|
67
65
|
it 'must not show any output' do
|
@@ -80,8 +78,8 @@ class TestDisplay < TestDsl::TestCase
|
|
80
78
|
end
|
81
79
|
|
82
80
|
it 'must set inactive positions' do
|
83
|
-
debug_file('display') {
|
84
|
-
|
81
|
+
debug_file('display') { state.display.must_equal [[nil, 'abc'],
|
82
|
+
[true, 'd']] }
|
85
83
|
end
|
86
84
|
|
87
85
|
it 'must display only the active position' do
|
@@ -99,7 +97,7 @@ class TestDisplay < TestDsl::TestCase
|
|
99
97
|
describe 'disable' do
|
100
98
|
it 'must disable a position' do
|
101
99
|
enter 'display d', 'disable display 1'
|
102
|
-
debug_file('display') {
|
100
|
+
debug_file('display') { state.display.must_equal [[false, 'd']] }
|
103
101
|
end
|
104
102
|
|
105
103
|
it 'must show an error if no displays are set' do
|
@@ -120,7 +118,7 @@ class TestDisplay < TestDsl::TestCase
|
|
120
118
|
describe 'enable' do
|
121
119
|
it 'must enable a position' do
|
122
120
|
enter 'display d', 'disable display 1', 'enable display 1'
|
123
|
-
debug_file('display') {
|
121
|
+
debug_file('display') { state.display.must_equal [[true, 'd']] }
|
124
122
|
end
|
125
123
|
end
|
126
124
|
end
|