airbrake-ruby 5.0.1-java → 5.2.1-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/airbrake-ruby.rb +4 -2
- data/lib/airbrake-ruby/async_sender.rb +3 -1
- data/lib/airbrake-ruby/config.rb +15 -6
- data/lib/airbrake-ruby/config/processor.rb +7 -20
- data/lib/airbrake-ruby/context.rb +51 -0
- data/lib/airbrake-ruby/file_cache.rb +1 -1
- data/lib/airbrake-ruby/filter_chain.rb +2 -0
- data/lib/airbrake-ruby/filters/context_filter.rb +4 -5
- data/lib/airbrake-ruby/filters/exception_attributes_filter.rb +1 -1
- data/lib/airbrake-ruby/filters/git_last_checkout_filter.rb +1 -1
- data/lib/airbrake-ruby/filters/git_revision_filter.rb +1 -1
- data/lib/airbrake-ruby/filters/keys_filter.rb +2 -2
- data/lib/airbrake-ruby/filters/sql_filter.rb +2 -2
- data/lib/airbrake-ruby/filters/thread_filter.rb +2 -3
- data/lib/airbrake-ruby/grouppable.rb +1 -1
- data/lib/airbrake-ruby/ignorable.rb +0 -2
- data/lib/airbrake-ruby/mergeable.rb +1 -1
- data/lib/airbrake-ruby/notice_notifier.rb +3 -4
- data/lib/airbrake-ruby/performance_notifier.rb +1 -2
- data/lib/airbrake-ruby/remote_settings.rb +10 -50
- data/lib/airbrake-ruby/remote_settings/callback.rb +44 -0
- data/lib/airbrake-ruby/remote_settings/settings_data.rb +3 -8
- data/lib/airbrake-ruby/tdigest.rb +7 -6
- data/lib/airbrake-ruby/thread_pool.rb +5 -3
- data/lib/airbrake-ruby/timed_trace.rb +1 -3
- data/lib/airbrake-ruby/version.rb +2 -2
- data/spec/airbrake_spec.rb +139 -76
- data/spec/async_sender_spec.rb +10 -8
- data/spec/backtrace_spec.rb +13 -10
- data/spec/benchmark_spec.rb +5 -3
- data/spec/code_hunk_spec.rb +24 -15
- data/spec/config/processor_spec.rb +29 -87
- data/spec/config/validator_spec.rb +5 -2
- data/spec/config_spec.rb +26 -17
- data/spec/context_spec.rb +54 -0
- data/spec/deploy_notifier_spec.rb +6 -4
- data/spec/file_cache_spec.rb +1 -0
- data/spec/filter_chain_spec.rb +29 -24
- data/spec/filters/context_filter_spec.rb +14 -5
- data/spec/filters/dependency_filter_spec.rb +3 -1
- data/spec/filters/exception_attributes_filter_spec.rb +5 -3
- data/spec/filters/gem_root_filter_spec.rb +5 -2
- data/spec/filters/git_last_checkout_filter_spec.rb +10 -12
- data/spec/filters/git_repository_filter.rb +9 -9
- data/spec/filters/git_revision_filter_spec.rb +19 -19
- data/spec/filters/keys_allowlist_spec.rb +25 -16
- data/spec/filters/keys_blocklist_spec.rb +25 -18
- data/spec/filters/root_directory_filter_spec.rb +3 -3
- data/spec/filters/sql_filter_spec.rb +26 -26
- data/spec/filters/system_exit_filter_spec.rb +4 -2
- data/spec/filters/thread_filter_spec.rb +16 -14
- data/spec/loggable_spec.rb +2 -2
- data/spec/monotonic_time_spec.rb +8 -6
- data/spec/nested_exception_spec.rb +46 -46
- data/spec/notice_notifier/options_spec.rb +23 -13
- data/spec/notice_notifier_spec.rb +52 -47
- data/spec/notice_spec.rb +6 -2
- data/spec/performance_notifier_spec.rb +67 -60
- data/spec/promise_spec.rb +38 -32
- data/spec/remote_settings/callback_spec.rb +162 -0
- data/spec/remote_settings/settings_data_spec.rb +23 -53
- data/spec/remote_settings_spec.rb +42 -75
- data/spec/response_spec.rb +34 -12
- data/spec/stashable_spec.rb +5 -5
- data/spec/stat_spec.rb +7 -5
- data/spec/sync_sender_spec.rb +49 -16
- data/spec/tdigest_spec.rb +61 -56
- data/spec/thread_pool_spec.rb +65 -55
- data/spec/time_truncate_spec.rb +4 -2
- data/spec/timed_trace_spec.rb +32 -30
- data/spec/truncator_spec.rb +72 -43
- metadata +53 -47
data/spec/tdigest_spec.rb
CHANGED
@@ -1,16 +1,18 @@
|
|
1
1
|
RSpec.describe Airbrake::TDigest do
|
2
|
+
subject(:tdigest) { described_class.new }
|
3
|
+
|
2
4
|
describe "byte serialization" do
|
3
5
|
it "loads serialized data" do
|
4
|
-
|
5
|
-
10.times {
|
6
|
-
bytes =
|
6
|
+
tdigest.push(60, 100)
|
7
|
+
10.times { tdigest.push(rand * 100) }
|
8
|
+
bytes = tdigest.as_bytes
|
7
9
|
new_tdigest = described_class.from_bytes(bytes)
|
8
|
-
expect(new_tdigest.percentile(0.9)).to eq(
|
10
|
+
expect(new_tdigest.percentile(0.9)).to eq(tdigest.percentile(0.9))
|
9
11
|
expect(new_tdigest.as_bytes).to eq(bytes)
|
10
12
|
end
|
11
13
|
|
12
14
|
it "handles zero size" do
|
13
|
-
bytes =
|
15
|
+
bytes = tdigest.as_bytes
|
14
16
|
expect(described_class.from_bytes(bytes).size).to be_zero
|
15
17
|
end
|
16
18
|
|
@@ -24,76 +26,75 @@ RSpec.describe Airbrake::TDigest do
|
|
24
26
|
|
25
27
|
describe "small byte serialization" do
|
26
28
|
it "loads serialized data" do
|
27
|
-
10.times {
|
28
|
-
bytes =
|
29
|
+
10.times { tdigest.push(10) }
|
30
|
+
bytes = tdigest.as_small_bytes
|
29
31
|
new_tdigest = described_class.from_bytes(bytes)
|
30
32
|
# Expect some rounding error due to compression
|
31
33
|
expect(new_tdigest.percentile(0.9).round(5)).to eq(
|
32
|
-
|
34
|
+
tdigest.percentile(0.9).round(5),
|
33
35
|
)
|
34
36
|
expect(new_tdigest.as_small_bytes).to eq(bytes)
|
35
37
|
end
|
36
38
|
|
37
39
|
it "handles zero size" do
|
38
|
-
bytes =
|
40
|
+
bytes = tdigest.as_small_bytes
|
39
41
|
expect(described_class.from_bytes(bytes).size).to be_zero
|
40
42
|
end
|
41
43
|
end
|
42
44
|
|
43
45
|
describe "JSON serialization" do
|
44
46
|
it "loads serialized data" do
|
45
|
-
|
46
|
-
json =
|
47
|
+
tdigest.push(60, 100)
|
48
|
+
json = tdigest.as_json
|
47
49
|
new_tdigest = described_class.from_json(json)
|
48
|
-
expect(new_tdigest.percentile(0.9)).to eq(
|
50
|
+
expect(new_tdigest.percentile(0.9)).to eq(tdigest.percentile(0.9))
|
49
51
|
end
|
50
52
|
end
|
51
53
|
|
52
54
|
describe "#percentile" do
|
53
55
|
it "returns nil if empty" do
|
54
|
-
expect(
|
56
|
+
expect(tdigest.percentile(0.90)).to be_nil # This should not crash
|
55
57
|
end
|
56
58
|
|
57
59
|
it "raises ArgumentError of input not between 0 and 1" do
|
58
|
-
expect {
|
60
|
+
expect { tdigest.percentile(1.1) }.to raise_error(ArgumentError)
|
59
61
|
end
|
60
62
|
|
61
63
|
describe "with only single value" do
|
62
64
|
it "returns the value" do
|
63
|
-
|
64
|
-
expect(
|
65
|
+
tdigest.push(60, 100)
|
66
|
+
expect(tdigest.percentile(0.90)).to eq(60)
|
65
67
|
end
|
66
68
|
|
67
69
|
it "returns 0 for all percentiles when only 0 present" do
|
68
|
-
|
69
|
-
expect(
|
70
|
+
tdigest.push(0)
|
71
|
+
expect(tdigest.percentile([0.0, 0.5, 1.0])).to eq([0, 0, 0])
|
70
72
|
end
|
71
73
|
end
|
72
74
|
|
73
75
|
describe "with alot of uniformly distributed points" do
|
74
76
|
it "has minimal error" do
|
75
77
|
seed = srand(1234) # Makes the values a proper fixture
|
76
|
-
N = 100_000
|
77
78
|
maxerr = 0
|
78
|
-
values = Array.new(
|
79
|
+
values = Array.new(100_000).map { rand }
|
79
80
|
srand(seed)
|
80
81
|
|
81
|
-
|
82
|
-
|
82
|
+
tdigest.push(values)
|
83
|
+
tdigest.compress!
|
83
84
|
|
84
85
|
0.step(1, 0.1).each do |i|
|
85
|
-
q =
|
86
|
+
q = tdigest.percentile(i)
|
86
87
|
maxerr = [maxerr, (i - q).abs].max
|
87
88
|
end
|
88
89
|
|
89
|
-
expect(maxerr).to be < 0.
|
90
|
+
expect(maxerr).to be < 0.02
|
90
91
|
end
|
91
92
|
end
|
92
93
|
end
|
93
94
|
|
94
95
|
describe "#push" do
|
95
96
|
it "calls _cumulate so won't crash because of uninitialized mean_cumn" do
|
96
|
-
|
97
|
+
tdigest.push(
|
97
98
|
[
|
98
99
|
125000000.0,
|
99
100
|
104166666.66666666,
|
@@ -132,59 +133,62 @@ RSpec.describe Airbrake::TDigest do
|
|
132
133
|
end
|
133
134
|
|
134
135
|
it "does not blow up if data comes in sorted" do
|
135
|
-
|
136
|
-
expect(
|
137
|
-
|
138
|
-
expect(
|
136
|
+
tdigest.push(0..10_000)
|
137
|
+
expect(tdigest.centroids.size).to be < 5_000
|
138
|
+
tdigest.compress!
|
139
|
+
expect(tdigest.centroids.size).to be < 1_000
|
139
140
|
end
|
140
141
|
end
|
141
142
|
|
142
143
|
describe "#size" do
|
143
144
|
it "reports the number of observations" do
|
144
145
|
n = 10_000
|
145
|
-
n.times {
|
146
|
-
|
147
|
-
expect(
|
146
|
+
n.times { tdigest.push(rand) }
|
147
|
+
tdigest.compress!
|
148
|
+
expect(tdigest.size).to eq(n)
|
148
149
|
end
|
149
150
|
end
|
150
151
|
|
151
152
|
describe "#+" do
|
152
153
|
it "works with empty tdigests" do
|
153
154
|
other = described_class.new(0.001, 50, 1.2)
|
154
|
-
expect((
|
155
|
+
expect((tdigest + other).centroids.size).to eq(0)
|
155
156
|
end
|
156
157
|
|
157
158
|
describe "adding two tdigests" do
|
159
|
+
let(:other) { described_class.new(0.001, 50, 1.2) }
|
160
|
+
|
158
161
|
before do
|
159
|
-
|
160
|
-
[subject, @other].each do |td|
|
162
|
+
[tdigest, other].each do |td|
|
161
163
|
td.push(60, 100)
|
162
164
|
10.times { td.push(rand * 100) }
|
163
165
|
end
|
164
166
|
end
|
165
167
|
|
168
|
+
# rubocop:disable RSpec/MultipleExpectations
|
166
169
|
it "has the parameters of the left argument (the calling tdigest)" do
|
167
|
-
new_tdigest =
|
170
|
+
new_tdigest = tdigest + other
|
168
171
|
expect(new_tdigest.instance_variable_get(:@delta)).to eq(
|
169
|
-
|
172
|
+
tdigest.instance_variable_get(:@delta),
|
170
173
|
)
|
171
174
|
expect(new_tdigest.instance_variable_get(:@k)).to eq(
|
172
|
-
|
175
|
+
tdigest.instance_variable_get(:@k),
|
173
176
|
)
|
174
177
|
expect(new_tdigest.instance_variable_get(:@cx)).to eq(
|
175
|
-
|
178
|
+
tdigest.instance_variable_get(:@cx),
|
176
179
|
)
|
177
180
|
end
|
181
|
+
# rubocop:enable RSpec/MultipleExpectations
|
178
182
|
|
179
183
|
it "returns a tdigest with less than or equal centroids" do
|
180
|
-
new_tdigest =
|
184
|
+
new_tdigest = tdigest + other
|
181
185
|
expect(new_tdigest.centroids.size)
|
182
|
-
.to be <=
|
186
|
+
.to be <= tdigest.centroids.size + other.centroids.size
|
183
187
|
end
|
184
188
|
|
185
189
|
it "has the size of the two digests combined" do
|
186
|
-
new_tdigest =
|
187
|
-
expect(new_tdigest.size).to eq(
|
190
|
+
new_tdigest = tdigest + other
|
191
|
+
expect(new_tdigest.size).to eq(tdigest.size + other.size)
|
188
192
|
end
|
189
193
|
end
|
190
194
|
end
|
@@ -192,14 +196,15 @@ RSpec.describe Airbrake::TDigest do
|
|
192
196
|
describe "#merge!" do
|
193
197
|
it "works with empty tdigests" do
|
194
198
|
other = described_class.new(0.001, 50, 1.2)
|
195
|
-
|
196
|
-
expect(
|
199
|
+
tdigest.merge!(other)
|
200
|
+
expect(tdigest.centroids.size).to be_zero
|
197
201
|
end
|
198
202
|
|
199
203
|
describe "with populated tdigests" do
|
204
|
+
let(:other) { described_class.new(0.001, 50, 1.2) }
|
205
|
+
|
200
206
|
before do
|
201
|
-
|
202
|
-
[subject, @other].each do |td|
|
207
|
+
[tdigest, other].each do |td|
|
203
208
|
td.push(60, 100)
|
204
209
|
10.times { td.push(rand * 100) }
|
205
210
|
end
|
@@ -207,23 +212,23 @@ RSpec.describe Airbrake::TDigest do
|
|
207
212
|
|
208
213
|
it "has the parameters of the calling tdigest" do
|
209
214
|
vars = %i[@delta @k @cx]
|
210
|
-
expected =
|
211
|
-
|
215
|
+
expected = vars.map { |v| [v, tdigest.instance_variable_get(v)] }.to_h
|
216
|
+
tdigest.merge!(other)
|
212
217
|
vars.each do |v|
|
213
|
-
expect(
|
218
|
+
expect(tdigest.instance_variable_get(v)).to eq(expected[v])
|
214
219
|
end
|
215
220
|
end
|
216
221
|
|
217
222
|
it "returns a tdigest with less than or equal centroids" do
|
218
|
-
combined_size =
|
219
|
-
|
220
|
-
expect(
|
223
|
+
combined_size = tdigest.centroids.size + other.centroids.size
|
224
|
+
tdigest.merge!(other)
|
225
|
+
expect(tdigest.centroids.size).to be <= combined_size
|
221
226
|
end
|
222
227
|
|
223
228
|
it "has the size of the two digests combined" do
|
224
|
-
combined_size =
|
225
|
-
|
226
|
-
expect(
|
229
|
+
combined_size = tdigest.size + other.size
|
230
|
+
tdigest.merge!(other)
|
231
|
+
expect(tdigest.size).to eq(combined_size)
|
227
232
|
end
|
228
233
|
end
|
229
234
|
end
|
data/spec/thread_pool_spec.rb
CHANGED
@@ -1,9 +1,5 @@
|
|
1
1
|
RSpec.describe Airbrake::ThreadPool do
|
2
|
-
|
3
|
-
let(:worker_size) { 1 }
|
4
|
-
let(:queue_size) { 2 }
|
5
|
-
|
6
|
-
subject do
|
2
|
+
subject(:thread_pool) do
|
7
3
|
described_class.new(
|
8
4
|
worker_size: worker_size,
|
9
5
|
queue_size: queue_size,
|
@@ -11,27 +7,27 @@ RSpec.describe Airbrake::ThreadPool do
|
|
11
7
|
)
|
12
8
|
end
|
13
9
|
|
10
|
+
let(:tasks) { [] }
|
11
|
+
let(:worker_size) { 1 }
|
12
|
+
let(:queue_size) { 2 }
|
13
|
+
|
14
14
|
describe "#<<" do
|
15
15
|
it "returns true" do
|
16
|
-
retval =
|
17
|
-
|
16
|
+
retval = thread_pool << 1
|
17
|
+
thread_pool.close
|
18
18
|
expect(retval).to eq(true)
|
19
19
|
end
|
20
20
|
|
21
21
|
it "performs work in background" do
|
22
|
-
|
23
|
-
|
24
|
-
|
22
|
+
thread_pool << 2
|
23
|
+
thread_pool << 1
|
24
|
+
thread_pool.close
|
25
25
|
|
26
26
|
expect(tasks).to eq([2, 1])
|
27
27
|
end
|
28
28
|
|
29
29
|
context "when the queue is full" do
|
30
|
-
|
31
|
-
allow(subject).to receive(:backlog).and_return(queue_size)
|
32
|
-
end
|
33
|
-
|
34
|
-
subject do
|
30
|
+
subject(:full_thread_pool) do
|
35
31
|
described_class.new(
|
36
32
|
worker_size: 1,
|
37
33
|
queue_size: 1,
|
@@ -39,26 +35,34 @@ RSpec.describe Airbrake::ThreadPool do
|
|
39
35
|
)
|
40
36
|
end
|
41
37
|
|
38
|
+
before do
|
39
|
+
# rubocop:disable RSpec/SubjectStub
|
40
|
+
allow(full_thread_pool).to receive(:backlog).and_return(queue_size)
|
41
|
+
# rubocop:enable RSpec/SubjectStub
|
42
|
+
end
|
43
|
+
|
42
44
|
it "returns false" do
|
43
|
-
retval =
|
44
|
-
|
45
|
+
retval = full_thread_pool << 1
|
46
|
+
full_thread_pool.close
|
45
47
|
expect(retval).to eq(false)
|
46
48
|
end
|
47
49
|
|
48
50
|
it "discards tasks" do
|
49
|
-
200.times {
|
50
|
-
|
51
|
+
200.times { full_thread_pool << 1 }
|
52
|
+
full_thread_pool.close
|
51
53
|
|
52
54
|
expect(tasks.size).to be_zero
|
53
55
|
end
|
54
56
|
|
55
57
|
it "logs discarded tasks" do
|
56
|
-
|
58
|
+
allow(Airbrake::Loggable.instance).to receive(:error)
|
59
|
+
|
60
|
+
15.times { full_thread_pool << 1 }
|
61
|
+
full_thread_pool.close
|
62
|
+
|
63
|
+
expect(Airbrake::Loggable.instance).to have_received(:error).with(
|
57
64
|
/reached its capacity/,
|
58
65
|
).exactly(15).times
|
59
|
-
|
60
|
-
15.times { subject << 1 }
|
61
|
-
subject.close
|
62
66
|
end
|
63
67
|
end
|
64
68
|
end
|
@@ -67,22 +71,22 @@ RSpec.describe Airbrake::ThreadPool do
|
|
67
71
|
let(:worker_size) { 0 }
|
68
72
|
|
69
73
|
it "returns the size of the queue" do
|
70
|
-
|
71
|
-
expect(
|
74
|
+
thread_pool << 1
|
75
|
+
expect(thread_pool.backlog).to eq(1)
|
72
76
|
end
|
73
77
|
end
|
74
78
|
|
75
79
|
describe "#has_workers?" do
|
76
80
|
it "returns false when the thread pool is not closed, but has 0 workers" do
|
77
|
-
|
81
|
+
thread_pool.workers.list.each do |worker|
|
78
82
|
worker.kill.join
|
79
83
|
end
|
80
|
-
expect(
|
84
|
+
expect(thread_pool).not_to have_workers
|
81
85
|
end
|
82
86
|
|
83
87
|
it "returns false when the thread pool is closed" do
|
84
|
-
|
85
|
-
expect(
|
88
|
+
thread_pool.close
|
89
|
+
expect(thread_pool).not_to have_workers
|
86
90
|
end
|
87
91
|
|
88
92
|
describe "forking behavior" do
|
@@ -93,20 +97,22 @@ RSpec.describe Airbrake::ThreadPool do
|
|
93
97
|
end
|
94
98
|
end
|
95
99
|
|
100
|
+
# rubocop:disable RSpec/MultipleExpectations
|
96
101
|
it "respawns workers on fork()" do
|
97
|
-
pid = fork { expect(
|
102
|
+
pid = fork { expect(thread_pool).to have_workers }
|
98
103
|
Process.wait(pid)
|
99
|
-
|
104
|
+
thread_pool.close
|
100
105
|
|
101
106
|
expect(Process.last_status).to be_success
|
102
|
-
expect(
|
107
|
+
expect(thread_pool).not_to have_workers
|
103
108
|
end
|
109
|
+
# rubocop:enable RSpec/MultipleExpectations
|
104
110
|
|
105
111
|
it "ensures that a new thread group is created per process" do
|
106
|
-
|
107
|
-
pid = fork {
|
112
|
+
thread_pool << 1
|
113
|
+
pid = fork { thread_pool.has_workers? }
|
108
114
|
Process.wait(pid)
|
109
|
-
|
115
|
+
thread_pool.close
|
110
116
|
|
111
117
|
expect(Process.last_status).to be_success
|
112
118
|
end
|
@@ -116,27 +122,29 @@ RSpec.describe Airbrake::ThreadPool do
|
|
116
122
|
describe "#close" do
|
117
123
|
context "when there's no work to do" do
|
118
124
|
it "joins the spawned thread" do
|
119
|
-
workers =
|
125
|
+
workers = thread_pool.workers.list
|
120
126
|
expect(workers).to all(be_alive)
|
121
127
|
|
122
|
-
|
128
|
+
thread_pool.close
|
123
129
|
expect(workers).to all(be_stop)
|
124
130
|
end
|
125
131
|
end
|
126
132
|
|
127
133
|
context "when there's some work to do" do
|
128
134
|
it "logs how many tasks are left to process" do
|
129
|
-
|
130
|
-
worker_size: 0, queue_size: 2, block: proc {},
|
131
|
-
)
|
135
|
+
allow(Airbrake::Loggable.instance).to receive(:debug)
|
132
136
|
|
133
|
-
|
134
|
-
|
137
|
+
thread_pool = described_class.new(
|
138
|
+
name: 'foo', worker_size: 0, queue_size: 2, block: proc {},
|
135
139
|
)
|
136
|
-
expect(Airbrake::Loggable.instance).to receive(:debug).with(/closed/)
|
137
140
|
|
138
141
|
2.times { thread_pool << 1 }
|
139
142
|
thread_pool.close
|
143
|
+
|
144
|
+
expect(Airbrake::Loggable.instance).to have_received(:debug).with(
|
145
|
+
/waiting to process \d+ task\(s\)/,
|
146
|
+
)
|
147
|
+
expect(Airbrake::Loggable.instance).to have_received(:debug).with(/foo.+closed/)
|
140
148
|
end
|
141
149
|
|
142
150
|
it "waits until the queue gets empty" do
|
@@ -144,7 +152,7 @@ RSpec.describe Airbrake::ThreadPool do
|
|
144
152
|
worker_size: 1, queue_size: 2, block: proc {},
|
145
153
|
)
|
146
154
|
|
147
|
-
10.times {
|
155
|
+
10.times { thread_pool << 1 }
|
148
156
|
thread_pool.close
|
149
157
|
expect(thread_pool.backlog).to be_zero
|
150
158
|
end
|
@@ -153,17 +161,17 @@ RSpec.describe Airbrake::ThreadPool do
|
|
153
161
|
context "when it was already closed" do
|
154
162
|
it "doesn't increase the queue size" do
|
155
163
|
begin
|
156
|
-
|
164
|
+
thread_pool.close
|
157
165
|
rescue Airbrake::Error
|
158
166
|
nil
|
159
167
|
end
|
160
168
|
|
161
|
-
expect(
|
169
|
+
expect(thread_pool.backlog).to be_zero
|
162
170
|
end
|
163
171
|
|
164
172
|
it "raises error" do
|
165
|
-
|
166
|
-
expect {
|
173
|
+
thread_pool.close
|
174
|
+
expect { thread_pool.close }.to raise_error(
|
167
175
|
Airbrake::Error, 'this thread pool is closed already'
|
168
176
|
)
|
169
177
|
end
|
@@ -171,17 +179,19 @@ RSpec.describe Airbrake::ThreadPool do
|
|
171
179
|
end
|
172
180
|
|
173
181
|
describe "#spawn_workers" do
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
expect(
|
182
|
+
after { thread_pool.close }
|
183
|
+
|
184
|
+
it "spawns an enclosed thread group" do
|
185
|
+
expect(thread_pool.workers).to be_a(ThreadGroup)
|
186
|
+
expect(thread_pool.workers).to be_enclosed
|
187
|
+
end
|
178
188
|
|
179
|
-
|
189
|
+
it "spawns threads that are alive" do
|
190
|
+
expect(thread_pool.workers.list).to all(be_alive)
|
180
191
|
end
|
181
192
|
|
182
193
|
it "spawns exactly `workers_size` workers" do
|
183
|
-
expect(
|
184
|
-
subject.close
|
194
|
+
expect(thread_pool.workers.list.size).to eq(worker_size)
|
185
195
|
end
|
186
196
|
end
|
187
197
|
end
|