airbrake-ruby 4.15.0 → 6.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (96) hide show
  1. checksums.yaml +4 -4
  2. data/lib/airbrake-ruby/async_sender.rb +4 -2
  3. data/lib/airbrake-ruby/backtrace.rb +6 -5
  4. data/lib/airbrake-ruby/config/processor.rb +77 -0
  5. data/lib/airbrake-ruby/config/validator.rb +6 -0
  6. data/lib/airbrake-ruby/config.rb +44 -35
  7. data/lib/airbrake-ruby/context.rb +51 -0
  8. data/lib/airbrake-ruby/file_cache.rb +1 -1
  9. data/lib/airbrake-ruby/filter_chain.rb +3 -0
  10. data/lib/airbrake-ruby/filters/context_filter.rb +4 -5
  11. data/lib/airbrake-ruby/filters/dependency_filter.rb +1 -0
  12. data/lib/airbrake-ruby/filters/exception_attributes_filter.rb +1 -1
  13. data/lib/airbrake-ruby/filters/gem_root_filter.rb +1 -0
  14. data/lib/airbrake-ruby/filters/git_last_checkout_filter.rb +3 -4
  15. data/lib/airbrake-ruby/filters/git_repository_filter.rb +11 -2
  16. data/lib/airbrake-ruby/filters/git_revision_filter.rb +3 -1
  17. data/lib/airbrake-ruby/filters/keys_filter.rb +23 -15
  18. data/lib/airbrake-ruby/filters/root_directory_filter.rb +1 -0
  19. data/lib/airbrake-ruby/filters/sql_filter.rb +11 -11
  20. data/lib/airbrake-ruby/filters/system_exit_filter.rb +1 -0
  21. data/lib/airbrake-ruby/filters/thread_filter.rb +4 -3
  22. data/lib/airbrake-ruby/grouppable.rb +1 -1
  23. data/lib/airbrake-ruby/ignorable.rb +1 -2
  24. data/lib/airbrake-ruby/mergeable.rb +1 -1
  25. data/lib/airbrake-ruby/monotonic_time.rb +1 -1
  26. data/lib/airbrake-ruby/notice.rb +1 -8
  27. data/lib/airbrake-ruby/notice_notifier.rb +4 -4
  28. data/lib/airbrake-ruby/performance_breakdown.rb +1 -6
  29. data/lib/airbrake-ruby/performance_notifier.rb +40 -54
  30. data/lib/airbrake-ruby/promise.rb +1 -0
  31. data/lib/airbrake-ruby/query.rb +1 -6
  32. data/lib/airbrake-ruby/queue.rb +1 -8
  33. data/lib/airbrake-ruby/remote_settings/callback.rb +44 -0
  34. data/lib/airbrake-ruby/remote_settings/settings_data.rb +116 -0
  35. data/lib/airbrake-ruby/remote_settings.rb +128 -0
  36. data/lib/airbrake-ruby/request.rb +1 -8
  37. data/lib/airbrake-ruby/stat.rb +2 -13
  38. data/lib/airbrake-ruby/sync_sender.rb +3 -2
  39. data/lib/airbrake-ruby/tdigest.rb +12 -9
  40. data/lib/airbrake-ruby/thread_pool.rb +9 -6
  41. data/lib/airbrake-ruby/time_truncate.rb +2 -2
  42. data/lib/airbrake-ruby/timed_trace.rb +1 -3
  43. data/lib/airbrake-ruby/truncator.rb +8 -2
  44. data/lib/airbrake-ruby/version.rb +11 -1
  45. data/lib/airbrake-ruby.rb +44 -54
  46. data/spec/airbrake_spec.rb +178 -92
  47. data/spec/async_sender_spec.rb +10 -8
  48. data/spec/backtrace_spec.rb +39 -36
  49. data/spec/benchmark_spec.rb +7 -5
  50. data/spec/code_hunk_spec.rb +26 -17
  51. data/spec/config/processor_spec.rb +167 -0
  52. data/spec/config/validator_spec.rb +23 -3
  53. data/spec/config_spec.rb +43 -55
  54. data/spec/context_spec.rb +54 -0
  55. data/spec/deploy_notifier_spec.rb +6 -4
  56. data/spec/file_cache_spec.rb +1 -0
  57. data/spec/filter_chain_spec.rb +29 -24
  58. data/spec/filters/context_filter_spec.rb +14 -5
  59. data/spec/filters/dependency_filter_spec.rb +3 -1
  60. data/spec/filters/exception_attributes_filter_spec.rb +5 -3
  61. data/spec/filters/gem_root_filter_spec.rb +9 -6
  62. data/spec/filters/git_last_checkout_filter_spec.rb +10 -12
  63. data/spec/filters/{git_repository_filter.rb → git_repository_filter_spec.rb} +26 -15
  64. data/spec/filters/git_revision_filter_spec.rb +20 -20
  65. data/spec/filters/keys_allowlist_spec.rb +26 -16
  66. data/spec/filters/keys_blocklist_spec.rb +35 -18
  67. data/spec/filters/root_directory_filter_spec.rb +7 -7
  68. data/spec/filters/sql_filter_spec.rb +28 -28
  69. data/spec/filters/system_exit_filter_spec.rb +4 -2
  70. data/spec/filters/thread_filter_spec.rb +16 -14
  71. data/spec/loggable_spec.rb +2 -2
  72. data/spec/monotonic_time_spec.rb +8 -6
  73. data/spec/nested_exception_spec.rb +46 -46
  74. data/spec/notice_notifier/options_spec.rb +25 -15
  75. data/spec/notice_notifier_spec.rb +54 -49
  76. data/spec/notice_spec.rb +7 -3
  77. data/spec/performance_breakdown_spec.rb +0 -12
  78. data/spec/performance_notifier_spec.rb +69 -87
  79. data/spec/promise_spec.rb +38 -32
  80. data/spec/query_spec.rb +1 -11
  81. data/spec/queue_spec.rb +1 -13
  82. data/spec/remote_settings/callback_spec.rb +162 -0
  83. data/spec/remote_settings/settings_data_spec.rb +348 -0
  84. data/spec/remote_settings_spec.rb +201 -0
  85. data/spec/request_spec.rb +1 -13
  86. data/spec/response_spec.rb +34 -12
  87. data/spec/spec_helper.rb +4 -4
  88. data/spec/stashable_spec.rb +5 -5
  89. data/spec/stat_spec.rb +7 -14
  90. data/spec/sync_sender_spec.rb +52 -17
  91. data/spec/tdigest_spec.rb +61 -56
  92. data/spec/thread_pool_spec.rb +67 -58
  93. data/spec/time_truncate_spec.rb +23 -6
  94. data/spec/timed_trace_spec.rb +32 -30
  95. data/spec/truncator_spec.rb +72 -43
  96. metadata +67 -51
@@ -20,14 +20,14 @@ RSpec.describe Airbrake::Filters::SqlFilter do
20
20
  end
21
21
  end
22
22
 
23
- ALL_DIALECTS = %i[mysql postgres sqlite cassandra oracle].freeze
23
+ all_dialects = %i[mysql postgres sqlite cassandra oracle].freeze
24
24
 
25
- # rubocop:disable Metrics/LineLength
25
+ # rubocop:disable Layout/LineLength
26
26
  [
27
27
  {
28
28
  input: 'SELECT * FROM things;',
29
29
  output: 'SELECT * FROM things;',
30
- dialects: ALL_DIALECTS,
30
+ dialects: all_dialects,
31
31
  }, {
32
32
  input: "SELECT `t001`.`c2` FROM `t001` WHERE `t001`.`c2` = 'value' AND c3=\"othervalue\" LIMIT ?",
33
33
  output: "SELECT `t001`.`c2` FROM `t001` WHERE `t001`.`c2` = ? AND c3=? LIMIT ?",
@@ -39,7 +39,7 @@ RSpec.describe Airbrake::Filters::SqlFilter do
39
39
  }, {
40
40
  input: "SELECT * FROM t WHERE foo='bar/*' AND baz='whatever */qux'",
41
41
  output: "SELECT * FROM t WHERE foo=? AND baz=?",
42
- dialects: ALL_DIALECTS,
42
+ dialects: all_dialects,
43
43
  }, {
44
44
  input: "SELECT \"t001\".\"c2\" FROM \"t001\" WHERE \"t001\".\"c2\" = 'value' AND c3=1234 LIMIT 1",
45
45
  output: "SELECT \"t001\".\"c2\" FROM \"t001\" WHERE \"t001\".\"c2\" = ? AND c3=? LIMIT ?",
@@ -51,19 +51,19 @@ RSpec.describe Airbrake::Filters::SqlFilter do
51
51
  }, {
52
52
  input: "SELECT * FROM t WHERE foo='bar--' AND\n baz='qux--'",
53
53
  output: "SELECT * FROM t WHERE foo=? AND\n baz=?",
54
- dialects: ALL_DIALECTS,
54
+ dialects: all_dialects,
55
55
  }, {
56
56
  input: "SELECT * FROM foo WHERE bar='baz' /* Hide Me */",
57
57
  output: "SELECT * FROM foo WHERE bar=? ?",
58
- dialects: ALL_DIALECTS,
58
+ dialects: all_dialects,
59
59
  }, {
60
60
  input: "SELECT * FROM foobar WHERE password='hunter2'\n-- No peeking!",
61
61
  output: "SELECT * FROM foobar WHERE password=?\n?",
62
- dialects: ALL_DIALECTS,
62
+ dialects: all_dialects,
63
63
  }, {
64
64
  input: "SELECT foo, bar FROM baz WHERE password='hunter2' # Secret",
65
65
  output: "SELECT foo, bar FROM baz WHERE password=? ?",
66
- dialects: ALL_DIALECTS,
66
+ dialects: all_dialects,
67
67
  }, {
68
68
  input: "SELECT \"col1\", \"col2\" from \"table\" WHERE \"col3\"=E'foo\\'bar\\\\baz' AND country=e'foo\\'bar\\\\baz'",
69
69
  output: "SELECT \"col1\", \"col2\" from \"table\" WHERE \"col3\"=E?",
@@ -79,11 +79,11 @@ RSpec.describe Airbrake::Filters::SqlFilter do
79
79
  }, {
80
80
  input: "SELECT c11.col1, c22.col2 FROM table c11, table c22 WHERE value='nothing'",
81
81
  output: "SELECT c11.col1, c22.col2 FROM table c11, table c22 WHERE value=?",
82
- dialects: ALL_DIALECTS,
82
+ dialects: all_dialects,
83
83
  }, {
84
84
  input: "INSERT INTO X VALUES(1, 23456, 123.456, 99+100)",
85
85
  output: "INSERT INTO X VALUES(?)",
86
- dialects: ALL_DIALECTS,
86
+ dialects: all_dialects,
87
87
  }, {
88
88
  input: "SELECT * FROM table WHERE name=\"foo\" AND value=\"don't\"",
89
89
  output: "SELECT * FROM table WHERE name=? AND value=?",
@@ -91,19 +91,19 @@ RSpec.describe Airbrake::Filters::SqlFilter do
91
91
  }, {
92
92
  input: "SELECT * FROM table WHERE name='foo' AND value = 'bar'",
93
93
  output: "SELECT * FROM table WHERE name=? AND value = ?",
94
- dialects: ALL_DIALECTS,
94
+ dialects: all_dialects,
95
95
  }, {
96
96
  input: "SELECT * FROM table WHERE col='foo\\''bar'",
97
97
  output: "SELECT * FROM table WHERE col=?",
98
- dialects: ALL_DIALECTS,
98
+ dialects: all_dialects,
99
99
  }, {
100
100
  input: "SELECT * FROM table WHERE col1='foo\"bar' AND col2='what\"ever'",
101
101
  output: "SELECT * FROM table WHERE col1=? AND col2=?",
102
- dialects: ALL_DIALECTS,
102
+ dialects: all_dialects,
103
103
  }, {
104
104
  input: "select * from accounts where accounts.name != 'dude\n newline' order by accounts.name",
105
105
  output: "select * from accounts where accounts.name != ? order by accounts.name",
106
- dialects: ALL_DIALECTS,
106
+ dialects: all_dialects,
107
107
  }, {
108
108
  input: "SELECT * FROM table WHERE col1=\"don't\" AND col2=\"won't\"",
109
109
  output: "SELECT * FROM table WHERE col1=? AND col2=?",
@@ -115,7 +115,7 @@ RSpec.describe Airbrake::Filters::SqlFilter do
115
115
  }, {
116
116
  input: "SELECT * FROM table WHERE name='foo\\' AND color='blue'",
117
117
  output: "SELECT * FROM table WHERE name=?",
118
- dialects: ALL_DIALECTS,
118
+ dialects: all_dialects,
119
119
  }, {
120
120
  input: "SELECT * FROM table WHERE foo=\"this string ends with a backslash\\\\\"",
121
121
  output: "SELECT * FROM table WHERE foo=?",
@@ -123,36 +123,36 @@ RSpec.describe Airbrake::Filters::SqlFilter do
123
123
  }, {
124
124
  input: "SELECT * FROM table WHERE foo='this string ends with a backslash\\\\'",
125
125
  output: "SELECT * FROM table WHERE foo=?",
126
- dialects: ALL_DIALECTS,
126
+ dialects: all_dialects,
127
127
  }, {
128
128
  # TODO: fix this example.
129
129
  input: "SELECT * FROM table WHERE name='foo\'' AND color='blue'",
130
130
  output: "Error: Airbrake::Query was not filtered",
131
- dialects: ALL_DIALECTS,
131
+ dialects: all_dialects,
132
132
  }, {
133
133
  input: "INSERT INTO X values('', 'a''b c',0, 1 , 'd''e f''s h')",
134
134
  output: "INSERT INTO X values(?)",
135
- dialects: ALL_DIALECTS,
135
+ dialects: all_dialects,
136
136
  }, {
137
137
  input: "SELECT * FROM t WHERE -- '\n bar='baz' -- '",
138
138
  output: "SELECT * FROM t WHERE ?\n bar=? ?",
139
- dialects: ALL_DIALECTS,
139
+ dialects: all_dialects,
140
140
  }, {
141
141
  input: "SELECT * FROM t WHERE /* ' */\n bar='baz' -- '",
142
142
  output: "SELECT * FROM t WHERE ?\n bar=? ?",
143
- dialects: ALL_DIALECTS,
143
+ dialects: all_dialects,
144
144
  }, {
145
145
  input: "SELECT * FROM t WHERE -- '\n /* ' */ c2='xxx' /* ' */\n c='x\n xx' -- '",
146
146
  output: "SELECT * FROM t WHERE ?\n ? c2=? ?\n c=? ?",
147
- dialects: ALL_DIALECTS,
147
+ dialects: all_dialects,
148
148
  }, {
149
149
  input: "SELECT * FROM t WHERE -- '\n c='x\n xx' -- '",
150
150
  output: "SELECT * FROM t WHERE ?\n c=? ?",
151
- dialects: ALL_DIALECTS,
151
+ dialects: all_dialects,
152
152
  }, {
153
153
  input: "SELECT * FROM foo WHERE col='value1' AND /* don't */ col2='value1' /* won't */",
154
154
  output: "SELECT * FROM foo WHERE col=? AND ? col2=? ?",
155
- dialects: ALL_DIALECTS,
155
+ dialects: all_dialects,
156
156
  }, {
157
157
  input: "SELECT * FROM table WHERE foo='bar' AND baz=\"nothing to see here'",
158
158
  output: "Error: Airbrake::Query was not filtered",
@@ -160,7 +160,7 @@ RSpec.describe Airbrake::Filters::SqlFilter do
160
160
  }, {
161
161
  input: "SELECT * FROM table WHERE foo='bar' AND baz='nothing to see here",
162
162
  output: "Error: Airbrake::Query was not filtered",
163
- dialects: ALL_DIALECTS,
163
+ dialects: all_dialects,
164
164
  }, {
165
165
  input: "SELECT * FROM \"foo\" WHERE \"foo\" = $a$dollar quotes can be $b$nested$b$$a$ and bar = 'baz'",
166
166
  output: "SELECT * FROM \"foo\" WHERE \"foo\" = ? and bar = ?",
@@ -172,11 +172,11 @@ RSpec.describe Airbrake::Filters::SqlFilter do
172
172
  }, {
173
173
  input: "select * from foo where bar = 'some\\tthing' and baz = 10",
174
174
  output: "select * from foo where bar = ? and baz = ?",
175
- dialects: ALL_DIALECTS,
175
+ dialects: all_dialects,
176
176
  }, {
177
177
  input: "select * from users where user = 'user1\\' password = 'hunter 2' -- ->don't count this quote",
178
178
  output: "select * from users where user = ?",
179
- dialects: ALL_DIALECTS,
179
+ dialects: all_dialects,
180
180
  }, {
181
181
  input: "select * from foo where bar=q'[baz's]' and x=5",
182
182
  output: "select * from foo where bar=? and x=?",
@@ -204,7 +204,7 @@ RSpec.describe Airbrake::Filters::SqlFilter do
204
204
  }, {
205
205
  input: "select * from foo where bar=1.234e-5 and x=5",
206
206
  output: "select * from foo where bar=? and x=?",
207
- dialects: ALL_DIALECTS,
207
+ dialects: all_dialects,
208
208
  }, {
209
209
  input: "select * from foo where bar=01234567-89ab-cdef-0123-456789abcdef and x=5",
210
210
  output: "select * from foo where bar=? and x=?",
@@ -229,7 +229,7 @@ RSpec.describe Airbrake::Filters::SqlFilter do
229
229
  ].each do |test|
230
230
  include_examples 'query filtering', test
231
231
  end
232
- # rubocop:enable Metrics/LineLength
232
+ # rubocop:enable Layout/LineLength
233
233
 
234
234
  [
235
235
  'COMMIT',
@@ -1,7 +1,9 @@
1
1
  RSpec.describe Airbrake::Filters::SystemExitFilter do
2
+ subject(:system_exit_filter) { described_class.new }
3
+
2
4
  it "marks SystemExit exceptions as ignored" do
3
5
  notice = Airbrake::Notice.new(SystemExit.new)
4
- expect { subject.call(notice) }.to(
6
+ expect { system_exit_filter.call(notice) }.to(
5
7
  change { notice.ignored? }.from(false).to(true),
6
8
  )
7
9
  end
@@ -9,6 +11,6 @@ RSpec.describe Airbrake::Filters::SystemExitFilter do
9
11
  it "doesn't mark non SystemExit exceptions as ignored" do
10
12
  notice = Airbrake::Notice.new(AirbrakeTestError.new)
11
13
  expect(notice).not_to be_ignored
12
- expect { subject.call(notice) }.not_to(change { notice.ignored? })
14
+ expect { system_exit_filter.call(notice) }.not_to(change { notice.ignored? })
13
15
  end
14
16
  end
@@ -1,4 +1,6 @@
1
1
  RSpec.describe Airbrake::Filters::ThreadFilter do
2
+ subject(:thread_filter) { described_class.new }
3
+
2
4
  let(:notice) { Airbrake::Notice.new(AirbrakeTestError.new) }
3
5
 
4
6
  def new_thread
@@ -17,7 +19,7 @@ RSpec.describe Airbrake::Filters::ThreadFilter do
17
19
  it "attaches the thread variable" do
18
20
  new_thread do |th|
19
21
  th.thread_variable_set(:bingo, var)
20
- subject.call(notice)
22
+ thread_filter.call(notice)
21
23
  end
22
24
 
23
25
  expect(notice[:params][:thread][:thread_variables][:bingo]).to eq(var)
@@ -60,7 +62,7 @@ RSpec.describe Airbrake::Filters::ThreadFilter do
60
62
  it "converts it to a String and attaches" do
61
63
  new_thread do |th|
62
64
  th.thread_variable_set(:bingo, Object.new)
63
- subject.call(notice)
65
+ thread_filter.call(notice)
64
66
  end
65
67
 
66
68
  vars = notice[:params][:thread][:thread_variables]
@@ -90,7 +92,7 @@ RSpec.describe Airbrake::Filters::ThreadFilter do
90
92
  it "converts objects to a safe objects" do
91
93
  new_thread do |th|
92
94
  th.thread_variable_set(:bingo, var)
93
- subject.call(notice)
95
+ thread_filter.call(notice)
94
96
  end
95
97
 
96
98
  vars = notice[:params][:thread][:thread_variables]
@@ -121,7 +123,7 @@ RSpec.describe Airbrake::Filters::ThreadFilter do
121
123
 
122
124
  new_thread do |th|
123
125
  th.thread_variable_set(var, :bingo)
124
- subject.call(notice)
126
+ thread_filter.call(notice)
125
127
  end
126
128
 
127
129
  thread_variables = notice[:params][:thread][:thread_variables]
@@ -134,7 +136,7 @@ RSpec.describe Airbrake::Filters::ThreadFilter do
134
136
  it "attaches the fiber variable" do
135
137
  new_thread do |th|
136
138
  th[:bingo] = var
137
- subject.call(notice)
139
+ thread_filter.call(notice)
138
140
  end
139
141
 
140
142
  expect(notice[:params][:thread][:fiber_variables][:bingo]).to eq(var)
@@ -177,7 +179,7 @@ RSpec.describe Airbrake::Filters::ThreadFilter do
177
179
  it "converts it to a String and attaches" do
178
180
  new_thread do |th|
179
181
  th[:bingo] = Object.new
180
- subject.call(notice)
182
+ thread_filter.call(notice)
181
183
  end
182
184
 
183
185
  vars = notice[:params][:thread][:fiber_variables]
@@ -207,7 +209,7 @@ RSpec.describe Airbrake::Filters::ThreadFilter do
207
209
  it "converts objects to a safe objects" do
208
210
  new_thread do |th|
209
211
  th[:bingo] = var
210
- subject.call(notice)
212
+ thread_filter.call(notice)
211
213
  end
212
214
 
213
215
  vars = notice[:params][:thread][:fiber_variables]
@@ -234,34 +236,34 @@ RSpec.describe Airbrake::Filters::ThreadFilter do
234
236
  end
235
237
  end
236
238
 
237
- it "appends name", skip: !Thread.current.respond_to?(:name) do
239
+ it "appends name" do
238
240
  new_thread do |th|
239
241
  th.name = 'bingo'
240
- subject.call(notice)
242
+ thread_filter.call(notice)
241
243
  end
242
244
 
243
245
  expect(notice[:params][:thread][:name]).to eq('bingo')
244
246
  end
245
247
 
246
248
  it "appends thread inspect (self)" do
247
- subject.call(notice)
249
+ thread_filter.call(notice)
248
250
  expect(notice[:params][:thread][:self]).to match(/\A#<Thread:.+>\z/)
249
251
  end
250
252
 
251
253
  it "appends thread group" do
252
- subject.call(notice)
254
+ thread_filter.call(notice)
253
255
  expect(notice[:params][:thread][:group][0]).to match(/\A#<Thread:.+>\z/)
254
256
  end
255
257
 
256
258
  it "appends priority" do
257
- subject.call(notice)
259
+ thread_filter.call(notice)
258
260
  expect(notice[:params][:thread][:priority]).to eq(0)
259
261
  end
260
262
 
261
263
  it "appends safe_level", skip: (
262
264
  "Not supported on this version of Ruby." unless Airbrake::HAS_SAFE_LEVEL
263
265
  ) do
264
- subject.call(notice)
266
+ thread_filter.call(notice)
265
267
  expect(notice[:params][:thread][:safe_level]).to eq(0)
266
268
  end
267
269
 
@@ -270,7 +272,7 @@ RSpec.describe Airbrake::Filters::ThreadFilter do
270
272
 
271
273
  new_thread do |th|
272
274
  th[key] = :bingo
273
- subject.call(notice)
275
+ thread_filter.call(notice)
274
276
  end
275
277
 
276
278
  fiber_variables = notice[:params][:thread][:fiber_variables]
@@ -6,12 +6,12 @@ RSpec.describe Airbrake::Loggable do
6
6
  end
7
7
 
8
8
  describe "#logger" do
9
- let(:subject) do
9
+ subject(:class_with_logger) do
10
10
  Class.new { include Airbrake::Loggable }.new
11
11
  end
12
12
 
13
13
  it "returns a logger that has Logger::WARN severity" do
14
- expect(subject.logger.level).to eq(Logger::WARN)
14
+ expect(class_with_logger.logger.level).to eq(Logger::WARN)
15
15
  end
16
16
  end
17
17
  end
@@ -1,23 +1,25 @@
1
1
  RSpec.describe Airbrake::MonotonicTime do
2
+ subject(:monotonic_time) { described_class }
3
+
2
4
  describe ".time_in_ms" do
3
5
  it "returns monotonic time in milliseconds" do
4
- expect(subject.time_in_ms).to be_a(Float)
6
+ expect(monotonic_time.time_in_ms).to be_a(Float)
5
7
  end
6
8
 
7
9
  it "always returns time in the future" do
8
- old_time = subject.time_in_ms
9
- expect(subject.time_in_ms).to be > old_time
10
+ old_time = monotonic_time.time_in_ms
11
+ expect(monotonic_time.time_in_ms).to be > old_time
10
12
  end
11
13
  end
12
14
 
13
15
  describe ".time_in_s" do
14
16
  it "returns monotonic time in seconds" do
15
- expect(subject.time_in_s).to be_a(Float)
17
+ expect(monotonic_time.time_in_s).to be_a(Float)
16
18
  end
17
19
 
18
20
  it "always returns time in the future" do
19
- old_time = subject.time_in_s
20
- expect(subject.time_in_s).to be > old_time
21
+ old_time = monotonic_time.time_in_s
22
+ expect(monotonic_time.time_in_s).to be > old_time
21
23
  end
22
24
  end
23
25
  end
@@ -1,73 +1,73 @@
1
1
  RSpec.describe Airbrake::NestedException do
2
2
  describe "#as_json" do
3
3
  context "given exceptions with backtraces" do
4
+ # rubocop:disable RSpec/MultipleExpectations
4
5
  it "unwinds nested exceptions" do
5
6
  begin
6
- begin
7
- raise AirbrakeTestError
8
- rescue AirbrakeTestError
9
- Ruby21Error.raise_error('bingo')
10
- end
11
- rescue Ruby21Error => ex
12
- nested_exception = described_class.new(ex)
13
- exceptions = nested_exception.as_json
14
-
15
- expect(exceptions.size).to eq(2)
16
- expect(exceptions[0][:message]).to eq('bingo')
17
- expect(exceptions[1][:message]).to eq('App crashed!')
18
- expect(exceptions[0][:backtrace]).not_to be_empty
19
- expect(exceptions[1][:backtrace]).not_to be_empty
7
+ raise AirbrakeTestError
8
+ rescue AirbrakeTestError
9
+ Ruby21Error.raise_error('bingo')
20
10
  end
11
+ rescue Ruby21Error => ex
12
+ nested_exception = described_class.new(ex)
13
+ exceptions = nested_exception.as_json
14
+
15
+ expect(exceptions.size).to eq(2)
16
+ expect(exceptions[0][:message]).to eq('bingo')
17
+ expect(exceptions[1][:message]).to eq('App crashed!')
18
+ expect(exceptions[0][:backtrace]).not_to be_empty
19
+ expect(exceptions[1][:backtrace]).not_to be_empty
21
20
  end
21
+ # rubocop:enable RSpec/MultipleExpectations
22
22
 
23
+ # rubocop:disable RSpec/MultipleExpectations
23
24
  it "unwinds no more than 3 nested exceptions" do
24
25
  begin
26
+ raise AirbrakeTestError
27
+ rescue AirbrakeTestError
25
28
  begin
26
- raise AirbrakeTestError
27
- rescue AirbrakeTestError
29
+ Ruby21Error.raise_error('bongo')
30
+ rescue Ruby21Error
28
31
  begin
29
- Ruby21Error.raise_error('bongo')
32
+ Ruby21Error.raise_error('bango')
30
33
  rescue Ruby21Error
31
- begin
32
- Ruby21Error.raise_error('bango')
33
- rescue Ruby21Error
34
- Ruby21Error.raise_error('bingo')
35
- end
34
+ Ruby21Error.raise_error('bingo')
36
35
  end
37
36
  end
38
- rescue Ruby21Error => ex
39
- nested_exception = described_class.new(ex)
40
- exceptions = nested_exception.as_json
41
-
42
- expect(exceptions.size).to eq(3)
43
- expect(exceptions[0][:message]).to eq('bingo')
44
- expect(exceptions[1][:message]).to eq('bango')
45
- expect(exceptions[2][:message]).to eq('bongo')
46
- expect(exceptions[0][:backtrace]).not_to be_empty
47
- expect(exceptions[1][:backtrace]).not_to be_empty
48
37
  end
38
+ rescue Ruby21Error => ex
39
+ nested_exception = described_class.new(ex)
40
+ exceptions = nested_exception.as_json
41
+
42
+ expect(exceptions.size).to eq(3)
43
+ expect(exceptions[0][:message]).to eq('bingo')
44
+ expect(exceptions[1][:message]).to eq('bango')
45
+ expect(exceptions[2][:message]).to eq('bongo')
46
+ expect(exceptions[0][:backtrace]).not_to be_empty
47
+ expect(exceptions[1][:backtrace]).not_to be_empty
49
48
  end
49
+ # rubocop:enable RSpec/MultipleExpectations
50
50
  end
51
51
 
52
52
  context "given exceptions without backtraces" do
53
+ # rubocop:disable RSpec/MultipleExpectations
53
54
  it "sets backtrace to nil" do
54
55
  begin
55
- begin
56
- raise AirbrakeTestError
57
- rescue AirbrakeTestError => ex2
58
- ex2.set_backtrace([])
59
- Ruby21Error.raise_error('bingo')
60
- end
61
- rescue Ruby21Error => ex1
62
- ex1.set_backtrace([])
63
- nested_exception = described_class.new(ex1)
64
- exceptions = nested_exception.as_json
65
-
66
- expect(exceptions.size).to eq(2)
67
- expect(exceptions[0][:backtrace]).to be_empty
68
- expect(exceptions[1][:backtrace]).to be_empty
56
+ raise AirbrakeTestError
57
+ rescue AirbrakeTestError => ex2
58
+ ex2.set_backtrace([])
59
+ Ruby21Error.raise_error('bingo')
69
60
  end
61
+ rescue Ruby21Error => ex1
62
+ ex1.set_backtrace([])
63
+ nested_exception = described_class.new(ex1)
64
+ exceptions = nested_exception.as_json
65
+
66
+ expect(exceptions.size).to eq(2)
67
+ expect(exceptions[0][:backtrace]).to be_empty
68
+ expect(exceptions[1][:backtrace]).to be_empty
70
69
  end
70
+ # rubocop:enable RSpec/MultipleExpectations
71
71
  end
72
72
  end
73
73
  end
@@ -1,4 +1,6 @@
1
1
  RSpec.describe Airbrake::NoticeNotifier do
2
+ subject(:notice_notifier) { described_class.new }
3
+
2
4
  let(:project_id) { 105138 }
3
5
  let(:project_key) { 'fd04e13d806a90f96614ad8e529b2822' }
4
6
  let(:localhost) { 'http://localhost:8080' }
@@ -27,7 +29,7 @@ RSpec.describe Airbrake::NoticeNotifier do
27
29
 
28
30
  example(title) do
29
31
  stub_request(:post, endpoint).to_return(status: 201, body: '{}')
30
- subject.notify_sync(ex)
32
+ notice_notifier.notify_sync(ex)
31
33
 
32
34
  expect(a_request(:post, endpoint)).to have_been_made.once
33
35
  end
@@ -35,7 +37,7 @@ RSpec.describe Airbrake::NoticeNotifier do
35
37
 
36
38
  path = '/api/v3/projects/105138/notices'
37
39
 
38
- context "given a full host" do
40
+ context "given a full host with port" do
39
41
  include_examples('endpoint', localhost = 'http://localhost:8080',
40
42
  URI.join(localhost, path),
41
43
  "sends notices to the specified host's endpoint")
@@ -63,13 +65,13 @@ RSpec.describe Airbrake::NoticeNotifier do
63
65
 
64
66
  describe ":root_directory" do
65
67
  before do
66
- subject.add_filter(
68
+ notice_notifier.add_filter(
67
69
  Airbrake::Filters::RootDirectoryFilter.new('/home/kyrylo/code'),
68
70
  )
69
71
  end
70
72
 
71
73
  it "filters out frames" do
72
- subject.notify_sync(ex)
74
+ notice_notifier.notify_sync(ex)
73
75
 
74
76
  expect(
75
77
  a_request(:post, endpoint)
@@ -82,7 +84,7 @@ RSpec.describe Airbrake::NoticeNotifier do
82
84
  before { Airbrake::Config.instance.merge(root_directory: dir) }
83
85
 
84
86
  it "being included into the notice's payload" do
85
- subject.notify_sync(ex)
87
+ notice_notifier.notify_sync(ex)
86
88
  expect(
87
89
  a_request(:post, endpoint)
88
90
  .with(body: %r{"rootDirectory":"/bingo/bango"}),
@@ -100,6 +102,7 @@ RSpec.describe Airbrake::NoticeNotifier do
100
102
  end
101
103
  end
102
104
 
105
+ # rubocop:disable RSpec/MultipleMemoizedHelpers
103
106
  describe ":proxy" do
104
107
  let(:proxy) do
105
108
  WEBrick::HTTPServer.new(
@@ -142,26 +145,27 @@ RSpec.describe Airbrake::NoticeNotifier do
142
145
  "safe to run this test on 2.6+ once we upgrade to Webmock 3.5+",
143
146
  )
144
147
  end
145
- subject.notify_sync(ex)
148
+ notice_notifier.notify_sync(ex)
146
149
 
147
150
  proxied_request = requests.pop(true)
148
151
 
149
152
  expect(proxied_request.header['proxy-authorization'].first)
150
153
  .to eq('Basic dXNlcjpwYXNzd29yZA==')
151
154
 
152
- # rubocop:disable Metrics/LineLength
155
+ # rubocop:disable Layout/LineLength
153
156
  expect(proxied_request.request_line)
154
157
  .to eq("POST http://localhost:#{proxy.config[:Port]}/api/v3/projects/105138/notices HTTP/1.1\r\n")
155
- # rubocop:enable Metrics/LineLength
158
+ # rubocop:enable Layout/LineLength
156
159
  end
157
160
  end
161
+ # rubocop:enable RSpec/MultipleMemoizedHelpers
158
162
 
159
163
  describe ":environment" do
160
164
  context "when present" do
161
165
  before { Airbrake::Config.instance.merge(environment: :production) }
162
166
 
163
167
  it "being included into the notice's payload" do
164
- subject.notify_sync(ex)
168
+ notice_notifier.notify_sync(ex)
165
169
  expect(
166
170
  a_request(:post, endpoint)
167
171
  .with(body: /"context":{.*"environment":"production".*}/),
@@ -175,7 +179,7 @@ RSpec.describe Airbrake::NoticeNotifier do
175
179
  before { Airbrake::Config.instance.merge(params) }
176
180
 
177
181
  it "sends a notice" do
178
- subject.notify_sync(ex)
182
+ notice_notifier.notify_sync(ex)
179
183
  expect(a_request(:post, endpoint)).to have_been_made
180
184
  end
181
185
  end
@@ -184,7 +188,7 @@ RSpec.describe Airbrake::NoticeNotifier do
184
188
  before { Airbrake::Config.instance.merge(params) }
185
189
 
186
190
  it "ignores exceptions occurring in envs that were not configured" do
187
- subject.notify_sync(ex)
191
+ notice_notifier.notify_sync(ex)
188
192
  expect(a_request(:post, endpoint)).not_to have_been_made
189
193
  end
190
194
  end
@@ -207,9 +211,15 @@ RSpec.describe Airbrake::NoticeNotifier do
207
211
  include_examples 'ignored notice', params
208
212
 
209
213
  it "returns early and doesn't try to parse the given exception" do
210
- expect(Airbrake::Notice).not_to receive(:new)
211
- expect(subject.notify_sync(ex))
214
+ allow(Airbrake::Notice).to receive(:new)
215
+
216
+ expect(notice_notifier.notify_sync(ex))
212
217
  .to eq('error' => "current environment 'development' is ignored")
218
+
219
+ expect(Airbrake::Notice).not_to have_received(:new)
220
+ end
221
+
222
+ it "doesn't make an HTTP request" do
213
223
  expect(a_request(:post, endpoint)).not_to have_been_made
214
224
  end
215
225
  end
@@ -246,9 +256,9 @@ RSpec.describe Airbrake::NoticeNotifier do
246
256
  end
247
257
 
248
258
  it "sends a notice" do
249
- notice = subject.build_notice(ex)
259
+ notice = notice_notifier.build_notice(ex)
250
260
  notice[:context][:headers] = 'banana'
251
- subject.notify_sync(notice)
261
+ notice_notifier.notify_sync(notice)
252
262
 
253
263
  expect(a_request(:post, endpoint)).to have_been_made
254
264
  end