byebug 1.8.2 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -1
  3. data/GUIDE.md +14 -22
  4. data/README.md +69 -6
  5. data/bin/byebug +3 -20
  6. data/ext/byebug/breakpoint.c +185 -101
  7. data/ext/byebug/byebug.c +393 -214
  8. data/ext/byebug/byebug.h +34 -15
  9. data/ext/byebug/context.c +327 -102
  10. data/ext/byebug/extconf.rb +1 -1
  11. data/ext/byebug/locker.c +54 -0
  12. data/ext/byebug/threads.c +113 -0
  13. data/lib/byebug.rb +19 -58
  14. data/lib/byebug/command.rb +18 -19
  15. data/lib/byebug/commands/breakpoints.rb +1 -4
  16. data/lib/byebug/commands/catchpoint.rb +1 -1
  17. data/lib/byebug/commands/condition.rb +1 -1
  18. data/lib/byebug/commands/control.rb +2 -3
  19. data/lib/byebug/commands/display.rb +2 -7
  20. data/lib/byebug/commands/edit.rb +1 -1
  21. data/lib/byebug/commands/enable.rb +12 -12
  22. data/lib/byebug/commands/eval.rb +4 -4
  23. data/lib/byebug/commands/finish.rb +1 -1
  24. data/lib/byebug/commands/frame.rb +12 -8
  25. data/lib/byebug/commands/info.rb +20 -52
  26. data/lib/byebug/commands/kill.rb +1 -5
  27. data/lib/byebug/commands/list.rb +2 -1
  28. data/lib/byebug/commands/quit.rb +1 -1
  29. data/lib/byebug/commands/repl.rb +2 -2
  30. data/lib/byebug/commands/save.rb +1 -1
  31. data/lib/byebug/commands/set.rb +84 -90
  32. data/lib/byebug/commands/show.rb +44 -53
  33. data/lib/byebug/commands/skip.rb +1 -1
  34. data/lib/byebug/commands/stepping.rb +5 -4
  35. data/lib/byebug/commands/threads.rb +202 -0
  36. data/lib/byebug/commands/trace.rb +1 -1
  37. data/lib/byebug/helper.rb +3 -3
  38. data/lib/byebug/interface.rb +2 -20
  39. data/lib/byebug/processor.rb +21 -100
  40. data/lib/byebug/remote.rb +3 -3
  41. data/lib/byebug/version.rb +1 -1
  42. data/old_doc/byebug.1 +0 -6
  43. data/old_doc/byebug.texi +29 -46
  44. data/test/breakpoints_test.rb +44 -65
  45. data/test/conditions_test.rb +0 -9
  46. data/test/continue_test.rb +2 -2
  47. data/test/display_test.rb +4 -23
  48. data/test/edit_test.rb +2 -16
  49. data/test/eval_test.rb +4 -13
  50. data/test/examples/thread.rb +32 -0
  51. data/test/finish_test.rb +1 -13
  52. data/test/frame_test.rb +5 -12
  53. data/test/help_test.rb +2 -12
  54. data/test/info_test.rb +8 -18
  55. data/test/kill_test.rb +1 -10
  56. data/test/list_test.rb +5 -14
  57. data/test/method_test.rb +1 -10
  58. data/test/post_mortem_test.rb +247 -14
  59. data/test/quit_test.rb +0 -9
  60. data/test/reload_test.rb +1 -15
  61. data/test/repl_test.rb +1 -9
  62. data/test/restart_test.rb +3 -18
  63. data/test/save_test.rb +1 -13
  64. data/test/set_test.rb +35 -32
  65. data/test/show_test.rb +8 -27
  66. data/test/source_test.rb +1 -8
  67. data/test/stepping_test.rb +65 -96
  68. data/test/support/test_dsl.rb +12 -17
  69. data/test/test_helper.rb +1 -1
  70. data/test/thread_test.rb +106 -0
  71. data/test/trace_test.rb +5 -17
  72. data/test/variables_test.rb +1 -10
  73. metadata +9 -7
  74. data/lib/byebug/commands/jump.rb +0 -52
  75. data/test/jump_test.rb +0 -77
  76. data/test/support/context.rb +0 -15
@@ -1,18 +1,8 @@
1
1
  require_relative 'test_helper'
2
2
 
3
3
  class TestShow < TestDsl::TestCase
4
-
5
- describe 'annotate' do
6
- it 'must show annotate setting' do
7
- enter 'show annotate'
8
- debug_file 'show'
9
- Byebug.annotate.must_equal 0
10
- check_output_includes 'Annotation level is 0'
11
- end
12
- end
13
-
14
4
  describe 'args' do
15
- temporary_change_hash Byebug::Command.settings, :argv, %w{foo bar}
5
+ temporary_change_hash Byebug.settings, :argv, %w{foo bar}
16
6
 
17
7
  describe 'default behaviour' do
18
8
  it 'must show args' do
@@ -109,11 +99,11 @@ class TestShow < TestDsl::TestCase
109
99
  end
110
100
  end
111
101
 
112
- describe 'linetrace+' do
102
+ describe 'linetrace_plus' do
113
103
  it 'must show default value' do
114
- enter 'show linetrace+'
104
+ enter 'show linetrace_plus'
115
105
  debug_file 'show'
116
- check_output_includes 'line tracing style is every line.'
106
+ check_output_includes 'line tracing style is different consecutive lines.'
117
107
  end
118
108
  end
119
109
 
@@ -125,9 +115,9 @@ class TestShow < TestDsl::TestCase
125
115
  end
126
116
  end
127
117
 
128
- describe 'trace' do
129
- it 'must show trace' do
130
- enter 'show trace'
118
+ describe 'stack_trace_on_error' do
119
+ it 'must show stack_trace_on_error' do
120
+ enter 'show stack_trace_on_error'
131
121
  debug_file 'show'
132
122
  check_output_includes 'Displaying stack trace is off.'
133
123
  end
@@ -137,7 +127,7 @@ class TestShow < TestDsl::TestCase
137
127
  it 'must show version' do
138
128
  enter 'show version'
139
129
  debug_file 'show'
140
- check_output_includes "byebug #{Byebug::VERSION}"
130
+ check_output_includes "Byebug #{Byebug::VERSION}"
141
131
  end
142
132
  end
143
133
 
@@ -274,13 +264,4 @@ class TestShow < TestDsl::TestCase
274
264
  check_output_includes /List of "show" subcommands:/
275
265
  end
276
266
  end
277
-
278
- describe 'Post Mortem' do
279
- it 'must work in post-mortem mode' do
280
- enter 'cont', 'show autolist'
281
- debug_file 'post_mortem'
282
- check_output_includes 'autolist is on.'
283
- end
284
- end
285
-
286
267
  end
@@ -28,7 +28,7 @@ class TestSource < TestDsl::TestCase
28
28
  it 'must show an error if file is not found' do
29
29
  enter 'source blabla'
30
30
  debug_file 'source'
31
- check_output_includes /File ".*blabla" not found/, interface.error_queue
31
+ check_error_includes /File ".*blabla" not found/
32
32
  end
33
33
 
34
34
  describe 'Help' do
@@ -39,11 +39,4 @@ class TestSource < TestDsl::TestCase
39
39
  "source FILE\texecutes a file containing byebug commands"
40
40
  end
41
41
  end
42
-
43
- describe 'Post Mortem' do
44
- it 'must work in post-mortem mode' do
45
- enter 'cont', "so #{filename}"
46
- debug_file('post_mortem') { Byebug.breakpoints[0].pos.must_equal 3 }
47
- end
48
- end
49
42
  end
@@ -4,137 +4,106 @@ class TestStepping < TestDsl::TestCase
4
4
 
5
5
  describe 'Next Command' do
6
6
 
7
- describe 'Usual mode' do
7
+ describe 'method call behaviour' do
8
+ before { enter 'break 10', 'cont' }
8
9
 
9
- describe 'method call behaviour' do
10
- before { enter 'break 10', 'cont' }
10
+ it 'must leave on the same line by default' do
11
+ enter 'next'
12
+ debug_file('stepping') { $state.line.must_equal 10 }
13
+ end
11
14
 
12
- it 'must leave on the same line by default' do
13
- enter 'next'
14
- debug_file('stepping') { $state.line.must_equal 10 }
15
- end
15
+ it 'must go to the next line if forced by "plus" sign' do
16
+ enter 'next+'
17
+ debug_file('stepping') { $state.line.must_equal 11 }
18
+ end
16
19
 
17
- it 'must go to the next line if forced by "plus" sign' do
18
- enter 'next+'
20
+ it 'must leave on the same line if forced by "minus" sign' do
21
+ enter 'next-'
22
+ debug_file('stepping') { $state.line.must_equal 10 }
23
+ end
24
+
25
+ describe 'when forcestep is set' do
26
+ temporary_change_hash Byebug.settings, :forcestep, true
27
+
28
+ it 'must go to the next line' do
29
+ enter 'next'
19
30
  debug_file('stepping') { $state.line.must_equal 11 }
20
31
  end
21
32
 
22
- it 'must leave on the same line if forced by "minus" sign' do
23
- enter 'next-'
24
- debug_file('stepping') { $state.line.must_equal 10 }
33
+ it 'must go to the next line (by shortcut)' do
34
+ enter 'n'
35
+ debug_file('stepping') { $state.line.must_equal 11 }
25
36
  end
26
37
 
27
- describe 'when force_stepping is set' do
28
- temporary_change_hash Byebug::Command.settings, :force_stepping, true
29
-
30
- it 'must go to the next line' do
31
- enter 'next'
32
- debug_file('stepping') { $state.line.must_equal 11 }
33
- end
34
-
35
- it 'must go to the next line (by shortcut)' do
36
- enter 'n'
37
- debug_file('stepping') { $state.line.must_equal 11 }
38
- end
39
-
40
- it 'must go the specified number of lines forward by default' do
41
- enter 'next 2'
42
- debug_file('stepping') { $state.line.must_equal 21 }
43
- end
44
-
45
- it 'must ignore it if "minus" is specified' do
46
- enter 'next-'
47
- debug_file('stepping') { $state.line.must_equal 10 }
48
- end
38
+ it 'must go the specified number of lines forward by default' do
39
+ enter 'next 2'
40
+ debug_file('stepping') { $state.line.must_equal 21 }
49
41
  end
50
- end
51
42
 
52
- describe 'block behaviour' do
53
- before { enter 'break 21', 'cont' }
54
-
55
- it 'must step over blocks' do
56
- enter 'next'
57
- debug_file('stepping') { $state.line.must_equal 25 }
43
+ it 'must ignore it if "minus" is specified' do
44
+ enter 'next-'
45
+ debug_file('stepping') { $state.line.must_equal 10 }
58
46
  end
59
47
  end
60
-
61
48
  end
62
49
 
63
- describe 'Post Mortem' do
64
- temporary_change_hash Byebug::Command.settings, :autoeval, false
50
+ describe 'block behaviour' do
51
+ before { enter 'break 21', 'cont' }
65
52
 
66
- it 'must not work in post-mortem mode' do
67
- enter 'cont', 'next'
68
- debug_file 'post_mortem'
69
- check_output_includes \
70
- 'Unknown command: "next". Try "help".', interface.error_queue
53
+ it 'must step over blocks' do
54
+ enter 'next'
55
+ debug_file('stepping') { $state.line.must_equal 25 }
71
56
  end
72
57
  end
73
-
74
58
  end
75
59
 
76
60
  describe 'Step Command' do
77
61
 
78
- describe 'Usual mode' do
79
-
80
- describe 'method call behaviour' do
81
- before { enter 'break 10', 'cont' }
82
-
83
- it 'must leave on the same line if forced by a setting' do
84
- enter 'step'
85
- debug_file('stepping') { $state.line.must_equal 10 }
86
- end
62
+ describe 'method call behaviour' do
63
+ before { enter 'break 10', 'cont' }
87
64
 
88
- it 'must go to the step line if forced to do that by "plus" sign' do
89
- enter 'step+'
90
- debug_file('stepping') { $state.line.must_equal 11 }
91
- end
92
-
93
- it 'must leave on the same line if forced to do that by "minus" sign' do
94
- enter 'step-'
95
- debug_file('stepping') { $state.line.must_equal 10 }
96
- end
65
+ it 'must leave on the same line if forced by a setting' do
66
+ enter 'step'
67
+ debug_file('stepping') { $state.line.must_equal 10 }
68
+ end
97
69
 
98
- describe 'when force_stepping is set' do
99
- temporary_change_hash Byebug::Command.settings, :force_stepping, true
70
+ it 'must go to the step line if forced to do that by "plus" sign' do
71
+ enter 'step+'
72
+ debug_file('stepping') { $state.line.must_equal 11 }
73
+ end
100
74
 
101
- it 'must go to the step line if forced by a setting' do
102
- enter 'step'
103
- debug_file('stepping') { $state.line.must_equal 11 }
104
- end
75
+ it 'must leave on the same line if forced to do that by "minus" sign' do
76
+ enter 'step-'
77
+ debug_file('stepping') { $state.line.must_equal 10 }
78
+ end
105
79
 
106
- it 'must go to the next line if forced by a setting (by shortcut)' do
107
- enter 's'
108
- debug_file('stepping') { $state.line.must_equal 11 }
109
- end
80
+ describe 'when forcestep is set' do
81
+ temporary_change_hash Byebug.settings, :forcestep, true
110
82
 
111
- it 'must go the specified number of lines forward by default' do
112
- enter 'step 2'
113
- debug_file('stepping') { $state.line.must_equal 15 }
114
- end
83
+ it 'must go to the step line if forced by a setting' do
84
+ enter 'step'
85
+ debug_file('stepping') { $state.line.must_equal 11 }
115
86
  end
116
- end
117
87
 
118
- describe 'block behaviour' do
119
- before { enter 'break 21', 'cont' }
88
+ it 'must go to the next line if forced by a setting (by shortcut)' do
89
+ enter 's'
90
+ debug_file('stepping') { $state.line.must_equal 11 }
91
+ end
120
92
 
121
- it 'must step into blocks' do
122
- enter 'step'
123
- debug_file('stepping') { $state.line.must_equal 22 }
93
+ it 'must go the specified number of lines forward by default' do
94
+ enter 'step 2'
95
+ debug_file('stepping') { $state.line.must_equal 15 }
124
96
  end
125
97
  end
126
98
  end
127
99
 
128
- describe 'Post Mortem' do
129
- temporary_change_hash Byebug::Command.settings, :autoeval, false
100
+ describe 'block behaviour' do
101
+ before { enter 'break 21', 'cont' }
130
102
 
131
- it 'must not work in post-mortem mode' do
132
- enter 'cont', 'step'
133
- debug_file 'post_mortem'
134
- check_output_includes \
135
- 'Unknown command: "step". Try "help".', interface.error_queue
103
+ it 'must step into blocks' do
104
+ enter 'step'
105
+ debug_file('stepping') { $state.line.must_equal 22 }
136
106
  end
137
107
  end
138
108
  end
139
-
140
109
  end
@@ -4,8 +4,8 @@ module TestDsl
4
4
  include TestDsl
5
5
 
6
6
  def setup
7
- Byebug.interface = TestInterface.new
8
- Byebug.handler.display.clear
7
+ Byebug.handler = Byebug::CommandProcessor.new(TestInterface.new)
8
+ Byebug.tracing = false
9
9
  end
10
10
 
11
11
  def self.temporary_change_hash hash, key, value
@@ -42,14 +42,14 @@ module TestDsl
42
42
  end
43
43
  end
44
44
 
45
- ##
45
+ #
46
46
  # Expand fullpath of a given example file
47
47
  #
48
48
  def fullpath(filename)
49
49
  (Pathname.new(__FILE__) + "../../examples/#{filename}.rb").cleanpath.to_s
50
50
  end
51
51
 
52
- ##
52
+ #
53
53
  # Adds commands to the input queue, so they will be later retrieved by
54
54
  # Processor, i.e., it emulates user's input.
55
55
  #
@@ -68,7 +68,7 @@ module TestDsl
68
68
  interface.input_queue.concat(messages)
69
69
  end
70
70
 
71
- ##
71
+ #
72
72
  # Runs byebug with the provided basename for a file.
73
73
  #
74
74
  # The file should be placed in the test/examples dir. You also can specify a
@@ -85,20 +85,11 @@ module TestDsl
85
85
  def debug_file(filename, &block)
86
86
  is_test_block_called = false
87
87
  debug_completed = false
88
- exception = nil
89
88
  Byebug.stubs(:run_init_script)
90
89
  if block
91
90
  interface.test_block= lambda do
92
91
  is_test_block_called = true
93
- # We need to store exception and reraise it after completing debugging,
94
- # because Byebug will swallow any exceptions, so e.g. our failed
95
- # assertions will be ignored
96
- begin
97
- block.call
98
- rescue Exception => e
99
- exception = e
100
- raise e
101
- end
92
+ block.call
102
93
  end
103
94
  end
104
95
  Byebug.start do
@@ -107,10 +98,9 @@ module TestDsl
107
98
  end
108
99
  flunk "Debug block was not completed" unless debug_completed
109
100
  flunk "Test block was provided, but not called" if block && !is_test_block_called
110
- raise exception if exception
111
101
  end
112
102
 
113
- ##
103
+ #
114
104
  # Checks the output of byebug.
115
105
  #
116
106
  # By default it checks output queue of the current interface, but you can
@@ -163,4 +153,9 @@ module TestDsl
163
153
  new_content = old_content.split("\n").tap { |c| c[line - 1] = new_line_content }.join("\n")
164
154
  File.open(file, 'w') { |f| f.write(new_content) }
165
155
  end
156
+
157
+ def must_restart
158
+ Byebug::RestartCommand.any_instance.unstub(:exec)
159
+ Byebug::RestartCommand.any_instance.expects(:exec)
160
+ end
166
161
  end
@@ -5,4 +5,4 @@ require 'byebug'
5
5
 
6
6
  Dir.glob(File.expand_path("../support/*.rb", __FILE__)).each { |f| require f }
7
7
 
8
- Byebug::Command.settings[:testing] = true
8
+ Byebug.settings[:testing] = true
@@ -0,0 +1,106 @@
1
+ require_relative 'test_helper'
2
+
3
+ class TestThread < TestDsl::TestCase
4
+ let(:release) { 'eval Thread.main[:should_break] = true' }
5
+
6
+ describe 'list' do
7
+ it 'must show current thread by "plus" sign' do
8
+ thnum = nil
9
+ enter 'break 8', 'cont', 'thread list', release
10
+ debug_file('thread') { thnum = Byebug.contexts.first.thnum }
11
+ check_output_includes /\+ #{thnum} #<Thread:\S+ run>\t#{fullpath('thread')}:8/
12
+ end
13
+
14
+ it 'must work with shortcut' do
15
+ thnum = nil
16
+ enter 'break 8', 'cont', 'th list', release
17
+ debug_file('thread') { thnum = Byebug.contexts.first.thnum }
18
+ check_output_includes /\+ #{thnum} #<Thread:\S+ run>\t#{fullpath('thread')}:8/
19
+ end
20
+
21
+ it 'must show 3 available threads' do
22
+ enter 'break 21', 'cont', 'thread list', release
23
+ debug_file 'thread'
24
+ check_output_includes /(\+)?\d+ #<Thread:\S+ (sleep|run)>/,
25
+ /(\+)?\d+ #<Thread:\S+ (sleep|run)>/,
26
+ /(\+)?\d+ #<Thread:\S+ (sleep|run)>/
27
+ end
28
+ end
29
+
30
+ describe 'stop' do
31
+ it 'must mark thread as suspended' do
32
+ thnum = nil
33
+ enter 'c 21', ->{ "thread stop #{Byebug.contexts.last.thnum}" }, release
34
+ debug_file('thread') { thnum = Byebug.contexts.last.thnum }
35
+ check_output_includes /\$ #{thnum} #<Thread:/
36
+ end
37
+
38
+ it 'must actually suspend thread execution' do
39
+ enter 'c 21', 'trace on',
40
+ ->{ "thread stop #{Byebug.contexts.last.thnum}" }, release
41
+ debug_file('thread')
42
+ check_output_doesnt_include /Tracing: #{fullpath('thread')}:16/,
43
+ /Tracing: #{fullpath('thread')}:17/
44
+ end
45
+
46
+ it 'must show error message if thread number is not specified' do
47
+ enter 'break 8', 'cont', 'thread stop', release
48
+ debug_file 'thread'
49
+ check_error_includes '"thread stop" needs a thread number'
50
+ end
51
+
52
+ it 'must show error message when trying to stop current thread' do
53
+ enter 'cont 8', ->{"thread stop #{Byebug.contexts.first.thnum}"}, release
54
+ debug_file 'thread'
55
+ check_error_includes "It's the current thread"
56
+ end
57
+ end
58
+
59
+ describe 'resume' do
60
+ it 'must mark remove thread from the suspended state' do
61
+ thnum = nil
62
+ enter 'cont 21',
63
+ -> { thnum = Byebug.contexts.last.thnum ; "thread stop #{thnum}" },
64
+ -> { "thread resume #{thnum}" }, release
65
+ debug_file('thread') { Byebug.contexts.last.suspended?.must_equal false }
66
+ check_output_includes /\$ #{thnum} #<Thread:/, /#{thnum} #<Thread:/
67
+ end
68
+
69
+ it 'must show error message if thread number is not specified' do
70
+ enter 'break 8', 'cont', 'thread resume', release
71
+ debug_file 'thread'
72
+ check_error_includes '"thread resume" needs a thread number'
73
+ end
74
+
75
+ it 'must show error message when trying to resume current thread' do
76
+ enter 'c 8', ->{ "thread resume #{Byebug.contexts.first.thnum}" }, release
77
+ debug_file 'thread'
78
+ check_error_includes "It's the current thread"
79
+ end
80
+
81
+ it 'must show error message if it is not stopped' do
82
+ enter 'c 21', ->{ "thread resume #{Byebug.contexts.last.thnum}" }, release
83
+ debug_file 'thread'
84
+ check_error_includes 'Already running'
85
+ end
86
+ end
87
+
88
+ describe 'switch' do
89
+ it 'must switch to another thread' do
90
+ enter 'c 21', ->{ "thread switch #{Byebug.contexts.last.thnum}" }, release
91
+ debug_file('thread') { $state.line.must_equal 16 }
92
+ end
93
+
94
+ it 'must show error message if thread number is not specified' do
95
+ enter 'break 8', 'cont', 'thread switch', release
96
+ debug_file 'thread'
97
+ check_error_includes '"thread switch" needs a thread number'
98
+ end
99
+
100
+ it 'must show error message when trying to switch current thread' do
101
+ enter 'c 8', ->{ "thread switch #{Byebug.contexts.first.thnum}" }, release
102
+ debug_file 'thread'
103
+ check_error_includes "It's the current thread"
104
+ end
105
+ end
106
+ end