/
thread_local_var_spec.rb
141 lines (110 loc) · 3.27 KB
/
thread_local_var_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
require 'rbconfig'
module Concurrent
require 'concurrent/atomic/thread_local_var'
RSpec.describe ThreadLocalVar do
context '#initialize' do
it 'can set an initial value' do
v = described_class.new(14)
expect(v.value).to eq 14
end
it 'sets nil as a default initial value' do
v = described_class.new
expect(v.value).to be_nil
end
it 'sets the same initial value for all threads' do
v = described_class.new(14)
t1 = Thread.new { v.value }
t2 = Thread.new { v.value }
expect(t1.value).to eq 14
expect(t2.value).to eq 14
end
if Concurrent.on_jruby?
it 'extends JavaThreadLocalVar' do
expect(described_class.ancestors).to include(Concurrent::JavaThreadLocalVar)
end
else
it 'extends RubyThreadLocalVar' do
expect(described_class.ancestors).to include(Concurrent::RubyThreadLocalVar)
end
end
it 'can set a block to be called to get the initial value' do
v = described_class.new { 14 }
expect(v.value).to eq 14
end
context 'when attempting to set both an initial value and a block' do
it do
expect { described_class.new(14) { 14 } }.to raise_error(ArgumentError)
end
end
end
context '#value' do
let(:v) { described_class.new(14) }
it 'returns the current value' do
expect(v.value).to eq 14
end
it 'returns the value after modification' do
v.value = 2
expect(v.value).to eq 2
end
context 'when using a block to initialize the value' do
it 'calls the block to initialize the value' do
block = proc { }
expect(block).to receive(:call)
v = described_class.new(&block)
v.value
end
it 'sets the block return value as the current value' do
value = 13
v = described_class.new { value += 1 }
v.value
expect(v.value).to be 14
end
it 'calls the block to initialize the value for each thread' do
block = proc { }
expect(block).to receive(:call).twice
v = described_class.new(&block)
Thread.new { v.value }.join
Thread.new { v.value }.join
end
end
end
context '#value=' do
let(:v) { described_class.new(14) }
it 'sets a new value' do
v.value = 2
expect(v.value).to eq 2
end
it 'returns the new value' do
expect(v.value = 2).to eq 2
end
it 'does not modify the initial value for other threads' do
v.value = 2
t = Thread.new { v.value }
expect(t.value).to eq 14
end
it 'does not modify the value for other threads' do
v.value = 2
b1 = CountDownLatch.new(2)
b2 = CountDownLatch.new(2)
t1 = Thread.new do
b1.count_down
b1.wait
v.value = 1
b2.count_down
b2.wait
v.value
end
t2 = Thread.new do
b1.count_down
b1.wait
v.value = 2
b2.count_down
b2.wait
v.value
end
expect(t1.value).to eq 1
expect(t2.value).to eq 2
end
end
end
end