File: atomic_fixnum_spec.rb

package info (click to toggle)
ruby-concurrent 1.1.6%2Bdfsg-5
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 30,284 kB
  • sloc: ruby: 30,875; java: 6,117; javascript: 1,114; ansic: 288; makefile: 10; sh: 6
file content (249 lines) | stat: -rw-r--r-- 6,274 bytes parent folder | download | duplicates (2)
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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
RSpec.shared_examples :atomic_fixnum do

  context 'construction' do

    it 'sets the initial value' do
      expect(described_class.new(10).value).to eq 10
    end

    it 'defaults the initial value to zero' do
      expect(described_class.new.value).to eq 0
    end

    it 'raises an exception if the initial value is not a Fixnum' do
      expect { described_class.new(10.01) }.to(raise_error { |error|
        expect(error.class).to be(ArgumentError).or(be(TypeError))
      })
    end
  end

  context '#value' do

    it 'returns the current value' do
      counter = described_class.new(10)
      expect(counter.value).to eq 10
      counter.increment
      expect(counter.value).to eq 11
      counter.decrement
      expect(counter.value).to eq 10
    end
  end

  context '#value=' do

    it 'sets the #value to the given `Fixnum`' do
      atomic = described_class.new(0)
      atomic.value = 10
      expect(atomic.value).to eq 10
    end

    it 'returns the new value' do
      atomic = described_class.new(0)
      expect(atomic.value = 10).to eq 10
    end

    it 'raises and exception if the value is not a `Fixnum`' do
      atomic = described_class.new(0)
      expect {
        atomic.value = 'foo'
      }.to(raise_error { |error|
        expect(error.class).to be(ArgumentError).or(be(TypeError))
      })
    end
  end

  context '#increment' do

    it 'increases the value by one when no argument is given' do
      counter = described_class.new(10)
      3.times{ counter.increment }
      expect(counter.value).to eq 13
    end

    it 'returns the new value when no argument is given' do
      counter = described_class.new(10)
      expect(counter.increment).to eq 11
    end

    it 'increases the value by the given argument' do
      counter = described_class.new(10)
      counter.increment(5)
      expect(counter.value).to eq 15
    end

    it 'returns the new value the given argument' do
      counter = described_class.new(10)
      expect(counter.increment(5)).to eq 15
    end

    it 'is aliased as #up' do
      expect(described_class.new(10).up).to eq 11
    end
  end

  context '#decrement' do

    it 'decreases the value by one when no argument is given' do
      counter = described_class.new(10)
      3.times{ counter.decrement }
      expect(counter.value).to eq 7
    end

    it 'returns the new value when no argument is given' do
      counter = described_class.new(10)
      expect(counter.decrement).to eq 9
    end

    it 'decreases the value by the given argument' do
      counter = described_class.new(10)
      counter.decrement(5)
      expect(counter.value).to eq 5
    end

    it 'returns the new value the given argument' do
      counter = described_class.new(10)
      expect(counter.decrement(5)).to eq 5
    end

    it 'is aliased as #down' do
      expect(described_class.new(10).down).to eq 9
    end
  end

  context '#compare_and_set' do

    it 'returns false if the value is not found' do
      expect(described_class.new(14).compare_and_set(2, 14)).to eq false
    end

    it 'returns true if the value is found' do
      expect(described_class.new(14).compare_and_set(14, 2)).to eq true
    end

    it 'sets if the value is found' do
      f = described_class.new(14)
      f.compare_and_set(14, 2)
      expect(f.value).to eq 2
    end

    it 'does not set if the value is not found' do
      f = described_class.new(14)
      f.compare_and_set(2, 12)
      expect(f.value).to eq 14
    end
  end

  context '#update' do

    it 'passes the current value to the block' do
      atomic = described_class.new(1000)
      atomic.update { |v| (expect(v).to eq 1000); 1 }
    end

    it 'atomically sets the value to the return value from the block' do
      atomic = described_class.new(1000)
      atomic.update { |v| v + 1 }
      expect(atomic.value).to eq 1001
    end

    it 'returns the new value' do
      atomic = described_class.new(1000)
      expect(atomic.update { |v| v + 1 }).to eq 1001
    end
  end
end

module Concurrent

  RSpec.describe MutexAtomicFixnum do

    it_should_behave_like :atomic_fixnum

    context 'construction' do

      it 'raises an exception if the initial value is too big' do
        expect {
          described_class.new(Utility::NativeInteger::MAX_VALUE + 1)
        }.to raise_error(RangeError)
      end

      it 'raises an exception if the initial value is too small' do
        expect {
          described_class.new(Utility::NativeInteger::MIN_VALUE - 1)
        }.to raise_error(RangeError)
      end
    end

    context 'instance methods' do

      before(:each) do
        expect(subject).to receive(:synchronize).with(no_args).and_call_original
      end

      specify 'value is synchronized' do
        subject.value
      end

      specify 'value= is synchronized' do
        subject.value = 10
      end

      specify 'increment is synchronized' do
        subject.increment
      end

      specify 'decrement is synchronized' do
        subject.decrement
      end

      specify 'compare_and_set is synchronized' do
        subject.compare_and_set(14, 2)
      end
    end
  end

  if defined? Concurrent::CAtomicFixnum

    RSpec.describe CAtomicFixnum do
      it_should_behave_like :atomic_fixnum
    end
  end

  if Concurrent.on_jruby?

    RSpec.describe JavaAtomicFixnum do
      it_should_behave_like :atomic_fixnum
    end
  end

  RSpec.describe AtomicFixnum do
    if RUBY_ENGINE != 'ruby'
      it 'does not load the C extension' do
        expect(defined?(Concurrent::CAtomicFixnum)).to be_falsey
      end
    end

    if Concurrent.on_jruby?
      it 'inherits from JavaAtomicFixnum' do
        expect(AtomicFixnum.ancestors).to include(JavaAtomicFixnum)
      end
    elsif defined? Concurrent::CAtomicFixnum
      it 'inherits from CAtomicFixnum' do
        expect(AtomicFixnum.ancestors).to include(CAtomicFixnum)
      end
    else
      it 'inherits from MutexAtomicFixnum' do
        expect(AtomicFixnum.ancestors).to include(MutexAtomicFixnum)
      end
    end

    describe '#to_s and #inspect' do
      it 'includes the value' do
        subject = described_class.new(42)
        expect(subject.to_s).to include('42')
        expect(subject.inspect).to include('42')
      end
    end

  end
end