File: binding_of_caller_spec.rb

package info (click to toggle)
ruby-binding-of-caller 1.0.0-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 168 kB
  • sloc: ruby: 432; makefile: 4; sh: 4
file content (168 lines) | stat: -rw-r--r-- 3,909 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
require 'spec_helper'

puts "Testing binding_of_caller version #{BindingOfCaller::VERSION}..."
puts "Ruby version: #{RUBY_VERSION}"

RSpec.describe BindingOfCaller do
  describe "#of_caller" do
    it "fetches the immediate caller's binding when 0 is passed" do
      o = Object.new
      def o.a
        var = 1
        binding.of_caller(0).eval('var')
      end

      expect(o. a).to eq 1
    end

    it "fetches the parent of caller's binding when 1 is passed" do
      o = Object.new
      def o.a
        var = 1
        b
      end

      def o.b
        binding.of_caller(1).eval('var')
      end

      expect(o.a).to eq 1
    end

    it "modifies locals in the parent of caller's binding" do
      o = Object.new
      def o.a
        var = 1
        b
        var
      end

      def o.b
        binding.of_caller(1).eval('var = 20')
      end

      expect(o.a).to eq 20
    end

    it "raises an exception when retrieving an out-of-band binding" do
      o = Object.new
      def o.a
        binding.of_caller(100)
      end

      expect { o.a }.to raise_error(RuntimeError)
    end
  end

  describe "#callers" do
    before do
      @o = Object.new
    end

    it 'returns the first non-internal binding when using callers.first' do
      def @o.meth
        x = :a_local
        [binding.callers.first, binding.of_caller(0)]
      end

      b1, b2 = @o.meth
      expect(b1.eval("x")).to eq :a_local
      expect(b2.eval("x")).to eq :a_local
    end
  end

  describe "#frame_count" do
    it 'equals the binding callers.count' do
      expect(binding.frame_count).to eq binding.callers.count
    end
  end

  describe "#frame_descripton" do
    it 'can be called on ordinary binding without raising' do
      expect { binding.frame_description }.not_to raise_error
    end

    describe "when inside a block" do
      before { @binding = proc { binding.of_caller(0) }.call }

      it 'describes a block frame' do
        expect(@binding.frame_description).to match /block/
      end
    end

    describe "when inside an instance method" do
      before do
        o = Object.new
        def o.horsey_malone; binding.of_caller(0); end
        @binding = o.horsey_malone;
      end

      it 'describes a method frame with the method name' do
        expect(@binding.frame_description).to match /horsey_malone/
      end
    end

    describe "when inside a class definition" do
      before do
        class HorseyMalone
          @binding = binding.of_caller(0)
          def self.binding; @binding; end
        end
        @binding = HorseyMalone.binding
      end

      it 'describes a class frame' do
        expect(@binding.frame_description).to match /class/i
        Object.remove_const(:HorseyMalone)
      end
    end
  end

  describe "#frame_type" do
    it 'can be called on ordinary binding without raising' do
      expect { binding.frame_type }.not_to raise_error
    end

    describe "when inside a class definition" do
      before do
        class HorseyMalone
          @binding = binding.of_caller(0)
          def self.binding; @binding; end
        end
        @binding = HorseyMalone.binding
      end

      it 'returns :class' do
        expect(@binding.frame_type).to eq :class
      end
    end

    describe "when evaluated" do
      before { @binding = eval("binding.of_caller(0)") }

      it 'returns :eval' do
        expect(@binding.frame_type).to eq :eval
      end
    end

    describe "when inside a block" do
      before { @binding = proc { binding.of_caller(0) }.call }

      it 'returns :block' do
        expect(@binding.frame_type).to eq :block
      end
    end

    describe "when inside an instance method" do
      before do
        o = Object.new
        def o.a; binding.of_caller(0); end
        @binding = o.a;
      end

      it 'returns :method' do
        expect(@binding.frame_type).to eq :method
      end
    end
  end
end