File: memory_spec.rb

package info (click to toggle)
ruby-unparser 0.6.13-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 936 kB
  • sloc: ruby: 7,691; sh: 6; makefile: 4
file content (130 lines) | stat: -rw-r--r-- 2,772 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
RSpec.describe Unparser::Adamantium::Memory do
  describe '#fetch' do
    let(:events)  { []                         }
    let(:monitor) { instance_double(Monitor)   }
    let(:name)    { :some_name                 }
    let(:object)  { described_class.new(proxy) }
    let(:value_was_read) { -> {} }

    let(:block) do
      lambda do
        events << :block_call
        @counter += 1
      end
    end

    let(:proxy) do
      proxy  = instance_double(Hash)
      values = values()

      allow(proxy).to receive(:fetch) do |name, &block|
        events << :fetch
        values.fetch(name) do
          value_was_read.call
          block.call
        end
      end

      allow(proxy).to receive(:[]=) do |name, value|
        events << :set
        values[name] = value
      end

      proxy
    end


    def apply
      object.fetch(name, &block)
    end

    before do
      allow(Monitor).to receive_messages(new: monitor)

      allow(monitor).to receive(:synchronize) do |&block|
        events << :synchronize_start
        block.call.tap do
          events << :synchronize_end
        end
      end

      @counter = 0
    end

    shared_examples 'expected events' do
      it 'triggers expected events' do
        expect { apply }
          .to change(events, :to_a)
          .from([]).to(expected_events)
      end

      it 'returns expected value' do
        expect(apply).to be(1)
      end

      it 'creates frozen objects' do
        expect(object.frozen?).to be(true)
      end
    end

    context 'when value is present in memory' do
      let(:values)          { { name => 1 } }
      let(:expected_events) { %i[fetch] }

      include_examples 'expected events'
    end

    context 'when value is not present in memory initially' do
      let(:values) { {} }

      let(:expected_events) do
        %i[
          fetch
          synchronize_start
          fetch
          block_call
          set
          synchronize_end
        ]
      end

      include_examples 'expected events'

      context 'but is present inside the lock' do
        let(:value_was_read) { ->() { values[name] = 1 } }

        let(:expected_events) do
          %i[
            fetch
            synchronize_start
            fetch
            synchronize_end
          ]
        end

        include_examples 'expected events'
      end

      context 'and is re-read after initial generation' do
        def apply
          super()
          super()
        end

        let(:expected_events) do
          %i[
            fetch
            synchronize_start
            fetch
            block_call
            set
            synchronize_end
            fetch
          ]
        end

        include_examples 'expected events'
      end
    end
  end
end