activesupport 8.0.2.1 → 8.1.0.beta1
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 +247 -136
- data/README.rdoc +1 -1
- data/lib/active_support/backtrace_cleaner.rb +71 -0
- data/lib/active_support/broadcast_logger.rb +46 -59
- data/lib/active_support/cache/mem_cache_store.rb +25 -27
- data/lib/active_support/cache/redis_cache_store.rb +36 -30
- data/lib/active_support/cache/strategy/local_cache.rb +16 -7
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +7 -7
- data/lib/active_support/cache.rb +70 -6
- data/lib/active_support/configurable.rb +28 -0
- data/lib/active_support/continuous_integration.rb +145 -0
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +1 -1
- data/lib/active_support/core_ext/date_time/conversions.rb +4 -2
- data/lib/active_support/core_ext/enumerable.rb +16 -4
- data/lib/active_support/core_ext/erb/util.rb +3 -3
- data/lib/active_support/core_ext/object/json.rb +8 -1
- 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/range/overlap.rb +3 -3
- data/lib/active_support/core_ext/range/sole.rb +17 -0
- data/lib/active_support/core_ext/range.rb +1 -1
- 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/current_attributes/test_helper.rb +2 -2
- data/lib/active_support/current_attributes.rb +26 -16
- data/lib/active_support/deprecation/reporting.rb +4 -2
- data/lib/active_support/deprecation.rb +1 -1
- data/lib/active_support/editor.rb +70 -0
- data/lib/active_support/error_reporter.rb +50 -6
- data/lib/active_support/event_reporter/test_helper.rb +32 -0
- data/lib/active_support/event_reporter.rb +570 -0
- data/lib/active_support/evented_file_update_checker.rb +5 -1
- data/lib/active_support/execution_context.rb +64 -7
- data/lib/active_support/file_update_checker.rb +7 -5
- 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 +47 -24
- data/lib/active_support/i18n_railtie.rb +1 -2
- data/lib/active_support/inflector/inflections.rb +31 -15
- data/lib/active_support/inflector/transliterate.rb +6 -8
- data/lib/active_support/isolated_execution_state.rb +7 -13
- data/lib/active_support/json/decoding.rb +6 -4
- data/lib/active_support/json/encoding.rb +103 -14
- data/lib/active_support/lazy_load_hooks.rb +1 -1
- data/lib/active_support/log_subscriber.rb +2 -0
- data/lib/active_support/logger_thread_safe_level.rb +6 -3
- data/lib/active_support/message_encryptors.rb +52 -0
- data/lib/active_support/message_pack/extensions.rb +5 -0
- data/lib/active_support/message_verifiers.rb +52 -0
- data/lib/active_support/messages/rotation_coordinator.rb +9 -0
- data/lib/active_support/messages/rotator.rb +5 -0
- data/lib/active_support/multibyte/chars.rb +8 -1
- data/lib/active_support/multibyte.rb +4 -0
- data/lib/active_support/railtie.rb +26 -12
- data/lib/active_support/syntax_error_proxy.rb +3 -0
- data/lib/active_support/test_case.rb +61 -6
- data/lib/active_support/testing/assertions.rb +34 -6
- data/lib/active_support/testing/error_reporter_assertions.rb +18 -1
- data/lib/active_support/testing/event_reporter_assertions.rb +217 -0
- data/lib/active_support/testing/notification_assertions.rb +92 -0
- data/lib/active_support/testing/parallelization/worker.rb +2 -0
- data/lib/active_support/testing/parallelization.rb +13 -0
- data/lib/active_support/testing/tests_without_assertions.rb +1 -1
- data/lib/active_support/testing/time_helpers.rb +7 -3
- data/lib/active_support/time_with_zone.rb +19 -5
- data/lib/active_support/values/time_zone.rb +8 -1
- data/lib/active_support/xml_mini.rb +1 -2
- data/lib/active_support.rb +11 -0
- metadata +11 -5
- data/lib/active_support/core_ext/range/each.rb +0 -24
@@ -26,6 +26,9 @@ module ActiveSupport
|
|
26
26
|
# as the first rotation and <tt>transitional = true</tt>. Then, after all
|
27
27
|
# servers have been updated, perform a second rolling deploy with
|
28
28
|
# <tt>transitional = false</tt>.
|
29
|
+
#
|
30
|
+
#--
|
31
|
+
# Implemented by ActiveSupport::Messages::RotationCoordinator#transitional
|
29
32
|
|
30
33
|
##
|
31
34
|
# :singleton-method: new
|
@@ -43,6 +46,9 @@ module ActiveSupport
|
|
43
46
|
# end
|
44
47
|
#
|
45
48
|
# encryptors.rotate(base: "...")
|
49
|
+
#
|
50
|
+
#--
|
51
|
+
# Implemented by ActiveSupport::Messages::RotationCoordinator#initialize
|
46
52
|
|
47
53
|
##
|
48
54
|
# :method: []
|
@@ -51,12 +57,18 @@ module ActiveSupport
|
|
51
57
|
# Returns a MessageEncryptor configured with a secret derived from the
|
52
58
|
# given +salt+, and options from #rotate. MessageEncryptor instances will
|
53
59
|
# be memoized, so the same +salt+ will return the same instance.
|
60
|
+
#
|
61
|
+
#--
|
62
|
+
# Implemented by ActiveSupport::Messages::RotationCoordinator#[]
|
54
63
|
|
55
64
|
##
|
56
65
|
# :method: []=
|
57
66
|
# :call-seq: []=(salt, encryptor)
|
58
67
|
#
|
59
68
|
# Overrides a MessageEncryptor instance associated with a given +salt+.
|
69
|
+
#
|
70
|
+
#--
|
71
|
+
# Implemented by ActiveSupport::Messages::RotationCoordinator#[]=
|
60
72
|
|
61
73
|
##
|
62
74
|
# :method: rotate
|
@@ -106,18 +118,55 @@ module ActiveSupport
|
|
106
118
|
#
|
107
119
|
# # Uses `serializer: Marshal, url_safe: false`.
|
108
120
|
# encryptors[:baz]
|
121
|
+
#
|
122
|
+
#--
|
123
|
+
# Implemented by ActiveSupport::Messages::RotationCoordinator#rotate
|
124
|
+
|
125
|
+
##
|
126
|
+
# :method: prepend
|
127
|
+
# :call-seq:
|
128
|
+
# prepend(**options)
|
129
|
+
# prepend(&block)
|
130
|
+
#
|
131
|
+
# Just like #rotate, but prepends the given options or block to the list of
|
132
|
+
# option sets.
|
133
|
+
#
|
134
|
+
# This can be useful when you have an already-configured +MessageEncryptors+
|
135
|
+
# instance, but you want to override the way messages are encrypted.
|
136
|
+
#
|
137
|
+
# module ThirdParty
|
138
|
+
# ENCRYPTORS = ActiveSupport::MessageEncryptors.new { ... }.
|
139
|
+
# rotate(serializer: Marshal, url_safe: true).
|
140
|
+
# rotate(serializer: Marshal, url_safe: false)
|
141
|
+
# end
|
142
|
+
#
|
143
|
+
# ThirdParty.ENCRYPTORS.prepend(serializer: JSON, url_safe: true)
|
144
|
+
#
|
145
|
+
# # Uses `serializer: JSON, url_safe: true`.
|
146
|
+
# # Falls back to `serializer: Marshal, url_safe: true` or
|
147
|
+
# # `serializer: Marshal, url_safe: false`.
|
148
|
+
# ThirdParty.ENCRYPTORS[:foo]
|
149
|
+
#
|
150
|
+
#--
|
151
|
+
# Implemented by ActiveSupport::Messages::RotationCoordinator#prepend
|
109
152
|
|
110
153
|
##
|
111
154
|
# :method: rotate_defaults
|
112
155
|
# :call-seq: rotate_defaults
|
113
156
|
#
|
114
157
|
# Invokes #rotate with the default options.
|
158
|
+
#
|
159
|
+
#--
|
160
|
+
# Implemented by ActiveSupport::Messages::RotationCoordinator#rotate_defaults
|
115
161
|
|
116
162
|
##
|
117
163
|
# :method: clear_rotations
|
118
164
|
# :call-seq: clear_rotations
|
119
165
|
#
|
120
166
|
# Clears the list of option sets.
|
167
|
+
#
|
168
|
+
#--
|
169
|
+
# Implemented by ActiveSupport::Messages::RotationCoordinator#clear_rotations
|
121
170
|
|
122
171
|
##
|
123
172
|
# :method: on_rotation
|
@@ -129,6 +178,9 @@ module ActiveSupport
|
|
129
178
|
# For example, this callback could log each time it is called, and thus
|
130
179
|
# indicate whether old option sets are still in use or can be removed from
|
131
180
|
# rotation.
|
181
|
+
#
|
182
|
+
#--
|
183
|
+
# Implemented by ActiveSupport::Messages::RotationCoordinator#on_rotation
|
132
184
|
|
133
185
|
##
|
134
186
|
private
|
@@ -7,6 +7,7 @@ require "pathname"
|
|
7
7
|
require "uri/generic"
|
8
8
|
require "msgpack/bigint"
|
9
9
|
require "active_support/hash_with_indifferent_access"
|
10
|
+
require "active_support/core_ext/string/output_safety"
|
10
11
|
require "active_support/time"
|
11
12
|
|
12
13
|
module ActiveSupport
|
@@ -102,6 +103,10 @@ module ActiveSupport
|
|
102
103
|
packer: method(:write_hash_with_indifferent_access),
|
103
104
|
unpacker: method(:read_hash_with_indifferent_access),
|
104
105
|
recursive: true
|
106
|
+
|
107
|
+
registry.register_type 18, ActiveSupport::SafeBuffer,
|
108
|
+
packer: :to_s,
|
109
|
+
unpacker: :new
|
105
110
|
end
|
106
111
|
|
107
112
|
def install_unregistered_type_error(registry)
|
@@ -26,6 +26,9 @@ module ActiveSupport
|
|
26
26
|
# as the first rotation and <tt>transitional = true</tt>. Then, after all
|
27
27
|
# servers have been updated, perform a second rolling deploy with
|
28
28
|
# <tt>transitional = false</tt>.
|
29
|
+
#
|
30
|
+
#--
|
31
|
+
# Implemented by ActiveSupport::Messages::RotationCoordinator#transitional
|
29
32
|
|
30
33
|
##
|
31
34
|
# :singleton-method: new
|
@@ -42,6 +45,9 @@ module ActiveSupport
|
|
42
45
|
# end
|
43
46
|
#
|
44
47
|
# verifiers.rotate(base: "...")
|
48
|
+
#
|
49
|
+
#--
|
50
|
+
# Implemented by ActiveSupport::Messages::RotationCoordinator#initialize
|
45
51
|
|
46
52
|
##
|
47
53
|
# :method: []
|
@@ -50,12 +56,18 @@ module ActiveSupport
|
|
50
56
|
# Returns a MessageVerifier configured with a secret derived from the
|
51
57
|
# given +salt+, and options from #rotate. MessageVerifier instances will
|
52
58
|
# be memoized, so the same +salt+ will return the same instance.
|
59
|
+
#
|
60
|
+
#--
|
61
|
+
# Implemented by ActiveSupport::Messages::RotationCoordinator#[]
|
53
62
|
|
54
63
|
##
|
55
64
|
# :method: []=
|
56
65
|
# :call-seq: []=(salt, verifier)
|
57
66
|
#
|
58
67
|
# Overrides a MessageVerifier instance associated with a given +salt+.
|
68
|
+
#
|
69
|
+
#--
|
70
|
+
# Implemented by ActiveSupport::Messages::RotationCoordinator#[]=
|
59
71
|
|
60
72
|
##
|
61
73
|
# :method: rotate
|
@@ -104,18 +116,55 @@ module ActiveSupport
|
|
104
116
|
#
|
105
117
|
# # Uses `serializer: Marshal, url_safe: false`.
|
106
118
|
# verifiers[:baz]
|
119
|
+
#
|
120
|
+
#--
|
121
|
+
# Implemented by ActiveSupport::Messages::RotationCoordinator#rotate
|
122
|
+
|
123
|
+
##
|
124
|
+
# :method: prepend
|
125
|
+
# :call-seq:
|
126
|
+
# prepend(**options)
|
127
|
+
# prepend(&block)
|
128
|
+
#
|
129
|
+
# Just like #rotate, but prepends the given options or block to the list of
|
130
|
+
# option sets.
|
131
|
+
#
|
132
|
+
# This can be useful when you have an already-configured +MessageVerifiers+
|
133
|
+
# instance, but you want to override the way messages are signed.
|
134
|
+
#
|
135
|
+
# module ThirdParty
|
136
|
+
# VERIFIERS = ActiveSupport::MessageVerifiers.new { ... }.
|
137
|
+
# rotate(serializer: Marshal, url_safe: true).
|
138
|
+
# rotate(serializer: Marshal, url_safe: false)
|
139
|
+
# end
|
140
|
+
#
|
141
|
+
# ThirdParty.VERIFIERS.prepend(serializer: JSON, url_safe: true)
|
142
|
+
#
|
143
|
+
# # Uses `serializer: JSON, url_safe: true`.
|
144
|
+
# # Falls back to `serializer: Marshal, url_safe: true` or
|
145
|
+
# # `serializer: Marshal, url_safe: false`.
|
146
|
+
# ThirdParty.VERIFIERS[:foo]
|
147
|
+
#
|
148
|
+
#--
|
149
|
+
# Implemented by ActiveSupport::Messages::RotationCoordinator#prepend
|
107
150
|
|
108
151
|
##
|
109
152
|
# :method: rotate_defaults
|
110
153
|
# :call-seq: rotate_defaults
|
111
154
|
#
|
112
155
|
# Invokes #rotate with the default options.
|
156
|
+
#
|
157
|
+
#--
|
158
|
+
# Implemented by ActiveSupport::Messages::RotationCoordinator#rotate_defaults
|
113
159
|
|
114
160
|
##
|
115
161
|
# :method: clear_rotations
|
116
162
|
# :call-seq: clear_rotations
|
117
163
|
#
|
118
164
|
# Clears the list of option sets.
|
165
|
+
#
|
166
|
+
#--
|
167
|
+
# Implemented by ActiveSupport::Messages::RotationCoordinator#clear_rotations
|
119
168
|
|
120
169
|
##
|
121
170
|
# :method: on_rotation
|
@@ -127,6 +176,9 @@ module ActiveSupport
|
|
127
176
|
# For example, this callback could log each time it is called, and thus
|
128
177
|
# indicate whether old option sets are still in use or can be removed from
|
129
178
|
# rotation.
|
179
|
+
#
|
180
|
+
#--
|
181
|
+
# Implemented by ActiveSupport::Messages::RotationCoordinator#on_rotation
|
130
182
|
|
131
183
|
##
|
132
184
|
private
|
@@ -32,6 +32,15 @@ module ActiveSupport
|
|
32
32
|
self
|
33
33
|
end
|
34
34
|
|
35
|
+
def prepend(**options, &block)
|
36
|
+
raise ArgumentError, "Options cannot be specified when using a block" if block && !options.empty?
|
37
|
+
changing_configuration!
|
38
|
+
|
39
|
+
@rotate_options.unshift(block || options)
|
40
|
+
|
41
|
+
self
|
42
|
+
end
|
43
|
+
|
35
44
|
def rotate_defaults
|
36
45
|
rotate()
|
37
46
|
end
|
@@ -53,7 +53,14 @@ module ActiveSupport # :nodoc:
|
|
53
53
|
delegate :<=>, :=~, :match?, :acts_like_string?, to: :wrapped_string
|
54
54
|
|
55
55
|
# Creates a new Chars instance by wrapping _string_.
|
56
|
-
def initialize(string)
|
56
|
+
def initialize(string, deprecation: true)
|
57
|
+
if deprecation
|
58
|
+
ActiveSupport.deprecator.warn(
|
59
|
+
"ActiveSupport::Multibyte::Chars is deprecated and will be removed in Rails 8.2. " \
|
60
|
+
"Use normal string methods instead."
|
61
|
+
)
|
62
|
+
end
|
63
|
+
|
57
64
|
@wrapped_string = string
|
58
65
|
if string.encoding != Encoding::UTF_8
|
59
66
|
@wrapped_string = @wrapped_string.dup
|
@@ -12,6 +12,10 @@ module ActiveSupport # :nodoc:
|
|
12
12
|
#
|
13
13
|
# ActiveSupport::Multibyte.proxy_class = CharsForUTF32
|
14
14
|
def self.proxy_class=(klass)
|
15
|
+
ActiveSupport.deprecator.warn(
|
16
|
+
"ActiveSupport::Multibyte.proxy_class= is deprecated and will be removed in Rails 8.2. " \
|
17
|
+
"Use normal string methods instead."
|
18
|
+
)
|
15
19
|
@proxy_class = klass
|
16
20
|
end
|
17
21
|
|
@@ -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
|
@@ -97,9 +113,7 @@ module ActiveSupport
|
|
97
113
|
end
|
98
114
|
|
99
115
|
initializer "active_support.to_time_preserves_timezone" do |app|
|
100
|
-
config.
|
101
|
-
ActiveSupport.to_time_preserves_timezone = app.config.active_support.to_time_preserves_timezone
|
102
|
-
end
|
116
|
+
ActiveSupport.to_time_preserves_timezone = app.config.active_support.to_time_preserves_timezone
|
103
117
|
end
|
104
118
|
|
105
119
|
# Sets the default week start
|
@@ -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
|
@@ -51,8 +68,8 @@ module ActiveSupport
|
|
51
68
|
# is forked. For each process a new database will be created suffixed
|
52
69
|
# with the worker number.
|
53
70
|
#
|
54
|
-
# test-
|
55
|
-
# test-
|
71
|
+
# test-database_0
|
72
|
+
# test-database_1
|
56
73
|
#
|
57
74
|
# If <tt>ENV["PARALLEL_WORKERS"]</tt> is set the workers argument will be ignored
|
58
75
|
# and the environment variable will be used instead. This is useful for CI
|
@@ -78,14 +95,45 @@ module ActiveSupport
|
|
78
95
|
# Because parallelization presents an overhead, it is only enabled when the
|
79
96
|
# number of tests to run is above the +threshold+ param. The default value is
|
80
97
|
# 50, and it's configurable via +config.active_support.test_parallelization_threshold+.
|
81
|
-
|
82
|
-
|
83
|
-
|
98
|
+
#
|
99
|
+
# If you want to skip Rails default creation of one database per process in favor of
|
100
|
+
# writing your own implementation, you can set +parallelize_databases+, or configure it
|
101
|
+
# via +config.active_support.parallelize_test_databases+.
|
102
|
+
#
|
103
|
+
# parallelize(workers: :number_of_processors, parallelize_databases: false)
|
104
|
+
#
|
105
|
+
# Note that your test suite may deadlock if you attempt to use only one database
|
106
|
+
# with multiple processes.
|
107
|
+
def parallelize(workers: :number_of_processors, with: :processes, threshold: ActiveSupport.test_parallelization_threshold, parallelize_databases: ActiveSupport.parallelize_test_databases)
|
108
|
+
case
|
109
|
+
when ENV["PARALLEL_WORKERS"]
|
110
|
+
workers = ENV["PARALLEL_WORKERS"].to_i
|
111
|
+
when workers == :number_of_processors
|
112
|
+
workers = (Concurrent.available_processor_count || Concurrent.processor_count).floor
|
113
|
+
end
|
114
|
+
|
115
|
+
if with == :processes
|
116
|
+
ActiveSupport.parallelize_test_databases = parallelize_databases
|
117
|
+
end
|
84
118
|
|
85
119
|
Minitest.parallel_executor = ActiveSupport::Testing::ParallelizeExecutor.new(size: workers, with: with, threshold: threshold)
|
86
120
|
end
|
87
121
|
|
88
|
-
#
|
122
|
+
# Before fork hook for parallel testing. This can be used to run anything
|
123
|
+
# before the processes are forked.
|
124
|
+
#
|
125
|
+
# In your +test_helper.rb+ add the following:
|
126
|
+
#
|
127
|
+
# class ActiveSupport::TestCase
|
128
|
+
# parallelize_before_fork do
|
129
|
+
# # run this before fork
|
130
|
+
# end
|
131
|
+
# end
|
132
|
+
def parallelize_before_fork(&block)
|
133
|
+
ActiveSupport::Testing::Parallelization.before_fork_hook(&block)
|
134
|
+
end
|
135
|
+
|
136
|
+
# Setup hook for parallel testing. This can be used if you have multiple
|
89
137
|
# databases or any behavior that needs to be run after the process is forked
|
90
138
|
# but before the tests run.
|
91
139
|
#
|
@@ -141,11 +189,18 @@ module ActiveSupport
|
|
141
189
|
|
142
190
|
alias_method :method_name, :name
|
143
191
|
|
192
|
+
# Returns the current parallel worker ID if tests are running in parallel
|
193
|
+
def parallel_worker_id
|
194
|
+
self.class.parallel_worker_id
|
195
|
+
end
|
196
|
+
|
144
197
|
include ActiveSupport::Testing::TaggedLogging
|
145
198
|
prepend ActiveSupport::Testing::SetupAndTeardown
|
146
199
|
prepend ActiveSupport::Testing::TestsWithoutAssertions
|
147
200
|
include ActiveSupport::Testing::Assertions
|
148
201
|
include ActiveSupport::Testing::ErrorReporterAssertions
|
202
|
+
include ActiveSupport::Testing::EventReporterAssertions
|
203
|
+
include ActiveSupport::Testing::NotificationAssertions
|
149
204
|
include ActiveSupport::Testing::Deprecation
|
150
205
|
include ActiveSupport::Testing::ConstantStubbing
|
151
206
|
include ActiveSupport::Testing::TimeHelpers
|
@@ -71,19 +71,19 @@ module ActiveSupport
|
|
71
71
|
# post :delete, params: { id: ... }
|
72
72
|
# end
|
73
73
|
#
|
74
|
-
# An array of expressions can
|
74
|
+
# An array of expressions can be passed in and evaluated.
|
75
75
|
#
|
76
76
|
# assert_difference [ 'Article.count', 'Post.count' ], 2 do
|
77
77
|
# post :create, params: { article: {...} }
|
78
78
|
# end
|
79
79
|
#
|
80
|
-
# A hash of expressions/numeric differences can
|
80
|
+
# A hash of expressions/numeric differences can be passed in and evaluated.
|
81
81
|
#
|
82
|
-
# assert_difference
|
82
|
+
# assert_difference({ 'Article.count' => 1, 'Notification.count' => 2 }) do
|
83
83
|
# post :create, params: { article: {...} }
|
84
84
|
# end
|
85
85
|
#
|
86
|
-
# A lambda or a
|
86
|
+
# A lambda, a list of lambdas or a hash of lambdas/numeric differences can be passed in and evaluated:
|
87
87
|
#
|
88
88
|
# assert_difference ->{ Article.count }, 2 do
|
89
89
|
# post :create, params: { article: {...} }
|
@@ -93,6 +93,10 @@ module ActiveSupport
|
|
93
93
|
# post :create, params: { article: {...} }
|
94
94
|
# end
|
95
95
|
#
|
96
|
+
# assert_difference ->{ Article.count } => 1, ->{ Notification.count } => 2 do
|
97
|
+
# post :create, params: { article: {...} }
|
98
|
+
# end
|
99
|
+
#
|
96
100
|
# An error message can be specified.
|
97
101
|
#
|
98
102
|
# assert_difference 'Article.count', -1, 'An Article should be destroyed' do
|
@@ -181,12 +185,24 @@ module ActiveSupport
|
|
181
185
|
#
|
182
186
|
# The keyword arguments +:from+ and +:to+ can be given to specify the
|
183
187
|
# expected initial value and the expected value after the block was
|
184
|
-
# executed.
|
188
|
+
# executed. The comparison is done using case equality (===), which means
|
189
|
+
# you can specify patterns or classes:
|
185
190
|
#
|
191
|
+
# # Exact value match
|
186
192
|
# assert_changes :@object, from: nil, to: :foo do
|
187
193
|
# @object = :foo
|
188
194
|
# end
|
189
195
|
#
|
196
|
+
# # Case equality
|
197
|
+
# assert_changes -> { user.token }, to: /\w{32}/ do
|
198
|
+
# user.generate_token
|
199
|
+
# end
|
200
|
+
#
|
201
|
+
# # Type check
|
202
|
+
# assert_changes -> { current_error }, from: nil, to: RuntimeError do
|
203
|
+
# raise "Oops"
|
204
|
+
# end
|
205
|
+
#
|
190
206
|
# An error message can be specified.
|
191
207
|
#
|
192
208
|
# assert_changes -> { Status.all_good? }, 'Expected the status to be bad' do
|
@@ -238,12 +254,24 @@ module ActiveSupport
|
|
238
254
|
# end
|
239
255
|
#
|
240
256
|
# Provide the optional keyword argument +:from+ to specify the expected
|
241
|
-
# initial value.
|
257
|
+
# initial value. The comparison is done using case equality (===), which means
|
258
|
+
# you can specify patterns or classes:
|
242
259
|
#
|
260
|
+
# # Exact value match
|
243
261
|
# assert_no_changes -> { Status.all_good? }, from: true do
|
244
262
|
# post :create, params: { status: { ok: true } }
|
245
263
|
# end
|
246
264
|
#
|
265
|
+
# # Case equality
|
266
|
+
# assert_no_changes -> { user.token }, from: /\w{32}/ do
|
267
|
+
# user.touch
|
268
|
+
# end
|
269
|
+
#
|
270
|
+
# # Type check
|
271
|
+
# assert_no_changes -> { current_error }, from: RuntimeError do
|
272
|
+
# retry_operation
|
273
|
+
# end
|
274
|
+
#
|
247
275
|
# An error message can be specified.
|
248
276
|
#
|
249
277
|
# assert_no_changes -> { Status.all_good? }, 'Expected the status to be good' do
|
@@ -44,7 +44,7 @@ module ActiveSupport
|
|
44
44
|
ActiveSupport.error_reporter.subscribe(self)
|
45
45
|
@subscribed = true
|
46
46
|
else
|
47
|
-
|
47
|
+
flunk("No error reporter is configured")
|
48
48
|
end
|
49
49
|
end
|
50
50
|
end
|
@@ -102,6 +102,23 @@ module ActiveSupport
|
|
102
102
|
assert(false, message)
|
103
103
|
end
|
104
104
|
end
|
105
|
+
|
106
|
+
# Captures reported errors from within the block that match the given
|
107
|
+
# error class.
|
108
|
+
#
|
109
|
+
# reports = capture_error_reports(IOError) do
|
110
|
+
# Rails.error.report(IOError.new("Oops"))
|
111
|
+
# Rails.error.report(IOError.new("Oh no"))
|
112
|
+
# Rails.error.report(StandardError.new)
|
113
|
+
# end
|
114
|
+
#
|
115
|
+
# assert_equal 2, reports.size
|
116
|
+
# assert_equal "Oops", reports.first.error.message
|
117
|
+
# assert_equal "Oh no", reports.last.error.message
|
118
|
+
def capture_error_reports(error_class = StandardError, &block)
|
119
|
+
reports = ErrorCollector.record(&block)
|
120
|
+
reports.select { |r| error_class === r.error }
|
121
|
+
end
|
105
122
|
end
|
106
123
|
end
|
107
124
|
end
|