activesupport 6.1.7.10 → 7.0.0.alpha1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activesupport might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +151 -664
- data/MIT-LICENSE +1 -1
- data/lib/active_support/actionable_error.rb +1 -1
- data/lib/active_support/array_inquirer.rb +0 -2
- data/lib/active_support/benchmarkable.rb +2 -2
- data/lib/active_support/cache/file_store.rb +15 -9
- data/lib/active_support/cache/mem_cache_store.rb +119 -28
- data/lib/active_support/cache/memory_store.rb +21 -13
- data/lib/active_support/cache/null_store.rb +10 -2
- data/lib/active_support/cache/redis_cache_store.rb +39 -59
- data/lib/active_support/cache/strategy/local_cache.rb +29 -49
- data/lib/active_support/cache.rb +189 -45
- data/lib/active_support/callbacks.rb +35 -31
- data/lib/active_support/concern.rb +5 -5
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +2 -4
- data/lib/active_support/concurrency/share_lock.rb +2 -2
- data/lib/active_support/configurable.rb +6 -3
- data/lib/active_support/configuration_file.rb +1 -1
- data/lib/active_support/core_ext/array/access.rb +1 -5
- data/lib/active_support/core_ext/array/conversions.rb +6 -6
- data/lib/active_support/core_ext/array/grouping.rb +6 -6
- data/lib/active_support/core_ext/big_decimal/conversions.rb +1 -1
- data/lib/active_support/core_ext/date/blank.rb +1 -1
- data/lib/active_support/core_ext/date/calculations.rb +2 -2
- data/lib/active_support/core_ext/date_time/blank.rb +1 -1
- data/lib/active_support/core_ext/digest/uuid.rb +13 -13
- data/lib/active_support/core_ext/enumerable.rb +64 -12
- data/lib/active_support/core_ext/file/atomic.rb +1 -1
- data/lib/active_support/core_ext/hash/keys.rb +1 -1
- data/lib/active_support/core_ext/kernel/reporting.rb +4 -4
- data/lib/active_support/core_ext/module/delegation.rb +2 -8
- data/lib/active_support/core_ext/name_error.rb +2 -8
- data/lib/active_support/core_ext/numeric/conversions.rb +2 -2
- data/lib/active_support/core_ext/object/blank.rb +2 -2
- data/lib/active_support/core_ext/object/deep_dup.rb +1 -1
- data/lib/active_support/core_ext/object/duplicable.rb +11 -0
- data/lib/active_support/core_ext/object/json.rb +29 -24
- data/lib/active_support/core_ext/object/to_query.rb +2 -2
- data/lib/active_support/core_ext/object/try.rb +20 -20
- data/lib/active_support/core_ext/range/compare_range.rb +0 -25
- data/lib/active_support/core_ext/range/each.rb +1 -1
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +1 -1
- data/lib/active_support/core_ext/string/filters.rb +1 -1
- data/lib/active_support/core_ext/string/inflections.rb +1 -1
- data/lib/active_support/core_ext/string/output_safety.rb +60 -68
- data/lib/active_support/core_ext/symbol/starts_ends_with.rb +0 -8
- data/lib/active_support/core_ext/time/calculations.rb +4 -5
- data/lib/active_support/core_ext/time/zones.rb +2 -17
- data/lib/active_support/core_ext/uri.rb +0 -14
- data/lib/active_support/current_attributes.rb +17 -2
- 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 +4 -1
- data/lib/active_support/deprecation/method_wrappers.rb +3 -3
- data/lib/active_support/deprecation/proxy_wrappers.rb +1 -1
- data/lib/active_support/deprecation.rb +1 -1
- data/lib/active_support/descendants_tracker.rb +12 -9
- data/lib/active_support/digest.rb +4 -4
- data/lib/active_support/duration/iso8601_parser.rb +3 -3
- data/lib/active_support/duration/iso8601_serializer.rb +9 -1
- data/lib/active_support/duration.rb +80 -52
- data/lib/active_support/encrypted_configuration.rb +11 -1
- data/lib/active_support/encrypted_file.rb +10 -9
- data/lib/active_support/environment_inquirer.rb +1 -1
- data/lib/active_support/evented_file_update_checker.rb +1 -1
- data/lib/active_support/execution_wrapper.rb +13 -16
- data/lib/active_support/fork_tracker.rb +2 -4
- data/lib/active_support/gem_version.rb +4 -4
- data/lib/active_support/hash_with_indifferent_access.rb +3 -1
- data/lib/active_support/i18n.rb +1 -0
- data/lib/active_support/inflector/inflections.rb +11 -4
- data/lib/active_support/inflector/methods.rb +23 -46
- data/lib/active_support/json/encoding.rb +3 -3
- data/lib/active_support/key_generator.rb +18 -1
- data/lib/active_support/locale/en.yml +1 -1
- data/lib/active_support/log_subscriber.rb +13 -3
- data/lib/active_support/logger_thread_safe_level.rb +5 -13
- data/lib/active_support/message_encryptor.rb +3 -3
- data/lib/active_support/message_verifier.rb +4 -4
- data/lib/active_support/messages/metadata.rb +2 -2
- data/lib/active_support/multibyte/chars.rb +10 -11
- data/lib/active_support/multibyte.rb +1 -1
- data/lib/active_support/notifications/fanout.rb +31 -11
- data/lib/active_support/notifications/instrumenter.rb +17 -0
- data/lib/active_support/notifications.rb +10 -0
- data/lib/active_support/number_helper/number_converter.rb +1 -3
- 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 +1 -1
- data/lib/active_support/number_helper/number_to_phone_converter.rb +1 -1
- data/lib/active_support/number_helper/rounding_helper.rb +1 -5
- data/lib/active_support/number_helper.rb +0 -2
- data/lib/active_support/option_merger.rb +4 -16
- data/lib/active_support/ordered_hash.rb +1 -1
- data/lib/active_support/parameter_filter.rb +5 -0
- data/lib/active_support/per_thread_registry.rb +1 -1
- data/lib/active_support/railtie.rb +33 -10
- data/lib/active_support/reloader.rb +1 -1
- data/lib/active_support/rescuable.rb +2 -2
- data/lib/active_support/secure_compare_rotator.rb +1 -1
- data/lib/active_support/string_inquirer.rb +0 -2
- data/lib/active_support/subscriber.rb +5 -0
- data/lib/active_support/test_case.rb +9 -21
- data/lib/active_support/testing/assertions.rb +34 -4
- data/lib/active_support/testing/deprecation.rb +1 -1
- data/lib/active_support/testing/isolation.rb +1 -1
- data/lib/active_support/testing/method_call_assertions.rb +5 -5
- 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 +76 -0
- data/lib/active_support/testing/stream.rb +3 -5
- data/lib/active_support/testing/tagged_logging.rb +1 -1
- data/lib/active_support/testing/time_helpers.rb +13 -2
- data/lib/active_support/time_with_zone.rb +19 -6
- data/lib/active_support/values/time_zone.rb +25 -11
- data/lib/active_support/xml_mini/jdom.rb +1 -1
- 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 +4 -4
- data/lib/active_support/xml_mini/nokogirisax.rb +1 -1
- data/lib/active_support/xml_mini/rexml.rb +1 -1
- data/lib/active_support/xml_mini.rb +2 -1
- data/lib/active_support.rb +14 -1
- metadata +11 -26
- data/lib/active_support/core_ext/marshal.rb +0 -26
- data/lib/active_support/dependencies/zeitwerk_integration.rb +0 -120
@@ -35,16 +35,12 @@ module ActiveSupport
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def absolute_precision(number)
|
38
|
-
if significant && options[:precision] > 0
|
38
|
+
if options[:significant] && options[:precision] > 0
|
39
39
|
options[:precision] - digit_count(convert_to_decimal(number))
|
40
40
|
else
|
41
41
|
options[:precision]
|
42
42
|
end
|
43
43
|
end
|
44
|
-
|
45
|
-
def significant
|
46
|
-
options[:significant]
|
47
|
-
end
|
48
44
|
end
|
49
45
|
end
|
50
46
|
end
|
@@ -99,8 +99,6 @@ module ActiveSupport
|
|
99
99
|
# number_to_currency(1234567890.506, locale: :fr) # => "1 234 567 890,51 €"
|
100
100
|
# number_to_currency('123a456') # => "$123a456"
|
101
101
|
#
|
102
|
-
# number_to_currency("123a456", raise: true) # => InvalidNumberError
|
103
|
-
#
|
104
102
|
# number_to_currency(-0.456789, precision: 0)
|
105
103
|
# # => "$0"
|
106
104
|
# number_to_currency(-1234567890.50, negative_format: '(%u%n)')
|
@@ -1,10 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "active_support/core_ext/hash/deep_merge"
|
4
|
-
require "active_support/core_ext/symbol/starts_ends_with"
|
5
4
|
|
6
5
|
module ActiveSupport
|
7
|
-
class OptionMerger
|
6
|
+
class OptionMerger # :nodoc:
|
8
7
|
instance_methods.each do |method|
|
9
8
|
undef_method(method) unless method.start_with?("__", "instance_eval", "class", "object_id")
|
10
9
|
end
|
@@ -25,20 +24,9 @@ module ActiveSupport
|
|
25
24
|
options = @options
|
26
25
|
end
|
27
26
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
if RUBY_VERSION >= "2.7"
|
32
|
-
def invoke_method(method, arguments, options, &block)
|
33
|
-
if options
|
34
|
-
@context.__send__(method, *arguments, **options, &block)
|
35
|
-
else
|
36
|
-
@context.__send__(method, *arguments, &block)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
else
|
40
|
-
def invoke_method(method, arguments, options, &block)
|
41
|
-
arguments << options.dup if options
|
27
|
+
if options
|
28
|
+
@context.__send__(method, *arguments, **options, &block)
|
29
|
+
else
|
42
30
|
@context.__send__(method, *arguments, &block)
|
43
31
|
end
|
44
32
|
end
|
@@ -21,7 +21,7 @@ module ActiveSupport
|
|
21
21
|
#
|
22
22
|
# <tt>ActiveSupport::OrderedHash</tt> is namespaced to prevent conflicts
|
23
23
|
# with other implementations.
|
24
|
-
class OrderedHash < ::Hash
|
24
|
+
class OrderedHash < ::Hash # :nodoc:
|
25
25
|
def to_yaml_type
|
26
26
|
"!tag:yaml.org,2002:omap"
|
27
27
|
end
|
@@ -16,6 +16,11 @@ module ActiveSupport
|
|
16
16
|
# ActiveSupport::ParameterFilter.new([:foo, "bar"])
|
17
17
|
# => replaces the value to all keys matching /foo|bar/i with "[FILTERED]"
|
18
18
|
#
|
19
|
+
# ActiveSupport::ParameterFilter.new([/\Apin\z/i, /\Apin_/i])
|
20
|
+
# => replaces the value for the exact (case-insensitive) key 'pin' and all
|
21
|
+
# (case-insensitive) keys beginning with 'pin_', with "[FILTERED]".
|
22
|
+
# Does not match keys with 'pin' as a substring, such as 'shipping_id'.
|
23
|
+
#
|
19
24
|
# ActiveSupport::ParameterFilter.new(["credit_card.code"])
|
20
25
|
# => replaces { credit_card: {code: "xxxx"} } with "[FILTERED]", does not
|
21
26
|
# change { file: { code: "xxxx"} }
|
@@ -9,6 +9,15 @@ module ActiveSupport
|
|
9
9
|
|
10
10
|
config.eager_load_namespaces << ActiveSupport
|
11
11
|
|
12
|
+
initializer "active_support.remove_deprecated_time_with_zone_name" do |app|
|
13
|
+
config.after_initialize do
|
14
|
+
if app.config.active_support.remove_deprecated_time_with_zone_name
|
15
|
+
require "active_support/time_with_zone"
|
16
|
+
TimeWithZone.singleton_class.remove_method(:name)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
12
21
|
initializer "active_support.set_authenticated_message_encryption" do |app|
|
13
22
|
config.after_initialize do
|
14
23
|
unless app.config.active_support.use_authenticated_message_encryption.nil?
|
@@ -30,16 +39,22 @@ module ActiveSupport
|
|
30
39
|
end
|
31
40
|
|
32
41
|
initializer "active_support.deprecation_behavior" do |app|
|
33
|
-
if
|
34
|
-
ActiveSupport::Deprecation.
|
35
|
-
|
42
|
+
if app.config.active_support.report_deprecations == false
|
43
|
+
ActiveSupport::Deprecation.silenced = true
|
44
|
+
ActiveSupport::Deprecation.behavior = :silence
|
45
|
+
ActiveSupport::Deprecation.disallowed_behavior = :silence
|
46
|
+
else
|
47
|
+
if deprecation = app.config.active_support.deprecation
|
48
|
+
ActiveSupport::Deprecation.behavior = deprecation
|
49
|
+
end
|
36
50
|
|
37
|
-
|
38
|
-
|
39
|
-
|
51
|
+
if disallowed_deprecation = app.config.active_support.disallowed_deprecation
|
52
|
+
ActiveSupport::Deprecation.disallowed_behavior = disallowed_deprecation
|
53
|
+
end
|
40
54
|
|
41
|
-
|
42
|
-
|
55
|
+
if disallowed_warnings = app.config.active_support.disallowed_deprecation_warnings
|
56
|
+
ActiveSupport::Deprecation.disallowed_warnings = disallowed_warnings
|
57
|
+
end
|
43
58
|
end
|
44
59
|
end
|
45
60
|
|
@@ -88,9 +103,9 @@ module ActiveSupport
|
|
88
103
|
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
89
104
|
config.active_support.use_sha1_digests is deprecated and will
|
90
105
|
be removed from Rails 7.0. Use
|
91
|
-
config.active_support.hash_digest_class = ::Digest::SHA1 instead.
|
106
|
+
config.active_support.hash_digest_class = OpenSSL::Digest::SHA1 instead.
|
92
107
|
MSG
|
93
|
-
ActiveSupport::Digest.hash_digest_class = ::Digest::SHA1
|
108
|
+
ActiveSupport::Digest.hash_digest_class = OpenSSL::Digest::SHA1
|
94
109
|
end
|
95
110
|
|
96
111
|
if klass = app.config.active_support.hash_digest_class
|
@@ -98,5 +113,13 @@ module ActiveSupport
|
|
98
113
|
end
|
99
114
|
end
|
100
115
|
end
|
116
|
+
|
117
|
+
initializer "active_support.set_key_generator_hash_digest_class" do |app|
|
118
|
+
config.after_initialize do
|
119
|
+
if klass = app.config.active_support.key_generator_hash_digest_class
|
120
|
+
ActiveSupport::KeyGenerator.hash_digest_class = klass
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
101
124
|
end
|
102
125
|
end
|
@@ -100,7 +100,7 @@ module ActiveSupport
|
|
100
100
|
end
|
101
101
|
end
|
102
102
|
|
103
|
-
def handler_for_rescue(exception, object: self)
|
103
|
+
def handler_for_rescue(exception, object: self) # :nodoc:
|
104
104
|
case rescuer = find_rescue_handler(exception)
|
105
105
|
when Symbol
|
106
106
|
method = object.method(rescuer)
|
@@ -167,7 +167,7 @@ module ActiveSupport
|
|
167
167
|
|
168
168
|
# Internal handler lookup. Delegates to class method. Some libraries call
|
169
169
|
# this directly, so keeping it around for compatibility.
|
170
|
-
def handler_for_rescue(exception)
|
170
|
+
def handler_for_rescue(exception) # :nodoc:
|
171
171
|
self.class.handler_for_rescue exception, object: self
|
172
172
|
end
|
173
173
|
end
|
@@ -17,7 +17,7 @@ module ActiveSupport
|
|
17
17
|
#
|
18
18
|
# class MyController < ApplicationController
|
19
19
|
# def authenticate_request
|
20
|
-
# rotator = ActiveSupport::
|
20
|
+
# rotator = ActiveSupport::SecureCompareRotator.new('new_password')
|
21
21
|
# rotator.rotate('old_password')
|
22
22
|
#
|
23
23
|
# authenticate_or_request_with_http_basic do |username, password|
|
@@ -150,6 +150,11 @@ module ActiveSupport
|
|
150
150
|
send(method, event)
|
151
151
|
end
|
152
152
|
|
153
|
+
def publish_event(event) # :nodoc:
|
154
|
+
method = event.name.split(".").first
|
155
|
+
send(method, event)
|
156
|
+
end
|
157
|
+
|
153
158
|
private
|
154
159
|
def event_stack
|
155
160
|
SubscriberQueueRegistry.instance.get_queue(@queue_key)
|
@@ -12,6 +12,7 @@ require "active_support/testing/constant_lookup"
|
|
12
12
|
require "active_support/testing/time_helpers"
|
13
13
|
require "active_support/testing/file_fixtures"
|
14
14
|
require "active_support/testing/parallelization"
|
15
|
+
require "active_support/testing/parallelize_executor"
|
15
16
|
require "concurrent/utility/processor_counter"
|
16
17
|
|
17
18
|
module ActiveSupport
|
@@ -71,26 +72,17 @@ module ActiveSupport
|
|
71
72
|
#
|
72
73
|
# The threaded parallelization uses minitest's parallel executor directly.
|
73
74
|
# The processes parallelization uses a Ruby DRb server.
|
74
|
-
|
75
|
+
#
|
76
|
+
# Because parallelization presents an overhead, it is only enabled when the
|
77
|
+
# number of tests to run is above the +threshold+ param. The default value is
|
78
|
+
# 50, and it's configurable via +config.active_support.test_parallelization_threshold+.
|
79
|
+
def parallelize(workers: :number_of_processors, with: :processes, threshold: ActiveSupport.test_parallelization_threshold)
|
75
80
|
workers = Concurrent.physical_processor_count if workers == :number_of_processors
|
76
81
|
workers = ENV["PARALLEL_WORKERS"].to_i if ENV["PARALLEL_WORKERS"]
|
77
82
|
|
78
83
|
return if workers <= 1
|
79
84
|
|
80
|
-
|
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!
|
85
|
+
Minitest.parallel_executor = ActiveSupport::Testing::ParallelizeExecutor.new(size: workers, with: with, threshold: threshold)
|
94
86
|
end
|
95
87
|
|
96
88
|
# Set up hook for parallel testing. This can be used if you have multiple
|
@@ -107,9 +99,7 @@ module ActiveSupport
|
|
107
99
|
# end
|
108
100
|
# end
|
109
101
|
def parallelize_setup(&block)
|
110
|
-
ActiveSupport::Testing::Parallelization.after_fork_hook
|
111
|
-
yield worker
|
112
|
-
end
|
102
|
+
ActiveSupport::Testing::Parallelization.after_fork_hook(&block)
|
113
103
|
end
|
114
104
|
|
115
105
|
# Clean up hook for parallel testing. This can be used to drop databases
|
@@ -126,9 +116,7 @@ module ActiveSupport
|
|
126
116
|
# end
|
127
117
|
# end
|
128
118
|
def parallelize_teardown(&block)
|
129
|
-
ActiveSupport::Testing::Parallelization.run_cleanup_hook
|
130
|
-
yield worker
|
131
|
-
end
|
119
|
+
ActiveSupport::Testing::Parallelization.run_cleanup_hook(&block)
|
132
120
|
end
|
133
121
|
end
|
134
122
|
|
@@ -99,7 +99,7 @@ module ActiveSupport
|
|
99
99
|
}
|
100
100
|
before = exps.map(&:call)
|
101
101
|
|
102
|
-
retval =
|
102
|
+
retval = _assert_nothing_raised_or_warn("assert_difference", &block)
|
103
103
|
|
104
104
|
expressions.zip(exps, before) do |(code, diff), exp, before_value|
|
105
105
|
error = "#{code.inspect} didn't change by #{diff}"
|
@@ -176,7 +176,7 @@ module ActiveSupport
|
|
176
176
|
exp = expression.respond_to?(:call) ? expression : -> { eval(expression.to_s, block.binding) }
|
177
177
|
|
178
178
|
before = exp.call
|
179
|
-
retval =
|
179
|
+
retval = _assert_nothing_raised_or_warn("assert_changes", &block)
|
180
180
|
|
181
181
|
unless from == UNTRACKED
|
182
182
|
error = "Expected change from #{from.inspect}"
|
@@ -207,16 +207,30 @@ module ActiveSupport
|
|
207
207
|
# post :create, params: { status: { ok: true } }
|
208
208
|
# end
|
209
209
|
#
|
210
|
+
# Provide the optional keyword argument :from to specify the expected
|
211
|
+
# initial value.
|
212
|
+
#
|
213
|
+
# assert_no_changes -> { Status.all_good? }, from: true do
|
214
|
+
# post :create, params: { status: { ok: true } }
|
215
|
+
# end
|
216
|
+
#
|
210
217
|
# An error message can be specified.
|
211
218
|
#
|
212
219
|
# assert_no_changes -> { Status.all_good? }, 'Expected the status to be good' do
|
213
220
|
# post :create, params: { status: { ok: false } }
|
214
221
|
# end
|
215
|
-
def assert_no_changes(expression, message = nil, &block)
|
222
|
+
def assert_no_changes(expression, message = nil, from: UNTRACKED, &block)
|
216
223
|
exp = expression.respond_to?(:call) ? expression : -> { eval(expression.to_s, block.binding) }
|
217
224
|
|
218
225
|
before = exp.call
|
219
|
-
retval =
|
226
|
+
retval = _assert_nothing_raised_or_warn("assert_no_changes", &block)
|
227
|
+
|
228
|
+
unless from == UNTRACKED
|
229
|
+
error = "Expected initial value of #{from.inspect}"
|
230
|
+
error = "#{message}.\n#{error}" if message
|
231
|
+
assert from === before, error
|
232
|
+
end
|
233
|
+
|
220
234
|
after = exp.call
|
221
235
|
|
222
236
|
error = "#{expression.inspect} changed"
|
@@ -230,6 +244,22 @@ module ActiveSupport
|
|
230
244
|
|
231
245
|
retval
|
232
246
|
end
|
247
|
+
|
248
|
+
private
|
249
|
+
def _assert_nothing_raised_or_warn(assertion, &block)
|
250
|
+
assert_nothing_raised(&block)
|
251
|
+
rescue Minitest::UnexpectedError => e
|
252
|
+
if tagged_logger && tagged_logger.warn?
|
253
|
+
warning = <<~MSG
|
254
|
+
#{self.class} - #{name}: #{e.error.class} raised.
|
255
|
+
If you expected this exception, use `assert_raises` as near to the code that raises as possible.
|
256
|
+
Other block based assertions (e.g. `#{assertion}`) can be used, as long as `assert_raises` is inside their block.
|
257
|
+
MSG
|
258
|
+
tagged_logger.warn warning
|
259
|
+
end
|
260
|
+
|
261
|
+
raise
|
262
|
+
end
|
233
263
|
end
|
234
264
|
end
|
235
265
|
end
|
@@ -4,7 +4,7 @@ require "active_support/deprecation"
|
|
4
4
|
|
5
5
|
module ActiveSupport
|
6
6
|
module Testing
|
7
|
-
module Deprecation
|
7
|
+
module Deprecation # :nodoc:
|
8
8
|
def assert_deprecated(match = nil, deprecator = nil, &block)
|
9
9
|
result, warnings = collect_deprecations(deprecator, &block)
|
10
10
|
assert !warnings.empty?, "Expected a deprecation warning within the block but received none"
|
@@ -6,10 +6,10 @@ module ActiveSupport
|
|
6
6
|
module Testing
|
7
7
|
module MethodCallAssertions # :nodoc:
|
8
8
|
private
|
9
|
-
def assert_called(object, method_name, message = nil, times: 1, returns: nil)
|
9
|
+
def assert_called(object, method_name, message = nil, times: 1, returns: nil, &block)
|
10
10
|
times_called = 0
|
11
11
|
|
12
|
-
object.stub(method_name, proc { times_called += 1; returns })
|
12
|
+
object.stub(method_name, proc { times_called += 1; returns }, &block)
|
13
13
|
|
14
14
|
error = "Expected #{method_name} to be called #{times} times, " \
|
15
15
|
"but was called #{times_called} times"
|
@@ -17,16 +17,16 @@ module ActiveSupport
|
|
17
17
|
assert_equal times, times_called, error
|
18
18
|
end
|
19
19
|
|
20
|
-
def assert_called_with(object, method_name, args, returns: nil)
|
20
|
+
def assert_called_with(object, method_name, args, returns: nil, &block)
|
21
21
|
mock = Minitest::Mock.new
|
22
22
|
|
23
|
-
if args.all?
|
23
|
+
if args.all?(Array)
|
24
24
|
args.each { |arg| mock.expect(:call, returns, arg) }
|
25
25
|
else
|
26
26
|
mock.expect(:call, returns, args)
|
27
27
|
end
|
28
28
|
|
29
|
-
object.stub(method_name, mock)
|
29
|
+
object.stub(method_name, mock, &block)
|
30
30
|
|
31
31
|
mock.verify
|
32
32
|
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveSupport
|
4
|
+
module Testing
|
5
|
+
class ParallelizeExecutor # :nodoc:
|
6
|
+
attr_reader :size, :parallelize_with, :threshold
|
7
|
+
|
8
|
+
def initialize(size:, with:, threshold: ActiveSupport.test_parallelization_threshold)
|
9
|
+
@size = size
|
10
|
+
@parallelize_with = with
|
11
|
+
@threshold = threshold
|
12
|
+
end
|
13
|
+
|
14
|
+
def start
|
15
|
+
parallelize if should_parallelize?
|
16
|
+
show_execution_info
|
17
|
+
|
18
|
+
parallel_executor.start if parallelized?
|
19
|
+
end
|
20
|
+
|
21
|
+
def <<(work)
|
22
|
+
parallel_executor << work if parallelized?
|
23
|
+
end
|
24
|
+
|
25
|
+
def shutdown
|
26
|
+
parallel_executor.shutdown if parallelized?
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
def parallel_executor
|
31
|
+
@parallel_executor ||= build_parallel_executor
|
32
|
+
end
|
33
|
+
|
34
|
+
def build_parallel_executor
|
35
|
+
case parallelize_with
|
36
|
+
when :processes
|
37
|
+
Testing::Parallelization.new(size)
|
38
|
+
when :threads
|
39
|
+
ActiveSupport::TestCase.lock_threads = false if defined?(ActiveSupport::TestCase.lock_threads)
|
40
|
+
Minitest::Parallel::Executor.new(size)
|
41
|
+
else
|
42
|
+
raise ArgumentError, "#{parallelize_with} is not a supported parallelization executor."
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def parallelize
|
47
|
+
@parallelized = true
|
48
|
+
Minitest::Test.parallelize_me!
|
49
|
+
end
|
50
|
+
|
51
|
+
def parallelized?
|
52
|
+
@parallelized if defined?(@parallelized)
|
53
|
+
end
|
54
|
+
|
55
|
+
def should_parallelize?
|
56
|
+
ENV["PARALLEL_WORKERS"] || tests_count > threshold
|
57
|
+
end
|
58
|
+
|
59
|
+
def tests_count
|
60
|
+
@tests_count ||= Minitest::Runnable.runnables.sum { |runnable| runnable.runnable_methods.size }
|
61
|
+
end
|
62
|
+
|
63
|
+
def show_execution_info
|
64
|
+
puts execution_info
|
65
|
+
end
|
66
|
+
|
67
|
+
def execution_info
|
68
|
+
if parallelized?
|
69
|
+
"Running #{tests_count} tests in parallel using #{parallel_executor.size} #{parallelize_with}"
|
70
|
+
else
|
71
|
+
"Running #{tests_count} tests in a single process (parallelization threshold is #{threshold})"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module ActiveSupport
|
4
4
|
module Testing
|
5
|
-
module Stream
|
5
|
+
module Stream # :nodoc:
|
6
6
|
private
|
7
7
|
def silence_stream(stream)
|
8
8
|
old_stream = stream.dup
|
@@ -14,11 +14,9 @@ module ActiveSupport
|
|
14
14
|
old_stream.close
|
15
15
|
end
|
16
16
|
|
17
|
-
def quietly
|
17
|
+
def quietly(&block)
|
18
18
|
silence_stream(STDOUT) do
|
19
|
-
silence_stream(STDERR)
|
20
|
-
yield
|
21
|
-
end
|
19
|
+
silence_stream(STDERR, &block)
|
22
20
|
end
|
23
21
|
end
|
24
22
|
|
@@ -4,7 +4,7 @@ module ActiveSupport
|
|
4
4
|
module Testing
|
5
5
|
# Logs a "PostsControllerTest: test name" heading before each test to
|
6
6
|
# make test.log easier to search and follow along with.
|
7
|
-
module TaggedLogging
|
7
|
+
module TaggedLogging # :nodoc:
|
8
8
|
attr_writer :tagged_logger
|
9
9
|
|
10
10
|
def before_setup
|
@@ -126,7 +126,7 @@ module ActiveSupport
|
|
126
126
|
# end
|
127
127
|
# Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
|
128
128
|
def travel_to(date_or_time)
|
129
|
-
if block_given? &&
|
129
|
+
if block_given? && in_block
|
130
130
|
travel_to_nested_block_call = <<~MSG
|
131
131
|
|
132
132
|
Calling `travel_to` with a block, when we have previously already made a call to `travel_to`, can lead to confusing time stubbing.
|
@@ -156,19 +156,28 @@ module ActiveSupport
|
|
156
156
|
|
157
157
|
if date_or_time.is_a?(Date) && !date_or_time.is_a?(DateTime)
|
158
158
|
now = date_or_time.midnight.to_time
|
159
|
+
elsif date_or_time.is_a?(String)
|
160
|
+
now = Time.zone.parse(date_or_time)
|
159
161
|
else
|
160
162
|
now = date_or_time.to_time.change(usec: 0)
|
161
163
|
end
|
162
164
|
|
165
|
+
stubbed_time = Time.now if simple_stubs.stubbing(Time, :now)
|
163
166
|
simple_stubs.stub_object(Time, :now) { at(now.to_i) }
|
164
167
|
simple_stubs.stub_object(Date, :today) { jd(now.to_date.jd) }
|
165
168
|
simple_stubs.stub_object(DateTime, :now) { jd(now.to_date.jd, now.hour, now.min, now.sec, Rational(now.utc_offset, 86400)) }
|
166
169
|
|
167
170
|
if block_given?
|
168
171
|
begin
|
172
|
+
self.in_block = true
|
169
173
|
yield
|
170
174
|
ensure
|
171
|
-
|
175
|
+
if stubbed_time
|
176
|
+
travel_to stubbed_time
|
177
|
+
else
|
178
|
+
travel_back
|
179
|
+
end
|
180
|
+
self.in_block = false
|
172
181
|
end
|
173
182
|
end
|
174
183
|
end
|
@@ -230,6 +239,8 @@ module ActiveSupport
|
|
230
239
|
def simple_stubs
|
231
240
|
@simple_stubs ||= SimpleStubs.new
|
232
241
|
end
|
242
|
+
|
243
|
+
attr_accessor :in_block
|
233
244
|
end
|
234
245
|
end
|
235
246
|
end
|