/
count_down_latch_spec.rb
170 lines (132 loc) · 3.88 KB
/
count_down_latch_spec.rb
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
RSpec.shared_examples :count_down_latch do
let(:latch) { described_class.new(3) }
let(:zero_count_latch) { described_class.new(0) }
context '#initialize' do
it 'raises an exception if the initial count is less than zero' do
expect {
described_class.new(-1)
}.to raise_error(ArgumentError)
end
it 'raises an exception if the initial count is not an integer' do
expect {
described_class.new('foo')
}.to raise_error(ArgumentError)
end
it 'defaults the count to 1' do
latch = described_class.new
expect(latch.count).to eq 1
end
end
describe '#count' do
it 'should be the value passed to the constructor' do
expect(latch.count).to eq 3
end
it 'should be decreased after every count down' do
latch.count_down
expect(latch.count).to eq 2
end
it 'should not go below zero' do
5.times { latch.count_down }
expect(latch.count).to eq 0
end
end
describe '#wait' do
context 'count set to zero' do
it 'should return true immediately' do
result = zero_count_latch.wait
expect(result).to be_truthy
end
it 'should return true immediately with timeout' do
result = zero_count_latch.wait(5)
expect(result).to be_truthy
end
end
context 'non zero count' do
it 'should block thread until counter is set to zero' do
3.times do
Thread.new { sleep(0.1); latch.count_down }
end
result = latch.wait
expect(result).to be_truthy
expect(latch.count).to eq 0
end
it 'should block until counter is set to zero with timeout' do
3.times do
Thread.new { sleep(0.1); latch.count_down }
end
result = latch.wait(1)
expect(result).to be_truthy
expect(latch.count).to eq 0
end
it 'should block until timeout and return false when counter is not set to zero' do
result = latch.wait(0.1)
expect(result).to be_falsey
expect(latch.count).to eq 3
end
end
end
end
module Concurrent
RSpec.describe MutexCountDownLatch do
it_should_behave_like :count_down_latch
context 'spurious wake ups' do
subject { described_class.new(3) }
before(:each) do
def subject.simulate_spurious_wake_up
synchronize do
ns_signal
ns_broadcast
end
end
end
it 'should resist to spurious wake ups without timeout' do
latch = Concurrent::CountDownLatch.new(1)
expected = false
t = Thread.new do
latch.wait(1)
subject.wait
expected = true
end
latch.count_down
t.join(0.1)
subject.simulate_spurious_wake_up
t.join(0.1)
expect(expected).to be_falsey
end
it 'should resist to spurious wake ups with timeout' do
start_latch = Concurrent::CountDownLatch.new(1)
finish_latch = Concurrent::CountDownLatch.new(1)
expected = false
t = Thread.new do
start_latch.wait(1)
subject.wait(0.5)
expected = true
finish_latch.count_down
end
start_latch.count_down
t.join(0.1)
subject.simulate_spurious_wake_up
t.join(0.1)
expect(expected).to be_falsey
finish_latch.wait(1)
expect(expected).to be_truthy
end
end
end
if Concurrent.on_jruby?
RSpec.describe JavaCountDownLatch do
it_should_behave_like :count_down_latch
end
end
RSpec.describe CountDownLatch do
if Concurrent.on_jruby?
it 'inherits from JavaCountDownLatch' do
expect(CountDownLatch.ancestors).to include(JavaCountDownLatch)
end
else
it 'inherits from MutexCountDownLatch' do
expect(CountDownLatch.ancestors).to include(MutexCountDownLatch)
end
end
end
end