exception_handling 2.17.0.pre.tstarck.1 → 3.0.pre.1

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 (48) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +0 -3
  3. data/.ruby-version +1 -1
  4. data/Gemfile +16 -12
  5. data/Gemfile.lock +138 -153
  6. data/README.md +21 -90
  7. data/Rakefile +11 -8
  8. data/exception_handling.gemspec +10 -14
  9. data/lib/exception_handling/exception_info.rb +11 -15
  10. data/lib/exception_handling/honeybadger_callbacks.rb +59 -0
  11. data/lib/exception_handling/log_stub_error.rb +1 -2
  12. data/lib/exception_handling/methods.rb +53 -6
  13. data/lib/exception_handling/testing.rb +10 -20
  14. data/lib/exception_handling/version.rb +1 -1
  15. data/lib/exception_handling.rb +34 -135
  16. data/semaphore_ci/setup.sh +3 -0
  17. data/{spec → test}/helpers/exception_helpers.rb +2 -2
  18. data/{spec/spec_helper.rb → test/test_helper.rb} +45 -75
  19. data/test/unit/exception_handling/exception_catalog_test.rb +85 -0
  20. data/test/unit/exception_handling/exception_description_test.rb +82 -0
  21. data/{spec/unit/exception_handling/exception_info_spec.rb → test/unit/exception_handling/exception_info_test.rb} +114 -170
  22. data/test/unit/exception_handling/honeybadger_callbacks_test.rb +122 -0
  23. data/{spec/unit/exception_handling/log_error_stub_spec.rb → test/unit/exception_handling/log_error_stub_test.rb} +22 -38
  24. data/{spec/unit/exception_handling/mailer_spec.rb → test/unit/exception_handling/mailer_test.rb} +18 -17
  25. data/test/unit/exception_handling/methods_test.rb +84 -0
  26. data/test/unit/exception_handling/sensu_test.rb +52 -0
  27. data/test/unit/exception_handling_test.rb +1109 -0
  28. metadata +59 -99
  29. data/.github/CODEOWNERS +0 -1
  30. data/.github/workflows/pipeline.yml +0 -36
  31. data/.rspec +0 -3
  32. data/.tool-versions +0 -1
  33. data/Appraisals +0 -19
  34. data/CHANGELOG.md +0 -149
  35. data/gemfiles/rails_5.gemfile +0 -18
  36. data/gemfiles/rails_6.gemfile +0 -18
  37. data/gemfiles/rails_7.gemfile +0 -18
  38. data/lib/exception_handling/escalate_callback.rb +0 -19
  39. data/lib/exception_handling/logging_methods.rb +0 -27
  40. data/spec/rake_test_warning_false.rb +0 -20
  41. data/spec/unit/exception_handling/escalate_callback_spec.rb +0 -81
  42. data/spec/unit/exception_handling/exception_catalog_spec.rb +0 -85
  43. data/spec/unit/exception_handling/exception_description_spec.rb +0 -82
  44. data/spec/unit/exception_handling/logging_methods_spec.rb +0 -38
  45. data/spec/unit/exception_handling/methods_spec.rb +0 -105
  46. data/spec/unit/exception_handling/sensu_spec.rb +0 -51
  47. data/spec/unit/exception_handling_spec.rb +0 -1465
  48. /data/{spec → test}/helpers/controller_helpers.rb +0 -0
@@ -1,50 +1,42 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'rspec'
4
- require 'rspec/mocks'
5
- require 'rspec_junit_formatter'
6
-
3
+ require 'active_support'
4
+ require 'active_support/time'
5
+ require 'active_support/test_case'
6
+ require 'active_model'
7
+ require 'action_mailer'
8
+ require 'action_dispatch'
9
+ require 'hobo_support'
10
+ require 'shoulda'
11
+ require 'rr'
12
+ require 'minitest/autorun'
7
13
  require 'pry'
8
- require 'pry-byebug'
9
14
  require 'honeybadger'
10
15
  require 'contextual_logger'
11
16
 
12
17
  require 'exception_handling'
13
18
  require 'exception_handling/testing'
14
19
 
20
+ ActiveSupport::TestCase.test_order = :sorted
21
+
15
22
  class LoggerStub
16
- include ContextualLogger::LoggerMixin
17
- attr_accessor :logged, :level
23
+ include ContextualLogger
24
+ attr_accessor :logged
18
25
 
19
26
  def initialize
20
- @level = Logger::Severity::DEBUG
21
- @progname = nil
22
- @logdev = nil
23
27
  clear
24
28
  end
25
29
 
26
- def debug(message, **log_context)
27
- super.tap do
28
- logged << { message: message, context: log_context, severity: 'DEBUG' }
29
- end
30
- end
31
-
32
- def info(message, **log_context)
33
- super.tap do
34
- logged << { message: message, context: log_context, severity: 'INFO' }
35
- end
30
+ def info(message, log_context = {})
31
+ logged << { message: message, context: log_context }
36
32
  end
37
33
 
38
- def warn(message, **log_context)
39
- super.tap do
40
- logged << { message: message, context: log_context, severity: 'WARN' }
41
- end
34
+ def warn(message, log_context = {})
35
+ logged << { message: message, context: log_context }
42
36
  end
43
37
 
44
- def fatal(message, **log_context)
45
- super.tap do
46
- logged << { message: message, context: log_context, severity: 'FATAL' }
47
- end
38
+ def fatal(message, log_context = {})
39
+ logged << { message: message, context: log_context }
48
40
  end
49
41
 
50
42
  def clear
@@ -85,17 +77,27 @@ end
85
77
 
86
78
  ActionMailer::Base.delivery_method = :test
87
79
 
80
+ _ = ActiveSupport
81
+ _ = ActiveSupport::TestCase
88
82
 
89
- module TestHelper
90
- @constant_overrides = []
91
- class << self
92
- attr_accessor :constant_overrides
93
- end
83
+ class ActiveSupport::TestCase
84
+ @@constant_overrides = []
94
85
 
86
+ setup do
87
+ unless @@constant_overrides.nil? || @@constant_overrides.empty?
88
+ raise "Uh-oh! constant_overrides left over: #{@@constant_overrides.inspect}"
89
+ end
90
+
91
+ unless defined?(Rails) && defined?(Rails.env)
92
+ module ::Rails
93
+ class << self
94
+ attr_writer :env
95
95
 
96
- def setup_constant_overrides
97
- unless TestHelper.constant_overrides.nil? || TestHelper.constant_overrides.empty?
98
- raise "Uh-oh! constant_overrides left over: #{TestHelper.constant_overrides.inspect}"
96
+ def env
97
+ @env ||= 'test'
98
+ end
99
+ end
100
+ end
99
101
  end
100
102
 
101
103
  Time.now_override = nil
@@ -115,8 +117,8 @@ module TestHelper
115
117
  ExceptionHandling.sensu_prefix = ""
116
118
  end
117
119
 
118
- def teardown_constant_overrides
119
- TestHelper.constant_overrides&.reverse&.each do |parent_module, k, v|
120
+ teardown do
121
+ @@constant_overrides&.reverse&.each do |parent_module, k, v|
120
122
  ExceptionHandling.ensure_safe "constant cleanup #{k.inspect}, #{parent_module}(#{parent_module.class})::#{v.inspect}(#{v.class})" do
121
123
  silence_warnings do
122
124
  if v == :never_defined
@@ -127,7 +129,7 @@ module TestHelper
127
129
  end
128
130
  end
129
131
  end
130
- TestHelper.constant_overrides = []
132
+ @@constant_overrides = []
131
133
  end
132
134
 
133
135
  def set_test_const(const_name, value)
@@ -147,7 +149,7 @@ module TestHelper
147
149
  end
148
150
  end
149
151
 
150
- TestHelper.constant_overrides << [final_parent_module, final_const_name, original_value]
152
+ @@constant_overrides << [final_parent_module, final_const_name, original_value]
151
153
 
152
154
  silence_warnings { final_parent_module.const_set(final_const_name, value) }
153
155
  end
@@ -159,15 +161,15 @@ module TestHelper
159
161
  else
160
162
  original_count = 0
161
163
  end
162
- expect(ActionMailer::Base.deliveries.size - original_count).to eq(expected), "wrong number of emails#{': ' + message.to_s if message}"
164
+ assert_equal expected, ActionMailer::Base.deliveries.size - original_count, "wrong number of emails#{': ' + message.to_s if message}"
163
165
  end
164
166
  end
165
167
 
166
168
  def assert_equal_with_diff(arg1, arg2, msg = '')
167
169
  if arg1 == arg2
168
- expect(true).to be_truthy # To keep the assertion count accurate
170
+ assert true # To keep the assertion count accurate
169
171
  else
170
- expect(arg1).to eq(arg2), "#{msg}\n#{Diff.compare(arg1, arg2)}"
172
+ assert_equal arg1, arg2, "#{msg}\n#{Diff.compare(arg1, arg2)}"
171
173
  end
172
174
  end
173
175
 
@@ -198,35 +200,3 @@ class Time
198
200
  end
199
201
  end
200
202
  end
201
-
202
- RSpec.configure do |config|
203
- config.add_formatter(RspecJunitFormatter, 'spec/reports/rspec.xml')
204
- config.include TestHelper
205
-
206
- config.before(:each) do
207
- setup_constant_overrides
208
- unless defined?(Rails) && defined?(Rails.env)
209
- module Rails
210
- class << self
211
- attr_writer :env
212
-
213
- def env
214
- @env ||= 'test'
215
- end
216
- end
217
- end
218
- end
219
- end
220
-
221
- config.after(:each) do
222
- teardown_constant_overrides
223
- end
224
-
225
- config.mock_with :rspec do |mocks|
226
- mocks.verify_partial_doubles = true
227
- end
228
-
229
- config.expect_with(:rspec, :test_unit)
230
-
231
- RSpec::Support::ObjectFormatter.default_instance.max_formatted_output_length = 2_000
232
- end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ require File.expand_path('../../test_helper', __dir__)
4
+
5
+ module ExceptionHandling
6
+ class ExceptionCatalogTest < ActiveSupport::TestCase
7
+
8
+ context "With stubbed yaml content" do
9
+ setup do
10
+ filter_list = { exception1: { error: "my error message" },
11
+ exception2: { error: "some other message", session: "misc data" } }
12
+ stub(YAML).load_file { filter_list }
13
+
14
+ # bump modified time up to get the above filter loaded
15
+ stub(File).mtime { incrementing_mtime }
16
+ end
17
+
18
+ context "with loaded data" do
19
+ setup do
20
+ stub(File).mtime { incrementing_mtime }
21
+ @exception_catalog = ExceptionCatalog.new(ExceptionHandling.filter_list_filename)
22
+ @exception_catalog.send :load_file
23
+ end
24
+
25
+ should "have loaded filters" do
26
+ assert_equal 2, @exception_catalog.instance_eval("@filters").size
27
+ end
28
+
29
+ should "find messages in the catalog" do
30
+ assert !@exception_catalog.find(error: "Scott says unlikely to ever match")
31
+ end
32
+
33
+ should "find matching data" do
34
+ exception_description = @exception_catalog.find(error: "this is my error message, which should match something")
35
+ assert exception_description
36
+ assert_equal :exception1, exception_description.filter_name
37
+ end
38
+ end
39
+
40
+ should "write errors loading the yaml file directly to the log file" do
41
+ @exception_catalog = ExceptionCatalog.new(ExceptionHandling.filter_list_filename)
42
+
43
+ mock(ExceptionHandling).log_error.never
44
+ mock(ExceptionHandling).write_exception_to_log(anything, "ExceptionCatalog#refresh_filters: ./config/exception_filters.yml", anything)
45
+ mock(@exception_catalog).load_file { raise "noooooo" }
46
+
47
+ @exception_catalog.find({})
48
+ end
49
+ end
50
+
51
+ context "with live yaml content" do
52
+ setup do
53
+ @filename = File.expand_path('../../../config/exception_filters.yml', __dir__)
54
+ @exception_catalog = ExceptionCatalog.new(@filename)
55
+ assert_nothing_raised "Loading the exception filter should not raise" do
56
+ @exception_catalog.send :load_file
57
+ end
58
+ end
59
+
60
+ should "load the filter data" do
61
+ assert !@exception_catalog.find(error: "Scott says unlikely to ever match")
62
+ assert !@exception_catalog.find(error: "Scott says unlikely to ever match")
63
+ end
64
+ end
65
+
66
+ context "with no yaml content" do
67
+ setup do
68
+ @exception_catalog = ExceptionCatalog.new(nil)
69
+ end
70
+
71
+ should "not load filter data" do
72
+ mock(ExceptionHandling).write_exception_to_log.with_any_args.never
73
+ @exception_catalog.find(error: "Scott says unlikely to ever match")
74
+ end
75
+ end
76
+
77
+ private
78
+
79
+ def incrementing_mtime
80
+ @mtime ||= Time.now
81
+ @mtime += 1.day
82
+ end
83
+
84
+ end
85
+ end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ require File.expand_path('../../test_helper', __dir__)
4
+
5
+ module ExceptionHandling
6
+ class ExceptionDescriptionTest < ActiveSupport::TestCase
7
+
8
+ context "Filter" do
9
+ should "allow direct matching of strings" do
10
+ @f = ExceptionDescription.new(:filter1, error: "my error message")
11
+ assert @f.match?('error' => "my error message")
12
+ end
13
+
14
+ should "allow direct matching of strings on with symbol keys" do
15
+ @f = ExceptionDescription.new(:filter1, error: "my error message")
16
+ assert @f.match?(error: "my error message")
17
+ end
18
+
19
+ should "allow wildcards to cross line boundries" do
20
+ @f = ExceptionDescription.new(:filter1, error: "my error message.*with multiple lines")
21
+ assert @f.match?(error: "my error message\nwith more than one, with multiple lines")
22
+ end
23
+
24
+ should "complain when no regexps have a value" do
25
+ assert_raise(ArgumentError, "has all blank regexe") { ExceptionDescription.new(:filter1, error: nil) }
26
+ end
27
+
28
+ should "report when an invalid key is passed" do
29
+ assert_raise(ArgumentError, "Unknown section: not_a_parameter") { ExceptionDescription.new(:filter1, error: "my error message", not_a_parameter: false) }
30
+ end
31
+
32
+ should "allow send_to_honeybadger to be specified and have it disabled by default" do
33
+ assert !ExceptionDescription.new(:filter1, error: "my error message", send_to_honeybadger: false).send_to_honeybadger
34
+ assert ExceptionDescription.new(:filter1, error: "my error message", send_to_honeybadger: true).send_to_honeybadger
35
+ assert !ExceptionDescription.new(:filter1, error: "my error message").send_to_honeybadger
36
+ end
37
+
38
+ should "allow send_metric to be configured" do
39
+ assert !ExceptionDescription.new(:filter1, error: "my error message", send_metric: false).send_metric
40
+ assert ExceptionDescription.new(:filter1, error: "my error message").send_metric
41
+ end
42
+
43
+ should "provide metric name" do
44
+ assert_equal "filter1", ExceptionDescription.new(:filter1, error: "my error message").metric_name
45
+ assert_equal "some_other_metric_name", ExceptionDescription.new(:filter1, error: "my error message", metric_name: :some_other_metric_name).metric_name
46
+ end
47
+
48
+ should "replace spaces in metric name" do
49
+ @f = ExceptionDescription.new(:"filter has spaces", error: "my error message")
50
+ assert_equal "filter_has_spaces", @f.metric_name
51
+ end
52
+
53
+ should "allow notes to be recorded" do
54
+ assert_nil ExceptionDescription.new(:filter1, error: "my error message").notes
55
+ assert_equal "a long string", ExceptionDescription.new(:filter1, error: "my error message", notes: "a long string").notes
56
+ end
57
+
58
+ should "not consider config options in the filter set" do
59
+ assert ExceptionDescription.new(:filter1, error: "my error message", send_metric: false).match?(error: "my error message")
60
+ assert ExceptionDescription.new(:filter1, error: "my error message", metric_name: "false").match?(error: "my error message")
61
+ assert ExceptionDescription.new(:filter1, error: "my error message", notes: "hey").match?(error: "my error message")
62
+ end
63
+
64
+ should "provide exception details" do
65
+ exception_description = ExceptionDescription.new(:filter1, error: "my error message", notes: "hey")
66
+
67
+ expected = { "send_metric" => true, "metric_name" => "filter1", "notes" => "hey" }
68
+
69
+ assert_equal expected, exception_description.exception_data
70
+ end
71
+
72
+ should "match multiple email addresses" do
73
+ mobi = "ExceptionHandling::Warning: LoginAttempt::IPAddressLocked: failed login for 'mcc@mobistreak.com'"
74
+ credit = "ExceptionHandling::Warning: LoginAttempt::IPAddressLocked: failed login for 'damon@thecreditpros.com'"
75
+
76
+ exception_description = ExceptionDescription.new(:filter1, error: "ExceptionHandling::Warning: LoginAttempt::IPAddressLocked: failed login for '(mcc\@mobistreak|damon\@thecreditpros).com'")
77
+ assert exception_description.match?(error: mobi), "does not match mobi"
78
+ assert exception_description.match?(error: credit), "does not match credit"
79
+ end
80
+ end
81
+ end
82
+ end