activesupport 6.1.0 → 7.1.5.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1075 -325
- data/MIT-LICENSE +1 -1
- data/README.rdoc +7 -7
- data/lib/active_support/actionable_error.rb +4 -2
- data/lib/active_support/array_inquirer.rb +2 -2
- data/lib/active_support/backtrace_cleaner.rb +32 -7
- data/lib/active_support/benchmarkable.rb +3 -2
- data/lib/active_support/broadcast_logger.rb +251 -0
- data/lib/active_support/builder.rb +1 -1
- data/lib/active_support/cache/coder.rb +153 -0
- data/lib/active_support/cache/entry.rb +134 -0
- data/lib/active_support/cache/file_store.rb +53 -20
- data/lib/active_support/cache/mem_cache_store.rb +201 -62
- data/lib/active_support/cache/memory_store.rb +86 -24
- data/lib/active_support/cache/null_store.rb +16 -2
- data/lib/active_support/cache/redis_cache_store.rb +186 -193
- data/lib/active_support/cache/serializer_with_fallback.rb +175 -0
- data/lib/active_support/cache/strategy/local_cache.rb +63 -71
- data/lib/active_support/cache.rb +487 -249
- data/lib/active_support/callbacks.rb +227 -105
- data/lib/active_support/code_generator.rb +70 -0
- data/lib/active_support/concern.rb +9 -7
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +44 -7
- data/lib/active_support/concurrency/null_lock.rb +13 -0
- data/lib/active_support/concurrency/share_lock.rb +2 -2
- data/lib/active_support/configurable.rb +18 -5
- data/lib/active_support/configuration_file.rb +7 -2
- data/lib/active_support/core_ext/array/access.rb +1 -5
- data/lib/active_support/core_ext/array/conversions.rb +15 -13
- data/lib/active_support/core_ext/array/grouping.rb +6 -6
- data/lib/active_support/core_ext/array/inquiry.rb +2 -2
- data/lib/active_support/core_ext/big_decimal/conversions.rb +1 -1
- data/lib/active_support/core_ext/class/subclasses.rb +37 -26
- data/lib/active_support/core_ext/date/blank.rb +1 -1
- data/lib/active_support/core_ext/date/calculations.rb +24 -9
- data/lib/active_support/core_ext/date/conversions.rb +16 -15
- data/lib/active_support/core_ext/date_and_time/calculations.rb +14 -4
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +1 -1
- data/lib/active_support/core_ext/date_time/blank.rb +1 -1
- data/lib/active_support/core_ext/date_time/calculations.rb +4 -0
- data/lib/active_support/core_ext/date_time/conversions.rb +19 -15
- data/lib/active_support/core_ext/digest/uuid.rb +30 -13
- data/lib/active_support/core_ext/enumerable.rb +85 -83
- data/lib/active_support/core_ext/erb/util.rb +196 -0
- data/lib/active_support/core_ext/file/atomic.rb +3 -1
- data/lib/active_support/core_ext/hash/conversions.rb +1 -2
- data/lib/active_support/core_ext/hash/deep_merge.rb +22 -14
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +3 -3
- data/lib/active_support/core_ext/hash/indifferent_access.rb +3 -3
- data/lib/active_support/core_ext/hash/keys.rb +4 -4
- data/lib/active_support/core_ext/integer/inflections.rb +12 -12
- data/lib/active_support/core_ext/kernel/reporting.rb +4 -4
- data/lib/active_support/core_ext/kernel/singleton_class.rb +1 -1
- data/lib/active_support/core_ext/module/attribute_accessors.rb +8 -0
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +49 -22
- data/lib/active_support/core_ext/module/concerning.rb +6 -6
- data/lib/active_support/core_ext/module/delegation.rb +81 -43
- data/lib/active_support/core_ext/module/deprecation.rb +15 -12
- data/lib/active_support/core_ext/module/introspection.rb +0 -1
- data/lib/active_support/core_ext/name_error.rb +2 -8
- data/lib/active_support/core_ext/numeric/bytes.rb +9 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +82 -77
- data/lib/active_support/core_ext/object/acts_like.rb +29 -5
- data/lib/active_support/core_ext/object/blank.rb +2 -2
- data/lib/active_support/core_ext/object/deep_dup.rb +17 -1
- data/lib/active_support/core_ext/object/duplicable.rb +31 -11
- data/lib/active_support/core_ext/object/inclusion.rb +13 -5
- data/lib/active_support/core_ext/object/instance_variables.rb +22 -12
- data/lib/active_support/core_ext/object/json.rb +49 -27
- data/lib/active_support/core_ext/object/to_query.rb +2 -4
- data/lib/active_support/core_ext/object/try.rb +20 -20
- data/lib/active_support/core_ext/object/with.rb +44 -0
- data/lib/active_support/core_ext/object/with_options.rb +25 -6
- data/lib/active_support/core_ext/object.rb +1 -0
- data/lib/active_support/core_ext/pathname/blank.rb +16 -0
- data/lib/active_support/core_ext/pathname/existence.rb +23 -0
- data/lib/active_support/core_ext/pathname.rb +4 -0
- data/lib/active_support/core_ext/range/compare_range.rb +0 -25
- data/lib/active_support/core_ext/range/conversions.rb +34 -13
- data/lib/active_support/core_ext/range/each.rb +1 -1
- data/lib/active_support/core_ext/range/overlap.rb +40 -0
- data/lib/active_support/core_ext/range.rb +1 -2
- data/lib/active_support/core_ext/securerandom.rb +25 -13
- data/lib/active_support/core_ext/string/conversions.rb +2 -2
- data/lib/active_support/core_ext/string/filters.rb +21 -15
- data/lib/active_support/core_ext/string/indent.rb +1 -1
- data/lib/active_support/core_ext/string/inflections.rb +17 -10
- data/lib/active_support/core_ext/string/inquiry.rb +1 -1
- data/lib/active_support/core_ext/string/output_safety.rb +85 -165
- data/lib/active_support/core_ext/symbol/starts_ends_with.rb +0 -8
- data/lib/active_support/core_ext/thread/backtrace/location.rb +12 -0
- data/lib/active_support/core_ext/time/calculations.rb +30 -8
- data/lib/active_support/core_ext/time/conversions.rb +15 -13
- data/lib/active_support/core_ext/time/zones.rb +12 -28
- data/lib/active_support/core_ext.rb +2 -1
- data/lib/active_support/current_attributes.rb +47 -20
- data/lib/active_support/deep_mergeable.rb +53 -0
- data/lib/active_support/dependencies/autoload.rb +17 -12
- data/lib/active_support/dependencies/interlock.rb +10 -18
- data/lib/active_support/dependencies/require_dependency.rb +28 -0
- data/lib/active_support/dependencies.rb +58 -788
- data/lib/active_support/deprecation/behaviors.rb +66 -40
- data/lib/active_support/deprecation/constant_accessor.rb +5 -4
- data/lib/active_support/deprecation/deprecators.rb +104 -0
- data/lib/active_support/deprecation/disallowed.rb +6 -8
- data/lib/active_support/deprecation/instance_delegator.rb +31 -4
- data/lib/active_support/deprecation/method_wrappers.rb +9 -26
- data/lib/active_support/deprecation/proxy_wrappers.rb +38 -23
- data/lib/active_support/deprecation/reporting.rb +43 -26
- data/lib/active_support/deprecation.rb +32 -5
- data/lib/active_support/deprecator.rb +7 -0
- data/lib/active_support/descendants_tracker.rb +150 -72
- data/lib/active_support/digest.rb +5 -3
- data/lib/active_support/duration/iso8601_parser.rb +3 -3
- data/lib/active_support/duration/iso8601_serializer.rb +9 -3
- data/lib/active_support/duration.rb +83 -52
- data/lib/active_support/encrypted_configuration.rb +72 -9
- data/lib/active_support/encrypted_file.rb +29 -13
- data/lib/active_support/environment_inquirer.rb +23 -3
- data/lib/active_support/error_reporter/test_helper.rb +15 -0
- data/lib/active_support/error_reporter.rb +203 -0
- data/lib/active_support/evented_file_update_checker.rb +20 -7
- data/lib/active_support/execution_context/test_helper.rb +13 -0
- data/lib/active_support/execution_context.rb +53 -0
- data/lib/active_support/execution_wrapper.rb +44 -22
- data/lib/active_support/executor/test_helper.rb +7 -0
- data/lib/active_support/file_update_checker.rb +4 -2
- data/lib/active_support/fork_tracker.rb +28 -11
- data/lib/active_support/gem_version.rb +4 -4
- data/lib/active_support/gzip.rb +2 -0
- data/lib/active_support/hash_with_indifferent_access.rb +44 -19
- data/lib/active_support/html_safe_translation.rb +53 -0
- data/lib/active_support/i18n.rb +2 -1
- data/lib/active_support/i18n_railtie.rb +21 -14
- data/lib/active_support/inflector/inflections.rb +25 -7
- data/lib/active_support/inflector/methods.rb +50 -64
- data/lib/active_support/inflector/transliterate.rb +4 -2
- data/lib/active_support/isolated_execution_state.rb +76 -0
- data/lib/active_support/json/decoding.rb +2 -1
- data/lib/active_support/json/encoding.rb +27 -45
- data/lib/active_support/key_generator.rb +31 -6
- data/lib/active_support/lazy_load_hooks.rb +33 -7
- data/lib/active_support/locale/en.yml +4 -2
- data/lib/active_support/log_subscriber/test_helper.rb +2 -2
- data/lib/active_support/log_subscriber.rb +97 -35
- data/lib/active_support/logger.rb +9 -60
- data/lib/active_support/logger_thread_safe_level.rb +11 -34
- data/lib/active_support/message_encryptor.rb +206 -56
- data/lib/active_support/message_encryptors.rb +141 -0
- data/lib/active_support/message_pack/cache_serializer.rb +23 -0
- data/lib/active_support/message_pack/extensions.rb +292 -0
- data/lib/active_support/message_pack/serializer.rb +63 -0
- data/lib/active_support/message_pack.rb +50 -0
- data/lib/active_support/message_verifier.rb +235 -84
- data/lib/active_support/message_verifiers.rb +135 -0
- data/lib/active_support/messages/codec.rb +65 -0
- data/lib/active_support/messages/metadata.rb +112 -46
- data/lib/active_support/messages/rotation_coordinator.rb +93 -0
- data/lib/active_support/messages/rotator.rb +34 -32
- data/lib/active_support/messages/serializer_with_fallback.rb +158 -0
- data/lib/active_support/multibyte/chars.rb +12 -11
- data/lib/active_support/multibyte/unicode.rb +9 -49
- data/lib/active_support/multibyte.rb +1 -1
- data/lib/active_support/notifications/fanout.rb +304 -114
- data/lib/active_support/notifications/instrumenter.rb +117 -35
- data/lib/active_support/notifications.rb +25 -25
- data/lib/active_support/number_helper/number_converter.rb +14 -7
- data/lib/active_support/number_helper/number_to_currency_converter.rb +11 -6
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +1 -1
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +4 -4
- data/lib/active_support/number_helper/number_to_phone_converter.rb +2 -1
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +10 -6
- data/lib/active_support/number_helper/rounding_helper.rb +2 -6
- data/lib/active_support/number_helper.rb +379 -319
- data/lib/active_support/option_merger.rb +10 -18
- data/lib/active_support/ordered_hash.rb +4 -4
- data/lib/active_support/ordered_options.rb +15 -1
- data/lib/active_support/parameter_filter.rb +105 -81
- data/lib/active_support/proxy_object.rb +2 -0
- data/lib/active_support/railtie.rb +83 -21
- data/lib/active_support/reloader.rb +13 -5
- data/lib/active_support/rescuable.rb +18 -16
- data/lib/active_support/ruby_features.rb +7 -0
- data/lib/active_support/secure_compare_rotator.rb +18 -11
- data/lib/active_support/security_utils.rb +1 -1
- data/lib/active_support/string_inquirer.rb +3 -3
- data/lib/active_support/subscriber.rb +11 -40
- data/lib/active_support/syntax_error_proxy.rb +60 -0
- data/lib/active_support/tagged_logging.rb +65 -25
- data/lib/active_support/test_case.rb +166 -27
- data/lib/active_support/testing/assertions.rb +61 -15
- data/lib/active_support/testing/autorun.rb +0 -2
- data/lib/active_support/testing/constant_stubbing.rb +32 -0
- data/lib/active_support/testing/deprecation.rb +53 -2
- data/lib/active_support/testing/error_reporter_assertions.rb +107 -0
- data/lib/active_support/testing/isolation.rb +30 -29
- data/lib/active_support/testing/method_call_assertions.rb +24 -11
- data/lib/active_support/testing/parallelization/server.rb +4 -0
- data/lib/active_support/testing/parallelization/worker.rb +3 -0
- data/lib/active_support/testing/parallelization.rb +4 -0
- data/lib/active_support/testing/parallelize_executor.rb +81 -0
- data/lib/active_support/testing/setup_and_teardown.rb +2 -0
- data/lib/active_support/testing/stream.rb +4 -6
- data/lib/active_support/testing/strict_warnings.rb +39 -0
- data/lib/active_support/testing/tagged_logging.rb +1 -1
- data/lib/active_support/testing/time_helpers.rb +49 -16
- data/lib/active_support/time_with_zone.rb +39 -28
- data/lib/active_support/values/time_zone.rb +50 -18
- data/lib/active_support/version.rb +1 -1
- data/lib/active_support/xml_mini/jdom.rb +4 -11
- data/lib/active_support/xml_mini/libxml.rb +5 -5
- data/lib/active_support/xml_mini/libxmlsax.rb +1 -1
- data/lib/active_support/xml_mini/nokogiri.rb +5 -5
- data/lib/active_support/xml_mini/nokogirisax.rb +2 -2
- data/lib/active_support/xml_mini/rexml.rb +2 -2
- data/lib/active_support/xml_mini.rb +7 -6
- data/lib/active_support.rb +28 -1
- metadata +150 -18
- data/lib/active_support/core_ext/marshal.rb +0 -26
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +0 -28
- data/lib/active_support/core_ext/range/overlaps.rb +0 -10
- data/lib/active_support/core_ext/uri.rb +0 -29
- data/lib/active_support/dependencies/zeitwerk_integration.rb +0 -117
- data/lib/active_support/per_thread_registry.rb +0 -60
@@ -4,7 +4,9 @@ require "active_support/security_utils"
|
|
4
4
|
require "active_support/messages/rotator"
|
5
5
|
|
6
6
|
module ActiveSupport
|
7
|
-
#
|
7
|
+
# = Secure Compare Rotator
|
8
|
+
#
|
9
|
+
# The ActiveSupport::SecureCompareRotator is a wrapper around ActiveSupport::SecurityUtils.secure_compare
|
8
10
|
# and allows you to rotate a previously defined value to a new one.
|
9
11
|
#
|
10
12
|
# It can be used as follow:
|
@@ -17,7 +19,7 @@ module ActiveSupport
|
|
17
19
|
#
|
18
20
|
# class MyController < ApplicationController
|
19
21
|
# def authenticate_request
|
20
|
-
# rotator = ActiveSupport::
|
22
|
+
# rotator = ActiveSupport::SecureCompareRotator.new('new_password')
|
21
23
|
# rotator.rotate('old_password')
|
22
24
|
#
|
23
25
|
# authenticate_or_request_with_http_basic do |username, password|
|
@@ -29,23 +31,28 @@ module ActiveSupport
|
|
29
31
|
# end
|
30
32
|
class SecureCompareRotator
|
31
33
|
include SecurityUtils
|
32
|
-
prepend Messages::Rotator
|
33
34
|
|
34
35
|
InvalidMatch = Class.new(StandardError)
|
35
36
|
|
36
|
-
def initialize(value,
|
37
|
+
def initialize(value, on_rotation: nil)
|
37
38
|
@value = value
|
39
|
+
@rotate_values = []
|
40
|
+
@on_rotation = on_rotation
|
38
41
|
end
|
39
42
|
|
40
|
-
def
|
41
|
-
|
42
|
-
run_rotations(on_rotation) { |wrapper| wrapper.secure_compare!(other_value) } ||
|
43
|
-
raise(InvalidMatch)
|
43
|
+
def rotate(previous_value)
|
44
|
+
@rotate_values << previous_value
|
44
45
|
end
|
45
46
|
|
46
|
-
|
47
|
-
|
48
|
-
|
47
|
+
def secure_compare!(other_value, on_rotation: @on_rotation)
|
48
|
+
if secure_compare(@value, other_value)
|
49
|
+
true
|
50
|
+
elsif @rotate_values.any? { |value| secure_compare(value, other_value) }
|
51
|
+
on_rotation&.call
|
52
|
+
true
|
53
|
+
else
|
54
|
+
raise InvalidMatch
|
49
55
|
end
|
56
|
+
end
|
50
57
|
end
|
51
58
|
end
|
@@ -31,7 +31,7 @@ module ActiveSupport
|
|
31
31
|
# the secret length. This should be considered when using secure_compare
|
32
32
|
# to compare weak, short secrets to user input.
|
33
33
|
def secure_compare(a, b)
|
34
|
-
a.
|
34
|
+
a.bytesize == b.bytesize && fixed_length_secure_compare(a, b)
|
35
35
|
end
|
36
36
|
module_function :secure_compare
|
37
37
|
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "active_support/core_ext/symbol/starts_ends_with"
|
4
|
-
|
5
3
|
module ActiveSupport
|
4
|
+
# = \String Inquirer
|
5
|
+
#
|
6
6
|
# Wrapping a string in this class gives you a prettier way to test
|
7
7
|
# for equality. The value returned by <tt>Rails.env</tt> is wrapped
|
8
8
|
# in a StringInquirer object, so instead of calling this:
|
@@ -13,7 +13,7 @@ module ActiveSupport
|
|
13
13
|
#
|
14
14
|
# Rails.env.production?
|
15
15
|
#
|
16
|
-
# == Instantiating a new StringInquirer
|
16
|
+
# == Instantiating a new \StringInquirer
|
17
17
|
#
|
18
18
|
# vehicle = ActiveSupport::StringInquirer.new('car')
|
19
19
|
# vehicle.car? # => true
|
@@ -1,10 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "active_support/per_thread_registry"
|
4
3
|
require "active_support/notifications"
|
5
4
|
|
6
5
|
module ActiveSupport
|
7
|
-
#
|
6
|
+
# = Active Support \Subscriber
|
7
|
+
#
|
8
|
+
# +ActiveSupport::Subscriber+ is an object set to consume
|
8
9
|
# ActiveSupport::Notifications. The subscriber dispatches notifications to
|
9
10
|
# a registered object based on its given namespace.
|
10
11
|
#
|
@@ -21,9 +22,9 @@ module ActiveSupport
|
|
21
22
|
# end
|
22
23
|
# end
|
23
24
|
#
|
24
|
-
# After configured, whenever a "sql.active_record" notification is
|
25
|
-
# it will properly dispatch the event
|
26
|
-
# the +sql+ method.
|
25
|
+
# After configured, whenever a <tt>"sql.active_record"</tt> notification is
|
26
|
+
# published, it will properly dispatch the event
|
27
|
+
# (ActiveSupport::Notifications::Event) to the +sql+ method.
|
27
28
|
#
|
28
29
|
# We can detach a subscriber as well:
|
29
30
|
#
|
@@ -127,48 +128,18 @@ module ActiveSupport
|
|
127
128
|
attr_reader :patterns # :nodoc:
|
128
129
|
|
129
130
|
def initialize
|
130
|
-
@queue_key = [self.class.name, object_id].join "-"
|
131
131
|
@patterns = {}
|
132
132
|
super
|
133
133
|
end
|
134
134
|
|
135
|
-
def
|
136
|
-
|
137
|
-
event.start!
|
138
|
-
parent = event_stack.last
|
139
|
-
parent << event if parent
|
140
|
-
|
141
|
-
event_stack.push event
|
142
|
-
end
|
143
|
-
|
144
|
-
def finish(name, id, payload)
|
145
|
-
event = event_stack.pop
|
146
|
-
event.finish!
|
147
|
-
event.payload.merge!(payload)
|
148
|
-
|
149
|
-
method = name.split(".").first
|
135
|
+
def call(event)
|
136
|
+
method = event.name[0, event.name.index(".")]
|
150
137
|
send(method, event)
|
151
138
|
end
|
152
139
|
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
# This is a registry for all the event stacks kept for subscribers.
|
160
|
-
#
|
161
|
-
# See the documentation of <tt>ActiveSupport::PerThreadRegistry</tt>
|
162
|
-
# for further details.
|
163
|
-
class SubscriberQueueRegistry # :nodoc:
|
164
|
-
extend PerThreadRegistry
|
165
|
-
|
166
|
-
def initialize
|
167
|
-
@registry = {}
|
168
|
-
end
|
169
|
-
|
170
|
-
def get_queue(queue_key)
|
171
|
-
@registry[queue_key] ||= []
|
140
|
+
def publish_event(event) # :nodoc:
|
141
|
+
method = event.name[0, event.name.index(".")]
|
142
|
+
send(method, event)
|
172
143
|
end
|
173
144
|
end
|
174
145
|
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "delegate"
|
4
|
+
|
5
|
+
module ActiveSupport
|
6
|
+
# This is a class for wrapping syntax errors. The purpose of this class
|
7
|
+
# is to enhance the backtraces on SyntaxError exceptions to include the
|
8
|
+
# source location of the syntax error. That way we can display the error
|
9
|
+
# source on error pages in development.
|
10
|
+
class SyntaxErrorProxy < DelegateClass(SyntaxError) # :nodoc:
|
11
|
+
def backtrace
|
12
|
+
parse_message_for_trace + super
|
13
|
+
end
|
14
|
+
|
15
|
+
class BacktraceLocation < Struct.new(:path, :lineno, :to_s) # :nodoc:
|
16
|
+
def spot(_)
|
17
|
+
end
|
18
|
+
|
19
|
+
def label
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class BacktraceLocationProxy < DelegateClass(Thread::Backtrace::Location) # :nodoc:
|
24
|
+
def initialize(loc, ex)
|
25
|
+
super(loc)
|
26
|
+
@ex = ex
|
27
|
+
end
|
28
|
+
|
29
|
+
def spot(_)
|
30
|
+
super(@ex.__getobj__)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def backtrace_locations
|
35
|
+
return nil if super.nil?
|
36
|
+
|
37
|
+
parse_message_for_trace.map { |trace|
|
38
|
+
file, line = trace.match(/^(.+?):(\d+).*$/, &:captures) || trace
|
39
|
+
BacktraceLocation.new(file, line.to_i, trace)
|
40
|
+
# We have to wrap these backtrace locations because we need the
|
41
|
+
# spot information to come from the originating exception, not the
|
42
|
+
# proxy object that's generating these
|
43
|
+
} + super.map { |loc| BacktraceLocationProxy.new(loc, self) }
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
def parse_message_for_trace
|
48
|
+
if __getobj__.to_s.start_with?("(eval")
|
49
|
+
# If the exception is coming from a call to eval, we need to keep
|
50
|
+
# the path of the file in which eval was called to ensure we can
|
51
|
+
# return the right source fragment to show the location of the
|
52
|
+
# error
|
53
|
+
location = __getobj__.backtrace_locations[0]
|
54
|
+
["#{location.path}:#{location.lineno}: #{__getobj__}"]
|
55
|
+
else
|
56
|
+
__getobj__.to_s.split("\n")
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -6,14 +6,16 @@ require "logger"
|
|
6
6
|
require "active_support/logger"
|
7
7
|
|
8
8
|
module ActiveSupport
|
9
|
+
# = Active Support Tagged Logging
|
10
|
+
#
|
9
11
|
# Wraps any standard Logger object to provide tagging capabilities.
|
10
12
|
#
|
11
13
|
# May be called with a block:
|
12
14
|
#
|
13
15
|
# logger = ActiveSupport::TaggedLogging.new(Logger.new(STDOUT))
|
14
|
-
# logger.tagged('BCX') { logger.info 'Stuff' }
|
15
|
-
# logger.tagged('BCX', "Jason") {
|
16
|
-
# logger.tagged('BCX') { logger.tagged('Jason') { logger.info 'Stuff' } }
|
16
|
+
# logger.tagged('BCX') { logger.info 'Stuff' } # Logs "[BCX] Stuff"
|
17
|
+
# logger.tagged('BCX', "Jason") { |tagged_logger| tagged_logger.info 'Stuff' } # Logs "[BCX] [Jason] Stuff"
|
18
|
+
# logger.tagged('BCX') { logger.tagged('Jason') { logger.info 'Stuff' } } # Logs "[BCX] [Jason] Stuff"
|
17
19
|
#
|
18
20
|
# If called without a block, a new logger will be returned with applied tags:
|
19
21
|
#
|
@@ -29,60 +31,98 @@ module ActiveSupport
|
|
29
31
|
module Formatter # :nodoc:
|
30
32
|
# This method is invoked when a log event occurs.
|
31
33
|
def call(severity, timestamp, progname, msg)
|
32
|
-
super(severity, timestamp, progname,
|
34
|
+
super(severity, timestamp, progname, tag_stack.format_message(msg))
|
33
35
|
end
|
34
36
|
|
35
37
|
def tagged(*tags)
|
36
|
-
|
38
|
+
pushed_count = tag_stack.push_tags(tags).size
|
37
39
|
yield self
|
38
40
|
ensure
|
39
|
-
pop_tags(
|
41
|
+
pop_tags(pushed_count)
|
40
42
|
end
|
41
43
|
|
42
44
|
def push_tags(*tags)
|
43
|
-
tags
|
44
|
-
tags.reject!(&:blank?)
|
45
|
-
current_tags.concat tags
|
46
|
-
tags
|
45
|
+
tag_stack.push_tags(tags)
|
47
46
|
end
|
48
47
|
|
49
|
-
def pop_tags(
|
50
|
-
|
48
|
+
def pop_tags(count = 1)
|
49
|
+
tag_stack.pop_tags(count)
|
51
50
|
end
|
52
51
|
|
53
52
|
def clear_tags!
|
54
|
-
|
53
|
+
tag_stack.clear
|
55
54
|
end
|
56
55
|
|
57
|
-
def
|
56
|
+
def tag_stack
|
58
57
|
# We use our object ID here to avoid conflicting with other instances
|
59
|
-
|
60
|
-
|
58
|
+
@thread_key ||= "activesupport_tagged_logging_tags:#{object_id}"
|
59
|
+
IsolatedExecutionState[@thread_key] ||= TagStack.new
|
60
|
+
end
|
61
|
+
|
62
|
+
def current_tags
|
63
|
+
tag_stack.tags
|
61
64
|
end
|
62
65
|
|
63
66
|
def tags_text
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
67
|
+
tag_stack.format_message("")
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
class TagStack # :nodoc:
|
72
|
+
attr_reader :tags
|
73
|
+
|
74
|
+
def initialize
|
75
|
+
@tags = []
|
76
|
+
@tags_string = nil
|
77
|
+
end
|
78
|
+
|
79
|
+
def push_tags(tags)
|
80
|
+
@tags_string = nil
|
81
|
+
tags.flatten!
|
82
|
+
tags.reject!(&:blank?)
|
83
|
+
@tags.concat(tags)
|
84
|
+
tags
|
85
|
+
end
|
86
|
+
|
87
|
+
def pop_tags(count)
|
88
|
+
@tags_string = nil
|
89
|
+
@tags.pop(count)
|
90
|
+
end
|
91
|
+
|
92
|
+
def clear
|
93
|
+
@tags_string = nil
|
94
|
+
@tags.clear
|
95
|
+
end
|
96
|
+
|
97
|
+
def format_message(message)
|
98
|
+
if @tags.empty?
|
99
|
+
message
|
100
|
+
elsif @tags.size == 1
|
101
|
+
"[#{@tags[0]}] #{message}"
|
102
|
+
else
|
103
|
+
@tags_string ||= "[#{@tags.join("] [")}] "
|
104
|
+
"#{@tags_string}#{message}"
|
69
105
|
end
|
70
106
|
end
|
71
107
|
end
|
72
108
|
|
73
109
|
module LocalTagStorage # :nodoc:
|
74
|
-
attr_accessor :
|
110
|
+
attr_accessor :tag_stack
|
75
111
|
|
76
112
|
def self.extended(base)
|
77
|
-
base.
|
113
|
+
base.tag_stack = TagStack.new
|
78
114
|
end
|
79
115
|
end
|
80
116
|
|
81
117
|
def self.new(logger)
|
82
|
-
logger = logger.
|
118
|
+
logger = logger.clone
|
83
119
|
|
84
120
|
if logger.formatter
|
85
|
-
logger.formatter = logger.formatter.
|
121
|
+
logger.formatter = logger.formatter.clone
|
122
|
+
|
123
|
+
# Workaround for https://bugs.ruby-lang.org/issues/20250
|
124
|
+
# Can be removed when Ruby 3.4 is the least supported version.
|
125
|
+
logger.formatter.object_id if logger.formatter.is_a?(Proc)
|
86
126
|
else
|
87
127
|
# Ensure we set a default formatter so we aren't extending nil!
|
88
128
|
logger.formatter = ActiveSupport::Logger::SimpleFormatter.new
|
@@ -1,17 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
gem "minitest" # make sure we get the gem, not stdlib
|
4
3
|
require "minitest"
|
5
4
|
require "active_support/testing/tagged_logging"
|
6
5
|
require "active_support/testing/setup_and_teardown"
|
7
6
|
require "active_support/testing/assertions"
|
7
|
+
require "active_support/testing/error_reporter_assertions"
|
8
8
|
require "active_support/testing/deprecation"
|
9
9
|
require "active_support/testing/declarative"
|
10
10
|
require "active_support/testing/isolation"
|
11
11
|
require "active_support/testing/constant_lookup"
|
12
12
|
require "active_support/testing/time_helpers"
|
13
|
+
require "active_support/testing/constant_stubbing"
|
13
14
|
require "active_support/testing/file_fixtures"
|
14
15
|
require "active_support/testing/parallelization"
|
16
|
+
require "active_support/testing/parallelize_executor"
|
15
17
|
require "concurrent/utility/processor_counter"
|
16
18
|
|
17
19
|
module ActiveSupport
|
@@ -65,32 +67,21 @@ module ActiveSupport
|
|
65
67
|
# The default parallelization method is to fork processes. If you'd like to
|
66
68
|
# use threads instead you can pass <tt>with: :threads</tt> to the +parallelize+
|
67
69
|
# method. Note the threaded parallelization does not create multiple
|
68
|
-
#
|
70
|
+
# databases and will not work with system tests.
|
69
71
|
#
|
70
72
|
# parallelize(workers: :number_of_processors, with: :threads)
|
71
73
|
#
|
72
74
|
# The threaded parallelization uses minitest's parallel executor directly.
|
73
75
|
# The processes parallelization uses a Ruby DRb server.
|
74
|
-
|
76
|
+
#
|
77
|
+
# Because parallelization presents an overhead, it is only enabled when the
|
78
|
+
# number of tests to run is above the +threshold+ param. The default value is
|
79
|
+
# 50, and it's configurable via +config.active_support.test_parallelization_threshold+.
|
80
|
+
def parallelize(workers: :number_of_processors, with: :processes, threshold: ActiveSupport.test_parallelization_threshold)
|
75
81
|
workers = Concurrent.physical_processor_count if workers == :number_of_processors
|
76
82
|
workers = ENV["PARALLEL_WORKERS"].to_i if ENV["PARALLEL_WORKERS"]
|
77
83
|
|
78
|
-
|
79
|
-
|
80
|
-
executor = case with
|
81
|
-
when :processes
|
82
|
-
Testing::Parallelization.new(workers)
|
83
|
-
when :threads
|
84
|
-
Minitest::Parallel::Executor.new(workers)
|
85
|
-
else
|
86
|
-
raise ArgumentError, "#{with} is not a supported parallelization executor."
|
87
|
-
end
|
88
|
-
|
89
|
-
self.lock_threads = false if defined?(self.lock_threads) && with == :threads
|
90
|
-
|
91
|
-
Minitest.parallel_executor = executor
|
92
|
-
|
93
|
-
parallelize_me!
|
84
|
+
Minitest.parallel_executor = ActiveSupport::Testing::ParallelizeExecutor.new(size: workers, with: with, threshold: threshold)
|
94
85
|
end
|
95
86
|
|
96
87
|
# Set up hook for parallel testing. This can be used if you have multiple
|
@@ -107,9 +98,7 @@ module ActiveSupport
|
|
107
98
|
# end
|
108
99
|
# end
|
109
100
|
def parallelize_setup(&block)
|
110
|
-
ActiveSupport::Testing::Parallelization.after_fork_hook
|
111
|
-
yield worker
|
112
|
-
end
|
101
|
+
ActiveSupport::Testing::Parallelization.after_fork_hook(&block)
|
113
102
|
end
|
114
103
|
|
115
104
|
# Clean up hook for parallel testing. This can be used to drop databases
|
@@ -126,10 +115,27 @@ module ActiveSupport
|
|
126
115
|
# end
|
127
116
|
# end
|
128
117
|
def parallelize_teardown(&block)
|
129
|
-
ActiveSupport::Testing::Parallelization.run_cleanup_hook
|
130
|
-
yield worker
|
131
|
-
end
|
118
|
+
ActiveSupport::Testing::Parallelization.run_cleanup_hook(&block)
|
132
119
|
end
|
120
|
+
|
121
|
+
# :singleton-method: fixture_paths
|
122
|
+
#
|
123
|
+
# Returns the ActiveRecord::FixtureSet collection.
|
124
|
+
#
|
125
|
+
# In your +test_helper.rb+ you must have <tt>require "rails/test_help"</tt>.
|
126
|
+
|
127
|
+
# :singleton-method: fixture_paths=
|
128
|
+
#
|
129
|
+
# :call-seq:
|
130
|
+
# fixture_paths=(fixture_paths)
|
131
|
+
#
|
132
|
+
# Sets the given path to the fixture set.
|
133
|
+
#
|
134
|
+
# Can also append multiple paths.
|
135
|
+
#
|
136
|
+
# ActiveSupport::TestCase.fixture_paths << "component1/test/fixtures"
|
137
|
+
#
|
138
|
+
# In your +test_helper.rb+ you must have <tt>require "rails/test_help"</tt>.
|
133
139
|
end
|
134
140
|
|
135
141
|
alias_method :method_name, :name
|
@@ -137,27 +143,160 @@ module ActiveSupport
|
|
137
143
|
include ActiveSupport::Testing::TaggedLogging
|
138
144
|
prepend ActiveSupport::Testing::SetupAndTeardown
|
139
145
|
include ActiveSupport::Testing::Assertions
|
146
|
+
include ActiveSupport::Testing::ErrorReporterAssertions
|
140
147
|
include ActiveSupport::Testing::Deprecation
|
148
|
+
include ActiveSupport::Testing::ConstantStubbing
|
141
149
|
include ActiveSupport::Testing::TimeHelpers
|
142
150
|
include ActiveSupport::Testing::FileFixtures
|
143
151
|
extend ActiveSupport::Testing::Declarative
|
144
152
|
|
145
|
-
|
146
|
-
|
153
|
+
##
|
154
|
+
# :method: assert_not_empty
|
155
|
+
#
|
156
|
+
# :call-seq:
|
157
|
+
# assert_not_empty(obj, msg = nil)
|
158
|
+
#
|
159
|
+
# Alias for: refute_empty[https://docs.seattlerb.org/minitest/Minitest/Assertions.html#method-i-refute_empty]
|
160
|
+
|
161
|
+
#
|
147
162
|
alias :assert_not_empty :refute_empty
|
163
|
+
|
164
|
+
##
|
165
|
+
# :method: assert_not_equal
|
166
|
+
#
|
167
|
+
# :call-seq:
|
168
|
+
# assert_not_equal(exp, act, msg = nil)
|
169
|
+
#
|
170
|
+
# Alias for: refute_equal[https://docs.seattlerb.org/minitest/Minitest/Assertions.html#method-i-refute_equal]
|
171
|
+
|
172
|
+
#
|
148
173
|
alias :assert_not_equal :refute_equal
|
174
|
+
|
175
|
+
##
|
176
|
+
# :method: assert_not_in_delta
|
177
|
+
#
|
178
|
+
# :call-seq:
|
179
|
+
# assert_not_in_delta(exp, act, delta = 0.001, msg = nil)
|
180
|
+
#
|
181
|
+
# Alias for: refute_in_delta[https://docs.seattlerb.org/minitest/Minitest/Assertions.html#method-i-refute_in_delta]
|
182
|
+
|
183
|
+
#
|
149
184
|
alias :assert_not_in_delta :refute_in_delta
|
185
|
+
|
186
|
+
##
|
187
|
+
# :method: assert_not_in_epsilon
|
188
|
+
#
|
189
|
+
# :call-seq:
|
190
|
+
# assert_not_in_epsilon(a, b, epsilon = 0.001, msg = nil)
|
191
|
+
#
|
192
|
+
# Alias for: refute_in_epsilon[https://docs.seattlerb.org/minitest/Minitest/Assertions.html#method-i-refute_in_epsilon]
|
193
|
+
|
194
|
+
#
|
150
195
|
alias :assert_not_in_epsilon :refute_in_epsilon
|
196
|
+
|
197
|
+
##
|
198
|
+
# :method: assert_not_includes
|
199
|
+
#
|
200
|
+
# :call-seq:
|
201
|
+
# assert_not_includes(collection, obj, msg = nil)
|
202
|
+
#
|
203
|
+
# Alias for: refute_includes[https://docs.seattlerb.org/minitest/Minitest/Assertions.html#method-i-refute_includes]
|
204
|
+
|
205
|
+
#
|
151
206
|
alias :assert_not_includes :refute_includes
|
207
|
+
|
208
|
+
##
|
209
|
+
# :method: assert_not_instance_of
|
210
|
+
#
|
211
|
+
# :call-seq:
|
212
|
+
# assert_not_instance_of(cls, obj, msg = nil)
|
213
|
+
#
|
214
|
+
# Alias for: refute_instance_of[https://docs.seattlerb.org/minitest/Minitest/Assertions.html#method-i-refute_instance_of]
|
215
|
+
|
216
|
+
#
|
152
217
|
alias :assert_not_instance_of :refute_instance_of
|
218
|
+
|
219
|
+
##
|
220
|
+
# :method: assert_not_kind_of
|
221
|
+
#
|
222
|
+
# :call-seq:
|
223
|
+
# assert_not_kind_of(cls, obj, msg = nil)
|
224
|
+
#
|
225
|
+
# Alias for: refute_kind_of[https://docs.seattlerb.org/minitest/Minitest/Assertions.html#method-i-refute_kind_of]
|
226
|
+
|
227
|
+
#
|
153
228
|
alias :assert_not_kind_of :refute_kind_of
|
229
|
+
|
230
|
+
##
|
231
|
+
# :method: assert_no_match
|
232
|
+
#
|
233
|
+
# :call-seq:
|
234
|
+
# assert_no_match(matcher, obj, msg = nil)
|
235
|
+
#
|
236
|
+
# Alias for: refute_match[https://docs.seattlerb.org/minitest/Minitest/Assertions.html#method-i-refute_match]
|
237
|
+
|
238
|
+
#
|
154
239
|
alias :assert_no_match :refute_match
|
240
|
+
|
241
|
+
##
|
242
|
+
# :method: assert_not_nil
|
243
|
+
#
|
244
|
+
# :call-seq:
|
245
|
+
# assert_not_nil(obj, msg = nil)
|
246
|
+
#
|
247
|
+
# Alias for: refute_nil[https://docs.seattlerb.org/minitest/Minitest/Assertions.html#method-i-refute_nil]
|
248
|
+
|
249
|
+
#
|
155
250
|
alias :assert_not_nil :refute_nil
|
251
|
+
|
252
|
+
##
|
253
|
+
# :method: assert_not_operator
|
254
|
+
#
|
255
|
+
# :call-seq:
|
256
|
+
# assert_not_operator(o1, op, o2 = UNDEFINED, msg = nil)
|
257
|
+
#
|
258
|
+
# Alias for: refute_operator[https://docs.seattlerb.org/minitest/Minitest/Assertions.html#method-i-refute_operator]
|
259
|
+
|
260
|
+
#
|
156
261
|
alias :assert_not_operator :refute_operator
|
262
|
+
|
263
|
+
##
|
264
|
+
# :method: assert_not_predicate
|
265
|
+
#
|
266
|
+
# :call-seq:
|
267
|
+
# assert_not_predicate(o1, op, msg = nil)
|
268
|
+
#
|
269
|
+
# Alias for: refute_predicate[https://docs.seattlerb.org/minitest/Minitest/Assertions.html#method-i-refute_predicate]
|
270
|
+
|
271
|
+
#
|
157
272
|
alias :assert_not_predicate :refute_predicate
|
273
|
+
|
274
|
+
##
|
275
|
+
# :method: assert_not_respond_to
|
276
|
+
#
|
277
|
+
# :call-seq:
|
278
|
+
# assert_not_respond_to(obj, meth, msg = nil)
|
279
|
+
#
|
280
|
+
# Alias for: refute_respond_to[https://docs.seattlerb.org/minitest/Minitest/Assertions.html#method-i-refute_respond_to]
|
281
|
+
|
282
|
+
#
|
158
283
|
alias :assert_not_respond_to :refute_respond_to
|
284
|
+
|
285
|
+
##
|
286
|
+
# :method: assert_not_same
|
287
|
+
#
|
288
|
+
# :call-seq:
|
289
|
+
# assert_not_same(exp, act, msg = nil)
|
290
|
+
#
|
291
|
+
# Alias for: refute_same[https://docs.seattlerb.org/minitest/Minitest/Assertions.html#method-i-refute_same]
|
292
|
+
|
293
|
+
#
|
159
294
|
alias :assert_not_same :refute_same
|
160
295
|
|
161
296
|
ActiveSupport.run_load_hooks(:active_support_test_case, self)
|
297
|
+
|
298
|
+
def inspect # :nodoc:
|
299
|
+
Object.instance_method(:to_s).bind_call(self)
|
300
|
+
end
|
162
301
|
end
|
163
302
|
end
|