pry-stack 0.5.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.
@@ -0,0 +1,65 @@
1
+ require 'helper'
2
+
3
+ Pry.config.output = StringIO.new
4
+
5
+ describe PryStack::FrameManager do
6
+
7
+ before do
8
+ @pry_instance = Pry.new
9
+ @bindings = [binding, binding, binding, binding]
10
+ @bindings.each_with_index { |v, i| v.eval("x = #{i}") }
11
+ @pry_instance.binding_stack.push @bindings.last
12
+ @frame_manager = PE::FrameManager.new(@bindings, @pry_instance)
13
+ end
14
+
15
+ describe "creation" do
16
+ it "should make bindings accessible via 'bindings' method" do
17
+ @frame_manager.bindings.should == @bindings
18
+ end
19
+
20
+ it "should set binding_index to 0" do
21
+ @frame_manager.binding_index.should == 0
22
+ end
23
+
24
+ it "should set current_frame to first frame" do
25
+ @frame_manager.current_frame.should == @bindings.first
26
+ end
27
+ end
28
+
29
+ describe "FrameManager#change_frame_to" do
30
+ it 'should change the frame to the given one' do
31
+ @frame_manager.change_frame_to(1)
32
+
33
+ @frame_manager.binding_index.should == 1
34
+ @frame_manager.current_frame.should == @bindings[1]
35
+ @pry_instance.binding_stack.last.should == @frame_manager.current_frame
36
+ end
37
+
38
+ it 'should accept negative indices when specifying frame' do
39
+ @frame_manager.change_frame_to(-1)
40
+
41
+ # negative index is converted to a positive one inside change_frame_to
42
+ @frame_manager.binding_index.should == @bindings.size - 1
43
+
44
+ @frame_manager.current_frame.should == @bindings[-1]
45
+ @pry_instance.binding_stack.last.should == @frame_manager.current_frame
46
+ end
47
+ end
48
+
49
+ describe "FrameManager#refresh_frame" do
50
+ it 'should change the Pry frame to the active one in the FrameManager' do
51
+ @frame_manager.binding_index = 2
52
+ @frame_manager.refresh_frame
53
+
54
+ @pry_instance.binding_stack.last.should == @frame_manager.current_frame
55
+ end
56
+ end
57
+
58
+ describe "FrameManager is Enumerable" do
59
+ it 'should perform an Enumerable#map on the frames' do
60
+ @frame_manager.map { |v| v.eval("x") }.should == (0..(@bindings.size - 1)).to_a
61
+ end
62
+ end
63
+
64
+ end
65
+
@@ -0,0 +1,393 @@
1
+ require 'helper'
2
+
3
+ describe PryStack do
4
+
5
+ describe "Pry.start" do
6
+ before do
7
+ Pry.config.hooks.add_hook(:when_started, :save_caller_bindings, WhenStartedHook)
8
+ Pry.config.hooks.add_hook(:after_session, :delete_frame_manager, AfterSessionHook)
9
+
10
+ @o = Object.new
11
+ class << @o; attr_reader :frame; end
12
+ def @o.bing() bong end
13
+ def @o.bong() bang end
14
+ def @o.bang() Pry.start(binding) end
15
+ end
16
+
17
+ after do
18
+ Pry.config.hooks.delete_hook(:when_started, :save_caller_bindings)
19
+ Pry.config.hooks.delete_hook(:after_session, :delete_frame_manager)
20
+ end
21
+
22
+ describe ":initial_frame option" do
23
+ it 'should default to first frame when no option provided' do
24
+ redirect_pry_io(StringIO.new("@frame = __method__\nexit\n"), out=StringIO.new) do
25
+ @o.bing
26
+ end
27
+
28
+ @o.frame.should == :bang
29
+ end
30
+
31
+ it 'should begin at correct frame even if Pry.start is monkey-patched (only works with one monkey-patch currently)' do
32
+ class << Pry
33
+ alias_method :old_start, :start
34
+
35
+ def start(*args, &block)
36
+ old_start(*args, &block)
37
+ end
38
+ end
39
+
40
+ o = Object.new
41
+ class << o; attr_reader :frames; end
42
+ def o.bing() bong end
43
+ def o.bong() bang end
44
+ def o.bang() Pry.start(binding) end
45
+
46
+ redirect_pry_io(InputTester.new(
47
+ "@frames = SE.frame_manager(_pry_).bindings.take(3)",
48
+ "exit-all")) do
49
+ o.bing
50
+ end
51
+
52
+ o.frames.map { |f| f.eval("__method__") }.should == [:bang, :bong, :bing]
53
+
54
+ class << Pry
55
+ alias_method :start, :old_start
56
+ end
57
+ end
58
+
59
+ it 'should begin session at specified frame' do
60
+ o = Object.new
61
+ class << o; attr_reader :frame; end
62
+ def o.bing() bong end
63
+ def o.bong() bang end
64
+ def o.bang() Pry.start(binding, :initial_frame => 1) end #*
65
+
66
+ redirect_pry_io(StringIO.new("@frame = __method__\nexit-all\n"), out=StringIO.new) do
67
+ o.bing
68
+ end
69
+
70
+ o.frame.should == :bong
71
+ end
72
+
73
+ it 'should begin session at specified frame when using :call_stack' do
74
+ o = Object.new
75
+ class << o; attr_accessor :frame; end
76
+ def o.alpha() binding end
77
+ def o.beta() binding end
78
+ def o.gamma() binding end
79
+
80
+ redirect_pry_io(StringIO.new("@frame = __method__\nexit\n"), out=StringIO.new) do
81
+ Pry.start(binding, :call_stack => [o.gamma, o.beta, o.alpha], :initial_frame => 1)
82
+ end
83
+
84
+ o.frame.should == :beta
85
+ end
86
+
87
+ # regression test for #12
88
+ it 'does not infinite loop when pry is started in MyObject#==' do
89
+ o = Object.new
90
+ def o.==(other)
91
+ binding.pry
92
+ end
93
+
94
+ redirect_pry_io(InputTester.new(":hello", "exit-all"), out=StringIO.new) do
95
+ o.==(1)
96
+ end
97
+
98
+ out.string.should =~ /hello/
99
+ end
100
+ end
101
+
102
+ describe ":call_stack option" do
103
+ it 'should invoke a session with the call stack set' do
104
+ redirect_pry_io(StringIO.new("show-stack\nexit\n"), out=StringIO.new) do
105
+ @o.bing
106
+ end
107
+
108
+ out.string.should =~ /bang.*?bong.*?bing/m
109
+ end
110
+
111
+ it 'should set no call stack when :call_stack => false' do
112
+ o = Object.new
113
+ def o.bing() bong end
114
+ def o.bong() bang end
115
+ def o.bang() Pry.start(binding, :call_stack => false) end
116
+
117
+ redirect_pry_io(StringIO.new("show-stack\nexit\n"), out=StringIO.new) do
118
+ o.bing
119
+ end
120
+
121
+ out.string.should =~ /No caller stack/
122
+ end
123
+
124
+ it 'should set custom call stack when :call_stack => [b1, b2]' do
125
+ o = Object.new
126
+ def o.alpha() binding end
127
+ def o.beta() binding end
128
+ def o.gamma() binding end
129
+
130
+ redirect_pry_io(StringIO.new("show-stack\nexit\n"), out=StringIO.new) do
131
+ Pry.start(binding, :call_stack => [o.beta, o.gamma, o.alpha])
132
+ end
133
+
134
+ out.string.should =~ /beta.*?gamma.*?alpha/m
135
+ end
136
+
137
+ it 'should raise if custom call stack does not contain bindings' do
138
+ o = OpenStruct.new
139
+ redirect_pry_io(StringIO.new("self.errors = _pry_.hooks.errors\nexit\n")) do
140
+ Pry.start(o, :call_stack => [1, 2, 3])
141
+ end
142
+ o.errors.first.is_a?(ArgumentError).should == true
143
+ end
144
+
145
+ it 'should raise if custom call stack is empty' do
146
+ o = OpenStruct.new
147
+ redirect_pry_io(StringIO.new("self.errors = _pry_.hooks.errors\nexit\n")) do
148
+ Pry.start o, :call_stack => []
149
+ end
150
+ o.errors.first.is_a?(ArgumentError).should == true
151
+ end
152
+ end
153
+ end
154
+
155
+ describe "unit tests for PryStack class methods" do
156
+ before do
157
+ @pry_instance = Pry.new
158
+ @bindings = [binding, binding]
159
+ end
160
+
161
+ after do
162
+ PE.clear_frame_managers(@pry_instance)
163
+ end
164
+
165
+ describe "PryStack.create_and_push_frame_manager" do
166
+
167
+ it "should create and push one new FrameManager" do
168
+ PE.create_and_push_frame_manager(@bindings, @pry_instance)
169
+ PE.frame_manager(@pry_instance).is_a?(PE::FrameManager).should == true
170
+ PE.frame_managers(@pry_instance).count.should == 1
171
+ end
172
+
173
+ it "should refresh Pry instance to use FrameManager's active binding" do
174
+ PE.create_and_push_frame_manager(@bindings, @pry_instance)
175
+ @pry_instance.binding_stack.size.should == 1
176
+ @pry_instance.binding_stack.first.should == @bindings.first
177
+ end
178
+
179
+ it 'should save prior binding in FrameManager instance' do
180
+ _pry_ = Pry.new
181
+ _pry_.binding_stack.push(b=binding)
182
+ PryStack.create_and_push_frame_manager(@bindings, _pry_)
183
+ PryStack.frame_manager(_pry_).prior_binding.should == b
184
+ end
185
+
186
+ describe ":initial_frame option" do
187
+ it 'should start on specified frame' do
188
+ PE.create_and_push_frame_manager(@bindings, @pry_instance, :initial_frame => 1)
189
+ @pry_instance.binding_stack.size.should == 1
190
+ @pry_instance.binding_stack.first.should == @bindings.last
191
+ end
192
+
193
+ describe "negative numbers" do
194
+ it 'should work with negative frame number (-1)' do
195
+ PE.create_and_push_frame_manager(@bindings, @pry_instance, :initial_frame => -1)
196
+ @pry_instance.binding_stack.size.should == 1
197
+ @pry_instance.binding_stack.first.should == @bindings.last
198
+ end
199
+
200
+ it 'should work with negative frame number (-2)' do
201
+ PE.create_and_push_frame_manager(@bindings, @pry_instance, :initial_frame => -2)
202
+ @pry_instance.binding_stack.size.should == 1
203
+ @pry_instance.binding_stack.first.should == @bindings.first
204
+ end
205
+ end
206
+ end
207
+
208
+ it 'should save prior backtrace in FrameManager instance' do
209
+ _pry_ = Pry.new
210
+ _pry_.backtrace = ["my backtrace"]
211
+ PryStack.create_and_push_frame_manager(@bindings, _pry_)
212
+ PryStack.frame_manager(_pry_).prior_backtrace.should == _pry_.backtrace
213
+ end
214
+
215
+ it "should create and push multiple FrameManagers" do
216
+ PE.create_and_push_frame_manager(@bindings, @pry_instance)
217
+ PE.create_and_push_frame_manager(@bindings, @pry_instance)
218
+ PE.frame_managers(@pry_instance).count.should == 2
219
+ end
220
+
221
+ it 'should push FrameManagers to stacks based on Pry instance' do
222
+ p2 = Pry.new
223
+ bindings = [binding, binding]
224
+ PE.create_and_push_frame_manager(@bindings, @pry_instance)
225
+ PE.create_and_push_frame_manager(bindings, p2)
226
+ PE.frame_managers(@pry_instance).count.should == 1
227
+ PE.frame_managers(p2).count.should == 1
228
+ end
229
+ end
230
+
231
+ describe "PryStack.frame_manager" do
232
+ it "should have the correct bindings" do
233
+ PE.create_and_push_frame_manager(@bindings, @pry_instance)
234
+ PE.frame_manager(@pry_instance).bindings.should == @bindings
235
+ end
236
+
237
+ it "should return the last pushed FrameManager" do
238
+ bindings = [binding, binding]
239
+ PE.create_and_push_frame_manager(@bindings, @pry_instance)
240
+ PE.create_and_push_frame_manager(bindings, @pry_instance)
241
+ PE.frame_manager(@pry_instance).bindings.should == bindings
242
+ end
243
+
244
+ it "should return the correct FrameManager for the given Pry instance" do
245
+ bindings = [binding, binding]
246
+ p2 = Pry.new
247
+ PE.create_and_push_frame_manager(@bindings, @pry_instance)
248
+ PE.create_and_push_frame_manager(bindings, p2)
249
+ PE.frame_manager(@pry_instance).bindings.should == @bindings
250
+ PE.frame_manager(p2).bindings.should == bindings
251
+ end
252
+ end
253
+
254
+ describe "PryStack.pop_frame_manager" do
255
+ it "should remove FrameManager from stack" do
256
+ PE.create_and_push_frame_manager(@bindings, @pry_instance)
257
+ PE.create_and_push_frame_manager(@bindings, @pry_instance)
258
+ PE.pop_frame_manager(@pry_instance)
259
+ PE.frame_managers(@pry_instance).count.should == 1
260
+ end
261
+
262
+ it "should return the most recently added FrameManager" do
263
+ bindings = [binding, binding]
264
+ PE.create_and_push_frame_manager(@bindings, @pry_instance)
265
+ PE.create_and_push_frame_manager(bindings, @pry_instance)
266
+ PE.pop_frame_manager(@pry_instance).bindings.should == bindings
267
+ end
268
+
269
+ it "should remove FrameManager from the appropriate stack based on Pry instance" do
270
+ p2 = Pry.new
271
+ bindings = [binding, binding]
272
+ PE.create_and_push_frame_manager(@bindings, @pry_instance)
273
+ PE.create_and_push_frame_manager(bindings, p2)
274
+ PE.pop_frame_manager(@pry_instance)
275
+ PE.frame_managers(@pry_instance).count.should == 0
276
+ PE.frame_managers(p2).count.should == 1
277
+ end
278
+
279
+ it "should remove key when no frames remaining for Pry instance" do
280
+ PE.create_and_push_frame_manager(@bindings, @pry_instance)
281
+ PE.create_and_push_frame_manager(@bindings, @pry_instance)
282
+ PE.pop_frame_manager(@pry_instance)
283
+ PE.pop_frame_manager(@pry_instance)
284
+ PE.frame_hash.has_key?(@pry_instance).should == false
285
+ end
286
+
287
+ it 'should not change size of binding_stack when popping' do
288
+ bindings = [bindings, bindings]
289
+ PE.create_and_push_frame_manager(bindings, @pry_instance)
290
+ PE.create_and_push_frame_manager(@bindings, @pry_instance)
291
+ PE.pop_frame_manager(@pry_instance)
292
+ @pry_instance.binding_stack.size.should == 1
293
+ end
294
+
295
+ it 'should return nil when popping non-existent frame manager' do
296
+ PE.pop_frame_manager(@pry_instance).should == nil
297
+ end
298
+
299
+ describe "restoring previous binding" do
300
+ it 'should restore previous binding for Pry instance on pop, where previous binding is not first frame' do
301
+ bindings = [binding, binding]
302
+ PE.create_and_push_frame_manager(bindings, @pry_instance).binding_index = 1
303
+ PE.create_and_push_frame_manager(@bindings, @pry_instance)
304
+ PE.pop_frame_manager(@pry_instance)
305
+ @pry_instance.binding_stack.first.should == bindings[1]
306
+ end
307
+
308
+ it 'should restore previous binding for Pry instance on pop (previous frame frame manager)' do
309
+ bindings = [binding, binding]
310
+ PE.create_and_push_frame_manager(bindings, @pry_instance)
311
+ PE.create_and_push_frame_manager(@bindings, @pry_instance)
312
+ PE.pop_frame_manager(@pry_instance)
313
+ @pry_instance.binding_stack.first.should == bindings.first
314
+ end
315
+
316
+ it 'should restore previous binding for Pry instance on pop (no previous frame manager)' do
317
+ b = binding
318
+ @pry_instance.binding_stack = [b]
319
+ PE.create_and_push_frame_manager(@bindings, @pry_instance)
320
+ PE.pop_frame_manager(@pry_instance)
321
+ @pry_instance.binding_stack.first.should == b
322
+ end
323
+
324
+ it 'should restore previous binding for Pry instance on pop (no previous frame manager AND no empty binding_stack)' do
325
+ b = binding
326
+ @pry_instance.binding_stack = [b]
327
+ PE.create_and_push_frame_manager(@bindings, @pry_instance)
328
+ @pry_instance.binding_stack.clear
329
+ PE.pop_frame_manager(@pry_instance)
330
+ @pry_instance.binding_stack.first.should == b
331
+ end
332
+ end
333
+
334
+ describe "_pry_.backtrace" do
335
+ it "should restore backtrace when frame is popped" do
336
+ p1 = Pry.new
337
+ bindings = [binding, binding]
338
+ p1.backtrace = "my backtrace1"
339
+ PE.create_and_push_frame_manager(bindings, p1)
340
+ p1.backtrace = "my backtrace2"
341
+ PE.create_and_push_frame_manager(bindings, p1)
342
+ p1.backtrace = "my backtrace3"
343
+
344
+ PE.pop_frame_manager(p1)
345
+ p1.backtrace.should == "my backtrace2"
346
+ PE.pop_frame_manager(p1)
347
+ p1.backtrace.should == "my backtrace1"
348
+ end
349
+ end
350
+ end
351
+
352
+ describe "PryStack.clear_frame_managers" do
353
+ it "should clear all FrameManagers for a Pry instance" do
354
+ PE.create_and_push_frame_manager(@bindings, @pry_instance)
355
+ PE.create_and_push_frame_manager(@bindings, @pry_instance)
356
+ PE.clear_frame_managers(@pry_instance)
357
+ PE.frame_hash.has_key?(@pry_instance).should == false
358
+ end
359
+
360
+ it "should clear all FrameManagers for a Pry instance but leave others untouched" do
361
+ p2 = Pry.new
362
+ bindings = [binding, binding]
363
+ PE.create_and_push_frame_manager(@bindings, @pry_instance)
364
+ PE.create_and_push_frame_manager(bindings, p2)
365
+ PE.clear_frame_managers(@pry_instance)
366
+ PE.frame_managers(p2).count.should == 1
367
+ PE.frame_hash.has_key?(@pry_instance).should == false
368
+ end
369
+
370
+ it "should remove key" do
371
+ PE.create_and_push_frame_manager(@bindings, @pry_instance)
372
+ PE.create_and_push_frame_manager(@bindings, @pry_instance)
373
+ PE.clear_frame_managers(@pry_instance)
374
+ PE.frame_hash.has_key?(@pry_instance).should == false
375
+ end
376
+
377
+ describe "_pry_.backtrace" do
378
+ it "should restore backtrace to initial one when frame managers are cleared" do
379
+ p1 = Pry.new
380
+ bindings = [binding, binding]
381
+ p1.backtrace = "my backtrace1"
382
+ PE.create_and_push_frame_manager(bindings, p1)
383
+ p1.backtrace = "my backtrace2"
384
+ PE.create_and_push_frame_manager(bindings, p1)
385
+ p1.backtrace = "my backtrace3"
386
+
387
+ PE.clear_frame_managers(p1)
388
+ p1.backtrace.should == "my backtrace1"
389
+ end
390
+ end
391
+ end
392
+ end
393
+ end