File: thread_local_var_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 (141 lines) | stat: -rw-r--r-- 3,338 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
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 = in_thread { v.value }
        t2 = in_thread { 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)
          in_thread { v.value }.join
          in_thread { 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 = in_thread { 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 = in_thread do
          b1.count_down
          b1.wait
          v.value = 1
          b2.count_down
          b2.wait
          v.value
        end

        t2 = in_thread 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