airbrake-ruby 6.1.0-java → 6.1.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/filters/git_last_checkout_filter.rb +1 -1
- data/lib/airbrake-ruby/nested_exception.rb +10 -1
- data/lib/airbrake-ruby/notice.rb +5 -3
- data/lib/airbrake-ruby/version.rb +1 -1
- metadata +4 -122
- data/spec/airbrake_spec.rb +0 -522
- data/spec/async_sender_spec.rb +0 -65
- data/spec/backtrace_spec.rb +0 -430
- data/spec/benchmark_spec.rb +0 -35
- data/spec/code_hunk_spec.rb +0 -124
- data/spec/config/processor_spec.rb +0 -167
- data/spec/config/validator_spec.rb +0 -204
- data/spec/config_spec.rb +0 -188
- data/spec/context_spec.rb +0 -54
- data/spec/deploy_notifier_spec.rb +0 -50
- data/spec/file_cache_spec.rb +0 -35
- data/spec/filter_chain_spec.rb +0 -124
- data/spec/filters/context_filter_spec.rb +0 -32
- data/spec/filters/dependency_filter_spec.rb +0 -14
- data/spec/filters/exception_attributes_filter_spec.rb +0 -52
- data/spec/filters/gem_root_filter_spec.rb +0 -44
- data/spec/filters/git_last_checkout_filter_spec.rb +0 -61
- data/spec/filters/git_repository_filter_spec.rb +0 -72
- data/spec/filters/git_revision_filter_spec.rb +0 -126
- data/spec/filters/keys_allowlist_spec.rb +0 -204
- data/spec/filters/keys_blocklist_spec.rb +0 -242
- data/spec/filters/root_directory_filter_spec.rb +0 -39
- data/spec/filters/sql_filter_spec.rb +0 -274
- data/spec/filters/system_exit_filter_spec.rb +0 -16
- data/spec/filters/thread_filter_spec.rb +0 -281
- data/spec/fixtures/notroot.txt +0 -7
- data/spec/fixtures/project_root/code.rb +0 -221
- data/spec/fixtures/project_root/empty_file.rb +0 -0
- data/spec/fixtures/project_root/long_line.txt +0 -1
- data/spec/fixtures/project_root/short_file.rb +0 -3
- data/spec/fixtures/project_root/vendor/bundle/ignored_file.rb +0 -5
- data/spec/helpers.rb +0 -9
- data/spec/ignorable_spec.rb +0 -14
- data/spec/inspectable_spec.rb +0 -45
- data/spec/loggable_spec.rb +0 -17
- data/spec/monotonic_time_spec.rb +0 -25
- data/spec/nested_exception_spec.rb +0 -73
- data/spec/notice_notifier/options_spec.rb +0 -269
- data/spec/notice_notifier_spec.rb +0 -361
- data/spec/notice_spec.rb +0 -300
- data/spec/performance_breakdown_spec.rb +0 -11
- data/spec/performance_notifier_spec.rb +0 -645
- data/spec/promise_spec.rb +0 -203
- data/spec/query_spec.rb +0 -11
- data/spec/queue_spec.rb +0 -18
- data/spec/remote_settings/callback_spec.rb +0 -162
- data/spec/remote_settings/settings_data_spec.rb +0 -348
- data/spec/remote_settings_spec.rb +0 -201
- data/spec/request_spec.rb +0 -9
- data/spec/response_spec.rb +0 -110
- data/spec/spec_helper.rb +0 -100
- data/spec/stashable_spec.rb +0 -23
- data/spec/stat_spec.rb +0 -39
- data/spec/sync_sender_spec.rb +0 -168
- data/spec/tdigest_spec.rb +0 -235
- data/spec/thread_pool_spec.rb +0 -196
- data/spec/time_truncate_spec.rb +0 -30
- data/spec/timed_trace_spec.rb +0 -127
- data/spec/truncator_spec.rb +0 -267
@@ -1,361 +0,0 @@
|
|
1
|
-
RSpec.describe Airbrake::NoticeNotifier do
|
2
|
-
subject(:notice_notifier) { described_class.new }
|
3
|
-
|
4
|
-
before do
|
5
|
-
Airbrake::Config.instance = Airbrake::Config.new(
|
6
|
-
project_id: 1,
|
7
|
-
project_key: 'abc',
|
8
|
-
logger: Logger.new('/dev/null'),
|
9
|
-
performance_stats: true,
|
10
|
-
)
|
11
|
-
end
|
12
|
-
|
13
|
-
describe "#new" do
|
14
|
-
describe "default filter addition" do
|
15
|
-
before { allow_any_instance_of(Airbrake::FilterChain).to receive(:add_filter) }
|
16
|
-
|
17
|
-
it "appends the context filter" do
|
18
|
-
expect_any_instance_of(Airbrake::FilterChain).to receive(:add_filter)
|
19
|
-
.with(instance_of(Airbrake::Filters::ContextFilter))
|
20
|
-
notice_notifier
|
21
|
-
end
|
22
|
-
|
23
|
-
it "appends the exception attributes filter" do
|
24
|
-
expect_any_instance_of(Airbrake::FilterChain).to receive(:add_filter)
|
25
|
-
.with(instance_of(Airbrake::Filters::ExceptionAttributesFilter))
|
26
|
-
notice_notifier
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
describe "#notify" do
|
32
|
-
let(:endpoint) { 'https://api.airbrake.io/api/v3/projects/1/notices' }
|
33
|
-
|
34
|
-
let(:body) do
|
35
|
-
{
|
36
|
-
'id' => '00054414-b147-6ffa-85d6-1524d83362a6',
|
37
|
-
'url' => 'http://localhost/locate/00054414-b147-6ffa-85d6-1524d83362a6',
|
38
|
-
}.to_json
|
39
|
-
end
|
40
|
-
|
41
|
-
before { stub_request(:post, endpoint).to_return(status: 201, body: body) }
|
42
|
-
|
43
|
-
it "returns a promise" do
|
44
|
-
expect(notice_notifier.notify('ex')).to be_an(Airbrake::Promise)
|
45
|
-
sleep 1
|
46
|
-
end
|
47
|
-
|
48
|
-
it "refines the notice object" do
|
49
|
-
notice_notifier.add_filter { |n| n[:params] = { foo: 'bar' } }
|
50
|
-
notice = notice_notifier.build_notice('ex')
|
51
|
-
notice_notifier.notify(notice)
|
52
|
-
expect(notice[:params]).to eq(foo: 'bar')
|
53
|
-
sleep 1
|
54
|
-
end
|
55
|
-
|
56
|
-
context "when config is invalid" do
|
57
|
-
before { Airbrake::Config.instance.merge(project_id: nil) }
|
58
|
-
|
59
|
-
it "returns a rejected promise" do
|
60
|
-
promise = notice_notifier.notify({})
|
61
|
-
expect(promise).to be_rejected
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
context "when a notice is not ignored" do
|
66
|
-
it "yields the notice" do
|
67
|
-
expect { |b| notice_notifier.notify('ex', &b) }
|
68
|
-
.to yield_with_args(Airbrake::Notice)
|
69
|
-
sleep 1
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
context "when a notice is ignored via a filter" do
|
74
|
-
before { notice_notifier.add_filter(&:ignore!) }
|
75
|
-
|
76
|
-
it "yields the notice" do
|
77
|
-
expect { |b| notice_notifier.notify('ex', &b) }
|
78
|
-
.to yield_with_args(Airbrake::Notice)
|
79
|
-
end
|
80
|
-
|
81
|
-
it "returns a rejected promise" do
|
82
|
-
value = notice_notifier.notify('ex').value
|
83
|
-
expect(value['error']).to match(/was marked as ignored/)
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
context "when a notice is ignored via an inline filter" do
|
88
|
-
before { notice_notifier.add_filter { raise AirbrakeTestError } }
|
89
|
-
|
90
|
-
it "doesn't invoke regular filters" do
|
91
|
-
expect { notice_notifier.notify('ex', &:ignore!) }.not_to raise_error
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
context "when async sender has workers" do
|
96
|
-
it "sends an exception asynchronously" do
|
97
|
-
expect_any_instance_of(Airbrake::AsyncSender).to receive(:send)
|
98
|
-
notice_notifier.notify('foo', bingo: 'bango')
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
context "when async sender doesn't have workers" do
|
103
|
-
it "sends an exception synchronously" do
|
104
|
-
allow_any_instance_of(Airbrake::AsyncSender)
|
105
|
-
.to receive(:has_workers?).and_return(false)
|
106
|
-
expect_any_instance_of(Airbrake::SyncSender).to receive(:send)
|
107
|
-
|
108
|
-
notice_notifier.notify('foo', bingo: 'bango')
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
context "when the provided environment is ignored" do
|
113
|
-
before do
|
114
|
-
Airbrake::Config.instance.merge(
|
115
|
-
environment: 'test',
|
116
|
-
ignore_environments: %w[test],
|
117
|
-
)
|
118
|
-
end
|
119
|
-
|
120
|
-
it "doesn't send an notice" do
|
121
|
-
expect_any_instance_of(Airbrake::AsyncSender).not_to receive(:send)
|
122
|
-
notice_notifier.notify('foo', bingo: 'bango')
|
123
|
-
end
|
124
|
-
|
125
|
-
it "returns a rejected promise" do
|
126
|
-
promise = notice_notifier.notify('foo', bingo: 'bango')
|
127
|
-
expect(promise.value).to eq('error' => "current environment 'test' is ignored")
|
128
|
-
end
|
129
|
-
end
|
130
|
-
end
|
131
|
-
|
132
|
-
describe "#notify_sync" do
|
133
|
-
let(:endpoint) { 'https://api.airbrake.io/api/v3/projects/1/notices' }
|
134
|
-
|
135
|
-
let(:body) do
|
136
|
-
{
|
137
|
-
'id' => '00054414-b147-6ffa-85d6-1524d83362a6',
|
138
|
-
'url' => 'http://localhost/locate/00054414-b147-6ffa-85d6-1524d83362a6',
|
139
|
-
}
|
140
|
-
end
|
141
|
-
|
142
|
-
before { stub_request(:post, endpoint).to_return(status: 201, body: body.to_json) }
|
143
|
-
|
144
|
-
it "returns a reponse hash" do
|
145
|
-
expect(notice_notifier.notify_sync('ex')).to eq(body)
|
146
|
-
end
|
147
|
-
|
148
|
-
it "refines the notice object" do
|
149
|
-
notice_notifier.add_filter { |n| n[:params] = { foo: 'bar' } }
|
150
|
-
notice = notice_notifier.build_notice('ex')
|
151
|
-
notice_notifier.notify_sync(notice)
|
152
|
-
expect(notice[:params]).to eq(foo: 'bar')
|
153
|
-
end
|
154
|
-
|
155
|
-
it "sends an exception synchronously" do
|
156
|
-
notice_notifier.notify_sync('foo', bingo: 'bango')
|
157
|
-
expect(
|
158
|
-
a_request(:post, endpoint).with(
|
159
|
-
body: /"params":{.*"bingo":"bango".*}/,
|
160
|
-
),
|
161
|
-
).to have_been_made.once
|
162
|
-
end
|
163
|
-
|
164
|
-
context "when a notice is not ignored" do
|
165
|
-
it "yields the notice" do
|
166
|
-
expect { |b| notice_notifier.notify_sync('ex', &b) }
|
167
|
-
.to yield_with_args(Airbrake::Notice)
|
168
|
-
end
|
169
|
-
end
|
170
|
-
|
171
|
-
context "when a notice is ignored via a filter" do
|
172
|
-
before { notice_notifier.add_filter(&:ignore!) }
|
173
|
-
|
174
|
-
it "yields the notice" do
|
175
|
-
expect { |b| notice_notifier.notify_sync('ex', &b) }
|
176
|
-
.to yield_with_args(Airbrake::Notice)
|
177
|
-
end
|
178
|
-
|
179
|
-
it "returns an error hash" do
|
180
|
-
response = notice_notifier.notify_sync('ex')
|
181
|
-
expect(response['error']).to match(/was marked as ignored/)
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
|
-
context "when a notice is ignored via an inline filter" do
|
186
|
-
before { notice_notifier.add_filter { raise AirbrakeTestError } }
|
187
|
-
|
188
|
-
it "doesn't invoke regular filters" do
|
189
|
-
expect { notice_notifier.notify('ex', &:ignore!) }.not_to raise_error
|
190
|
-
end
|
191
|
-
end
|
192
|
-
|
193
|
-
context "when the provided environment is ignored" do
|
194
|
-
before do
|
195
|
-
Airbrake::Config.instance.merge(
|
196
|
-
environment: 'test', ignore_environments: %w[test],
|
197
|
-
)
|
198
|
-
end
|
199
|
-
|
200
|
-
it "doesn't send an notice" do
|
201
|
-
expect_any_instance_of(Airbrake::SyncSender).not_to receive(:send)
|
202
|
-
notice_notifier.notify_sync('foo', bingo: 'bango')
|
203
|
-
end
|
204
|
-
|
205
|
-
it "returns an error hash" do
|
206
|
-
expect(notice_notifier.notify_sync('foo'))
|
207
|
-
.to eq('error' => "current environment 'test' is ignored")
|
208
|
-
end
|
209
|
-
end
|
210
|
-
end
|
211
|
-
|
212
|
-
describe "#add_filter" do
|
213
|
-
context "given a block" do
|
214
|
-
it "appends a new filter to the filter chain" do
|
215
|
-
notifier = notice_notifier
|
216
|
-
b = proc {}
|
217
|
-
# rubocop:disable RSpec/StubbedMock
|
218
|
-
expect_any_instance_of(Airbrake::FilterChain)
|
219
|
-
.to receive(:add_filter) { |*args| expect(args.last).to be(b) }
|
220
|
-
# rubocop:enable RSpec/StubbedMock
|
221
|
-
notifier.add_filter(&b)
|
222
|
-
end
|
223
|
-
end
|
224
|
-
|
225
|
-
context "given a class" do
|
226
|
-
it "appends a new filter to the filter chain" do
|
227
|
-
notifier = notice_notifier
|
228
|
-
klass = Class.new
|
229
|
-
expect_any_instance_of(Airbrake::FilterChain)
|
230
|
-
.to receive(:add_filter).with(klass)
|
231
|
-
notifier.add_filter(klass)
|
232
|
-
end
|
233
|
-
end
|
234
|
-
end
|
235
|
-
|
236
|
-
describe "#build_notice" do
|
237
|
-
context "when given exception is another notice" do
|
238
|
-
it "merges params with the notice" do
|
239
|
-
notice = notice_notifier.build_notice('ex')
|
240
|
-
other = notice_notifier.build_notice(notice, foo: 'bar')
|
241
|
-
expect(other[:params]).to eq(foo: 'bar')
|
242
|
-
end
|
243
|
-
|
244
|
-
it "returns the provided notice" do
|
245
|
-
notice = notice_notifier.build_notice('ex')
|
246
|
-
other = notice_notifier.build_notice(notice, foo: 'bar')
|
247
|
-
expect(other).to eq(notice)
|
248
|
-
end
|
249
|
-
end
|
250
|
-
|
251
|
-
context "when given exception is an Exception" do
|
252
|
-
it "prevents mutation of passed-in params hash" do
|
253
|
-
params = { immutable: true }
|
254
|
-
notice = notice_notifier.build_notice('ex', params)
|
255
|
-
notice[:params][:mutable] = true
|
256
|
-
expect(params).to eq(immutable: true)
|
257
|
-
end
|
258
|
-
|
259
|
-
context "and also when it doesn't have own backtrace" do
|
260
|
-
context "and when the generated backtrace consists only of library frames" do
|
261
|
-
it "returns the full generated backtrace" do
|
262
|
-
backtrace = [
|
263
|
-
"/lib/airbrake-ruby/a.rb:84:in `build_notice'",
|
264
|
-
"/lib/airbrake-ruby/b.rb:124:in `send_notice'",
|
265
|
-
]
|
266
|
-
allow(Kernel).to receive(:caller).and_return(backtrace)
|
267
|
-
|
268
|
-
notice = notice_notifier.build_notice(Exception.new)
|
269
|
-
|
270
|
-
expect(notice[:errors].first[:backtrace]).to eq(
|
271
|
-
[
|
272
|
-
{ file: '/lib/airbrake-ruby/a.rb', line: 84, function: 'build_notice' },
|
273
|
-
{ file: '/lib/airbrake-ruby/b.rb', line: 124, function: 'send_notice' },
|
274
|
-
],
|
275
|
-
)
|
276
|
-
end
|
277
|
-
end
|
278
|
-
|
279
|
-
context "and when the generated backtrace consists of mixed frames" do
|
280
|
-
it "returns the filtered backtrace" do
|
281
|
-
backtrace = [
|
282
|
-
"/airbrake-ruby/lib/airbrake-ruby/a.rb:84:in `b'",
|
283
|
-
"/airbrake-ruby/lib/foo/b.rb:84:in `build'",
|
284
|
-
"/airbrake-ruby/lib/bar/c.rb:124:in `send'",
|
285
|
-
]
|
286
|
-
allow(Kernel).to receive(:caller).and_return(backtrace)
|
287
|
-
|
288
|
-
notice = notice_notifier.build_notice(Exception.new)
|
289
|
-
|
290
|
-
expect(notice[:errors].first[:backtrace]).to eq(
|
291
|
-
[
|
292
|
-
{ file: '/airbrake-ruby/lib/foo/b.rb', line: 84, function: 'build' },
|
293
|
-
{ file: '/airbrake-ruby/lib/bar/c.rb', line: 124, function: 'send' },
|
294
|
-
],
|
295
|
-
)
|
296
|
-
end
|
297
|
-
end
|
298
|
-
end
|
299
|
-
end
|
300
|
-
|
301
|
-
# TODO: this seems to be bugged. Fix later.
|
302
|
-
context "when given exception is a Java exception", skip: true do
|
303
|
-
before do
|
304
|
-
allow(Airbrake::Backtrace).to receive(:java_exception?).and_return(true)
|
305
|
-
end
|
306
|
-
|
307
|
-
it "automatically generates the backtrace" do
|
308
|
-
backtrace = [
|
309
|
-
"org/jruby/RubyKernel.java:998:in `eval'",
|
310
|
-
"/ruby/stdlib/irb/workspace.rb:87:in `evaluate'",
|
311
|
-
"/ruby/stdlib/irb.rb:489:in `block in eval_input'",
|
312
|
-
]
|
313
|
-
allow(Kernel).to receive(:caller).and_return(backtrace)
|
314
|
-
|
315
|
-
notice = notice_notifier.build_notice(Exception.new)
|
316
|
-
|
317
|
-
# rubocop:disable Layout/LineLength
|
318
|
-
expect(notice[:errors].first[:backtrace]).to eq(
|
319
|
-
[
|
320
|
-
{ file: 'org/jruby/RubyKernel.java', line: 998, function: 'eval' },
|
321
|
-
{ file: '/ruby/stdlib/irb/workspace.rb', line: 87, function: 'evaluate' },
|
322
|
-
{ file: '/ruby/stdlib/irb.rb:489', line: 489, function: 'block in eval_input' },
|
323
|
-
],
|
324
|
-
)
|
325
|
-
# rubocop:enable Layout/LineLength
|
326
|
-
end
|
327
|
-
end
|
328
|
-
|
329
|
-
context "when async sender is closed" do
|
330
|
-
before do
|
331
|
-
allow_any_instance_of(Airbrake::AsyncSender)
|
332
|
-
.to receive(:closed?).and_return(true)
|
333
|
-
end
|
334
|
-
|
335
|
-
it "raises error" do
|
336
|
-
expect { notice_notifier.build_notice(Exception.new('oops')) }.to raise_error(
|
337
|
-
Airbrake::Error,
|
338
|
-
"Airbrake is closed; can't build exception: Exception: oops",
|
339
|
-
)
|
340
|
-
end
|
341
|
-
end
|
342
|
-
end
|
343
|
-
|
344
|
-
describe "#close" do
|
345
|
-
it "sends the close message to async sender" do
|
346
|
-
expect_any_instance_of(Airbrake::AsyncSender).to receive(:close)
|
347
|
-
notice_notifier.close
|
348
|
-
end
|
349
|
-
end
|
350
|
-
|
351
|
-
describe "#configured?" do
|
352
|
-
it { is_expected.to be_configured }
|
353
|
-
end
|
354
|
-
|
355
|
-
describe "#merge_context" do
|
356
|
-
it "merges the provided context with the notice object" do
|
357
|
-
expect_any_instance_of(Hash).to receive(:merge!).with(apples: 'oranges')
|
358
|
-
notice_notifier.merge_context(apples: 'oranges')
|
359
|
-
end
|
360
|
-
end
|
361
|
-
end
|
data/spec/notice_spec.rb
DELETED
@@ -1,300 +0,0 @@
|
|
1
|
-
RSpec.describe Airbrake::Notice do
|
2
|
-
let(:notice) { described_class.new(AirbrakeTestError.new, bingo: '1') }
|
3
|
-
|
4
|
-
describe "#to_json" do
|
5
|
-
context "app_version" do
|
6
|
-
context "when missing" do
|
7
|
-
before { Airbrake::Config.instance.merge(app_version: nil) }
|
8
|
-
|
9
|
-
it "doesn't include app_version" do
|
10
|
-
expect(notice.to_json).not_to match(/"context":{"version":"1.2.3"/)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
context "when present" do
|
15
|
-
let(:notice) { described_class.new(AirbrakeTestError.new) }
|
16
|
-
|
17
|
-
before do
|
18
|
-
Airbrake::Config.instance.merge(
|
19
|
-
app_version: "1.2.3",
|
20
|
-
root_directory: "/one/two",
|
21
|
-
)
|
22
|
-
end
|
23
|
-
|
24
|
-
it "includes app_version" do
|
25
|
-
expect(notice.to_json).to match(/"context":{"version":"1.2.3"/)
|
26
|
-
end
|
27
|
-
|
28
|
-
it "includes root_directory" do
|
29
|
-
expect(notice.to_json).to match(%r{"rootDirectory":"/one/two"})
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
context "when versions is empty" do
|
35
|
-
it "doesn't set the 'versions' payload" do
|
36
|
-
expect(notice.to_json).not_to match(
|
37
|
-
/"context":{"versions":{"dep":"1.2.3"}}/,
|
38
|
-
)
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
context "when versions is not empty" do
|
43
|
-
it "sets the 'versions' payload" do
|
44
|
-
notice[:context][:versions] = { 'dep' => '1.2.3' }
|
45
|
-
expect(notice.to_json).to match(
|
46
|
-
/"context":{.*"versions":{"dep":"1.2.3"}.*}/,
|
47
|
-
)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
context "truncation" do
|
52
|
-
shared_examples 'payloads' do |size, msg|
|
53
|
-
it msg do
|
54
|
-
ex = AirbrakeTestError.new
|
55
|
-
|
56
|
-
backtrace = []
|
57
|
-
size.times { backtrace << "bin/rails:3:in `<main>'" }
|
58
|
-
ex.set_backtrace(backtrace)
|
59
|
-
|
60
|
-
notice = described_class.new(ex)
|
61
|
-
|
62
|
-
expect(notice.to_json.bytesize).to be < 64000
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
max_msg = 'truncates to the max allowed size'
|
67
|
-
|
68
|
-
context "with an extremely huge payload" do
|
69
|
-
include_examples 'payloads', 200_000, max_msg
|
70
|
-
end
|
71
|
-
|
72
|
-
context "with a big payload" do
|
73
|
-
include_examples 'payloads', 50_000, max_msg
|
74
|
-
end
|
75
|
-
|
76
|
-
small_msg = "doesn't truncate it"
|
77
|
-
|
78
|
-
context "with a small payload" do
|
79
|
-
include_examples 'payloads', 1000, small_msg
|
80
|
-
end
|
81
|
-
|
82
|
-
context "with a tiny payload" do
|
83
|
-
include_examples 'payloads', 300, small_msg
|
84
|
-
end
|
85
|
-
|
86
|
-
context "when truncation failed" do
|
87
|
-
it "returns nil" do
|
88
|
-
allow_any_instance_of(Airbrake::Truncator)
|
89
|
-
.to receive(:reduce_max_size).and_return(0)
|
90
|
-
|
91
|
-
encoded = Base64.encode64("\xD3\xE6\xBC\x9D\xBA").encode!('ASCII-8BIT')
|
92
|
-
bad_string = Base64.decode64(encoded)
|
93
|
-
|
94
|
-
ex = AirbrakeTestError.new
|
95
|
-
|
96
|
-
backtrace = []
|
97
|
-
10.times { backtrace << "bin/rails:3:in `<#{bad_string}>'" }
|
98
|
-
ex.set_backtrace(backtrace)
|
99
|
-
|
100
|
-
notice = described_class.new(ex)
|
101
|
-
expect(notice.to_json).to be_nil
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
describe "object replacement with its string version" do
|
106
|
-
let(:klass) { Class.new }
|
107
|
-
let(:ex) { AirbrakeTestError.new }
|
108
|
-
let(:params) { { bingo: [Object.new, klass.new] } }
|
109
|
-
let(:notice) { described_class.new(ex, params) }
|
110
|
-
|
111
|
-
before do
|
112
|
-
backtrace = []
|
113
|
-
backtrace_size.times { backtrace << "bin/rails:3:in `<main>'" }
|
114
|
-
ex.set_backtrace(backtrace)
|
115
|
-
end
|
116
|
-
|
117
|
-
context "with payload within the limits" do
|
118
|
-
let(:backtrace_size) { 1000 }
|
119
|
-
|
120
|
-
it "doesn't happen" do
|
121
|
-
expect(notice.to_json)
|
122
|
-
.to match(/bingo":\["#<Object:.+>","#<#<Class:.+>:.+>"/)
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
context "with payload bigger than the limit" do
|
127
|
-
context "with payload within the limits" do
|
128
|
-
let(:backtrace_size) { 50_000 }
|
129
|
-
|
130
|
-
it "happens" do
|
131
|
-
expect(notice.to_json)
|
132
|
-
.to match(/bingo":\[".+Object.+",".+Class.+"/)
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
context "given a closed IO object" do
|
140
|
-
context "and when it is not monkey-patched by ActiveSupport" do
|
141
|
-
it "is not getting truncated" do
|
142
|
-
notice[:params] = { obj: IO.new(0).tap(&:close) }
|
143
|
-
expect(notice.to_json).to match(/"obj":"#<IO:0x.+>"/)
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
context "and when it is monkey-patched by ActiveSupport" do
|
148
|
-
# Instances of this class contain a closed IO object assigned to an
|
149
|
-
# instance variable. Normally, the JSON gem, which we depend on can
|
150
|
-
# parse closed IO objects. However, because ActiveSupport monkey-patches
|
151
|
-
# #to_json and calls #to_a on them, they raise IOError when we try to
|
152
|
-
# serialize them.
|
153
|
-
#
|
154
|
-
# @see https://goo.gl/0A3xNC
|
155
|
-
# rubocop:disable Lint/ConstantDefinitionInBlock, RSpec/LeakyConstantDeclaration
|
156
|
-
class ObjectWithIoIvars
|
157
|
-
def initialize
|
158
|
-
@bongo = Tempfile.new('bongo').tap(&:close)
|
159
|
-
end
|
160
|
-
|
161
|
-
# @raise [NotImplementedError] when inside a Rails environment
|
162
|
-
def to_json(*)
|
163
|
-
raise NotImplementedError
|
164
|
-
end
|
165
|
-
end
|
166
|
-
# rubocop:enable Lint/ConstantDefinitionInBlock, RSpec/LeakyConstantDeclaration
|
167
|
-
|
168
|
-
# @see ObjectWithIoIvars
|
169
|
-
# rubocop:disable Lint/ConstantDefinitionInBlock, RSpec/LeakyConstantDeclaration
|
170
|
-
class ObjectWithNestedIoIvars
|
171
|
-
def initialize
|
172
|
-
@bish = ObjectWithIoIvars.new
|
173
|
-
end
|
174
|
-
|
175
|
-
# @see ObjectWithIoIvars#to_json
|
176
|
-
def to_json(*)
|
177
|
-
raise NotImplementedError
|
178
|
-
end
|
179
|
-
end
|
180
|
-
# rubocop:enable Lint/ConstantDefinitionInBlock, RSpec/LeakyConstantDeclaration
|
181
|
-
|
182
|
-
context "and also when it's a closed Tempfile" do
|
183
|
-
it "doesn't fail" do
|
184
|
-
notice[:params] = { obj: Tempfile.new('bongo').tap(&:close) }
|
185
|
-
expect(notice.to_json).to match(/"obj":"#<(Temp)?file:0x.+>"/i)
|
186
|
-
end
|
187
|
-
end
|
188
|
-
|
189
|
-
context "and also when it's an IO ivar" do
|
190
|
-
it "doesn't fail" do
|
191
|
-
notice[:params] = { obj: ObjectWithIoIvars.new }
|
192
|
-
expect(notice.to_json).to match(/"obj":".+ObjectWithIoIvars.+"/)
|
193
|
-
end
|
194
|
-
|
195
|
-
context "and when it's deeply nested inside a hash" do
|
196
|
-
it "doesn't fail" do
|
197
|
-
notice[:params] = { a: { b: { c: ObjectWithIoIvars.new } } }
|
198
|
-
expect(notice.to_json).to match(
|
199
|
-
/"params":{"a":{"b":{"c":".+ObjectWithIoIvars.+"}}.*}/,
|
200
|
-
)
|
201
|
-
end
|
202
|
-
end
|
203
|
-
|
204
|
-
context "and when it's deeply nested inside an array" do
|
205
|
-
it "doesn't fail" do
|
206
|
-
notice[:params] = { a: [[ObjectWithIoIvars.new]] }
|
207
|
-
expect(notice.to_json).to match(
|
208
|
-
/"params":{"a":\[\[".+ObjectWithIoIvars.+"\]\].*}/,
|
209
|
-
)
|
210
|
-
end
|
211
|
-
end
|
212
|
-
end
|
213
|
-
|
214
|
-
context "and also when it's a non-IO ivar, which contains an IO ivar itself" do
|
215
|
-
it "doesn't fail" do
|
216
|
-
notice[:params] = { obj: ObjectWithNestedIoIvars.new }
|
217
|
-
expect(notice.to_json).to match(/"obj":".+ObjectWithNested.+"/)
|
218
|
-
end
|
219
|
-
end
|
220
|
-
end
|
221
|
-
end
|
222
|
-
|
223
|
-
it "overwrites the 'notifier' payload with the default values" do
|
224
|
-
notice[:notifier] = { name: 'bingo', bango: 'bongo' }
|
225
|
-
|
226
|
-
expect(notice.to_json)
|
227
|
-
.to match(/"notifier":{"name":"airbrake-ruby","version":".+","url":".+"}/)
|
228
|
-
end
|
229
|
-
|
230
|
-
it "always contains context/hostname" do
|
231
|
-
expect(notice.to_json)
|
232
|
-
.to match(/"context":{.*"hostname":".+".*}/)
|
233
|
-
end
|
234
|
-
|
235
|
-
it "defaults to the error severity" do
|
236
|
-
expect(notice.to_json).to match(/"context":{.*"severity":"error".*}/)
|
237
|
-
end
|
238
|
-
|
239
|
-
it "always contains environment/program_name" do
|
240
|
-
expect(notice.to_json)
|
241
|
-
.to match(%r|"environment":{"program_name":.+/rspec.*|)
|
242
|
-
end
|
243
|
-
|
244
|
-
it "contains errors" do
|
245
|
-
expect(notice.to_json)
|
246
|
-
.to match(/"errors":\[{"type":"AirbrakeTestError","message":"App crash/)
|
247
|
-
end
|
248
|
-
|
249
|
-
it "contains a backtrace" do
|
250
|
-
expect(notice.to_json)
|
251
|
-
.to match(%r|"backtrace":\[{"file":"/home/.+/spec/spec_helper.rb"|)
|
252
|
-
end
|
253
|
-
|
254
|
-
it "contains params" do
|
255
|
-
expect(notice.to_json).to match(/"params":{"bingo":"1"}/)
|
256
|
-
end
|
257
|
-
end
|
258
|
-
|
259
|
-
describe "#[]" do
|
260
|
-
it "accesses payload" do
|
261
|
-
expect(notice[:params]).to eq(bingo: '1')
|
262
|
-
end
|
263
|
-
|
264
|
-
it "raises error if notice is ignored" do
|
265
|
-
notice.ignore!
|
266
|
-
expect { notice[:params] }
|
267
|
-
.to raise_error(Airbrake::Error, 'cannot access ignored Airbrake::Notice')
|
268
|
-
end
|
269
|
-
end
|
270
|
-
|
271
|
-
describe "#[]=" do
|
272
|
-
it "sets a payload value" do
|
273
|
-
hash = { bingo: 'bango' }
|
274
|
-
notice[:params] = hash
|
275
|
-
expect(notice[:params]).to eq(hash)
|
276
|
-
end
|
277
|
-
|
278
|
-
it "raises error if notice is ignored" do
|
279
|
-
notice.ignore!
|
280
|
-
expect { notice[:params] = {} }
|
281
|
-
.to raise_error(Airbrake::Error, 'cannot access ignored Airbrake::Notice')
|
282
|
-
end
|
283
|
-
|
284
|
-
it "raises error when trying to assign unrecognized key" do
|
285
|
-
expect { notice[:bingo] = 1 }
|
286
|
-
.to raise_error(Airbrake::Error, /:bingo is not recognized among/)
|
287
|
-
end
|
288
|
-
|
289
|
-
it "raises when setting non-hash objects as the value" do
|
290
|
-
expect { notice[:params] = Object.new }
|
291
|
-
.to raise_error(Airbrake::Error, 'Got Object value, wanted a Hash')
|
292
|
-
end
|
293
|
-
end
|
294
|
-
|
295
|
-
describe "#stash" do
|
296
|
-
subject { described_class.new(AirbrakeTestError.new) }
|
297
|
-
|
298
|
-
it { is_expected.to respond_to(:stash) }
|
299
|
-
end
|
300
|
-
end
|