byebug 0.0.1

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 (133) hide show
  1. data/.gitignore +10 -0
  2. data/.travis.yml +8 -0
  3. data/AUTHORS +10 -0
  4. data/CHANGELOG.md +2 -0
  5. data/CONTRIBUTING.md +1 -0
  6. data/Gemfile +3 -0
  7. data/LICENSE +20 -0
  8. data/README.md +5 -0
  9. data/Rakefile +28 -0
  10. data/bin/byebug +395 -0
  11. data/byebug.gemspec +29 -0
  12. data/doc/hanoi.rb +35 -0
  13. data/doc/primes.rb +28 -0
  14. data/doc/rdebug-emacs.texi +1030 -0
  15. data/doc/test-tri2.rb +18 -0
  16. data/doc/tri3.rb +8 -0
  17. data/doc/triangle.rb +12 -0
  18. data/ext/byebug/breakpoint.c +476 -0
  19. data/ext/byebug/byebug.c +512 -0
  20. data/ext/byebug/byebug.h +131 -0
  21. data/ext/byebug/context.c +424 -0
  22. data/ext/byebug/extconf.rb +21 -0
  23. data/ext/byebug/locker.c +53 -0
  24. data/lib/byebug.rb +404 -0
  25. data/lib/byebug/command.rb +232 -0
  26. data/lib/byebug/commands/breakpoints.rb +153 -0
  27. data/lib/byebug/commands/catchpoint.rb +56 -0
  28. data/lib/byebug/commands/condition.rb +49 -0
  29. data/lib/byebug/commands/continue.rb +38 -0
  30. data/lib/byebug/commands/control.rb +110 -0
  31. data/lib/byebug/commands/display.rb +122 -0
  32. data/lib/byebug/commands/edit.rb +48 -0
  33. data/lib/byebug/commands/enable.rb +202 -0
  34. data/lib/byebug/commands/eval.rb +176 -0
  35. data/lib/byebug/commands/finish.rb +43 -0
  36. data/lib/byebug/commands/frame.rb +303 -0
  37. data/lib/byebug/commands/help.rb +56 -0
  38. data/lib/byebug/commands/info.rb +462 -0
  39. data/lib/byebug/commands/irb.rb +123 -0
  40. data/lib/byebug/commands/jump.rb +66 -0
  41. data/lib/byebug/commands/kill.rb +51 -0
  42. data/lib/byebug/commands/list.rb +94 -0
  43. data/lib/byebug/commands/method.rb +84 -0
  44. data/lib/byebug/commands/quit.rb +39 -0
  45. data/lib/byebug/commands/reload.rb +40 -0
  46. data/lib/byebug/commands/save.rb +90 -0
  47. data/lib/byebug/commands/set.rb +210 -0
  48. data/lib/byebug/commands/show.rb +246 -0
  49. data/lib/byebug/commands/skip.rb +35 -0
  50. data/lib/byebug/commands/source.rb +36 -0
  51. data/lib/byebug/commands/stepping.rb +83 -0
  52. data/lib/byebug/commands/threads.rb +189 -0
  53. data/lib/byebug/commands/tmate.rb +36 -0
  54. data/lib/byebug/commands/trace.rb +56 -0
  55. data/lib/byebug/commands/variables.rb +199 -0
  56. data/lib/byebug/context.rb +58 -0
  57. data/lib/byebug/helper.rb +69 -0
  58. data/lib/byebug/interface.rb +223 -0
  59. data/lib/byebug/processor.rb +468 -0
  60. data/lib/byebug/version.rb +3 -0
  61. data/man/rdebug.1 +241 -0
  62. data/test/breakpoints_test.rb +357 -0
  63. data/test/conditions_test.rb +77 -0
  64. data/test/continue_test.rb +44 -0
  65. data/test/display_test.rb +141 -0
  66. data/test/edit_test.rb +56 -0
  67. data/test/eval_test.rb +92 -0
  68. data/test/examples/breakpoint1.rb +15 -0
  69. data/test/examples/breakpoint2.rb +7 -0
  70. data/test/examples/conditions.rb +4 -0
  71. data/test/examples/continue.rb +4 -0
  72. data/test/examples/display.rb +5 -0
  73. data/test/examples/edit.rb +3 -0
  74. data/test/examples/edit2.rb +3 -0
  75. data/test/examples/eval.rb +4 -0
  76. data/test/examples/finish.rb +20 -0
  77. data/test/examples/frame.rb +20 -0
  78. data/test/examples/frame_threads.rb +31 -0
  79. data/test/examples/help.rb +2 -0
  80. data/test/examples/info.rb +38 -0
  81. data/test/examples/info2.rb +3 -0
  82. data/test/examples/info_threads.rb +48 -0
  83. data/test/examples/irb.rb +6 -0
  84. data/test/examples/jump.rb +14 -0
  85. data/test/examples/kill.rb +2 -0
  86. data/test/examples/list.rb +12 -0
  87. data/test/examples/method.rb +15 -0
  88. data/test/examples/post_mortem.rb +19 -0
  89. data/test/examples/quit.rb +2 -0
  90. data/test/examples/reload.rb +6 -0
  91. data/test/examples/restart.rb +6 -0
  92. data/test/examples/save.rb +3 -0
  93. data/test/examples/set.rb +3 -0
  94. data/test/examples/set_annotate.rb +12 -0
  95. data/test/examples/settings.rb +1 -0
  96. data/test/examples/show.rb +2 -0
  97. data/test/examples/source.rb +3 -0
  98. data/test/examples/stepping.rb +21 -0
  99. data/test/examples/thread.rb +32 -0
  100. data/test/examples/tmate.rb +10 -0
  101. data/test/examples/trace.rb +7 -0
  102. data/test/examples/trace_threads.rb +20 -0
  103. data/test/examples/variables.rb +26 -0
  104. data/test/finish_test.rb +48 -0
  105. data/test/frame_test.rb +143 -0
  106. data/test/help_test.rb +50 -0
  107. data/test/info_test.rb +313 -0
  108. data/test/irb_test.rb +81 -0
  109. data/test/jump_test.rb +70 -0
  110. data/test/kill_test.rb +48 -0
  111. data/test/list_test.rb +145 -0
  112. data/test/method_test.rb +70 -0
  113. data/test/post_mortem_test.rb +27 -0
  114. data/test/quit_test.rb +56 -0
  115. data/test/reload_test.rb +44 -0
  116. data/test/restart_test.rb +164 -0
  117. data/test/save_test.rb +92 -0
  118. data/test/set_test.rb +177 -0
  119. data/test/show_test.rb +293 -0
  120. data/test/source_test.rb +45 -0
  121. data/test/stepping_test.rb +130 -0
  122. data/test/support/breakpoint.rb +13 -0
  123. data/test/support/context.rb +14 -0
  124. data/test/support/matchers.rb +67 -0
  125. data/test/support/mocha_extensions.rb +72 -0
  126. data/test/support/processor.rb +7 -0
  127. data/test/support/test_dsl.rb +206 -0
  128. data/test/support/test_interface.rb +68 -0
  129. data/test/test_helper.rb +10 -0
  130. data/test/tmate_test.rb +44 -0
  131. data/test/trace_test.rb +159 -0
  132. data/test/variables_test.rb +119 -0
  133. metadata +265 -0
@@ -0,0 +1,77 @@
1
+ require_relative 'test_helper'
2
+
3
+ describe "Conditions" do
4
+ include TestDsl
5
+
6
+ describe "setting condition" do
7
+ before { enter 'break 3' }
8
+
9
+ describe "successfully" do
10
+ it "must assign the expression to breakpoint" do
11
+ enter ->{"cond #{breakpoint.id} b == 5"}, "cont"
12
+ debug_file('conditions') { breakpoint.expr.must_equal "b == 5" }
13
+ end
14
+
15
+ it "must stop at the breakpoint if condition is true" do
16
+ enter ->{"cond #{breakpoint.id} b == 5"}, "cont"
17
+ debug_file('conditions') { state.line.must_equal 3 }
18
+ end
19
+
20
+ it "must work with full command name too" do
21
+ enter ->{"condition #{breakpoint.id} b == 5"}, "cont"
22
+ debug_file('conditions') { state.line.must_equal 3 }
23
+ end
24
+ end
25
+
26
+ describe "unsucessfully" do
27
+ before { enter "break 4" }
28
+
29
+ it "must not stop at the breakpoint if condition is false" do
30
+ enter ->{"cond #{breakpoint.id} b == 3"}, "cont"
31
+ debug_file('conditions') { state.line.must_equal 4 }
32
+ end
33
+ it "must assign the expression to breakpoint in spite of incorrect syntax" do
34
+ enter ->{"cond #{breakpoint.id} b =="}, "cont"
35
+ debug_file('conditions') { breakpoint.expr.must_equal "b ==" }
36
+ end
37
+ it "must ignore the condition if when incorrect syntax" do
38
+ enter ->{"cond #{breakpoint.id} b =="}, "cont"
39
+ debug_file('conditions') { state.line.must_equal 4 }
40
+ end
41
+ end
42
+ end
43
+
44
+ describe "removing conditions" do
45
+ before { enter "break 3 if b == 3", "break 4", ->{"cond #{breakpoint.id}"}, "cont" }
46
+
47
+ it "must remove the condition from the breakpoint" do
48
+ debug_file('conditions') { breakpoint.expr.must_be_nil }
49
+ end
50
+
51
+ it "must not stop on the breakpoint" do
52
+ debug_file('conditions') { state.line.must_equal 3 }
53
+ end
54
+ end
55
+
56
+ describe "errors" do
57
+ it "must show error if there are no breakpoints" do
58
+ enter 'cond 1 true'
59
+ debug_file('conditions')
60
+ check_output_includes "No breakpoints have been set."
61
+ end
62
+
63
+ it "must not set breakpoint condition if breakpoint id is incorrect" do
64
+ enter 'break 3', 'cond 8 b == 3', 'cont'
65
+ debug_file('conditions') { state.line.must_equal 3 }
66
+ end
67
+ end
68
+
69
+ describe "Post Mortem" do
70
+ it "must be able to set conditions in post-mortem mode" do
71
+ skip("No post morten mode for now")
72
+ #enter 'cont', 'break 12', ->{"cond #{breakpoint.id} true"}, 'cont'
73
+ #debug_file("post_mortem") { state.line.must_equal 12 }
74
+ end
75
+ end
76
+
77
+ end
@@ -0,0 +1,44 @@
1
+ require_relative 'test_helper'
2
+
3
+ describe "Continue Command" do
4
+ include TestDsl
5
+
6
+ describe "successful" do
7
+ it "must continue up to breakpoint if no line specified" do
8
+ enter 'break 4', 'continue'
9
+ debug_file('continue') { state.line.must_equal 4 }
10
+ end
11
+
12
+ it "must work in abbreviated mode too" do
13
+ enter 'break 4', 'cont'
14
+ debug_file('continue') { state.line.must_equal 4 }
15
+ end
16
+
17
+ it "must continue up to specified line" do
18
+ enter 'cont 4'
19
+ debug_file('continue') { state.line.must_equal 4 }
20
+ end
21
+
22
+ # XXX: Decide whether to keep original behaviour (i don't like it but maybe
23
+ # I'm wrong) or make the test below pass
24
+ #it "must not keep temporal breakpoint when line specified" do
25
+ # enter 'cont 4'
26
+ # debug_file('continue') { Byebug.breakpoints.size.must_equal 0 }
27
+ #end
28
+ end
29
+
30
+ describe "unsuccessful" do
31
+ it "must ignore the command if specified line is not valid" do
32
+ enter 'cont 123'
33
+ debug_file('continue') { state.line.must_equal 2 }
34
+ end
35
+
36
+ it "must show error if specified line is not valid" do
37
+ enter 'cont 123'
38
+ debug_file('continue')
39
+ check_output_includes "Line 123 is not a stopping point in file \"#{fullpath('continue')}\".", interface.error_queue
40
+ end
41
+
42
+ it "must ignore the line if the context is dead"
43
+ end
44
+ end
@@ -0,0 +1,141 @@
1
+ require_relative 'test_helper'
2
+
3
+ describe "Display Command" do
4
+ include TestDsl
5
+
6
+ it "must show expressions" do
7
+ enter 'break 3', 'cont', 'display d + 1'
8
+ debug_file('display')
9
+ check_output_includes "1: ", "d + 1 = 5"
10
+ end
11
+
12
+ it "must work with shortcut" do
13
+ enter 'break 3', 'cont', 'disp d + 1'
14
+ debug_file('display')
15
+ check_output_includes "1: ", "d + 1 = 5"
16
+ end
17
+
18
+ it "must save displayed expressions" do
19
+ enter 'display d + 1'
20
+ debug_file('display') { state.display.must_equal [[true, "d + 1"]] }
21
+ end
22
+
23
+ it "displays all expressions available" do
24
+ enter 'break 3', 'cont', -> do
25
+ Byebug.handler.display.concat([[true, "abc"], [true, "d"]]); 'display'
26
+ end
27
+ debug_file('display')
28
+ check_output_includes "1: ", "abc = ", "2: ", "d = 4"
29
+ end
30
+
31
+ describe "undisplay" do
32
+ describe "undisplay all" do
33
+ before do
34
+ enter 'break 3', 'cont', -> do
35
+ Byebug.handler.display.concat([[true, "abc"], [true, "d"]])
36
+ 'undisplay'
37
+ end, confirm_response, 'display'
38
+ end
39
+
40
+ describe "confirmation is successful" do
41
+ let(:confirm_response) { 'y' }
42
+
43
+ it "must ask about confirmation" do
44
+ debug_file('display')
45
+ check_output_includes "Clear all expressions? (y/n)", interface.confirm_queue
46
+ end
47
+
48
+ it "must set all expressions saved to 'false'" do
49
+ debug_file('display') { state.display.must_equal [[false, "abc"], [false, "d"]] }
50
+ end
51
+
52
+ it "must not show any output" do
53
+ debug_file('display')
54
+ check_output_doesnt_include "1: ", "abc = ", "2: ", "d = 4"
55
+ end
56
+ end
57
+
58
+ describe "confirmation is unsuccessful" do
59
+ let(:confirm_response) { 'n' }
60
+
61
+ it "must set all expressions saved to 'false'" do
62
+ debug_file('display') { state.display.must_equal [[true, "abc"], [true, "d"]] }
63
+ end
64
+
65
+ it "must not show any output" do
66
+ debug_file('display')
67
+ check_output_includes "1: ", "abc = ", "2: ", "d = 4"
68
+ end
69
+ end
70
+ end
71
+
72
+ describe "undisplay specific position" do
73
+ before do
74
+ enter 'break 3', 'cont', -> do
75
+ Byebug.handler.display.concat([[true, "abc"], [true, "d"]])
76
+ 'undisplay 1'
77
+ end, 'display'
78
+ end
79
+
80
+ it "must set inactive positions" do
81
+ debug_file('display') { state.display.must_equal [[nil, "abc"], [true, "d"]] }
82
+ end
83
+
84
+ it "must display only the active position" do
85
+ debug_file('display')
86
+ check_output_includes "2: ", "d = 4"
87
+ end
88
+
89
+ it "must not display the disabled position" do
90
+ debug_file('display')
91
+ check_output_doesnt_include "1: ", "abc"
92
+ end
93
+ end
94
+ end
95
+
96
+ describe "disable" do
97
+ it "must disable a position" do
98
+ enter 'display d', 'disable display 1'
99
+ debug_file('display') { state.display.must_equal [[false, "d"]] }
100
+ end
101
+
102
+ it "must show an error if no displays are set" do
103
+ enter 'disable display 1'
104
+ debug_file('display')
105
+ check_output_includes "No display expressions have been set.", interface.error_queue
106
+ end
107
+
108
+ it "must show an error if there is no such display position" do
109
+ enter 'display d', 'disable display 4'
110
+ debug_file('display')
111
+ check_output_includes "Disable display argument '4' needs to at most 1."
112
+ end
113
+ end
114
+
115
+ describe "enable" do
116
+ it "must enable a position" do
117
+ enter 'display d', 'disable display 1', 'enable display 1'
118
+ debug_file('display') { state.display.must_equal [[true, "d"]] }
119
+ end
120
+ end
121
+
122
+ describe "annotate" do
123
+ temporary_change_method_value(Byebug, :annotate, 0)
124
+
125
+ it "must show display expression in annotation" do
126
+ enter 'display 2 + 2', 'set annotate 3', 'next', 'next'
127
+ debug_file 'display'
128
+ check_output_includes "\x1A\x1Adisplay", "1:", "2 + 2 = 4"
129
+ end
130
+ end
131
+
132
+ describe "Post Mortem" do
133
+ it "must be able to set display expressions in post-mortem mode" do
134
+ skip("No post morten mode for now")
135
+ # enter 'cont', 'display 2 + 2', 'cont'
136
+ # debug_file("post_mortem")
137
+ # check_output_includes "1:", "2 + 2 = 4"
138
+ end
139
+ end
140
+
141
+ end
@@ -0,0 +1,56 @@
1
+ require_relative 'test_helper'
2
+
3
+ describe "Edit Command" do
4
+ include TestDsl
5
+
6
+ it "must open an editor with current file and line" do
7
+ temporary_change_hash_value(ENV, "EDITOR", 'editr') do
8
+ Byebug::Edit.any_instance.expects(:system).with("editr +2 #{fullpath('edit')}")
9
+ enter 'edit'
10
+ debug_file 'edit'
11
+ end
12
+ end
13
+
14
+ it "must open a default editor with current file and line" do
15
+ temporary_change_hash_value(ENV, "EDITOR", nil) do
16
+ Byebug::Edit.any_instance.expects(:system).with("ex +2 #{fullpath('edit')}")
17
+ enter 'edit'
18
+ debug_file 'edit'
19
+ end
20
+ end
21
+
22
+ it "must open an editor with specified file and line" do
23
+ temporary_change_hash_value(ENV, "EDITOR", 'editr') do
24
+ Byebug::Edit.any_instance.expects(:system).with("editr +3 #{fullpath('edit2')}")
25
+ enter "edit #{fullpath('edit2')}:3"
26
+ debug_file 'edit'
27
+ end
28
+ end
29
+
30
+ it "must show an error if there is no such line" do
31
+ enter "edit #{fullpath('edit3')}:6"
32
+ debug_file 'edit'
33
+ check_output_includes "File \"#{fullpath('edit3')}\" is not readable.", interface.error_queue
34
+ end
35
+
36
+ it "must show an error if there is incorrect syntax" do
37
+ enter "edit blabla"
38
+ debug_file 'edit'
39
+ check_output_includes "Invalid file/line number specification: blabla", interface.error_queue
40
+ end
41
+
42
+
43
+ describe "Post Mortem" do
44
+ # TODO: This test fails with "Segmentation fault". Probably need to fix it somehow, or forbid this
45
+ # command in the post mortem mode
46
+ it "must work in post-mortem mode" do
47
+ skip("No post morten mode for now")
48
+ #temporary_change_hash_value(ENV, "EDITOR", 'editr') do
49
+ # Byebug::Edit.any_instance.expects(:system).with("editr +2 #{fullpath('edit')}")
50
+ # enter 'cont', "edit #{fullpath('edit')}:2", 'cont'
51
+ # debug_file "post_mortem"
52
+ #end
53
+ end
54
+ end
55
+
56
+ end
@@ -0,0 +1,92 @@
1
+ require_relative 'test_helper'
2
+
3
+ describe "Eval Command" do
4
+ include TestDsl
5
+
6
+ it "must evaluate an expression" do
7
+ enter 'eval 3 + 2'
8
+ debug_file 'eval'
9
+ check_output_includes "5"
10
+ end
11
+
12
+ it "must work with shortcut" do
13
+ enter 'e 3 + 2'
14
+ debug_file 'eval'
15
+ check_output_includes "5"
16
+ end
17
+
18
+ it "must work with another syntax" do
19
+ enter 'p 3 + 2'
20
+ debug_file 'eval'
21
+ check_output_includes "5"
22
+ end
23
+
24
+ describe "autoeval" do
25
+ temporary_change_hash_value(Byebug::Command.settings, :autoeval, false)
26
+
27
+ it "must eval the expression if no matching command is found" do
28
+ enter 'set autoeval', '[5,6,7].inject(&:+)'
29
+ debug_file 'eval'
30
+ check_output_includes "18"
31
+ end
32
+ end
33
+
34
+ describe "stack trace on error" do
35
+ temporary_change_hash_value(Byebug::Command.settings, :stack_trace_on_error, false)
36
+
37
+ it "must show a stack trace if showing trace on error is enabled" do
38
+ enter 'set notrace', 'eval 2 / 0'
39
+ debug_file 'eval'
40
+ check_output_includes "ZeroDivisionError Exception: divided by 0"
41
+ check_output_doesnt_include /\S+:\d+:in `eval':divided by 0/
42
+ end
43
+
44
+ it "must show a stack trace if showing trace on error is enabled" do
45
+ enter 'set trace', 'eval 2 / 0'
46
+ debug_file 'eval'
47
+ check_output_includes /\S+:\d+:in `eval':divided by 0/
48
+ check_output_doesnt_include "ZeroDivisionError Exception: divided by 0"
49
+ end
50
+ end
51
+
52
+
53
+ it "must pretty print the expression result" do
54
+ enter 'pp {a: "3" * 40, b: "4" * 30}'
55
+ debug_file 'eval'
56
+ check_output_includes "{:a=>\"#{"3" * 40}\",\n :b=>\"#{"4" * 30}\"}"
57
+ end
58
+
59
+ it "must print expression and columnize the result" do
60
+ temporary_change_hash_value(Byebug::PutLCommand.settings, :width, 20) do
61
+ enter 'putl [1, 2, 3, 4, 5, 9, 8, 7, 6]'
62
+ debug_file 'eval'
63
+ check_output_includes "1 3 5 8 6\n2 4 9 7"
64
+ end
65
+ end
66
+
67
+ it "must print expression and sort and columnize the result" do
68
+ temporary_change_hash_value(Byebug::PSCommand.settings, :width, 20) do
69
+ enter 'ps [1, 2, 3, 4, 5, 9, 8, 7, 6]'
70
+ debug_file 'eval'
71
+ check_output_includes "1 3 5 7 9\n2 4 6 8"
72
+ end
73
+ end
74
+
75
+ it "must set width by the 'set' command" do
76
+ temporary_change_hash_value(Byebug::PSCommand.settings, :width, 20) do
77
+ enter 'set width 10', 'ps [1, 2, 3, 4, 5, 9, 8, 7, 6]'
78
+ debug_file 'eval'
79
+ check_output_includes "1 4 7\n2 5 8\n3 6 9"
80
+ end
81
+ end
82
+
83
+ describe "Post Mortem" do
84
+ it "must work in post-mortem mode" do
85
+ skip("No post morten mode for now")
86
+ #enter 'cont', 'eval 2 + 2'
87
+ #debug_file "post_mortem"
88
+ #check_output_includes "4"
89
+ end
90
+ end
91
+
92
+ end
@@ -0,0 +1,15 @@
1
+ class A
2
+ def self.a
3
+ 4
4
+ end
5
+ def b
6
+ 3
7
+ end
8
+ end
9
+
10
+ a = 3
11
+ # A comment
12
+ byebug
13
+ b = 5
14
+ c = a + b
15
+ load Pathname.new(__FILE__ + "/../breakpoint2.rb").cleanpath
@@ -0,0 +1,7 @@
1
+ d = 4
2
+ c = 3
3
+ e = 3 + 4
4
+ f = e + 5
5
+
6
+ A.a
7
+ A.new.b
@@ -0,0 +1,4 @@
1
+ byebug
2
+ b = 5
3
+ c = b + 5
4
+ c
@@ -0,0 +1,4 @@
1
+ byebug
2
+ b = 5
3
+ c = b + 5
4
+ c