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,13 @@
1
+ module Byebug
2
+
3
+ class Breakpoint
4
+
5
+ def inspect
6
+ values = %w{id pos source expr hit_condition hit_count hit_value enabled?}.map do |field|
7
+ "#{field}: #{send(field)}"
8
+ end.join(", ")
9
+ "#<Byebug::Breakpoint #{values}>"
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,14 @@
1
+ module Byebug
2
+ class Context
3
+
4
+ def inspect
5
+ values = %w{
6
+ thread thnum stop_reason tracing ignored? stack_size dead? frame_line frame_file frame_self
7
+ }.map do |field|
8
+ "#{field}: #{send(field)}"
9
+ end.join(", ")
10
+ "#<Byebug::Context #{values}>"
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,67 @@
1
+ module MiniTest::Assertions
2
+
3
+ # This matcher checks that given collection is included into the original collection,
4
+ # and in correct order. It accepts both strings and regexps.
5
+ #
6
+ # Examples:
7
+ #
8
+ # assert_includes_in_order(%w{1 2 3 4 5}, %w{1 3 5}) # => pass
9
+ # assert_includes_in_order(%w{1 2 3 4 5}, %w{1 5 3}) # => fail
10
+ # assert_includes_in_order(w{1 2 3 4 5}, ["1", /\d+/, "5"]) # => pass
11
+ # assert_includes_in_order(w{1 2 3 4 5}, ["1", /\[a-z]+/, "5"]) # => fail
12
+ #
13
+ def assert_includes_in_order(given_collection, original_collection, msg = nil)
14
+ msg = message(msg) do
15
+ "Expected #{mu_pp(original_collection)} to include #{mu_pp(given_collection)} in order"
16
+ end
17
+ assert includes_in_order_result(original_collection, given_collection), msg
18
+ end
19
+
20
+ def refute_includes_in_order(given_collection, original_collection, msg = nil)
21
+ msg = message(msg) do
22
+ "Expected #{mu_pp(original_collection)} to not include #{mu_pp(given_collection)} in order"
23
+ end
24
+ refute includes_in_order_result(original_collection, given_collection), msg
25
+ end
26
+
27
+
28
+ private
29
+
30
+ def includes_in_order_result(original_collection, given_collection)
31
+ result = true
32
+ given_collection.each do |given_item|
33
+ result &&= case given_item
34
+ when String
35
+ index = original_collection.index(given_item)
36
+ if index
37
+ original_collection = original_collection[(index + 1)..-1]
38
+ true
39
+ else
40
+ false
41
+ end
42
+ when Regexp
43
+ index = nil
44
+ original_collection.each_with_index do |original_item, i|
45
+ if original_item =~ given_item
46
+ index = i
47
+ break
48
+ end
49
+ end
50
+ if index
51
+ original_collection = original_collection[(index + 1)..-1]
52
+ true
53
+ else
54
+ false
55
+ end
56
+ else
57
+ false
58
+ end
59
+ end
60
+ result
61
+ end
62
+ end
63
+
64
+ module MiniTest::Expectations
65
+ infect_an_assertion :assert_includes_in_order, :must_include_in_order
66
+ infect_an_assertion :refute_includes_in_order, :wont_include_in_order
67
+ end
@@ -0,0 +1,72 @@
1
+ module Mocha
2
+
3
+ class Expectation
4
+
5
+ # Allows to specify a block to execute when expectation will be matched.
6
+ # This way, we can specify dynamic values to return or just make some side effects
7
+ #
8
+ # Example:
9
+ #
10
+ # foo.expects(:bar).with('bla').calls { 2 + 3 }
11
+ # foo.bar('bla') # => 5
12
+ #
13
+ def calls(&block)
14
+ @calls ||= Call.new
15
+ @calls += Call.new(block)
16
+ self
17
+ end
18
+
19
+ def invoke_with_calls(arguments, &block)
20
+ invoke_without_calls(&block) || (@calls.next(arguments, &block) if @calls)
21
+ end
22
+ alias_method :invoke_without_calls, :invoke
23
+ alias_method :invoke, :invoke_with_calls
24
+
25
+ end
26
+
27
+ class Mock
28
+
29
+ # We monkey-patch that method to be able to pass arguments to Expectation#invoke method
30
+ def method_missing(symbol, *arguments, &block)
31
+ if @responder and not @responder.respond_to?(symbol)
32
+ raise NoMethodError, "undefined method `#{symbol}' for #{self.mocha_inspect} which responds like #{@responder.mocha_inspect}"
33
+ end
34
+ if matching_expectation_allowing_invocation = @expectations.match_allowing_invocation(symbol, *arguments)
35
+ # We change this line - added arguments
36
+ matching_expectation_allowing_invocation.invoke(arguments, &block)
37
+ else
38
+ if (matching_expectation = @expectations.match(symbol, *arguments)) || (!matching_expectation && !@everything_stubbed)
39
+ # We change this line - added arguments
40
+ matching_expectation.invoke(arguments, &block) if matching_expectation
41
+ message = UnexpectedInvocation.new(self, symbol, *arguments).to_s
42
+ require 'mocha/mockery'
43
+ message << Mockery.instance.mocha_inspect
44
+ raise ExpectationError.new(message, caller)
45
+ end
46
+ end
47
+ end
48
+
49
+ end
50
+
51
+ class Call
52
+
53
+ attr_reader :blocks
54
+
55
+ def initialize(*blocks)
56
+ @blocks = [ *blocks ]
57
+ end
58
+
59
+ def next(arguments, &block)
60
+ case @blocks.length
61
+ when 0 then nil
62
+ when 1 then @blocks.first.call(*arguments, &block)
63
+ else @blocks.shift.call(*arguments, &block)
64
+ end
65
+ end
66
+
67
+ def +(other)
68
+ self.class.new(*(@blocks + other.blocks))
69
+ end
70
+
71
+ end
72
+ end
@@ -0,0 +1,7 @@
1
+ class Byebug::Processor
2
+ class << self
3
+ def print(message)
4
+ Byebug.handler.interface.print_queue << message
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,206 @@
1
+ module TestDsl
2
+
3
+ module Shared
4
+ def fullpath(filename)
5
+ (Pathname.new(__FILE__) + "../../examples/#{filename}.rb").cleanpath.to_s
6
+ end
7
+ end
8
+
9
+ include Shared
10
+
11
+ def self.included(base)
12
+ base.class_eval do
13
+ extend ClassMethods
14
+ before do
15
+ Byebug.interface = TestInterface.new
16
+ Byebug.handler.display.clear
17
+ end
18
+ after do
19
+ Byebug.handler.display.clear
20
+ end
21
+ end
22
+ end
23
+
24
+ # Adds commands to the input queue, so they will be later retrieved by
25
+ # Processor, i.e. it emulates user's input.
26
+ #
27
+ # If a command is a Proc object, it will be executed before retrieving by
28
+ # Processor. May be handy when you need build a command depending on the
29
+ # current context/state.
30
+ #
31
+ # Usage:
32
+ # enter 'b 12'
33
+ # enter 'b 12', 'cont'
34
+ # enter ['b 12', 'cont']
35
+ # enter 'b 12', ->{"disable #{breakpoint.id}"}, 'cont'
36
+ #
37
+ def enter(*messages)
38
+ messages = messages.first.is_a?(Array) ? messages.first : messages
39
+ interface.input_queue.concat(messages)
40
+ end
41
+
42
+ # Runs a byebug with the provided basename for a file. The file should be
43
+ # placed in the test/examples dir.
44
+ #
45
+ # You also can specify a block, which will be executed when Processor extracts
46
+ # all the commands from the input queue. You can use it e.g. for making
47
+ # asserts for the current test. If you specified the block, and it never was
48
+ # executed, the test will fail.
49
+ #
50
+ # Usage:
51
+ # debug "ex1" # ex1 should be placed in test/examples/ex1.rb
52
+ #
53
+ # enter 'b 4', 'cont'
54
+ # debug("ex1") { state.line.must_equal 4 }
55
+ #
56
+ def debug_file(filename, &block)
57
+ is_test_block_called = false
58
+ debug_completed = false
59
+ exception = nil
60
+ Byebug.stubs(:run_init_script)
61
+ if block
62
+ interface.test_block= lambda do
63
+ is_test_block_called = true
64
+ # We need to store exception and reraise it after completing debugging,
65
+ # because Byebug will swallow any exceptions, so e.g. our failed
66
+ # assertions will be ignored
67
+ begin
68
+ block.call
69
+ rescue Exception => e
70
+ exception = e
71
+ raise e
72
+ end
73
+ end
74
+ end
75
+ Byebug.start do
76
+ load fullpath(filename)
77
+ debug_completed = true
78
+ end
79
+ flunk "Debug block was not completed" unless debug_completed
80
+ flunk "Test block was provided, but not called" if block && !is_test_block_called
81
+ raise exception if exception
82
+ end
83
+
84
+ #
85
+ # Checks the output of byebug. By default it checks output queue of the current
86
+ # interface, but you can check again any queue by providing it as a second
87
+ # argument.
88
+ #
89
+ # Usage:
90
+ # enter 'break 4', 'cont'
91
+ # debug("ex1")
92
+ # check_output "Breakpoint 1 at #{fullpath('ex1')}:4"
93
+ #
94
+ def check_output(check_method, *args)
95
+ queue = args.last.is_a?(String) || args.last.is_a?(Regexp) ? interface.output_queue : args.pop
96
+ queue_messages = queue.map(&:strip)
97
+ messages = Array(args).map { |msg| msg.is_a?(String) ? msg.strip : msg }
98
+ queue_messages.send(check_method, messages)
99
+ end
100
+
101
+ def check_output_includes(*args)
102
+ check_output :must_include_in_order, *args
103
+ end
104
+
105
+ def check_output_doesnt_include(*args)
106
+ check_output :wont_include_in_order, *args
107
+ end
108
+
109
+ def interface
110
+ Byebug.handler.interface
111
+ end
112
+
113
+ def state
114
+ $rdebug_state
115
+ end
116
+
117
+ def context
118
+ state.context
119
+ end
120
+
121
+ def breakpoint
122
+ Byebug.breakpoints.first
123
+ end
124
+
125
+ def force_set_const(klass, const, value)
126
+ klass.send(:remove_const, const) if klass.const_defined?(const)
127
+ klass.const_set(const, value)
128
+ end
129
+
130
+ def change_line_in_file(file, line, new_line_content)
131
+ old_content = File.read(file)
132
+ new_content = old_content.split("\n").tap { |c| c[line - 1] = new_line_content }.join("\n")
133
+ File.open(file, 'w') { |f| f.write(new_content) }
134
+ end
135
+
136
+ def temporary_change_method_value(item, method, value)
137
+ old = item.send(method)
138
+ item.send("#{method}=", value)
139
+ yield
140
+ ensure
141
+ item.send("#{method}=", old)
142
+ end
143
+
144
+ def temporary_change_hash_value(item, key, value)
145
+ old_value = item[key]
146
+ item[key] = value
147
+ yield
148
+ ensure
149
+ item[key] = old_value
150
+ end
151
+
152
+ def temporary_set_const(klass, const, value)
153
+ old_value = klass.const_defined?(const) ? klass.const_get(const) : :__undefined__
154
+ force_set_const(klass, const, value)
155
+ yield
156
+ ensure
157
+ if old_value == :__undefined__
158
+ klass.send(:remove_const, const)
159
+ else
160
+ force_set_const(klass, const, old_value)
161
+ end
162
+ end
163
+
164
+ module ClassMethods
165
+
166
+ include Shared
167
+
168
+ def temporary_change_method_value(item, method, value)
169
+ old_value = nil
170
+ before do
171
+ old_value = item.send(method)
172
+ item.send("#{method}=", value)
173
+ end
174
+ after do
175
+ item.send("#{method}=", old_value)
176
+ end
177
+ end
178
+
179
+ def temporary_change_hash_value(item, key, value)
180
+ old_value = nil
181
+ before do
182
+ old_value = item[key]
183
+ item[key] = value
184
+ end
185
+ after do
186
+ item[key] = old_value
187
+ end
188
+ end
189
+
190
+ def temporary_set_const(klass, const, value)
191
+ old_value = nil
192
+ before do
193
+ old_value = klass.const_defined?(const) ? klass.const_get(const) : :__undefined__
194
+ force_set_const(klass, const, value)
195
+ end
196
+ after do
197
+ if old_value == :__undefined__
198
+ klass.send(:remove_const, const)
199
+ else
200
+ force_set_const(klass, const, old_value)
201
+ end
202
+ end
203
+ end
204
+ end
205
+
206
+ end
@@ -0,0 +1,68 @@
1
+ class TestInterface < Byebug::Interface
2
+ attr_reader :input_queue, :output_queue, :error_queue, :confirm_queue
3
+
4
+ attr_accessor :command_queue, :histfile, :history_length, :history_save
5
+ attr_accessor :print_queue, :readline_support, :restart_file, :test_block
6
+
7
+ def initialize
8
+ @input_queue = []
9
+ @output_queue = []
10
+ @error_queue = []
11
+ @confirm_queue = []
12
+ @command_queue = []
13
+ @print_queue = []
14
+ @readline_support = false
15
+ end
16
+
17
+ def errmsg(*args)
18
+ @error_queue << format(args)
19
+ end
20
+
21
+ def read_command(*args)
22
+ if @input_queue.empty? && test_block
23
+ test_block.call
24
+ self.test_block = nil
25
+ end
26
+ result = @input_queue.shift
27
+ result.is_a?(Proc) ? result.call : result
28
+ end
29
+
30
+ def print(*args)
31
+ @output_queue << format(args)
32
+ end
33
+
34
+ def confirm(message)
35
+ @confirm_queue << message
36
+ read_command message
37
+ end
38
+
39
+ def readline_support?
40
+ @readline_support
41
+ end
42
+
43
+ def finalize
44
+ end
45
+
46
+ def close
47
+ end
48
+
49
+ def inspect
50
+ [
51
+ "input_queue: #{input_queue.inspect}",
52
+ "output_queue: #{output_queue.inspect}",
53
+ "error_queue: #{error_queue.inspect}",
54
+ "confirm_queue: #{confirm_queue.inspect}",
55
+ "print_queue: #{print_queue.inspect}"
56
+ ].join("\n")
57
+ end
58
+
59
+ private
60
+
61
+ def format(args)
62
+ if args.size > 1
63
+ args.first % args[1..-1]
64
+ else
65
+ args.first
66
+ end
67
+ end
68
+ end