activesupport 7.2.2.2 → 8.1.2
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 +368 -152
- data/README.rdoc +1 -1
- data/lib/active_support/backtrace_cleaner.rb +73 -2
- data/lib/active_support/benchmark.rb +21 -0
- data/lib/active_support/benchmarkable.rb +3 -2
- data/lib/active_support/broadcast_logger.rb +61 -74
- data/lib/active_support/cache/file_store.rb +14 -4
- data/lib/active_support/cache/mem_cache_store.rb +27 -29
- data/lib/active_support/cache/memory_store.rb +11 -5
- data/lib/active_support/cache/null_store.rb +2 -2
- data/lib/active_support/cache/redis_cache_store.rb +43 -34
- data/lib/active_support/cache/strategy/local_cache.rb +72 -27
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +7 -7
- data/lib/active_support/cache.rb +88 -20
- data/lib/active_support/callbacks.rb +28 -13
- data/lib/active_support/class_attribute.rb +33 -0
- data/lib/active_support/code_generator.rb +9 -0
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +8 -62
- data/lib/active_support/concurrency/share_lock.rb +0 -1
- data/lib/active_support/concurrency/thread_monitor.rb +55 -0
- data/lib/active_support/configurable.rb +34 -0
- data/lib/active_support/configuration_file.rb +15 -6
- data/lib/active_support/continuous_integration.rb +145 -0
- data/lib/active_support/core_ext/array/conversions.rb +3 -3
- data/lib/active_support/core_ext/array.rb +7 -7
- data/lib/active_support/core_ext/benchmark.rb +4 -14
- data/lib/active_support/core_ext/big_decimal.rb +1 -1
- data/lib/active_support/core_ext/class/attribute.rb +26 -20
- data/lib/active_support/core_ext/class.rb +2 -2
- data/lib/active_support/core_ext/date/conversions.rb +2 -0
- data/lib/active_support/core_ext/date.rb +5 -5
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +0 -35
- data/lib/active_support/core_ext/date_time/compatibility.rb +3 -5
- data/lib/active_support/core_ext/date_time/conversions.rb +4 -2
- data/lib/active_support/core_ext/date_time.rb +5 -5
- data/lib/active_support/core_ext/digest.rb +1 -1
- data/lib/active_support/core_ext/enumerable.rb +25 -8
- data/lib/active_support/core_ext/erb/util.rb +5 -5
- data/lib/active_support/core_ext/file.rb +1 -1
- data/lib/active_support/core_ext/hash/deep_merge.rb +1 -0
- data/lib/active_support/core_ext/hash/except.rb +0 -12
- data/lib/active_support/core_ext/hash.rb +8 -8
- data/lib/active_support/core_ext/integer.rb +3 -3
- data/lib/active_support/core_ext/kernel.rb +3 -3
- data/lib/active_support/core_ext/module/attr_internal.rb +3 -4
- data/lib/active_support/core_ext/module/introspection.rb +3 -0
- data/lib/active_support/core_ext/module.rb +11 -11
- data/lib/active_support/core_ext/numeric.rb +3 -3
- data/lib/active_support/core_ext/object/json.rb +24 -11
- data/lib/active_support/core_ext/object/to_query.rb +7 -1
- data/lib/active_support/core_ext/object/try.rb +2 -2
- data/lib/active_support/core_ext/object.rb +13 -13
- data/lib/active_support/core_ext/pathname.rb +2 -2
- data/lib/active_support/core_ext/range/overlap.rb +3 -3
- data/lib/active_support/core_ext/range/sole.rb +17 -0
- data/lib/active_support/core_ext/range.rb +4 -4
- data/lib/active_support/core_ext/securerandom.rb +24 -8
- data/lib/active_support/core_ext/string/filters.rb +3 -3
- data/lib/active_support/core_ext/string/multibyte.rb +12 -3
- data/lib/active_support/core_ext/string/output_safety.rb +19 -12
- data/lib/active_support/core_ext/string.rb +13 -13
- data/lib/active_support/core_ext/symbol.rb +1 -1
- data/lib/active_support/core_ext/thread/backtrace/location.rb +2 -7
- data/lib/active_support/core_ext/time/calculations.rb +7 -2
- data/lib/active_support/core_ext/time/compatibility.rb +2 -19
- data/lib/active_support/core_ext/time/conversions.rb +2 -0
- data/lib/active_support/core_ext/time.rb +5 -5
- data/lib/active_support/core_ext.rb +1 -1
- data/lib/active_support/current_attributes/test_helper.rb +2 -2
- data/lib/active_support/current_attributes.rb +27 -17
- data/lib/active_support/delegation.rb +25 -44
- data/lib/active_support/dependencies/interlock.rb +11 -5
- data/lib/active_support/dependencies.rb +6 -2
- data/lib/active_support/deprecation/reporting.rb +4 -21
- data/lib/active_support/deprecation.rb +1 -1
- data/lib/active_support/duration.rb +14 -10
- data/lib/active_support/editor.rb +70 -0
- data/lib/active_support/encrypted_configuration.rb +20 -2
- data/lib/active_support/error_reporter.rb +81 -4
- data/lib/active_support/event_reporter/test_helper.rb +32 -0
- data/lib/active_support/event_reporter.rb +592 -0
- data/lib/active_support/evented_file_update_checker.rb +5 -2
- data/lib/active_support/execution_context.rb +64 -7
- data/lib/active_support/execution_wrapper.rb +1 -1
- data/lib/active_support/file_update_checker.rb +8 -6
- data/lib/active_support/gem_version.rb +3 -3
- data/lib/active_support/gzip.rb +1 -0
- data/lib/active_support/hash_with_indifferent_access.rb +61 -38
- data/lib/active_support/i18n_railtie.rb +19 -11
- data/lib/active_support/inflector/inflections.rb +32 -15
- data/lib/active_support/inflector/methods.rb +2 -2
- data/lib/active_support/inflector/transliterate.rb +6 -8
- data/lib/active_support/isolated_execution_state.rb +17 -17
- data/lib/active_support/json/decoding.rb +6 -4
- data/lib/active_support/json/encoding.rb +157 -21
- data/lib/active_support/lazy_load_hooks.rb +1 -1
- data/lib/active_support/log_subscriber.rb +2 -6
- data/lib/active_support/logger_thread_safe_level.rb +6 -3
- data/lib/active_support/message_encryptors.rb +54 -2
- data/lib/active_support/message_pack/extensions.rb +6 -1
- data/lib/active_support/message_verifier.rb +9 -0
- data/lib/active_support/message_verifiers.rb +57 -3
- data/lib/active_support/messages/rotation_coordinator.rb +9 -0
- data/lib/active_support/messages/rotator.rb +10 -0
- data/lib/active_support/multibyte/chars.rb +12 -2
- data/lib/active_support/multibyte.rb +4 -0
- data/lib/active_support/notifications/fanout.rb +64 -43
- data/lib/active_support/notifications/instrumenter.rb +1 -1
- data/lib/active_support/number_helper.rb +22 -0
- data/lib/active_support/railtie.rb +32 -9
- data/lib/active_support/structured_event_subscriber.rb +99 -0
- data/lib/active_support/subscriber.rb +0 -5
- data/lib/active_support/syntax_error_proxy.rb +7 -0
- data/lib/active_support/tagged_logging.rb +5 -0
- data/lib/active_support/test_case.rb +67 -6
- data/lib/active_support/testing/assertions.rb +115 -27
- data/lib/active_support/testing/autorun.rb +5 -0
- data/lib/active_support/testing/error_reporter_assertions.rb +18 -1
- data/lib/active_support/testing/event_reporter_assertions.rb +227 -0
- data/lib/active_support/testing/isolation.rb +0 -2
- data/lib/active_support/testing/notification_assertions.rb +92 -0
- data/lib/active_support/testing/parallelization/server.rb +15 -2
- data/lib/active_support/testing/parallelization/worker.rb +8 -4
- data/lib/active_support/testing/parallelization.rb +25 -1
- data/lib/active_support/testing/tests_without_assertions.rb +1 -1
- data/lib/active_support/testing/time_helpers.rb +9 -4
- data/lib/active_support/time_with_zone.rb +36 -23
- data/lib/active_support/values/time_zone.rb +19 -10
- data/lib/active_support/xml_mini.rb +3 -2
- data/lib/active_support.rb +21 -9
- metadata +34 -12
- data/lib/active_support/core_ext/range/each.rb +0 -24
- data/lib/active_support/proxy_object.rb +0 -20
- data/lib/active_support/testing/strict_warnings.rb +0 -43
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "concurrent/map"
|
|
4
|
-
require "set"
|
|
5
4
|
require "active_support/core_ext/object/try"
|
|
6
5
|
|
|
7
6
|
module ActiveSupport
|
|
@@ -18,24 +17,30 @@ module ActiveSupport
|
|
|
18
17
|
|
|
19
18
|
module FanoutIteration # :nodoc:
|
|
20
19
|
private
|
|
21
|
-
def iterate_guarding_exceptions(collection)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
exceptions
|
|
28
|
-
exceptions << e
|
|
29
|
-
end
|
|
20
|
+
def iterate_guarding_exceptions(collection, &block)
|
|
21
|
+
case collection.size
|
|
22
|
+
when 0
|
|
23
|
+
when 1
|
|
24
|
+
collection.each(&block)
|
|
25
|
+
else
|
|
26
|
+
exceptions = nil
|
|
30
27
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
collection.each do |s|
|
|
29
|
+
yield s
|
|
30
|
+
rescue Exception => e
|
|
31
|
+
exceptions ||= []
|
|
32
|
+
exceptions << e
|
|
34
33
|
end
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
34
|
+
|
|
35
|
+
if exceptions
|
|
36
|
+
exceptions = exceptions.flat_map do |exception|
|
|
37
|
+
exception.is_a?(InstrumentationSubscriberError) ? exception.exceptions : [exception]
|
|
38
|
+
end
|
|
39
|
+
if exceptions.size == 1
|
|
40
|
+
raise exceptions.first
|
|
41
|
+
else
|
|
42
|
+
raise InstrumentationSubscriberError.new(exceptions), cause: exceptions.first
|
|
43
|
+
end
|
|
39
44
|
end
|
|
40
45
|
end
|
|
41
46
|
|
|
@@ -54,7 +59,6 @@ module ActiveSupport
|
|
|
54
59
|
@other_subscribers = []
|
|
55
60
|
@all_listeners_for = Concurrent::Map.new
|
|
56
61
|
@groups_for = Concurrent::Map.new
|
|
57
|
-
@silenceable_groups_for = Concurrent::Map.new
|
|
58
62
|
end
|
|
59
63
|
|
|
60
64
|
def inspect # :nodoc:
|
|
@@ -103,11 +107,9 @@ module ActiveSupport
|
|
|
103
107
|
if key
|
|
104
108
|
@all_listeners_for.delete(key)
|
|
105
109
|
@groups_for.delete(key)
|
|
106
|
-
@silenceable_groups_for.delete(key)
|
|
107
110
|
else
|
|
108
111
|
@all_listeners_for.clear
|
|
109
112
|
@groups_for.clear
|
|
110
|
-
@silenceable_groups_for.clear
|
|
111
113
|
end
|
|
112
114
|
end
|
|
113
115
|
|
|
@@ -185,25 +187,25 @@ module ActiveSupport
|
|
|
185
187
|
end
|
|
186
188
|
end
|
|
187
189
|
|
|
188
|
-
def
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
end
|
|
190
|
+
def group_listeners(listeners) # :nodoc:
|
|
191
|
+
listeners.group_by(&:group_class).transform_values do |s|
|
|
192
|
+
s.map(&:delegate).freeze
|
|
193
|
+
end.freeze
|
|
194
|
+
end
|
|
194
195
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
196
|
+
def groups_for(name) # :nodoc:
|
|
197
|
+
silenceable_groups, groups = @groups_for.compute_if_absent(name) do
|
|
198
|
+
listeners = all_listeners_for(name)
|
|
199
|
+
listeners.partition(&:silenceable).map { |l| group_listeners(l) }
|
|
199
200
|
end
|
|
200
201
|
|
|
201
202
|
unless silenceable_groups.empty?
|
|
202
|
-
groups = groups.dup
|
|
203
203
|
silenceable_groups.each do |group_class, subscriptions|
|
|
204
204
|
active_subscriptions = subscriptions.reject { |s| s.silenced?(name) }
|
|
205
205
|
unless active_subscriptions.empty?
|
|
206
|
-
groups
|
|
206
|
+
groups = groups.dup if groups.frozen?
|
|
207
|
+
base_groups = groups[group_class]
|
|
208
|
+
groups[group_class] = base_groups ? base_groups + active_subscriptions : active_subscriptions
|
|
207
209
|
end
|
|
208
210
|
end
|
|
209
211
|
end
|
|
@@ -228,13 +230,11 @@ module ActiveSupport
|
|
|
228
230
|
class Handle
|
|
229
231
|
include FanoutIteration
|
|
230
232
|
|
|
231
|
-
def initialize(notifier, name, id, payload) # :nodoc:
|
|
233
|
+
def initialize(notifier, name, id, groups, payload) # :nodoc:
|
|
232
234
|
@name = name
|
|
233
235
|
@id = id
|
|
234
236
|
@payload = payload
|
|
235
|
-
@groups =
|
|
236
|
-
group_klass.new(grouped_listeners, name, id, payload)
|
|
237
|
-
end
|
|
237
|
+
@groups = groups
|
|
238
238
|
@state = :initialized
|
|
239
239
|
end
|
|
240
240
|
|
|
@@ -268,10 +268,31 @@ module ActiveSupport
|
|
|
268
268
|
end
|
|
269
269
|
end
|
|
270
270
|
|
|
271
|
+
module NullHandle # :nodoc:
|
|
272
|
+
extend self
|
|
273
|
+
|
|
274
|
+
def start
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
def finish
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
def finish_with_values(_name, _id, _payload)
|
|
281
|
+
end
|
|
282
|
+
end
|
|
283
|
+
|
|
271
284
|
include FanoutIteration
|
|
272
285
|
|
|
273
286
|
def build_handle(name, id, payload)
|
|
274
|
-
|
|
287
|
+
groups = groups_for(name).map do |group_klass, grouped_listeners|
|
|
288
|
+
group_klass.new(grouped_listeners, name, id, payload)
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
if groups.empty?
|
|
292
|
+
NullHandle
|
|
293
|
+
else
|
|
294
|
+
Handle.new(self, name, id, groups, payload)
|
|
295
|
+
end
|
|
275
296
|
end
|
|
276
297
|
|
|
277
298
|
def start(name, id, payload)
|
|
@@ -287,8 +308,8 @@ module ActiveSupport
|
|
|
287
308
|
handle.finish_with_values(name, id, payload)
|
|
288
309
|
end
|
|
289
310
|
|
|
290
|
-
def publish(name,
|
|
291
|
-
iterate_guarding_exceptions(listeners_for(name)) { |s| s.publish(name,
|
|
311
|
+
def publish(name, ...)
|
|
312
|
+
iterate_guarding_exceptions(listeners_for(name)) { |s| s.publish(name, ...) }
|
|
292
313
|
end
|
|
293
314
|
|
|
294
315
|
def publish_event(event)
|
|
@@ -388,9 +409,9 @@ module ActiveSupport
|
|
|
388
409
|
EventedGroup
|
|
389
410
|
end
|
|
390
411
|
|
|
391
|
-
def publish(
|
|
412
|
+
def publish(...)
|
|
392
413
|
if @can_publish
|
|
393
|
-
@delegate.publish
|
|
414
|
+
@delegate.publish(...)
|
|
394
415
|
end
|
|
395
416
|
end
|
|
396
417
|
|
|
@@ -420,8 +441,8 @@ module ActiveSupport
|
|
|
420
441
|
TimedGroup
|
|
421
442
|
end
|
|
422
443
|
|
|
423
|
-
def publish(
|
|
424
|
-
@delegate.call
|
|
444
|
+
def publish(...)
|
|
445
|
+
@delegate.call(...)
|
|
425
446
|
end
|
|
426
447
|
end
|
|
427
448
|
|
|
@@ -164,7 +164,7 @@ module ActiveSupport
|
|
|
164
164
|
@cpu_time_finish - @cpu_time_start
|
|
165
165
|
end
|
|
166
166
|
|
|
167
|
-
# Returns the idle time
|
|
167
|
+
# Returns the idle time (in milliseconds) passed between the call to
|
|
168
168
|
# #start! and the call to #finish!.
|
|
169
169
|
def idle_time
|
|
170
170
|
diff = duration - cpu_time
|
|
@@ -1,6 +1,28 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module ActiveSupport
|
|
4
|
+
# = Number Helper
|
|
5
|
+
#
|
|
6
|
+
# Provides methods for formatting numbers into currencies, percentages,
|
|
7
|
+
# phone numbers, and more.
|
|
8
|
+
#
|
|
9
|
+
# Example usage in a class:
|
|
10
|
+
# class Topic
|
|
11
|
+
# include ActiveSupport::NumberHelper
|
|
12
|
+
#
|
|
13
|
+
# def price
|
|
14
|
+
# number_to_currency(@price)
|
|
15
|
+
# end
|
|
16
|
+
# end
|
|
17
|
+
#
|
|
18
|
+
# Example usage in a module:
|
|
19
|
+
# require "active_support/number_helper"
|
|
20
|
+
#
|
|
21
|
+
# module NumberFormatting
|
|
22
|
+
# def format_price(price)
|
|
23
|
+
# ActiveSupport::NumberHelper.number_to_currency(price)
|
|
24
|
+
# end
|
|
25
|
+
# end
|
|
4
26
|
module NumberHelper
|
|
5
27
|
extend ActiveSupport::Autoload
|
|
6
28
|
|
|
@@ -15,7 +15,7 @@ module ActiveSupport
|
|
|
15
15
|
|
|
16
16
|
initializer "active_support.isolation_level" do |app|
|
|
17
17
|
config.after_initialize do
|
|
18
|
-
if level = app.config.active_support.
|
|
18
|
+
if level = app.config.active_support.isolation_level
|
|
19
19
|
ActiveSupport::IsolatedExecutionState.isolation_level = level
|
|
20
20
|
end
|
|
21
21
|
end
|
|
@@ -38,19 +38,35 @@ module ActiveSupport
|
|
|
38
38
|
end
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
-
initializer "active_support.
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
initializer "active_support.set_event_reporter_context_store" do |app|
|
|
42
|
+
config.after_initialize do
|
|
43
|
+
if klass = app.config.active_support.event_reporter_context_store
|
|
44
|
+
ActiveSupport::EventReporter.context_store = klass
|
|
45
|
+
end
|
|
46
|
+
end
|
|
45
47
|
end
|
|
46
48
|
|
|
47
|
-
initializer "active_support.
|
|
48
|
-
app.reloader.before_class_unload
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
initializer "active_support.reset_execution_context" do |app|
|
|
50
|
+
app.reloader.before_class_unload do
|
|
51
|
+
ActiveSupport::CurrentAttributes.clear_all
|
|
52
|
+
ActiveSupport::ExecutionContext.clear
|
|
53
|
+
ActiveSupport.event_reporter.clear_context
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
app.executor.to_run do
|
|
57
|
+
ActiveSupport::ExecutionContext.push
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
app.executor.to_complete do
|
|
61
|
+
ActiveSupport::CurrentAttributes.clear_all
|
|
62
|
+
ActiveSupport::ExecutionContext.pop
|
|
63
|
+
ActiveSupport.event_reporter.clear_context
|
|
64
|
+
end
|
|
51
65
|
|
|
52
66
|
ActiveSupport.on_load(:active_support_test_case) do
|
|
53
67
|
if app.config.active_support.executor_around_test_case
|
|
68
|
+
ActiveSupport::ExecutionContext.nestable = true
|
|
69
|
+
|
|
54
70
|
require "active_support/executor/test_helper"
|
|
55
71
|
include ActiveSupport::Executor::TestHelper
|
|
56
72
|
else
|
|
@@ -63,6 +79,13 @@ module ActiveSupport
|
|
|
63
79
|
end
|
|
64
80
|
end
|
|
65
81
|
|
|
82
|
+
initializer "active_support.set_filter_parameters" do |app|
|
|
83
|
+
config.after_initialize do
|
|
84
|
+
ActiveSupport.filter_parameters += Rails.application.config.filter_parameters
|
|
85
|
+
ActiveSupport.event_reporter.reload_payload_filter
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
66
89
|
initializer "active_support.deprecation_behavior" do |app|
|
|
67
90
|
if app.config.active_support.report_deprecations == false
|
|
68
91
|
app.deprecators.silenced = true
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_support/subscriber"
|
|
4
|
+
|
|
5
|
+
module ActiveSupport
|
|
6
|
+
# = Active Support Structured Event \Subscriber
|
|
7
|
+
#
|
|
8
|
+
# +ActiveSupport::StructuredEventSubscriber+ consumes ActiveSupport::Notifications
|
|
9
|
+
# in order to emit structured events via +Rails.event+.
|
|
10
|
+
#
|
|
11
|
+
# An example would be the Action Controller structured event subscriber, responsible for
|
|
12
|
+
# emitting request processing events:
|
|
13
|
+
#
|
|
14
|
+
# module ActionController
|
|
15
|
+
# class StructuredEventSubscriber < ActiveSupport::StructuredEventSubscriber
|
|
16
|
+
# attach_to :action_controller
|
|
17
|
+
#
|
|
18
|
+
# def start_processing(event)
|
|
19
|
+
# emit_event("controller.request_started",
|
|
20
|
+
# controller: event.payload[:controller],
|
|
21
|
+
# action: event.payload[:action],
|
|
22
|
+
# format: event.payload[:format]
|
|
23
|
+
# )
|
|
24
|
+
# end
|
|
25
|
+
# end
|
|
26
|
+
# end
|
|
27
|
+
#
|
|
28
|
+
# After configured, whenever a <tt>"start_processing.action_controller"</tt> notification is published,
|
|
29
|
+
# it will properly dispatch the event (+ActiveSupport::Notifications::Event+) to the +start_processing+ method.
|
|
30
|
+
# The subscriber can then emit a structured event via the +emit_event+ method.
|
|
31
|
+
class StructuredEventSubscriber < Subscriber
|
|
32
|
+
class_attribute :debug_methods, instance_accessor: false, default: [] # :nodoc:
|
|
33
|
+
|
|
34
|
+
DEBUG_CHECK = proc { !ActiveSupport.event_reporter.debug_mode? }
|
|
35
|
+
|
|
36
|
+
class << self
|
|
37
|
+
def attach_to(...) # :nodoc:
|
|
38
|
+
result = super
|
|
39
|
+
set_silenced_events
|
|
40
|
+
result
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
private
|
|
44
|
+
def set_silenced_events
|
|
45
|
+
if subscriber
|
|
46
|
+
subscriber.silenced_events = debug_methods.to_h { |method| ["#{method}.#{namespace}", DEBUG_CHECK] }
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def debug_only(method)
|
|
51
|
+
self.debug_methods << method
|
|
52
|
+
set_silenced_events
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def initialize
|
|
57
|
+
super
|
|
58
|
+
@silenced_events = {}
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def silenced?(event)
|
|
62
|
+
ActiveSupport.event_reporter.subscribers.none? || @silenced_events[event]&.call
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
attr_writer :silenced_events # :nodoc:
|
|
66
|
+
|
|
67
|
+
# Emit a structured event via Rails.event.notify.
|
|
68
|
+
#
|
|
69
|
+
# ==== Arguments
|
|
70
|
+
#
|
|
71
|
+
# * +name+ - The event name as a string or symbol
|
|
72
|
+
# * +payload+ - The event payload as a hash or object
|
|
73
|
+
# * +caller_depth+ - Stack depth for source location (default: 1)
|
|
74
|
+
# * +kwargs+ - Additional payload data merged with the payload hash
|
|
75
|
+
def emit_event(name, payload = nil, caller_depth: 1, **kwargs)
|
|
76
|
+
ActiveSupport.event_reporter.notify(name, payload, caller_depth: caller_depth + 1, **kwargs)
|
|
77
|
+
rescue => e
|
|
78
|
+
handle_event_error(name, e)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Like +emit_event+, but only emits when the event reporter is in debug mode
|
|
82
|
+
def emit_debug_event(name, payload = nil, caller_depth: 1, **kwargs)
|
|
83
|
+
ActiveSupport.event_reporter.debug(name, payload, caller_depth: caller_depth + 1, **kwargs)
|
|
84
|
+
rescue => e
|
|
85
|
+
handle_event_error(name, e)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def call(event)
|
|
89
|
+
super
|
|
90
|
+
rescue => e
|
|
91
|
+
handle_event_error(event.name, e)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
private
|
|
95
|
+
def handle_event_error(name, error)
|
|
96
|
+
ActiveSupport.error_reporter.report(error, source: name)
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
@@ -113,6 +113,11 @@ module ActiveSupport
|
|
|
113
113
|
end
|
|
114
114
|
end
|
|
115
115
|
|
|
116
|
+
# Returns an `ActiveSupport::Logger` that has already been wrapped with tagged logging concern.
|
|
117
|
+
def self.logger(*args, **kwargs)
|
|
118
|
+
new ActiveSupport::Logger.new(*args, **kwargs)
|
|
119
|
+
end
|
|
120
|
+
|
|
116
121
|
def self.new(logger)
|
|
117
122
|
logger = logger.clone
|
|
118
123
|
|
|
@@ -6,6 +6,7 @@ require "active_support/testing/setup_and_teardown"
|
|
|
6
6
|
require "active_support/testing/tests_without_assertions"
|
|
7
7
|
require "active_support/testing/assertions"
|
|
8
8
|
require "active_support/testing/error_reporter_assertions"
|
|
9
|
+
require "active_support/testing/event_reporter_assertions"
|
|
9
10
|
require "active_support/testing/deprecation"
|
|
10
11
|
require "active_support/testing/declarative"
|
|
11
12
|
require "active_support/testing/isolation"
|
|
@@ -15,13 +16,29 @@ require "active_support/testing/constant_stubbing"
|
|
|
15
16
|
require "active_support/testing/file_fixtures"
|
|
16
17
|
require "active_support/testing/parallelization"
|
|
17
18
|
require "active_support/testing/parallelize_executor"
|
|
19
|
+
require "active_support/testing/notification_assertions"
|
|
18
20
|
require "concurrent/utility/processor_counter"
|
|
19
21
|
|
|
20
22
|
module ActiveSupport
|
|
21
23
|
class TestCase < ::Minitest::Test
|
|
22
24
|
Assertion = Minitest::Assertion
|
|
23
25
|
|
|
26
|
+
# Class variable to store the parallel worker ID
|
|
27
|
+
@@parallel_worker_id = nil
|
|
28
|
+
|
|
24
29
|
class << self
|
|
30
|
+
# Returns the current parallel worker ID if tests are running in parallel,
|
|
31
|
+
# nil otherwise.
|
|
32
|
+
#
|
|
33
|
+
# ActiveSupport::TestCase.parallel_worker_id # => 2
|
|
34
|
+
def parallel_worker_id
|
|
35
|
+
@@parallel_worker_id
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def parallel_worker_id=(value) # :nodoc:
|
|
39
|
+
@@parallel_worker_id = value
|
|
40
|
+
end
|
|
41
|
+
|
|
25
42
|
# Sets the order in which test cases are run.
|
|
26
43
|
#
|
|
27
44
|
# ActiveSupport::TestCase.test_order = :random # => :random
|
|
@@ -45,14 +62,20 @@ module ActiveSupport
|
|
|
45
62
|
ActiveSupport.test_order ||= :random
|
|
46
63
|
end
|
|
47
64
|
|
|
65
|
+
if Minitest.respond_to? :run_order # MT6 API change
|
|
66
|
+
def run_order # :nodoc:
|
|
67
|
+
test_order
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
48
71
|
# Parallelizes the test suite.
|
|
49
72
|
#
|
|
50
73
|
# Takes a +workers+ argument that controls how many times the process
|
|
51
74
|
# is forked. For each process a new database will be created suffixed
|
|
52
75
|
# with the worker number.
|
|
53
76
|
#
|
|
54
|
-
# test-
|
|
55
|
-
# test-
|
|
77
|
+
# test-database_0
|
|
78
|
+
# test-database_1
|
|
56
79
|
#
|
|
57
80
|
# If <tt>ENV["PARALLEL_WORKERS"]</tt> is set the workers argument will be ignored
|
|
58
81
|
# and the environment variable will be used instead. This is useful for CI
|
|
@@ -78,14 +101,45 @@ module ActiveSupport
|
|
|
78
101
|
# Because parallelization presents an overhead, it is only enabled when the
|
|
79
102
|
# number of tests to run is above the +threshold+ param. The default value is
|
|
80
103
|
# 50, and it's configurable via +config.active_support.test_parallelization_threshold+.
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
104
|
+
#
|
|
105
|
+
# If you want to skip Rails default creation of one database per process in favor of
|
|
106
|
+
# writing your own implementation, you can set +parallelize_databases+, or configure it
|
|
107
|
+
# via +config.active_support.parallelize_test_databases+.
|
|
108
|
+
#
|
|
109
|
+
# parallelize(workers: :number_of_processors, parallelize_databases: false)
|
|
110
|
+
#
|
|
111
|
+
# Note that your test suite may deadlock if you attempt to use only one database
|
|
112
|
+
# with multiple processes.
|
|
113
|
+
def parallelize(workers: :number_of_processors, with: :processes, threshold: ActiveSupport.test_parallelization_threshold, parallelize_databases: ActiveSupport.parallelize_test_databases)
|
|
114
|
+
case
|
|
115
|
+
when ENV["PARALLEL_WORKERS"]
|
|
116
|
+
workers = ENV["PARALLEL_WORKERS"].to_i
|
|
117
|
+
when workers == :number_of_processors
|
|
118
|
+
workers = (Concurrent.available_processor_count || Concurrent.processor_count).floor
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
if with == :processes
|
|
122
|
+
ActiveSupport.parallelize_test_databases = parallelize_databases
|
|
123
|
+
end
|
|
84
124
|
|
|
85
125
|
Minitest.parallel_executor = ActiveSupport::Testing::ParallelizeExecutor.new(size: workers, with: with, threshold: threshold)
|
|
86
126
|
end
|
|
87
127
|
|
|
88
|
-
#
|
|
128
|
+
# Before fork hook for parallel testing. This can be used to run anything
|
|
129
|
+
# before the processes are forked.
|
|
130
|
+
#
|
|
131
|
+
# In your +test_helper.rb+ add the following:
|
|
132
|
+
#
|
|
133
|
+
# class ActiveSupport::TestCase
|
|
134
|
+
# parallelize_before_fork do
|
|
135
|
+
# # run this before fork
|
|
136
|
+
# end
|
|
137
|
+
# end
|
|
138
|
+
def parallelize_before_fork(&block)
|
|
139
|
+
ActiveSupport::Testing::Parallelization.before_fork_hook(&block)
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
# Setup hook for parallel testing. This can be used if you have multiple
|
|
89
143
|
# databases or any behavior that needs to be run after the process is forked
|
|
90
144
|
# but before the tests run.
|
|
91
145
|
#
|
|
@@ -141,11 +195,18 @@ module ActiveSupport
|
|
|
141
195
|
|
|
142
196
|
alias_method :method_name, :name
|
|
143
197
|
|
|
198
|
+
# Returns the current parallel worker ID if tests are running in parallel
|
|
199
|
+
def parallel_worker_id
|
|
200
|
+
self.class.parallel_worker_id
|
|
201
|
+
end
|
|
202
|
+
|
|
144
203
|
include ActiveSupport::Testing::TaggedLogging
|
|
145
204
|
prepend ActiveSupport::Testing::SetupAndTeardown
|
|
146
205
|
prepend ActiveSupport::Testing::TestsWithoutAssertions
|
|
147
206
|
include ActiveSupport::Testing::Assertions
|
|
148
207
|
include ActiveSupport::Testing::ErrorReporterAssertions
|
|
208
|
+
include ActiveSupport::Testing::EventReporterAssertions
|
|
209
|
+
include ActiveSupport::Testing::NotificationAssertions
|
|
149
210
|
include ActiveSupport::Testing::Deprecation
|
|
150
211
|
include ActiveSupport::Testing::ConstantStubbing
|
|
151
212
|
include ActiveSupport::Testing::TimeHelpers
|