byebug 2.3.1 → 2.4.0
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.
- 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
|