byebug 3.0.0 → 3.1.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.
Files changed (125) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +15 -0
  3. data/GUIDE.md +2 -2
  4. data/LICENSE +3 -3
  5. data/README.md +5 -4
  6. data/byebug.gemspec +1 -1
  7. data/ext/byebug/byebug.c +20 -19
  8. data/lib/byebug.rb +2 -53
  9. data/lib/byebug/command.rb +9 -109
  10. data/lib/byebug/commands/breakpoints.rb +1 -1
  11. data/lib/byebug/commands/control.rb +20 -21
  12. data/lib/byebug/commands/display.rb +2 -3
  13. data/lib/byebug/commands/eval.rb +6 -16
  14. data/lib/byebug/commands/finish.rb +1 -1
  15. data/lib/byebug/commands/frame.rb +9 -9
  16. data/lib/byebug/commands/help.rb +2 -3
  17. data/lib/byebug/commands/history.rb +28 -0
  18. data/lib/byebug/commands/info.rb +3 -3
  19. data/lib/byebug/commands/list.rb +2 -13
  20. data/lib/byebug/commands/method.rb +5 -45
  21. data/lib/byebug/commands/reload.rb +1 -12
  22. data/lib/byebug/commands/repl.rb +6 -15
  23. data/lib/byebug/commands/save.rb +2 -7
  24. data/lib/byebug/commands/set.rb +45 -116
  25. data/lib/byebug/commands/show.rb +22 -126
  26. data/lib/byebug/commands/stepping.rb +1 -1
  27. data/lib/byebug/commands/trace.rb +14 -25
  28. data/lib/byebug/commands/variables.rb +3 -41
  29. data/lib/byebug/helper.rb +11 -42
  30. data/lib/byebug/history.rb +5 -13
  31. data/lib/byebug/processors/command_processor.rb +6 -6
  32. data/lib/byebug/setting.rb +82 -0
  33. data/lib/byebug/settings/autoeval.rb +20 -0
  34. data/lib/byebug/settings/autoirb.rb +19 -0
  35. data/lib/byebug/settings/autolist.rb +19 -0
  36. data/lib/byebug/settings/autoreload.rb +11 -0
  37. data/lib/byebug/settings/autosave.rb +11 -0
  38. data/lib/byebug/settings/basename.rb +7 -0
  39. data/lib/byebug/settings/callstyle.rb +15 -0
  40. data/lib/byebug/settings/forcestep.rb +11 -0
  41. data/lib/byebug/settings/fullpath.rb +11 -0
  42. data/lib/byebug/settings/histfile.rb +16 -0
  43. data/lib/byebug/settings/histsize.rb +18 -0
  44. data/lib/byebug/settings/linetrace.rb +15 -0
  45. data/lib/byebug/settings/listsize.rb +15 -0
  46. data/lib/byebug/settings/post_mortem.rb +15 -0
  47. data/lib/byebug/settings/stack_on_error.rb +7 -0
  48. data/lib/byebug/settings/testing.rb +7 -0
  49. data/lib/byebug/settings/tracing_plus.rb +7 -0
  50. data/lib/byebug/settings/verbose.rb +7 -0
  51. data/lib/byebug/settings/width.rb +29 -0
  52. data/lib/byebug/version.rb +1 -1
  53. data/test/breakpoints_test.rb +345 -324
  54. data/test/conditions_test.rb +61 -48
  55. data/test/continue_test.rb +38 -27
  56. data/test/debugger_alias_test.rb +5 -3
  57. data/test/display_test.rb +103 -92
  58. data/test/edit_test.rb +42 -34
  59. data/test/eval_test.rb +91 -75
  60. data/test/finish_test.rb +51 -40
  61. data/test/frame_test.rb +197 -184
  62. data/test/help_test.rb +47 -38
  63. data/test/history_test.rb +54 -0
  64. data/test/info_test.rb +306 -293
  65. data/test/interrupt_test.rb +44 -38
  66. data/test/kill_test.rb +40 -31
  67. data/test/list_test.rb +166 -133
  68. data/test/method_test.rb +67 -60
  69. data/test/post_mortem_test.rb +56 -48
  70. data/test/quit_test.rb +44 -35
  71. data/test/reload_test.rb +36 -24
  72. data/test/repl_test.rb +57 -47
  73. data/test/restart_test.rb +56 -69
  74. data/test/save_test.rb +62 -53
  75. data/test/set_test.rb +140 -118
  76. data/test/show_test.rb +68 -201
  77. data/test/source_test.rb +39 -29
  78. data/test/stepping_test.rb +163 -136
  79. data/test/support/test_dsl.rb +9 -11
  80. data/test/test_helper.rb +2 -7
  81. data/test/thread_test.rb +121 -107
  82. data/test/trace_test.rb +86 -83
  83. data/test/variables_test.rb +104 -98
  84. metadata +27 -86
  85. data/test/examples/breakpoint.rb +0 -6
  86. data/test/examples/breakpoint_deep.rb +0 -4
  87. data/test/examples/conditions.rb +0 -4
  88. data/test/examples/continue.rb +0 -5
  89. data/test/examples/display.rb +0 -5
  90. data/test/examples/edit.rb +0 -4
  91. data/test/examples/eval.rb +0 -4
  92. data/test/examples/finish.rb +0 -3
  93. data/test/examples/frame.rb +0 -4
  94. data/test/examples/frame_deep.rb +0 -1
  95. data/test/examples/gcd.rb +0 -15
  96. data/test/examples/hanoi.rb +0 -34
  97. data/test/examples/help.rb +0 -1
  98. data/test/examples/info.rb +0 -6
  99. data/test/examples/info2.rb +0 -3
  100. data/test/examples/interrupt.rb +0 -8
  101. data/test/examples/kill.rb +0 -2
  102. data/test/examples/list.rb +0 -23
  103. data/test/examples/method.rb +0 -4
  104. data/test/examples/post_mortem.rb +0 -4
  105. data/test/examples/primes.rb +0 -25
  106. data/test/examples/quit.rb +0 -2
  107. data/test/examples/reload.rb +0 -6
  108. data/test/examples/repl.rb +0 -6
  109. data/test/examples/restart.rb +0 -6
  110. data/test/examples/save.rb +0 -3
  111. data/test/examples/set.rb +0 -3
  112. data/test/examples/settings.rb +0 -1
  113. data/test/examples/show.rb +0 -1
  114. data/test/examples/source.rb +0 -3
  115. data/test/examples/stepping.rb +0 -8
  116. data/test/examples/stepping_raise_from_c_method.rb +0 -3
  117. data/test/examples/stepping_raise_from_ruby_method.rb +0 -3
  118. data/test/examples/test-triangle.rb +0 -14
  119. data/test/examples/thread.rb +0 -5
  120. data/test/examples/tmate.rb +0 -10
  121. data/test/examples/trace.rb +0 -8
  122. data/test/examples/tri3.rb +0 -6
  123. data/test/examples/triangle.rb +0 -13
  124. data/test/examples/variables.rb +0 -4
  125. data/test/timeout_test.rb +0 -9
@@ -0,0 +1,15 @@
1
+ module Byebug
2
+ class ListsizeSetting < Setting
3
+ def initialize
4
+ @value = 10
5
+ end
6
+
7
+ def help
8
+ 'Set number of source lines to list by default'
9
+ end
10
+
11
+ def to_s
12
+ "Number of source lines to list is #{value}\n"
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ module Byebug
2
+ class PostMortemSetting < Setting
3
+ def help
4
+ 'Enable/disable post-mortem mode'
5
+ end
6
+
7
+ def value=(v)
8
+ v ? Byebug.post_mortem : Byebug.post_mortem = v
9
+ end
10
+
11
+ def value
12
+ Byebug.post_mortem?
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,7 @@
1
+ module Byebug
2
+ class StackOnErrorSetting < Setting
3
+ def help
4
+ 'Display stack trace when "eval" raises an exception'
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Byebug
2
+ class TestingSetting < Setting
3
+ def help
4
+ 'Used when testing byebug'
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Byebug
2
+ class TracingPlusSetting < Setting
3
+ def help
4
+ 'Set line execution tracing to always show different lines'
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Byebug
2
+ class VerboseSetting < Setting
3
+ def help
4
+ 'Enable verbose output of TracePoint API events'
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,29 @@
1
+ module Byebug
2
+ class WidthSetting < Setting
3
+ def initialize
4
+ if ENV['COLUMNS'] =~ /^\d+$/
5
+ @value = ENV['COLUMNS'].to_i
6
+ elsif STDIN.tty? && exists?('stty')
7
+ @value = `stty size`.scan(/\d+/)[1].to_i
8
+ else
9
+ @value = 160
10
+ end
11
+ end
12
+
13
+ def help
14
+ "Number of characters per line in byebug's output"
15
+ end
16
+
17
+ def to_s
18
+ "Maximum width of byebug's output is #{value}"
19
+ end
20
+
21
+ private
22
+
23
+ def exists?(command)
24
+ ENV['PATH'].split(File::PATH_SEPARATOR).any? do |d|
25
+ File.exist?(File.join(d, command))
26
+ end
27
+ end
28
+ end
29
+ end
@@ -1,3 +1,3 @@
1
1
  module Byebug
2
- VERSION = '3.0.0'
2
+ VERSION = '3.1.0'
3
3
  end
@@ -1,453 +1,474 @@
1
- class BreakpointExample
2
- def self.a(num)
3
- 4
4
- end
5
- def b
6
- 3
7
- end
8
- end
9
-
10
- class BreakpointDeepExample
11
- def a
12
- z = 2
13
- b(z)
14
- end
15
-
16
- def b(num)
17
- v2 = 5 if 1 == num ; [1,2,v2].map { |a| a.to_f }
18
- c
19
- end
20
-
21
- def c
22
- z = 4
23
- z += 5
24
- byebug
25
- end
26
- end
1
+ module BreakpointsTest
2
+ class Example
3
+ def self.a(num)
4
+ 4
5
+ end
27
6
 
28
- class TestBreakpoints < TestDsl::TestCase
29
- before do
30
- @tst_file = fullpath('breakpoint')
7
+ def b
8
+ 3
9
+ end
31
10
  end
32
11
 
33
- describe 'setting breakpoint in the current file' do
34
- before { enter 'break 1' }
35
-
36
- subject { Byebug.breakpoints.first }
37
-
38
- def check_subject(field, value)
39
- debug_file('breakpoint') { subject.send(field).must_equal value }
12
+ class DeepExample
13
+ def a
14
+ z = 2
15
+ b(z)
40
16
  end
41
17
 
42
- it('must have correct pos') { check_subject(:pos, 1) }
43
- it('must have correct source') { check_subject(:source, @tst_file) }
44
- it('must have correct expression') { check_subject(:expr, nil) }
45
- it('must have correct hit count') { check_subject(:hit_count, 0) }
46
- it('must have correct hit value') { check_subject(:hit_value, 0) }
47
- it('must be enabled') { check_subject(:enabled?, true) }
48
-
49
- it('must return right response') do
50
- id = nil
51
- debug_file('breakpoint') { id = subject.id }
52
- check_output_includes "Created breakpoint #{id} at #{@tst_file}:1"
18
+ def b(num)
19
+ v2 = 5 if 1 == num ; [1,2,v2].map { |a| a.to_f }
20
+ c
53
21
  end
54
- end
55
22
 
56
- describe 'using shortcut for the command' do
57
- before { enter 'b 1' }
58
- it 'must set a breakpoint' do
59
- debug_file('breakpoint') { Byebug.breakpoints.size.must_equal 1 }
23
+ def c
24
+ z = 4
25
+ z += 5
26
+ byebug
60
27
  end
61
28
  end
62
29
 
63
- describe 'setting breakpoint to unexistent line' do
64
- before { enter 'break 100' }
30
+ class BreakpointsTestCase < TestDsl::TestCase
31
+ before do
32
+ @example = -> do
33
+ y = 3
34
+ # A comment
35
+ byebug
36
+ z = 5
37
+ Example.new.b
38
+ Example.a(y+z)
39
+ end
40
+ end
65
41
 
66
- it 'must not create a breakpoint' do
67
- debug_file('breakpoint') { Byebug.breakpoints.must_be_empty }
42
+ def first
43
+ Byebug.breakpoints.first
68
44
  end
69
45
 
70
- it 'must show an error' do
71
- debug_file('breakpoint')
72
- check_error_includes \
73
- "There are only #{LineCache.size(@tst_file)} lines in file #{@tst_file}"
46
+ def last
47
+ Byebug.breakpoints.last
74
48
  end
75
- end
76
49
 
77
- describe 'setting breakpoint to incorrect line' do
78
- before { enter 'break 2' }
50
+ describe 'setting breakpoint in the current file' do
51
+ before { enter 'break 33' }
79
52
 
80
- it 'must not create a breakpoint' do
81
- debug_file('breakpoint') { Byebug.breakpoints.must_be_empty }
82
- end
53
+ def check_first(field, value)
54
+ debug_proc(@example) { first.send(field).must_equal value }
55
+ end
83
56
 
84
- it 'must show an error' do
85
- debug_file('breakpoint')
86
- check_error_includes \
87
- "Line 2 is not a stopping point in file #{@tst_file}"
88
- end
89
- end
57
+ it('must have correct pos') { check_first(:pos, 33) }
58
+ it('must have correct source') { check_first(:source, __FILE__) }
59
+ it('must have correct expression') { check_first(:expr, nil) }
60
+ it('must have correct hit count') { check_first(:hit_count, 0) }
61
+ it('must have correct hit value') { check_first(:hit_value, 0) }
62
+ it('must be enabled') { check_first(:enabled?, true) }
90
63
 
91
- describe 'stopping at breakpoint' do
92
- it 'must stop at the correct line' do
93
- enter 'break 5', 'cont'
94
- debug_file('breakpoint') { state.line.must_equal 5 }
64
+ it('must return right response') do
65
+ id = nil
66
+ debug_proc(@example) { id = first.id }
67
+ check_output_includes "Created breakpoint #{id} at #{__FILE__}:33"
68
+ end
95
69
  end
96
70
 
97
- it 'must stop at the correct file' do
98
- enter 'break 5', 'cont'
99
- debug_file('breakpoint') { state.file.must_equal @tst_file }
71
+ describe 'using shortcut for the command' do
72
+ before { enter 'b 33' }
73
+ it 'must set a breakpoint' do
74
+ debug_proc(@example) { Byebug.breakpoints.size.must_equal 1 }
75
+ end
100
76
  end
101
77
 
102
- describe 'show a message' do
103
- describe 'with full filename' do
104
- it 'must show a message with full filename' do
105
- enter 'break 5', 'cont'
106
- debug_file('breakpoint') { @id = Byebug.breakpoints.first.id }
107
- check_output_includes "Created breakpoint #{@id} at #{@tst_file}:5"
108
- end
109
- end
78
+ describe 'setting breakpoint to unexistent line' do
79
+ before { enter 'break 1000' }
110
80
 
111
- describe 'with basename' do
112
- temporary_change_hash Byebug.settings, :basename, true
81
+ it 'must not create a breakpoint' do
82
+ debug_proc(@example) { Byebug.breakpoints.must_be_empty }
83
+ end
113
84
 
114
- it 'must show a message with basename' do
115
- enter 'break 5', 'cont'
116
- debug_file('breakpoint') { @id = Byebug.breakpoints.first.id }
117
- check_output_includes "Created breakpoint #{@id} at breakpoint.rb:5"
118
- end
85
+ it 'must show an error' do
86
+ debug_proc(@example)
87
+ check_error_includes \
88
+ "There are only #{LineCache.size(__FILE__)} lines in file #{__FILE__}"
119
89
  end
120
90
  end
121
- end
122
91
 
123
- describe 'reloading source on change' do
124
- describe 'autoreload not set' do
125
- temporary_change_hash Byebug.settings, :autoreload, false
92
+ describe 'setting breakpoint to incorrect line' do
93
+ before { enter 'break 6' }
126
94
 
127
- it 'must not reload source' do
128
- id = nil
129
- enter ->{ change_line_in_file(@tst_file, 5, ''); 'break 5' },
130
- ->{ change_line_in_file(@tst_file, 5, 'BreakpointExample.new.b');
131
- cont }
132
- debug_file('breakpoint') { id = Byebug.breakpoints.first.id }
133
- check_output_includes "Created breakpoint #{id} at #{@tst_file}:5"
95
+ it 'must not create a breakpoint' do
96
+ debug_proc(@example) { Byebug.breakpoints.must_be_empty }
134
97
  end
135
- end
136
98
 
137
- describe 'autoreload set' do
138
- it 'must reload source' do
139
- enter \
140
- ->{change_line_in_file(@tst_file, 5, ''); 'break 5'},
141
- ->{change_line_in_file(@tst_file, 5, 'BreakpointExample.new.b');
142
- 'next'}
143
- debug_file 'breakpoint'
99
+ it 'must show an error' do
100
+ debug_proc(@example)
144
101
  check_error_includes \
145
- "Line 5 is not a stopping point in file #{@tst_file}"
102
+ "Line 6 is not a stopping point in file #{__FILE__}"
146
103
  end
147
104
  end
148
- end
149
105
 
150
- describe 'set breakpoint in a file' do
151
- describe 'successfully' do
152
- before { enter "break #{__FILE__}:3", 'cont' }
106
+ describe 'stopping at breakpoint' do
107
+ before { enter 'break 37', 'cont' }
153
108
 
154
109
  it 'must stop at the correct line' do
155
- debug_file('breakpoint') { state.line.must_equal 3 }
110
+ debug_proc(@example) { state.line.must_equal 37 }
156
111
  end
157
112
 
158
113
  it 'must stop at the correct file' do
159
- debug_file('breakpoint') { state.file.must_equal __FILE__ }
114
+ debug_proc(@example) { state.file.must_equal __FILE__ }
160
115
  end
161
- end
162
116
 
163
- describe 'when setting breakpoint to unexisted file' do
164
- before do
165
- enter 'break asf:324'
166
- debug_file('breakpoint')
167
- end
117
+ describe 'show a message' do
118
+ describe 'with full filename' do
119
+ it 'must show a message with full filename' do
120
+ debug_proc(@example) { @id = first.id }
121
+ check_output_includes "Created breakpoint #{@id} at #{__FILE__}:37"
122
+ end
123
+ end
168
124
 
169
- it 'must show an error' do
170
- check_error_includes 'No source file named asf'
171
- end
125
+ describe 'with basename' do
126
+ temporary_change_hash Byebug::Setting, :basename, true
172
127
 
173
- it 'must ask about setting breakpoint anyway' do
174
- check_output_includes \
175
- 'Set breakpoint anyway? (y/n)', interface.confirm_queue
128
+ it 'must show a message with basename' do
129
+ debug_proc(@example) { @id = first.id }
130
+ check_output_includes \
131
+ "Created breakpoint #{@id} at #{File.basename(__FILE__)}:37"
132
+ end
133
+ end
176
134
  end
177
135
  end
178
- end
179
136
 
180
- describe 'set breakpoint to a method' do
181
- describe 'set breakpoint to an instance method' do
182
- before { enter 'break BreakpointExample#b', 'cont' }
137
+ describe 'reloading source on change' do
138
+ describe 'autoreload not set' do
139
+ temporary_change_hash Byebug::Setting, :autoreload, false
183
140
 
184
- it 'must stop at the correct line' do
185
- debug_file('breakpoint') { state.line.must_equal 5 }
141
+ it 'must not reload source' do
142
+ id = nil
143
+ enter \
144
+ -> { change_line_in_file(__FILE__, 37, ''); 'break 37' },
145
+ -> { change_line_in_file(__FILE__, 37, ' Example.new.b');
146
+ cont }
147
+
148
+ debug_proc(@example) { id = first.id }
149
+ check_output_includes "Created breakpoint #{id} at #{__FILE__}:37"
150
+ end
186
151
  end
187
152
 
188
- it 'must stop at the correct file' do
189
- debug_file('breakpoint') { state.file.must_equal __FILE__ }
153
+ describe 'autoreload set' do
154
+ it 'must reload source' do
155
+ enter \
156
+ -> { change_line_in_file(__FILE__, 37, ''); 'break 37' },
157
+ -> { change_line_in_file(__FILE__, 37, ' Example.new.b');
158
+ 'next' }
159
+
160
+ debug_proc(@example)
161
+ check_error_includes \
162
+ "Line 37 is not a stopping point in file #{__FILE__}"
163
+ end
190
164
  end
191
165
  end
192
166
 
193
- describe 'set breakpoint to a class method' do
194
- before { enter 'break BreakpointExample.a', 'cont' }
167
+ describe 'set breakpoint in a file' do
168
+ describe 'successfully' do
169
+ before { enter "break #{__FILE__}:4", 'cont' }
195
170
 
196
- it 'must stop at the correct line' do
197
- debug_file('breakpoint') { state.line.must_equal 2 }
198
- end
171
+ it 'must stop at the correct line' do
172
+ debug_proc(@example) { state.line.must_equal 4 }
173
+ end
199
174
 
200
- it 'must stop at the correct file' do
201
- debug_file('breakpoint') { state.file.must_equal __FILE__ }
175
+ it 'must stop at the correct file' do
176
+ debug_proc(@example) { state.file.must_equal __FILE__ }
177
+ end
202
178
  end
203
- end
204
179
 
205
- describe 'set breakpoint to unexisted class' do
206
- it 'must show an error' do
207
- enter 'break B.a'
208
- debug_file('breakpoint')
209
- check_error_includes 'Unknown class B.'
180
+ describe 'when setting breakpoint to unexisted file' do
181
+ before do
182
+ enter 'break asf:324'
183
+ debug_proc(@example)
184
+ end
185
+
186
+ it 'must show an error' do
187
+ check_error_includes 'No source file named asf'
188
+ end
189
+
190
+ it 'must ask about setting breakpoint anyway' do
191
+ check_output_includes \
192
+ 'Set breakpoint anyway? (y/n)', interface.confirm_queue
193
+ end
210
194
  end
211
195
  end
212
- end
213
196
 
214
- describe 'set breakpoint to an invalid location' do
215
- before { enter 'break foo' }
197
+ describe 'set breakpoint to a method' do
198
+ describe 'set breakpoint to an instance method' do
199
+ before { enter 'break Example#b', 'cont' }
216
200
 
217
- it 'must not create a breakpoint' do
218
- debug_file('breakpoint') { Byebug.breakpoints.must_be_empty }
219
- end
201
+ it 'must stop at the correct line' do
202
+ debug_proc(@example) { state.line.must_equal 7 }
203
+ end
220
204
 
221
- it 'must show an error' do
222
- debug_file('breakpoint')
223
- check_error_includes 'Invalid breakpoint location: foo.'
224
- end
225
- end
205
+ it 'must stop at the correct file' do
206
+ debug_proc(@example) { state.file.must_equal __FILE__ }
207
+ end
208
+ end
226
209
 
227
- describe 'disabling breakpoints' do
228
- describe 'successfully' do
229
- before { enter 'break 5', 'break 6' }
210
+ describe 'set breakpoint to a class method' do
211
+ before { enter 'break Example.a', 'cont' }
230
212
 
231
- describe 'short syntax' do
232
- before { enter ->{ "disable #{Byebug.breakpoints.first.id}" } }
213
+ it 'must stop at the correct line' do
214
+ debug_proc(@example) { state.line.must_equal 3 }
215
+ end
233
216
 
234
- it 'must have a breakpoint with #enabled? returning false' do
235
- debug_file('breakpoint') {
236
- Byebug.breakpoints.first.enabled?.must_equal false }
217
+ it 'must stop at the correct file' do
218
+ debug_proc(@example) { state.file.must_equal __FILE__ }
237
219
  end
220
+ end
238
221
 
239
- it 'must not stop on the disabled breakpoint' do
240
- enter 'cont'
241
- debug_file('breakpoint') { state.line.must_equal 6 }
222
+ describe 'set breakpoint to unexisted class' do
223
+ it 'must show an error' do
224
+ enter 'break B.a'
225
+ debug_proc(@example)
226
+ check_error_includes 'Unknown class B.'
242
227
  end
243
228
  end
229
+ end
244
230
 
245
- describe 'full syntax' do
246
- describe 'with no args' do
247
- before { enter 'disable breakpoints' }
231
+ describe 'set breakpoint to an invalid location' do
232
+ before { enter 'break foo' }
248
233
 
249
- it 'must have all breakoints with #enabled? returning false' do
250
- debug_file('breakpoint') do
251
- Byebug.breakpoints.first.enabled?.must_equal false
252
- Byebug.breakpoints.last.enabled?.must_equal false
253
- end
234
+ it 'must not create a breakpoint' do
235
+ debug_proc(@example) { Byebug.breakpoints.must_be_empty }
236
+ end
237
+
238
+ it 'must show an error' do
239
+ debug_proc(@example)
240
+ check_error_includes 'Invalid breakpoint location: foo.'
241
+ end
242
+ end
243
+
244
+ describe 'disabling breakpoints' do
245
+ describe 'successfully' do
246
+ before { enter 'break 37', 'break 38' }
247
+
248
+ describe 'short syntax' do
249
+ before { enter ->{ "disable #{first.id}" } }
250
+
251
+ it 'must have a breakpoint with #enabled? returning false' do
252
+ debug_proc(@example) { first.enabled?.must_equal false }
254
253
  end
255
254
 
256
- it 'must not stop on any disabled breakpoint' do
255
+ it 'must not stop on the disabled breakpoint' do
257
256
  enter 'cont'
258
- debug_file('breakpoint')
259
- # Obscure assert to check for program termination
260
- state.proceed.must_equal true
257
+ debug_proc(@example) { state.line.must_equal 38 }
261
258
  end
262
259
  end
263
260
 
264
- describe 'with specific breakpoint' do
265
- before do
266
- enter ->{ "disable breakpoints #{Byebug.breakpoints.first.id}" }
261
+ describe 'full syntax' do
262
+ describe 'with no args' do
263
+ before { enter 'disable breakpoints' }
264
+
265
+ it 'must have all breakoints with #enabled? returning false' do
266
+ debug_proc(@example) do
267
+ first.enabled?.must_equal false
268
+ last.enabled?.must_equal false
269
+ end
270
+ end
271
+
272
+ it 'must not stop on any disabled breakpoint' do
273
+ enter 'cont'
274
+ debug_proc(@example)
275
+ # Obscure assert to check for program termination
276
+ state.proceed.must_equal true
277
+ end
267
278
  end
268
279
 
269
- it 'must have a breakpoint with #enabled? returning false' do
270
- debug_file('breakpoint') {
271
- Byebug.breakpoints.first.enabled?.must_equal false }
280
+ describe 'with specific breakpoint' do
281
+ before do
282
+ enter ->{ "disable breakpoints #{first.id}" }
283
+ end
284
+
285
+ it 'must have a breakpoint with #enabled? returning false' do
286
+ debug_proc(@example) {
287
+ first.enabled?.must_equal false }
288
+ end
272
289
  end
273
290
  end
274
291
  end
275
- end
276
292
 
277
- describe 'unsuccesfully' do
278
- it 'must show an error if syntax is incorrect' do
279
- enter 'disable'
280
- debug_file('breakpoint')
281
- check_error_includes '"disable" must be followed by "display", ' \
282
- '"breakpoints" or breakpoint numbers.'
283
- end
293
+ describe 'unsuccesfully' do
294
+ it 'must show an error if syntax is incorrect' do
295
+ enter 'disable'
296
+ debug_proc(@example)
297
+ check_error_includes '"disable" must be followed by "display", ' \
298
+ '"breakpoints" or breakpoint numbers.'
299
+ end
284
300
 
285
- it 'must show an error if no breakpoints are set' do
286
- enter 'disable 1'
287
- debug_file('breakpoint')
288
- check_error_includes 'No breakpoints have been set.'
289
- end
301
+ it 'must show an error if no breakpoints are set' do
302
+ enter 'disable 1'
303
+ debug_proc(@example)
304
+ check_error_includes 'No breakpoints have been set.'
305
+ end
290
306
 
291
- it 'must show an error if a number is not provided as an argument' do
292
- enter 'break 5', 'disable foo'
293
- debug_file('breakpoint')
294
- check_output_includes \
295
- '"disable breakpoints" argument "foo" needs to be a number.'
307
+ it 'must show an error if a number is not provided as an argument' do
308
+ enter 'break 5', 'disable foo'
309
+ debug_proc(@example)
310
+ check_output_includes \
311
+ '"disable breakpoints" argument "foo" needs to be a number'
312
+ end
296
313
  end
297
314
  end
298
- end
299
315
 
300
- describe 'enabling breakpoints' do
301
- describe 'successfully' do
302
- before { enter 'break 5', 'break 6', 'disable breakpoints' }
316
+ describe 'enabling breakpoints' do
317
+ describe 'successfully' do
318
+ before { enter 'break 37', 'break 38', 'disable breakpoints' }
303
319
 
304
- describe 'short syntax' do
305
- before { enter ->{ "enable #{Byebug.breakpoints.first.id}" } }
320
+ describe 'short syntax' do
321
+ before { enter ->{ "enable #{first.id}" } }
306
322
 
307
- it 'must have a breakpoint with #enabled? returning true' do
308
- debug_file('breakpoint') {
309
- Byebug.breakpoints.first.enabled?.must_equal true }
310
- end
323
+ it 'must have a breakpoint with #enabled? returning true' do
324
+ debug_proc(@example) { first.enabled?.must_equal true }
325
+ end
311
326
 
312
- it 'must stop on the enabled breakpoint' do
313
- enter 'cont'
314
- debug_file('breakpoint') { state.line.must_equal 5 }
327
+ it 'must stop on the enabled breakpoint' do
328
+ enter 'cont'
329
+ debug_proc(@example) { state.line.must_equal 37 }
330
+ end
315
331
  end
316
- end
317
332
 
318
- describe 'full syntax' do
319
- describe 'with no args' do
320
- before { enter 'enable breakpoints' }
333
+ describe 'full syntax' do
334
+ describe 'with no args' do
335
+ before { enter 'enable breakpoints' }
321
336
 
322
- it 'must have all breakoints with #enabled? returning true' do
323
- debug_file('breakpoint') do
324
- Byebug.breakpoints.first.enabled?.must_equal true
325
- Byebug.breakpoints.last.enabled?.must_equal true
337
+ it 'must have all breakoints with #enabled? returning true' do
338
+ debug_proc(@example) do
339
+ first.enabled?.must_equal true
340
+ last.enabled?.must_equal true
341
+ end
326
342
  end
327
- end
328
343
 
329
- it 'must stop on the first breakpoint' do
330
- enter 'cont'
331
- debug_file('breakpoint') { state.line.must_equal 5 }
332
- end
344
+ it 'must stop on the first breakpoint' do
345
+ enter 'cont'
346
+ debug_proc(@example) { state.line.must_equal 37 }
347
+ end
333
348
 
334
- it 'must stop on the last breakpoint' do
335
- enter 'cont', 'cont'
336
- debug_file('breakpoint') { state.line.must_equal 6 }
349
+ it 'must stop on the last breakpoint' do
350
+ enter 'cont', 'cont'
351
+ debug_proc(@example) { state.line.must_equal 38 }
352
+ end
337
353
  end
338
- end
339
354
 
340
- describe 'with specific breakpoint' do
341
- before do
342
- enter ->{ "enable breakpoints #{Byebug.breakpoints.last.id}" }
343
- end
355
+ describe 'with specific breakpoint' do
356
+ before { enter ->{ "enable breakpoints #{last.id}" } }
344
357
 
345
- it 'must have a breakpoint with #enabled? returning true' do
346
- debug_file('breakpoint') {
347
- Byebug.breakpoints.last.enabled?.must_equal true }
348
- end
358
+ it 'must have a breakpoint with #enabled? returning true' do
359
+ debug_proc(@example) { last.enabled?.must_equal true }
360
+ end
349
361
 
350
- it 'must stop only on the enabled breakpoint' do
351
- enter 'cont'
352
- debug_file('breakpoint') { state.line.must_equal 6 }
362
+ it 'must stop only on the enabled breakpoint' do
363
+ enter 'cont'
364
+ debug_proc(@example) { state.line.must_equal 38 }
365
+ end
353
366
  end
354
367
  end
355
368
  end
356
- end
357
369
 
358
- describe 'errors' do
359
- it 'must show an error if syntax is incorrect' do
360
- enter 'enable'
361
- debug_file('breakpoint')
362
- check_error_includes '"enable" must be followed by "display", ' \
363
- '"breakpoints" or breakpoint numbers.'
370
+ describe 'errors' do
371
+ it 'must show an error if syntax is incorrect' do
372
+ enter 'enable'
373
+ debug_proc(@example)
374
+ check_error_includes '"enable" must be followed by "display", ' \
375
+ '"breakpoints" or breakpoint numbers.'
376
+ end
364
377
  end
365
378
  end
366
- end
367
379
 
368
- describe 'deleting a breakpoint' do
369
- before { enter 'break 5', ->{"delete #{Byebug.breakpoints.first.id}"},
370
- 'break 6' }
380
+ describe 'deleting a breakpoint' do
381
+ before { enter 'break 37', -> { "delete #{first.id}" }, 'break 38' }
371
382
 
372
- it 'must have only one breakpoint' do
373
- debug_file('breakpoint') { Byebug.breakpoints.size.must_equal 1 }
374
- end
383
+ it 'must have only one breakpoint' do
384
+ debug_proc(@example) { Byebug.breakpoints.size.must_equal 1 }
385
+ end
375
386
 
376
- it 'must not stop on the disabled breakpoint' do
377
- enter 'cont'
378
- debug_file('breakpoint') { state.line.must_equal 6 }
387
+ it 'must not stop on the disabled breakpoint' do
388
+ enter 'cont'
389
+ debug_proc(@example) { state.line.must_equal 38 }
390
+ end
379
391
  end
380
- end
381
392
 
382
- describe 'Conditional breakpoints' do
383
- it 'must stop if the condition is true' do
384
- enter 'break 5 if z == 5', 'break 6', 'cont'
385
- debug_file('breakpoint') { state.line.must_equal 5 }
386
- end
393
+ describe 'Conditional breakpoints' do
394
+ it 'must stop if the condition is true' do
395
+ enter 'break 37 if z == 5', 'break 38', 'cont'
396
+ debug_proc(@example) { state.line.must_equal 37 }
397
+ end
387
398
 
388
- it 'must skip if the condition is false' do
389
- enter 'break 5 if z == 3', 'break 6', 'cont'
390
- debug_file('breakpoint') { state.line.must_equal 6 }
391
- end
399
+ it 'must skip if the condition is false' do
400
+ enter 'break 37 if z == 3', 'break 38', 'cont'
401
+ debug_proc(@example) { state.line.must_equal 38 }
402
+ end
392
403
 
393
- it 'must show an error when conditional syntax is wrong' do
394
- enter 'break 5 ifa z == 3', 'break 6', 'cont'
395
- debug_file('breakpoint') { state.line.must_equal 6 }
396
- check_error_includes \
397
- 'Expecting "if" in breakpoint condition; got: ifa z == 3.'
398
- end
404
+ it 'must show an error when conditional syntax is wrong' do
405
+ enter 'break 37 ifa z == 3', 'break 38', 'cont'
406
+ debug_proc(@example) { state.line.must_equal 38 }
407
+ check_error_includes \
408
+ 'Expecting "if" in breakpoint condition; got: ifa z == 3.'
409
+ end
399
410
 
400
- describe 'enabling with wrong conditional syntax' do
401
- before { enter 'break 5',
402
- ->{"disable #{Byebug.breakpoints.first.id}"},
403
- ->{"cond #{Byebug.breakpoints.first.id} z -=( 3"},
404
- ->{"enable #{Byebug.breakpoints.first.id}"} }
411
+ describe 'enabling with wrong conditional syntax' do
412
+ before do
413
+ enter 'break 37', -> { "disable #{first.id}" },
414
+ -> { "cond #{first.id} z -=( 3" },
415
+ -> { "enable #{first.id}"}
416
+ end
405
417
 
406
- it 'must not enable a breakpoint' do
407
- debug_file('breakpoint') {
408
- Byebug.breakpoints.first.enabled?.must_equal false }
409
- end
418
+ it 'must not enable a breakpoint' do
419
+ debug_proc(@example) { first.enabled?.must_equal false }
420
+ end
410
421
 
411
- it 'must show an error' do
412
- debug_file('breakpoint')
413
- check_error_includes 'Expression "z -=( 3" syntactically incorrect; ' \
414
- 'breakpoint remains disabled.'
422
+ it 'must show an error' do
423
+ debug_proc(@example)
424
+ check_error_includes 'Expression "z -=( 3" syntactically incorrect; ' \
425
+ 'breakpoint remains disabled.'
426
+ end
415
427
  end
416
- end
417
428
 
418
- it 'must show an error if no file or line is specified' do
419
- enter 'break ifa z == 3', 'break 6', 'cont'
420
- debug_file('breakpoint') { state.line.must_equal 6 }
421
- check_error_includes 'Invalid breakpoint location: ifa z == 3.'
422
- end
429
+ it 'must show an error if no file or line is specified' do
430
+ enter 'break ifa z == 3', 'break 38', 'cont'
431
+ debug_proc(@example) { state.line.must_equal 38 }
432
+ check_error_includes 'Invalid breakpoint location: ifa z == 3.'
433
+ end
423
434
 
424
- it 'must show an error if expression syntax is invalid' do
425
- enter 'break if z -=) 3', 'break 6', 'cont'
426
- debug_file('breakpoint') { state.line.must_equal 6 }
427
- check_error_includes \
428
- 'Expression "z -=) 3" syntactically incorrect; breakpoint disabled.'
435
+ it 'must show an error if expression syntax is invalid' do
436
+ enter 'break if z -=) 3', 'break 38', 'cont'
437
+ debug_proc(@example) { state.line.must_equal 38 }
438
+ check_error_includes \
439
+ 'Expression "z -=) 3" syntactically incorrect; breakpoint disabled.'
440
+ end
429
441
  end
430
- end
431
442
 
432
- describe 'Stopping through `byebug` keyword' do
433
- describe 'when not the last instruction of a method' do
434
- it 'must stop in the next line' do
435
- debug_file('breakpoint') { state.line.must_equal 4 }
443
+ describe 'Stopping through `byebug` keyword' do
444
+ describe 'when not the last instruction of a method' do
445
+ it 'must stop in the next line' do
446
+ debug_proc(@example) { state.line.must_equal 36 }
447
+ end
436
448
  end
437
- end
438
449
 
439
- describe 'when last instruction of a method' do
440
- it 'must stop right before returning from the frame' do
441
- debug_file('breakpoint_deep') { state.line.must_equal 25 }
450
+ describe 'when last instruction of a method' do
451
+ before do
452
+ @deep_example = lambda do
453
+ ex = DeepExample.new.a
454
+ 2.times do
455
+ ex = ex ? ex : 1
456
+ end
457
+ end
458
+ end
459
+
460
+ it 'must stop right before returning from the frame' do
461
+ debug_proc(@deep_example) { state.line.must_equal 27 }
462
+ end
442
463
  end
443
464
  end
444
- end
445
465
 
446
- describe 'Help' do
447
- it 'must show info about setting breakpoints when using just "break"' do
448
- enter 'break', 'cont'
449
- debug_file 'breakpoint'
450
- check_output_includes(/b\[reak\] file:line \[if expr\]/)
466
+ describe 'Help' do
467
+ it 'must show info about setting breakpoints when using just "break"' do
468
+ enter 'break', 'cont'
469
+ debug_proc(@example)
470
+ check_output_includes(/b\[reak\] file:line \[if expr\]/)
471
+ end
451
472
  end
452
473
  end
453
474
  end