airbrake-ruby 4.15.0 → 6.1.0

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.
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
@@ -2,7 +2,7 @@ RSpec.describe Airbrake::Backtrace do
2
2
  describe ".parse" do
3
3
  context "UNIX backtrace" do
4
4
  let(:parsed_backtrace) do
5
- # rubocop:disable Metrics/LineLength, Style/HashSyntax, Layout/SpaceAroundOperators, Layout/SpaceInsideHashLiteralBraces
5
+ # rubocop:disable Layout/LineLength, Style/HashSyntax, Layout/SpaceAroundOperators, Layout/SpaceInsideHashLiteralBraces
6
6
  [{:file=>"/home/kyrylo/code/airbrake/ruby/spec/spec_helper.rb", :line=>23, :function=>"<top (required)>"},
7
7
  {:file=>"/opt/rubies/ruby-2.2.2/lib/ruby/2.2.0/rubygems/core_ext/kernel_require.rb", :line=>54, :function=>"require"},
8
8
  {:file=>"/opt/rubies/ruby-2.2.2/lib/ruby/2.2.0/rubygems/core_ext/kernel_require.rb", :line=>54, :function=>"require"},
@@ -16,7 +16,7 @@ RSpec.describe Airbrake::Backtrace do
16
16
  {:file=>"/home/kyrylo/.gem/ruby/2.2.2/gems/rspec-core-3.3.2/lib/rspec/core/runner.rb", :line=>73, :function=>"run"},
17
17
  {:file=>"/home/kyrylo/.gem/ruby/2.2.2/gems/rspec-core-3.3.2/lib/rspec/core/runner.rb", :line=>41, :function=>"invoke"},
18
18
  {:file=>"/home/kyrylo/.gem/ruby/2.2.2/gems/rspec-core-3.3.2/exe/rspec", :line=>4, :function=>"<main>"}]
19
- # rubocop:enable Metrics/LineLength, Style/HashSyntax, Layout/SpaceAroundOperators, Layout/SpaceInsideHashLiteralBraces
19
+ # rubocop:enable Layout/LineLength, Style/HashSyntax, Layout/SpaceAroundOperators, Layout/SpaceInsideHashLiteralBraces
20
20
  end
21
21
 
22
22
  it "returns a properly formatted array of hashes" do
@@ -34,10 +34,10 @@ RSpec.describe Airbrake::Backtrace do
34
34
  let(:ex) { AirbrakeTestError.new.tap { |e| e.set_backtrace(windows_bt) } }
35
35
 
36
36
  let(:parsed_backtrace) do
37
- # rubocop:disable Metrics/LineLength, Style/HashSyntax, Layout/SpaceInsideHashLiteralBraces, Layout/SpaceAroundOperators
37
+ # rubocop:disable Layout/LineLength, Style/HashSyntax, Layout/SpaceInsideHashLiteralBraces, Layout/SpaceAroundOperators
38
38
  [{:file=>"C:/Program Files/Server/app/models/user.rb", :line=>13, :function=>"magic"},
39
39
  {:file=>"C:/Program Files/Server/app/controllers/users_controller.rb", :line=>8, :function=>"index"}]
40
- # rubocop:enable Metrics/LineLength, Style/HashSyntax, Layout/SpaceInsideHashLiteralBraces, Layout/SpaceAroundOperators
40
+ # rubocop:enable Layout/LineLength, Style/HashSyntax, Layout/SpaceInsideHashLiteralBraces, Layout/SpaceAroundOperators
41
41
  end
42
42
 
43
43
  it "returns a properly formatted array of hashes" do
@@ -47,7 +47,7 @@ RSpec.describe Airbrake::Backtrace do
47
47
 
48
48
  context "JRuby Java exceptions" do
49
49
  let(:backtrace_array) do
50
- # rubocop:disable Metrics/LineLength, Style/HashSyntax, Layout/SpaceInsideHashLiteralBraces, Layout/SpaceAroundOperators
50
+ # rubocop:disable Layout/LineLength, Style/HashSyntax, Layout/SpaceInsideHashLiteralBraces, Layout/SpaceAroundOperators
51
51
  [{:file=>"InstanceMethodInvoker.java", :line=>26, :function=>"org.jruby.java.invokers.InstanceMethodInvoker.call"},
52
52
  {:file=>"Interpreter.java", :line=>126, :function=>"org.jruby.ir.interpreter.Interpreter.INTERPRET_EVAL"},
53
53
  {:file=>"RubyKernel$INVOKER$s$0$3$eval19.gen", :line=>nil, :function=>"org.jruby.RubyKernel$INVOKER$s$0$3$eval19.call"},
@@ -59,7 +59,7 @@ RSpec.describe Airbrake::Backtrace do
59
59
  {:file=>"Compiler.java", :line=>111, :function=>"org.jruby.ir.Compiler$1.load"},
60
60
  {:file=>"Main.java", :line=>225, :function=>"org.jruby.Main.run"},
61
61
  {:file=>"Main.java", :line=>197, :function=>"org.jruby.Main.main"}]
62
- # rubocop:enable Metrics/LineLength, Style/HashSyntax, Layout/SpaceInsideHashLiteralBraces, Layout/SpaceAroundOperators
62
+ # rubocop:enable Layout/LineLength, Style/HashSyntax, Layout/SpaceInsideHashLiteralBraces, Layout/SpaceAroundOperators
63
63
  end
64
64
 
65
65
  it "returns a properly formatted array of hashes" do
@@ -72,21 +72,21 @@ RSpec.describe Airbrake::Backtrace do
72
72
 
73
73
  context "JRuby classloader exceptions" do
74
74
  let(:backtrace) do
75
- # rubocop:disable Metrics/LineLength
75
+ # rubocop:disable Layout/LineLength
76
76
  ['uri_3a_classloader_3a_.META_minus_INF.jruby_dot_home.lib.ruby.stdlib.net.protocol.rbuf_fill(uri:classloader:/META-INF/jruby.home/lib/ruby/stdlib/net/protocol.rb:158)',
77
77
  'bin.processors.image_uploader.block in make_streams(bin/processors/image_uploader.rb:21)',
78
78
  'uri_3a_classloader_3a_.gems.faye_minus_websocket_minus_0_dot_10_dot_5.lib.faye.websocket.api.invokeOther13:dispatch_event(uri_3a_classloader_3a_/gems/faye_minus_websocket_minus_0_dot_10_dot_5/lib/faye/websocket/uri:classloader:/gems/faye-websocket-0.10.5/lib/faye/websocket/api.rb:109)',
79
79
  'tmp.jruby9022301782566983632extract.$dot.META_minus_INF.rails.file(/tmp/jruby9022301782566983632extract/./META-INF/rails.rb:13)']
80
- # rubocop:enable Metrics/LineLength
80
+ # rubocop:enable Layout/LineLength
81
81
  end
82
82
 
83
83
  let(:parsed_backtrace) do
84
- # rubocop:disable Metrics/LineLength
84
+ # rubocop:disable Layout/LineLength
85
85
  [{ file: 'uri:classloader:/META-INF/jruby.home/lib/ruby/stdlib/net/protocol.rb', line: 158, function: 'uri_3a_classloader_3a_.META_minus_INF.jruby_dot_home.lib.ruby.stdlib.net.protocol.rbuf_fill' },
86
86
  { file: 'bin/processors/image_uploader.rb', line: 21, function: 'bin.processors.image_uploader.block in make_streams' },
87
87
  { file: 'uri_3a_classloader_3a_/gems/faye_minus_websocket_minus_0_dot_10_dot_5/lib/faye/websocket/uri:classloader:/gems/faye-websocket-0.10.5/lib/faye/websocket/api.rb', line: 109, function: 'uri_3a_classloader_3a_.gems.faye_minus_websocket_minus_0_dot_10_dot_5.lib.faye.websocket.api.invokeOther13:dispatch_event' },
88
88
  { file: '/tmp/jruby9022301782566983632extract/./META-INF/rails.rb', line: 13, function: 'tmp.jruby9022301782566983632extract.$dot.META_minus_INF.rails.file' }]
89
- # rubocop:enable Metrics/LineLength
89
+ # rubocop:enable Layout/LineLength
90
90
  end
91
91
 
92
92
  let(:ex) { JavaAirbrakeTestError.new.tap { |e| e.set_backtrace(backtrace) } }
@@ -99,19 +99,19 @@ RSpec.describe Airbrake::Backtrace do
99
99
 
100
100
  context "JRuby non-throwable exceptions" do
101
101
  let(:backtrace) do
102
- # rubocop:disable Metrics/LineLength
102
+ # rubocop:disable Layout/LineLength
103
103
  ['org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(org/postgresql/core/v3/ConnectionFactoryImpl.java:257)',
104
104
  'org.postgresql.core.ConnectionFactory.openConnection(org/postgresql/core/ConnectionFactory.java:65)',
105
105
  'org.postgresql.jdbc2.AbstractJdbc2Connection.<init>(org/postgresql/jdbc2/AbstractJdbc2Connection.java:149)']
106
- # rubocop:enable Metrics/LineLength
106
+ # rubocop:enable Layout/LineLength
107
107
  end
108
108
 
109
109
  let(:parsed_backtrace) do
110
- # rubocop:disable Metrics/LineLength
110
+ # rubocop:disable Layout/LineLength
111
111
  [{ file: 'org/postgresql/core/v3/ConnectionFactoryImpl.java', line: 257, function: 'org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl' },
112
112
  { file: 'org/postgresql/core/ConnectionFactory.java', line: 65, function: 'org.postgresql.core.ConnectionFactory.openConnection' },
113
113
  { file: 'org/postgresql/jdbc2/AbstractJdbc2Connection.java', line: 149, function: 'org.postgresql.jdbc2.AbstractJdbc2Connection.<init>' }]
114
- # rubocop:enable Metrics/LineLength
114
+ # rubocop:enable Layout/LineLength
115
115
  end
116
116
 
117
117
  let(:ex) { AirbrakeTestError.new.tap { |e| e.set_backtrace(backtrace) } }
@@ -123,22 +123,22 @@ RSpec.describe Airbrake::Backtrace do
123
123
 
124
124
  context "generic backtrace" do
125
125
  context "when function is absent" do
126
- # rubocop:disable Metrics/LineLength
126
+ # rubocop:disable Layout/LineLength
127
127
  let(:generic_bt) do
128
128
  ["/home/bingo/bango/assets/stylesheets/error_pages.scss:139:in `animation'",
129
129
  "/home/bingo/bango/assets/stylesheets/error_pages.scss:139",
130
130
  "/home/bingo/.gem/ruby/2.2.2/gems/sass-3.4.20/lib/sass/tree/visitors/perform.rb:349:in `block in visit_mixin'"]
131
131
  end
132
- # rubocop:enable Metrics/LineLength
132
+ # rubocop:enable Layout/LineLength
133
133
 
134
134
  let(:ex) { AirbrakeTestError.new.tap { |e| e.set_backtrace(generic_bt) } }
135
135
 
136
136
  let(:parsed_backtrace) do
137
- # rubocop:disable Metrics/LineLength, Style/HashSyntax, Layout/SpaceInsideHashLiteralBraces, Layout/SpaceAroundOperators
137
+ # rubocop:disable Layout/LineLength, Style/HashSyntax, Layout/SpaceInsideHashLiteralBraces, Layout/SpaceAroundOperators
138
138
  [{:file=>"/home/bingo/bango/assets/stylesheets/error_pages.scss", :line=>139, :function=>"animation"},
139
139
  {:file=>"/home/bingo/bango/assets/stylesheets/error_pages.scss", :line=>139, :function=>nil},
140
140
  {:file=>"/home/bingo/.gem/ruby/2.2.2/gems/sass-3.4.20/lib/sass/tree/visitors/perform.rb", :line=>349, :function=>"block in visit_mixin"}]
141
- # rubocop:enable Metrics/LineLength, Style/HashSyntax, Layout/SpaceInsideHashLiteralBraces, Layout/SpaceAroundOperators
141
+ # rubocop:enable Layout/LineLength, Style/HashSyntax, Layout/SpaceInsideHashLiteralBraces, Layout/SpaceAroundOperators
142
142
  end
143
143
 
144
144
  it "returns a properly formatted array of hashes" do
@@ -177,10 +177,13 @@ RSpec.describe Airbrake::Backtrace do
177
177
  end
178
178
 
179
179
  it "logs frames that cannot be parsed" do
180
- expect(Airbrake::Loggable.instance).to receive(:error).with(
180
+ allow(Airbrake::Loggable.instance).to receive(:error)
181
+
182
+ described_class.parse(ex)
183
+
184
+ expect(Airbrake::Loggable.instance).to have_received(:error).with(
181
185
  /can't parse 'a b c 1 23 321 .rb'/,
182
186
  )
183
- described_class.parse(ex)
184
187
  end
185
188
  end
186
189
 
@@ -277,9 +280,9 @@ RSpec.describe Airbrake::Backtrace do
277
280
  93 => ' begin',
278
281
  94 => ' json = @payload.to_json',
279
282
  95 => ' rescue *JSON_EXCEPTIONS => ex',
280
- # rubocop:disable Metrics/LineLength,Lint/InterpolationCheck
283
+ # rubocop:disable Layout/LineLength,Lint/InterpolationCheck
281
284
  96 => ' @config.logger.debug("#{LOG_LABEL} `notice.to_json` failed: #{ex.class}: #{ex}")',
282
- # rubocop:enable Metrics/LineLength,Lint/InterpolationCheck
285
+ # rubocop:enable Layout/LineLength,Lint/InterpolationCheck
283
286
  },
284
287
  },
285
288
  {
@@ -298,9 +301,9 @@ RSpec.describe Airbrake::Backtrace do
298
301
  it "attaches code to those frames files of which match root_directory" do
299
302
  ex = RuntimeError.new
300
303
  backtrace = [
301
- project_root_path('code.rb') + ":94:in `to_json'",
302
- fixture_path('notroot.txt' + ":3:in `pineapple'"),
303
- project_root_path('vendor/bundle/ignored_file.rb') + ":2:in `ignore_me'",
304
+ "#{project_root_path('code.rb')}:94:in `to_json'",
305
+ fixture_path("notroot.txt:3:in `pineapple'"),
306
+ "#{project_root_path('vendor/bundle/ignored_file.rb')}:2:in `ignore_me'",
304
307
  ]
305
308
  ex.set_backtrace(backtrace)
306
309
  expect(described_class.parse(ex)).to eq(parsed_backtrace)
@@ -325,9 +328,9 @@ RSpec.describe Airbrake::Backtrace do
325
328
  93 => ' begin',
326
329
  94 => ' json = @payload.to_json',
327
330
  95 => ' rescue *JSON_EXCEPTIONS => ex',
328
- # rubocop:disable Metrics/LineLength,Lint/InterpolationCheck
331
+ # rubocop:disable Layout/LineLength,Lint/InterpolationCheck
329
332
  96 => ' @config.logger.debug("#{LOG_LABEL} `notice.to_json` failed: #{ex.class}: #{ex}")',
330
- # rubocop:enable Metrics/LineLength,Lint/InterpolationCheck
333
+ # rubocop:enable Layout/LineLength,Lint/InterpolationCheck
331
334
  },
332
335
  },
333
336
  ]
@@ -335,7 +338,7 @@ RSpec.describe Airbrake::Backtrace do
335
338
 
336
339
  it "attaches code to those frames files of which match root_directory" do
337
340
  ex = RuntimeError.new
338
- ex.set_backtrace([project_root_path('code.rb') + ":94:in `to_json'"])
341
+ ex.set_backtrace(["#{project_root_path('code.rb')}:94:in `to_json'"])
339
342
  expect(described_class.parse(ex)).to eq(parsed_backtrace)
340
343
  end
341
344
  end
@@ -357,9 +360,9 @@ RSpec.describe Airbrake::Backtrace do
357
360
  93 => ' begin',
358
361
  94 => ' json = @payload.to_json',
359
362
  95 => ' rescue *JSON_EXCEPTIONS => ex',
360
- # rubocop:disable Metrics/LineLength,Lint/InterpolationCheck
363
+ # rubocop:disable Layout/LineLength,Lint/InterpolationCheck
361
364
  96 => ' @config.logger.debug("#{LOG_LABEL} `notice.to_json` failed: #{ex.class}: #{ex}")',
362
- # rubocop:enable Metrics/LineLength,Lint/InterpolationCheck
365
+ # rubocop:enable Layout/LineLength,Lint/InterpolationCheck
363
366
  },
364
367
  },
365
368
  {
@@ -370,9 +373,9 @@ RSpec.describe Airbrake::Backtrace do
370
373
  93 => ' begin',
371
374
  94 => ' json = @payload.to_json',
372
375
  95 => ' rescue *JSON_EXCEPTIONS => ex',
373
- # rubocop:disable Metrics/LineLength,Lint/InterpolationCheck
376
+ # rubocop:disable Layout/LineLength,Lint/InterpolationCheck
374
377
  96 => ' @config.logger.debug("#{LOG_LABEL} `notice.to_json` failed: #{ex.class}: #{ex}")',
375
- # rubocop:enable Metrics/LineLength,Lint/InterpolationCheck
378
+ # rubocop:enable Layout/LineLength,Lint/InterpolationCheck
376
379
  97 => ' else',
377
380
  },
378
381
  },
@@ -387,9 +390,9 @@ RSpec.describe Airbrake::Backtrace do
387
390
  it "attaches code to first N frames" do
388
391
  ex = RuntimeError.new
389
392
  backtrace = [
390
- project_root_path('code.rb') + ":94:in `to_json'",
391
- project_root_path('code.rb') + ":95:in `to_json'",
392
- project_root_path('code.rb') + ":96:in `to_json'",
393
+ "#{project_root_path('code.rb')}:94:in `to_json'",
394
+ "#{project_root_path('code.rb')}:95:in `to_json'",
395
+ "#{project_root_path('code.rb')}:96:in `to_json'",
393
396
  ]
394
397
  ex.set_backtrace(backtrace)
395
398
  expect(described_class.parse(ex)).to eq(parsed_backtrace)
@@ -417,7 +420,7 @@ RSpec.describe Airbrake::Backtrace do
417
420
 
418
421
  it "doesn't attach code to frames" do
419
422
  ex = RuntimeError.new
420
- backtrace = [project_root_path('code.rb') + ":94:in `to_json'"]
423
+ backtrace = ["#{project_root_path('code.rb')}:94:in `to_json'"]
421
424
  ex.set_backtrace(backtrace)
422
425
  expect(described_class.parse(ex)).to eq(parsed_backtrace)
423
426
  end
@@ -1,4 +1,6 @@
1
1
  RSpec.describe Airbrake::Benchmark do
2
+ subject(:benchmark) { described_class.new }
3
+
2
4
  describe ".measure" do
3
5
  it "returns measured performance time" do
4
6
  expect(described_class.measure { '10' * 10 }).to be_kind_of(Numeric)
@@ -6,16 +8,16 @@ RSpec.describe Airbrake::Benchmark do
6
8
  end
7
9
 
8
10
  describe "#stop" do
9
- before { subject }
11
+ before { benchmark }
10
12
 
11
13
  context "when called one time" do
12
- its(:stop) { is_expected.to eq(true) }
14
+ its(:stop) { is_expected.to be(true) }
13
15
  end
14
16
 
15
17
  context "when called twice or more" do
16
- before { subject.stop }
18
+ before { benchmark.stop }
17
19
 
18
- its(:stop) { is_expected.to eq(false) }
20
+ its(:stop) { is_expected.to be(false) }
19
21
  end
20
22
  end
21
23
 
@@ -25,7 +27,7 @@ RSpec.describe Airbrake::Benchmark do
25
27
  end
26
28
 
27
29
  context "when #stop was called" do
28
- before { subject.stop }
30
+ before { benchmark.stop }
29
31
 
30
32
  its(:duration) { is_expected.to be > 0 }
31
33
  end
@@ -1,4 +1,6 @@
1
1
  RSpec.describe Airbrake::CodeHunk do
2
+ subject(:code_hunk) { described_class.new }
3
+
2
4
  after do
3
5
  %w[empty_file.rb code.rb banana.rb short_file.rb long_line.txt].each do |f|
4
6
  Airbrake::FileCache[project_root_path(f)] = nil
@@ -27,26 +29,30 @@ RSpec.describe Airbrake::CodeHunk do
27
29
  end
28
30
 
29
31
  context "when a file has less than NLINES lines before start line" do
30
- subject { described_class.new.get(project_root_path('code.rb'), 1) }
32
+ subject(:code_hunk) do
33
+ described_class.new.get(project_root_path('code.rb'), 1)
34
+ end
31
35
 
32
36
  it do
33
- is_expected.to(
37
+ expect(code_hunk).to(
34
38
  eq(
35
39
  1 => 'module Airbrake',
36
40
  2 => ' ##',
37
- # rubocop:disable Metrics/LineLength
41
+ # rubocop:disable Layout/LineLength
38
42
  3 => ' # Represents a chunk of information that is meant to be either sent to',
39
- # rubocop:enable Metrics/LineLength
43
+ # rubocop:enable Layout/LineLength
40
44
  ),
41
45
  )
42
46
  end
43
47
  end
44
48
 
45
49
  context "when a file has less than NLINES lines after end line" do
46
- subject { described_class.new.get(project_root_path('code.rb'), 222) }
50
+ subject(:code_hunk) do
51
+ described_class.new.get(project_root_path('code.rb'), 222)
52
+ end
47
53
 
48
54
  it do
49
- is_expected.to(
55
+ expect(code_hunk).to(
50
56
  eq(
51
57
  220 => ' end',
52
58
  221 => 'end',
@@ -56,12 +62,12 @@ RSpec.describe Airbrake::CodeHunk do
56
62
  end
57
63
 
58
64
  context "when a file has less than NLINES lines before and after" do
59
- subject do
65
+ subject(:code_hunk) do
60
66
  described_class.new.get(project_root_path('short_file.rb'), 2)
61
67
  end
62
68
 
63
69
  it do
64
- is_expected.to(
70
+ expect(code_hunk).to(
65
71
  eq(
66
72
  1 => 'module Banana',
67
73
  2 => ' attr_reader :bingo',
@@ -72,10 +78,12 @@ RSpec.describe Airbrake::CodeHunk do
72
78
  end
73
79
 
74
80
  context "when a file has enough lines before and after" do
75
- subject { described_class.new.get(project_root_path('code.rb'), 100) }
81
+ subject(:code_hunk) do
82
+ described_class.new.get(project_root_path('code.rb'), 100)
83
+ end
76
84
 
77
85
  it do
78
- is_expected.to(
86
+ expect(code_hunk).to(
79
87
  eq(
80
88
  98 => ' return json if json && json.bytesize <= MAX_NOTICE_SIZE',
81
89
  99 => ' end',
@@ -88,27 +96,28 @@ RSpec.describe Airbrake::CodeHunk do
88
96
  end
89
97
 
90
98
  context "when a line exceeds the length limit" do
91
- subject do
99
+ subject(:code_hunk) do
92
100
  described_class.new.get(project_root_path('long_line.txt'), 1)
93
101
  end
94
102
 
95
103
  it "strips the line" do
96
- expect(subject[1]).to eq('l' + 'o' * 196 + 'ng')
104
+ expect(code_hunk[1]).to eq("l#{'o' * 196}ng")
97
105
  end
98
106
  end
99
107
 
100
108
  context "when an error occurrs while fetching code" do
101
109
  before do
102
- expect(Airbrake::FileCache).to receive(:[]).and_raise(Errno::EACCES)
110
+ allow(Airbrake::Loggable.instance).to receive(:error)
111
+ allow(Airbrake::FileCache).to receive(:[]).and_raise(Errno::EACCES)
103
112
  end
104
113
 
105
114
  it "logs error and returns nil" do
106
- expect(Airbrake::Loggable.instance).to receive(:error).with(
107
- /can't read code hunk.+Permission denied/,
108
- )
109
- expect(subject.get(project_root_path('code.rb'), 1)).to(
115
+ expect(code_hunk.get(project_root_path('code.rb'), 1)).to(
110
116
  eq(1 => ''),
111
117
  )
118
+ expect(Airbrake::Loggable.instance).to have_received(:error).with(
119
+ /can't read code hunk.+Permission denied/,
120
+ )
112
121
  end
113
122
  end
114
123
  end
@@ -0,0 +1,167 @@
1
+ RSpec.describe Airbrake::Config::Processor do
2
+ let(:notifier) { Airbrake::NoticeNotifier.new }
3
+
4
+ describe "#process_blocklist" do
5
+ let(:config) { Airbrake::Config.new(blocklist_keys: %w[a b c]) }
6
+
7
+ context "when there ARE blocklist keys" do
8
+ it "adds the blocklist filter" do
9
+ described_class.new(config).process_blocklist(notifier)
10
+ expect(notifier.has_filter?(Airbrake::Filters::KeysBlocklist)).to be(true)
11
+ end
12
+ end
13
+
14
+ context "when there are NO blocklist keys" do
15
+ let(:config) { Airbrake::Config.new(blocklist_keys: %w[]) }
16
+
17
+ it "doesn't add the blocklist filter" do
18
+ described_class.new(config).process_blocklist(notifier)
19
+ expect(notifier.has_filter?(Airbrake::Filters::KeysBlocklist))
20
+ .to be(false)
21
+ end
22
+ end
23
+ end
24
+
25
+ describe "#process_allowlist" do
26
+ let(:config) { Airbrake::Config.new(allowlist_keys: %w[a b c]) }
27
+
28
+ context "when there ARE allowlist keys" do
29
+ it "adds the allowlist filter" do
30
+ described_class.new(config).process_allowlist(notifier)
31
+ expect(notifier.has_filter?(Airbrake::Filters::KeysAllowlist)).to be(true)
32
+ end
33
+ end
34
+
35
+ context "when there are NO allowlist keys" do
36
+ let(:config) { Airbrake::Config.new(allowlist_keys: %w[]) }
37
+
38
+ it "doesn't add the allowlist filter" do
39
+ described_class.new(config).process_allowlist(notifier)
40
+ expect(notifier.has_filter?(Airbrake::Filters::KeysAllowlist))
41
+ .to be(false)
42
+ end
43
+ end
44
+ end
45
+
46
+ describe "#process_remote_configuration" do
47
+ before do
48
+ allow(Airbrake::RemoteSettings).to receive(:poll)
49
+ end
50
+
51
+ context "when the config doesn't define a project_id" do
52
+ let(:config) { Airbrake::Config.new(project_id: nil) }
53
+
54
+ it "doesn't set remote settings" do
55
+ described_class.new(config).process_remote_configuration
56
+
57
+ expect(Airbrake::RemoteSettings).not_to have_received(:poll)
58
+ end
59
+ end
60
+
61
+ context "when the config sets environment to 'test'" do
62
+ let(:config) { Airbrake::Config.new(project_id: 123, environment: 'test') }
63
+
64
+ it "doesn't set remote settings" do
65
+ described_class.new(config).process_remote_configuration
66
+
67
+ expect(Airbrake::RemoteSettings).not_to have_received(:poll)
68
+ end
69
+ end
70
+
71
+ context "when the config sets :ignore_environments and :environment matches" do
72
+ let(:config) do
73
+ Airbrake::Config.new(
74
+ project_id: 123,
75
+ ignore_environments: %w[dev],
76
+ environment: 'dev',
77
+ )
78
+ end
79
+
80
+ it "doesn't set remote settings" do
81
+ described_class.new(config).process_remote_configuration
82
+
83
+ expect(Airbrake::RemoteSettings).not_to have_received(:poll)
84
+ end
85
+ end
86
+
87
+ context "when the config defines a project_id" do
88
+ let(:config) do
89
+ Airbrake::Config.new(project_id: 123, environment: 'not-test')
90
+ end
91
+
92
+ it "sets remote settings" do
93
+ described_class.new(config).process_remote_configuration
94
+
95
+ expect(Airbrake::RemoteSettings).to have_received(:poll)
96
+ end
97
+ end
98
+
99
+ context "when the config disables the remote_config option" do
100
+ let(:config) { Airbrake::Config.new(project_id: 123, remote_config: false) }
101
+
102
+ it "doesn't set remote settings" do
103
+ described_class.new(config).process_remote_configuration
104
+
105
+ expect(Airbrake::RemoteSettings).not_to have_received(:poll)
106
+ end
107
+ end
108
+ end
109
+
110
+ describe "#add_filters" do
111
+ context "when there's a root directory" do
112
+ let(:config) { Airbrake::Config.new(root_directory: '/abc') }
113
+
114
+ it "adds RootDirectoryFilter" do
115
+ described_class.new(config).add_filters(notifier)
116
+ expect(notifier.has_filter?(Airbrake::Filters::RootDirectoryFilter))
117
+ .to be(true)
118
+ end
119
+
120
+ it "adds GitRevisionFilter" do
121
+ described_class.new(config).add_filters(notifier)
122
+ expect(notifier.has_filter?(Airbrake::Filters::GitRevisionFilter))
123
+ .to be(true)
124
+ end
125
+
126
+ it "adds GitRepositoryFilter" do
127
+ described_class.new(config).add_filters(notifier)
128
+ expect(notifier.has_filter?(Airbrake::Filters::GitRepositoryFilter))
129
+ .to be(true)
130
+ end
131
+
132
+ it "adds GitLastCheckoutFilter" do
133
+ described_class.new(config).add_filters(notifier)
134
+ expect(notifier.has_filter?(Airbrake::Filters::GitLastCheckoutFilter))
135
+ .to be(true)
136
+ end
137
+ end
138
+
139
+ context "when there's NO root directory" do
140
+ let(:config) { Airbrake::Config.new(root_directory: nil) }
141
+
142
+ it "doesn't add RootDirectoryFilter" do
143
+ described_class.new(config).add_filters(notifier)
144
+ expect(notifier.has_filter?(Airbrake::Filters::RootDirectoryFilter))
145
+ .to be(false)
146
+ end
147
+
148
+ it "doesn't add GitRevisionFilter" do
149
+ described_class.new(config).add_filters(notifier)
150
+ expect(notifier.has_filter?(Airbrake::Filters::GitRevisionFilter))
151
+ .to be(false)
152
+ end
153
+
154
+ it "doesn't add GitRepositoryFilter" do
155
+ described_class.new(config).add_filters(notifier)
156
+ expect(notifier.has_filter?(Airbrake::Filters::GitRepositoryFilter))
157
+ .to be(false)
158
+ end
159
+
160
+ it "doesn't add GitLastCheckoutFilter" do
161
+ described_class.new(config).add_filters(notifier)
162
+ expect(notifier.has_filter?(Airbrake::Filters::GitLastCheckoutFilter))
163
+ .to be(false)
164
+ end
165
+ end
166
+ end
167
+ end
@@ -169,15 +169,35 @@ RSpec.describe Airbrake::Config::Validator do
169
169
  }
170
170
  end
171
171
 
172
- it "returns a rejected promise" do
172
+ it "returns a resolved promise" do
173
173
  promise = described_class.check_notify_ability(config)
174
174
  expect(promise).to be_resolved
175
175
  end
176
176
 
177
177
  it "warns about 'no effect'" do
178
- expect(config.logger).to receive(:warn)
179
- .with(/'ignore_environments' has no effect/)
178
+ allow(config.logger).to receive(:warn)
179
+
180
180
  described_class.check_notify_ability(config)
181
+
182
+ expect(config.logger).to have_received(:warn)
183
+ .with(/'ignore_environments' has no effect/)
184
+ end
185
+ end
186
+
187
+ context "when the error_notifications option is false" do
188
+ let(:config_params) do
189
+ {
190
+ project_id: valid_id,
191
+ project_key: valid_key,
192
+ error_notifications: false,
193
+ }
194
+ end
195
+
196
+ it "returns a rejected promise" do
197
+ promise = described_class.check_notify_ability(config)
198
+ expect(promise.value).to eq(
199
+ 'error' => "error notifications are disabled",
200
+ )
181
201
  end
182
202
  end
183
203
  end