activesupport 7.0.8 → 7.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +142 -428
- data/MIT-LICENSE +1 -1
- data/README.rdoc +4 -4
- data/lib/active_support/actionable_error.rb +3 -1
- data/lib/active_support/array_inquirer.rb +3 -1
- data/lib/active_support/backtrace_cleaner.rb +39 -7
- data/lib/active_support/benchmarkable.rb +1 -0
- 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 +49 -17
- data/lib/active_support/cache/mem_cache_store.rb +94 -128
- data/lib/active_support/cache/memory_store.rb +80 -25
- data/lib/active_support/cache/null_store.rb +6 -0
- data/lib/active_support/cache/redis_cache_store.rb +165 -152
- data/lib/active_support/cache/serializer_with_fallback.rb +152 -0
- data/lib/active_support/cache/strategy/local_cache.rb +29 -14
- data/lib/active_support/cache.rb +363 -291
- data/lib/active_support/callbacks.rb +118 -134
- data/lib/active_support/code_generator.rb +15 -10
- data/lib/active_support/concern.rb +4 -2
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +42 -3
- data/lib/active_support/concurrency/null_lock.rb +13 -0
- data/lib/active_support/configurable.rb +10 -0
- data/lib/active_support/core_ext/array/conversions.rb +1 -2
- data/lib/active_support/core_ext/array.rb +0 -1
- data/lib/active_support/core_ext/class/subclasses.rb +17 -34
- data/lib/active_support/core_ext/date/blank.rb +4 -0
- data/lib/active_support/core_ext/date/conversions.rb +1 -2
- data/lib/active_support/core_ext/date.rb +0 -1
- data/lib/active_support/core_ext/date_and_time/calculations.rb +10 -0
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +28 -1
- data/lib/active_support/core_ext/date_time/blank.rb +4 -0
- data/lib/active_support/core_ext/date_time/conversions.rb +2 -2
- data/lib/active_support/core_ext/date_time.rb +0 -1
- data/lib/active_support/core_ext/digest/uuid.rb +7 -10
- data/lib/active_support/core_ext/enumerable.rb +3 -75
- data/lib/active_support/core_ext/erb/util.rb +201 -0
- data/lib/active_support/core_ext/hash/conversions.rb +1 -1
- data/lib/active_support/core_ext/hash/deep_merge.rb +22 -14
- data/lib/active_support/core_ext/hash/keys.rb +4 -4
- data/lib/active_support/core_ext/module/attr_internal.rb +17 -6
- data/lib/active_support/core_ext/module/attribute_accessors.rb +6 -0
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +34 -16
- data/lib/active_support/core_ext/module/concerning.rb +6 -6
- data/lib/active_support/core_ext/module/delegation.rb +20 -119
- data/lib/active_support/core_ext/module/deprecation.rb +12 -12
- data/lib/active_support/core_ext/module/introspection.rb +0 -1
- data/lib/active_support/core_ext/numeric/bytes.rb +9 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +5 -3
- data/lib/active_support/core_ext/numeric.rb +0 -1
- data/lib/active_support/core_ext/object/blank.rb +45 -1
- data/lib/active_support/core_ext/object/deep_dup.rb +16 -0
- data/lib/active_support/core_ext/object/duplicable.rb +24 -15
- data/lib/active_support/core_ext/object/inclusion.rb +13 -5
- data/lib/active_support/core_ext/object/instance_variables.rb +4 -2
- data/lib/active_support/core_ext/object/json.rb +17 -7
- data/lib/active_support/core_ext/object/with.rb +46 -0
- data/lib/active_support/core_ext/object/with_options.rb +4 -4
- data/lib/active_support/core_ext/object.rb +1 -0
- data/lib/active_support/core_ext/pathname/blank.rb +20 -0
- data/lib/active_support/core_ext/pathname/existence.rb +2 -0
- data/lib/active_support/core_ext/pathname.rb +1 -0
- data/lib/active_support/core_ext/range/conversions.rb +28 -7
- 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 +1 -5
- data/lib/active_support/core_ext/string/conversions.rb +1 -1
- 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 +16 -5
- data/lib/active_support/core_ext/string/multibyte.rb +1 -1
- data/lib/active_support/core_ext/string/output_safety.rb +34 -177
- data/lib/active_support/core_ext/thread/backtrace/location.rb +12 -0
- data/lib/active_support/core_ext/time/calculations.rb +36 -30
- data/lib/active_support/core_ext/time/compatibility.rb +16 -0
- data/lib/active_support/core_ext/time/conversions.rb +1 -3
- data/lib/active_support/core_ext/time/zones.rb +4 -4
- data/lib/active_support/core_ext/time.rb +0 -1
- data/lib/active_support/core_ext.rb +0 -1
- data/lib/active_support/current_attributes.rb +53 -46
- data/lib/active_support/deep_mergeable.rb +53 -0
- data/lib/active_support/delegation.rb +202 -0
- data/lib/active_support/dependencies/autoload.rb +9 -16
- data/lib/active_support/deprecation/behaviors.rb +65 -42
- data/lib/active_support/deprecation/constant_accessor.rb +47 -25
- data/lib/active_support/deprecation/deprecators.rb +104 -0
- data/lib/active_support/deprecation/disallowed.rb +3 -5
- data/lib/active_support/deprecation/method_wrappers.rb +6 -23
- data/lib/active_support/deprecation/proxy_wrappers.rb +34 -22
- data/lib/active_support/deprecation/reporting.rb +49 -27
- data/lib/active_support/deprecation.rb +39 -9
- data/lib/active_support/deprecator.rb +7 -0
- data/lib/active_support/descendants_tracker.rb +66 -172
- data/lib/active_support/duration/iso8601_parser.rb +2 -2
- data/lib/active_support/duration/iso8601_serializer.rb +1 -4
- data/lib/active_support/duration.rb +13 -7
- data/lib/active_support/encrypted_configuration.rb +30 -9
- data/lib/active_support/encrypted_file.rb +9 -4
- data/lib/active_support/environment_inquirer.rb +22 -2
- data/lib/active_support/error_reporter/test_helper.rb +15 -0
- data/lib/active_support/error_reporter.rb +160 -36
- data/lib/active_support/evented_file_update_checker.rb +0 -1
- data/lib/active_support/execution_wrapper.rb +4 -5
- data/lib/active_support/file_update_checker.rb +5 -3
- data/lib/active_support/fork_tracker.rb +4 -32
- data/lib/active_support/gem_version.rb +3 -3
- data/lib/active_support/gzip.rb +2 -0
- data/lib/active_support/hash_with_indifferent_access.rb +41 -25
- data/lib/active_support/html_safe_translation.rb +19 -6
- data/lib/active_support/i18n.rb +1 -1
- data/lib/active_support/i18n_railtie.rb +20 -13
- data/lib/active_support/inflector/inflections.rb +2 -0
- data/lib/active_support/inflector/methods.rb +23 -11
- data/lib/active_support/inflector/transliterate.rb +3 -1
- data/lib/active_support/isolated_execution_state.rb +26 -22
- data/lib/active_support/json/decoding.rb +2 -1
- data/lib/active_support/json/encoding.rb +25 -43
- data/lib/active_support/key_generator.rb +9 -1
- data/lib/active_support/lazy_load_hooks.rb +6 -4
- data/lib/active_support/locale/en.yml +2 -0
- data/lib/active_support/log_subscriber.rb +74 -34
- data/lib/active_support/logger.rb +22 -60
- data/lib/active_support/logger_thread_safe_level.rb +10 -32
- data/lib/active_support/message_encryptor.rb +197 -53
- 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 +305 -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 +220 -89
- 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 +111 -45
- 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 +4 -2
- data/lib/active_support/multibyte/unicode.rb +9 -37
- data/lib/active_support/notifications/fanout.rb +248 -87
- data/lib/active_support/notifications/instrumenter.rb +93 -25
- data/lib/active_support/notifications.rb +29 -28
- data/lib/active_support/number_helper/number_converter.rb +16 -7
- data/lib/active_support/number_helper/number_to_currency_converter.rb +6 -6
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +3 -3
- data/lib/active_support/number_helper/number_to_phone_converter.rb +1 -0
- data/lib/active_support/number_helper.rb +379 -318
- data/lib/active_support/option_merger.rb +2 -2
- data/lib/active_support/ordered_hash.rb +3 -3
- data/lib/active_support/ordered_options.rb +67 -15
- data/lib/active_support/parameter_filter.rb +84 -69
- data/lib/active_support/proxy_object.rb +8 -3
- data/lib/active_support/railtie.rb +25 -20
- data/lib/active_support/reloader.rb +12 -4
- data/lib/active_support/rescuable.rb +2 -0
- data/lib/active_support/secure_compare_rotator.rb +16 -9
- data/lib/active_support/string_inquirer.rb +4 -2
- data/lib/active_support/subscriber.rb +10 -27
- data/lib/active_support/syntax_error_proxy.rb +60 -0
- data/lib/active_support/tagged_logging.rb +64 -25
- data/lib/active_support/test_case.rb +156 -7
- data/lib/active_support/testing/assertions.rb +28 -12
- data/lib/active_support/testing/autorun.rb +0 -2
- data/lib/active_support/testing/constant_stubbing.rb +54 -0
- data/lib/active_support/testing/deprecation.rb +20 -27
- data/lib/active_support/testing/error_reporter_assertions.rb +107 -0
- data/lib/active_support/testing/isolation.rb +21 -9
- data/lib/active_support/testing/method_call_assertions.rb +7 -8
- data/lib/active_support/testing/parallelization/server.rb +3 -0
- data/lib/active_support/testing/parallelize_executor.rb +8 -3
- data/lib/active_support/testing/setup_and_teardown.rb +2 -0
- data/lib/active_support/testing/stream.rb +1 -1
- data/lib/active_support/testing/strict_warnings.rb +43 -0
- data/lib/active_support/testing/tests_without_assertions.rb +19 -0
- data/lib/active_support/testing/time_helpers.rb +38 -16
- data/lib/active_support/time_with_zone.rb +12 -18
- data/lib/active_support/values/time_zone.rb +25 -14
- data/lib/active_support/version.rb +1 -1
- data/lib/active_support/xml_mini/jdom.rb +3 -10
- data/lib/active_support/xml_mini/nokogiri.rb +1 -1
- 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 +12 -3
- data/lib/active_support.rb +15 -3
- metadata +145 -24
- data/lib/active_support/core_ext/array/deprecated_conversions.rb +0 -25
- data/lib/active_support/core_ext/date/deprecated_conversions.rb +0 -40
- data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +0 -36
- data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +0 -60
- data/lib/active_support/core_ext/range/deprecated_conversions.rb +0 -36
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +0 -5
- data/lib/active_support/core_ext/range/overlaps.rb +0 -10
- data/lib/active_support/core_ext/time/deprecated_conversions.rb +0 -73
- data/lib/active_support/core_ext/uri.rb +0 -5
- data/lib/active_support/deprecation/instance_delegator.rb +0 -38
- data/lib/active_support/per_thread_registry.rb +0 -65
- data/lib/active_support/ruby_features.rb +0 -7
@@ -0,0 +1,107 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveSupport
|
4
|
+
module Testing
|
5
|
+
module ErrorReporterAssertions
|
6
|
+
module ErrorCollector # :nodoc:
|
7
|
+
@subscribed = false
|
8
|
+
@mutex = Mutex.new
|
9
|
+
|
10
|
+
Report = Struct.new(:error, :handled, :severity, :context, :source, keyword_init: true)
|
11
|
+
class Report
|
12
|
+
alias_method :handled?, :handled
|
13
|
+
end
|
14
|
+
|
15
|
+
class << self
|
16
|
+
def record
|
17
|
+
subscribe
|
18
|
+
recorders = ActiveSupport::IsolatedExecutionState[:active_support_error_reporter_assertions] ||= []
|
19
|
+
reports = []
|
20
|
+
recorders << reports
|
21
|
+
begin
|
22
|
+
yield
|
23
|
+
reports
|
24
|
+
ensure
|
25
|
+
recorders.delete_if { |r| reports.equal?(r) }
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def report(error, **kwargs)
|
30
|
+
report = Report.new(error: error, **kwargs)
|
31
|
+
ActiveSupport::IsolatedExecutionState[:active_support_error_reporter_assertions]&.each do |reports|
|
32
|
+
reports << report
|
33
|
+
end
|
34
|
+
true
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
def subscribe
|
39
|
+
return if @subscribed
|
40
|
+
@mutex.synchronize do
|
41
|
+
return if @subscribed
|
42
|
+
|
43
|
+
if ActiveSupport.error_reporter
|
44
|
+
ActiveSupport.error_reporter.subscribe(self)
|
45
|
+
@subscribed = true
|
46
|
+
else
|
47
|
+
raise Minitest::Assertion, "No error reporter is configured"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Assertion that the block should not cause an exception to be reported
|
55
|
+
# to +Rails.error+.
|
56
|
+
#
|
57
|
+
# Passes if evaluated code in the yielded block reports no exception.
|
58
|
+
#
|
59
|
+
# assert_no_error_reported do
|
60
|
+
# perform_service(param: 'no_exception')
|
61
|
+
# end
|
62
|
+
def assert_no_error_reported(&block)
|
63
|
+
reports = ErrorCollector.record do
|
64
|
+
_assert_nothing_raised_or_warn("assert_no_error_reported", &block)
|
65
|
+
end
|
66
|
+
assert_predicate(reports, :empty?)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Assertion that the block should cause at least one exception to be reported
|
70
|
+
# to +Rails.error+.
|
71
|
+
#
|
72
|
+
# Passes if the evaluated code in the yielded block reports a matching exception.
|
73
|
+
#
|
74
|
+
# assert_error_reported(IOError) do
|
75
|
+
# Rails.error.report(IOError.new("Oops"))
|
76
|
+
# end
|
77
|
+
#
|
78
|
+
# To test further details about the reported exception, you can use the return
|
79
|
+
# value.
|
80
|
+
#
|
81
|
+
# report = assert_error_reported(IOError) do
|
82
|
+
# # ...
|
83
|
+
# end
|
84
|
+
# assert_equal "Oops", report.error.message
|
85
|
+
# assert_equal "admin", report.context[:section]
|
86
|
+
# assert_equal :warning, report.severity
|
87
|
+
# assert_predicate report, :handled?
|
88
|
+
def assert_error_reported(error_class = StandardError, &block)
|
89
|
+
reports = ErrorCollector.record do
|
90
|
+
_assert_nothing_raised_or_warn("assert_error_reported", &block)
|
91
|
+
end
|
92
|
+
|
93
|
+
if reports.empty?
|
94
|
+
assert(false, "Expected a #{error_class.name} to be reported, but there were no errors reported.")
|
95
|
+
elsif (report = reports.find { |r| error_class === r.error })
|
96
|
+
self.assertions += 1
|
97
|
+
report
|
98
|
+
else
|
99
|
+
message = "Expected a #{error_class.name} to be reported, but none of the " \
|
100
|
+
"#{reports.size} reported errors matched: \n" \
|
101
|
+
"#{reports.map { |r| r.error.class.name }.join("\n ")}"
|
102
|
+
assert(false, message)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -1,13 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "active_support/testing/parallelize_executor"
|
4
|
+
|
3
5
|
module ActiveSupport
|
4
6
|
module Testing
|
5
7
|
module Isolation
|
6
8
|
require "thread"
|
7
9
|
|
10
|
+
SubprocessCrashed = Class.new(StandardError)
|
11
|
+
|
8
12
|
def self.included(klass) # :nodoc:
|
9
13
|
klass.class_eval do
|
10
|
-
parallelize_me!
|
14
|
+
parallelize_me! unless Minitest.parallel_executor.is_a?(ActiveSupport::Testing::ParallelizeExecutor)
|
11
15
|
end
|
12
16
|
end
|
13
17
|
|
@@ -16,10 +20,17 @@ module ActiveSupport
|
|
16
20
|
end
|
17
21
|
|
18
22
|
def run
|
19
|
-
serialized = run_in_isolation do
|
23
|
+
status, serialized = run_in_isolation do
|
20
24
|
super
|
21
25
|
end
|
22
26
|
|
27
|
+
unless status&.success?
|
28
|
+
error = SubprocessCrashed.new("Subprocess exited with an error: #{status.inspect}\noutput: #{serialized.inspect}")
|
29
|
+
error.set_backtrace(caller)
|
30
|
+
self.failures << Minitest::UnexpectedError.new(error)
|
31
|
+
return defined?(Minitest::Result) ? Minitest::Result.from(self) : dup
|
32
|
+
end
|
33
|
+
|
23
34
|
Marshal.load(serialized)
|
24
35
|
end
|
25
36
|
|
@@ -50,13 +61,13 @@ module ActiveSupport
|
|
50
61
|
end
|
51
62
|
|
52
63
|
write.puts [result].pack("m")
|
53
|
-
exit!
|
64
|
+
exit!(0)
|
54
65
|
end
|
55
66
|
|
56
67
|
write.close
|
57
68
|
result = read.read
|
58
|
-
Process.wait2(pid)
|
59
|
-
result.unpack1("m")
|
69
|
+
_, status = Process.wait2(pid)
|
70
|
+
return status, result.unpack1("m")
|
60
71
|
end
|
61
72
|
end
|
62
73
|
end
|
@@ -64,7 +75,7 @@ module ActiveSupport
|
|
64
75
|
module Subprocess
|
65
76
|
ORIG_ARGV = ARGV.dup unless defined?(ORIG_ARGV)
|
66
77
|
|
67
|
-
# Complicated H4X to get this working in
|
78
|
+
# Complicated H4X to get this working in Windows / JRuby with
|
68
79
|
# no forking.
|
69
80
|
def run_in_isolation(&blk)
|
70
81
|
require "tempfile"
|
@@ -75,7 +86,7 @@ module ActiveSupport
|
|
75
86
|
File.open(ENV["ISOLATION_OUTPUT"], "w") do |file|
|
76
87
|
file.puts [Marshal.dump(test_result)].pack("m")
|
77
88
|
end
|
78
|
-
exit!
|
89
|
+
exit!(0)
|
79
90
|
else
|
80
91
|
Tempfile.open("isolation") do |tmpfile|
|
81
92
|
env = {
|
@@ -93,13 +104,14 @@ module ActiveSupport
|
|
93
104
|
|
94
105
|
child = IO.popen([env, Gem.ruby, *load_path_args, $0, *ORIG_ARGV, test_opts])
|
95
106
|
|
107
|
+
status = nil
|
96
108
|
begin
|
97
|
-
Process.
|
109
|
+
_, status = Process.wait2(child.pid)
|
98
110
|
rescue Errno::ECHILD # The child process may exit before we wait
|
99
111
|
nil
|
100
112
|
end
|
101
113
|
|
102
|
-
return tmpfile.read.unpack1("m")
|
114
|
+
return status, tmpfile.read.unpack1("m")
|
103
115
|
end
|
104
116
|
end
|
105
117
|
end
|
@@ -17,24 +17,23 @@ 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:
|
20
|
+
def assert_called_with(object, method_name, args, returns: false, **kwargs, &block)
|
21
21
|
mock = Minitest::Mock.new
|
22
|
-
|
23
|
-
if args.all?(Array)
|
24
|
-
args.each { |arg| mock.expect(:call, returns, arg) }
|
25
|
-
else
|
26
|
-
mock.expect(:call, returns, args)
|
27
|
-
end
|
22
|
+
expect_called_with(mock, args, returns: returns, **kwargs)
|
28
23
|
|
29
24
|
object.stub(method_name, mock, &block)
|
30
25
|
|
31
|
-
mock
|
26
|
+
assert_mock(mock)
|
32
27
|
end
|
33
28
|
|
34
29
|
def assert_not_called(object, method_name, message = nil, &block)
|
35
30
|
assert_called(object, method_name, message, times: 0, &block)
|
36
31
|
end
|
37
32
|
|
33
|
+
def expect_called_with(mock, args, returns: false, **kwargs)
|
34
|
+
mock.expect(:call, returns, args, **kwargs)
|
35
|
+
end
|
36
|
+
|
38
37
|
def assert_called_on_instance_of(klass, method_name, message = nil, times: 1, returns: nil)
|
39
38
|
times_called = 0
|
40
39
|
klass.define_method("stubbed_#{method_name}") do |*|
|
@@ -6,6 +6,8 @@ require "drb/unix" unless Gem.win_platform?
|
|
6
6
|
module ActiveSupport
|
7
7
|
module Testing
|
8
8
|
class Parallelization # :nodoc:
|
9
|
+
PrerecordResultClass = Struct.new(:name)
|
10
|
+
|
9
11
|
class Server
|
10
12
|
include DRb::DRbUndumped
|
11
13
|
|
@@ -21,6 +23,7 @@ module ActiveSupport
|
|
21
23
|
@in_flight.delete([result.klass, result.name])
|
22
24
|
|
23
25
|
reporter.synchronize do
|
26
|
+
reporter.prerecord(PrerecordResultClass.new(result.klass), result.name)
|
24
27
|
reporter.record(result)
|
25
28
|
end
|
26
29
|
end
|
@@ -9,6 +9,7 @@ module ActiveSupport
|
|
9
9
|
@size = size
|
10
10
|
@parallelize_with = with
|
11
11
|
@threshold = threshold
|
12
|
+
@parallelized = false
|
12
13
|
end
|
13
14
|
|
14
15
|
def start
|
@@ -49,11 +50,15 @@ module ActiveSupport
|
|
49
50
|
end
|
50
51
|
|
51
52
|
def parallelized?
|
52
|
-
@parallelized
|
53
|
+
@parallelized
|
53
54
|
end
|
54
55
|
|
55
56
|
def should_parallelize?
|
56
|
-
ENV["PARALLEL_WORKERS"] || tests_count > threshold
|
57
|
+
(ENV["PARALLEL_WORKERS"] || tests_count > threshold) && many_workers?
|
58
|
+
end
|
59
|
+
|
60
|
+
def many_workers?
|
61
|
+
size > 1
|
57
62
|
end
|
58
63
|
|
59
64
|
def tests_count
|
@@ -67,7 +72,7 @@ module ActiveSupport
|
|
67
72
|
def execution_info
|
68
73
|
if parallelized?
|
69
74
|
"Running #{tests_count} tests in parallel using #{parallel_executor.size} #{parallelize_with}"
|
70
|
-
|
75
|
+
elsif many_workers?
|
71
76
|
"Running #{tests_count} tests in a single process (parallelization threshold is #{threshold})"
|
72
77
|
end
|
73
78
|
end
|
@@ -23,7 +23,7 @@ module ActiveSupport
|
|
23
23
|
def capture(stream)
|
24
24
|
stream = stream.to_s
|
25
25
|
captured_stream = Tempfile.new(stream)
|
26
|
-
stream_io = eval("$#{stream}")
|
26
|
+
stream_io = eval("$#{stream}", binding, __FILE__, __LINE__)
|
27
27
|
origin_stream = stream_io.dup
|
28
28
|
stream_io.reopen(captured_stream)
|
29
29
|
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
$VERBOSE = true
|
4
|
+
Warning[:deprecated] = true
|
5
|
+
|
6
|
+
module ActiveSupport
|
7
|
+
module RaiseWarnings # :nodoc:
|
8
|
+
class WarningError < StandardError; end
|
9
|
+
|
10
|
+
PROJECT_ROOT = File.expand_path("../../../../", __dir__)
|
11
|
+
ALLOWED_WARNINGS = Regexp.union(
|
12
|
+
/circular require considered harmful.*delayed_job/, # Bug in delayed job.
|
13
|
+
|
14
|
+
# Expected non-verbose warning emitted by Rails.
|
15
|
+
/Ignoring .*\.yml because it has expired/,
|
16
|
+
/Failed to validate the schema cache because/,
|
17
|
+
|
18
|
+
# TODO: We need to decide what to do with this.
|
19
|
+
/Status code :unprocessable_entity is deprecated/
|
20
|
+
)
|
21
|
+
|
22
|
+
SUPPRESSED_WARNINGS = Regexp.union(
|
23
|
+
# TODO: remove if https://github.com/mikel/mail/pull/1557 or similar fix
|
24
|
+
%r{/lib/mail/parsers/.*statement not reached},
|
25
|
+
%r{/lib/mail/parsers/.*assigned but unused variable - disp_type_s},
|
26
|
+
%r{/lib/mail/parsers/.*assigned but unused variable - testEof}
|
27
|
+
)
|
28
|
+
|
29
|
+
def warn(message, ...)
|
30
|
+
return if SUPPRESSED_WARNINGS.match?(message)
|
31
|
+
|
32
|
+
super
|
33
|
+
|
34
|
+
return unless message.include?(PROJECT_ROOT)
|
35
|
+
return if ALLOWED_WARNINGS.match?(message)
|
36
|
+
return unless ENV["RAILS_STRICT_WARNINGS"] || ENV["BUILDKITE"]
|
37
|
+
|
38
|
+
raise WarningError.new(message)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
Warning.singleton_class.prepend(ActiveSupport::RaiseWarnings)
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveSupport
|
4
|
+
module Testing
|
5
|
+
# Warns when a test case does not perform any assertions.
|
6
|
+
#
|
7
|
+
# This is helpful in detecting broken tests that do not perform intended assertions.
|
8
|
+
module TestsWithoutAssertions # :nodoc:
|
9
|
+
def after_teardown
|
10
|
+
super
|
11
|
+
|
12
|
+
if assertions.zero? && !skipped? && !error?
|
13
|
+
file, line = method(name).source_location
|
14
|
+
warn "Test is missing assertions: `#{name}` #{file}:#{line}"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -2,7 +2,6 @@
|
|
2
2
|
|
3
3
|
require "active_support/core_ext/module/redefine_method"
|
4
4
|
require "active_support/core_ext/time/calculations"
|
5
|
-
require "concurrent/map"
|
6
5
|
|
7
6
|
module ActiveSupport
|
8
7
|
module Testing
|
@@ -11,7 +10,7 @@ module ActiveSupport
|
|
11
10
|
Stub = Struct.new(:object, :method_name, :original_method)
|
12
11
|
|
13
12
|
def initialize
|
14
|
-
@stubs =
|
13
|
+
@stubs = Hash.new { |h, k| h[k] = {} }
|
15
14
|
end
|
16
15
|
|
17
16
|
# Stubs object.method_name with the given block
|
@@ -26,7 +25,7 @@ module ActiveSupport
|
|
26
25
|
unstub_object(stub)
|
27
26
|
end
|
28
27
|
|
29
|
-
new_name = "__simple_stub__#{method_name}"
|
28
|
+
new_name = "__simple_stub__#{method_name}__#{object_id}"
|
30
29
|
|
31
30
|
@stubs[object.object_id][method_name] = Stub.new(object, method_name, new_name)
|
32
31
|
|
@@ -76,6 +75,11 @@ module ActiveSupport
|
|
76
75
|
# stubbing +Time.now+, +Date.today+, and +DateTime.now+. The stubs are automatically removed
|
77
76
|
# at the end of the test.
|
78
77
|
#
|
78
|
+
# Note that the usec for the resulting time will be set to 0 to prevent rounding
|
79
|
+
# errors with external services, like MySQL (which will round instead of floor,
|
80
|
+
# leading to off-by-one-second errors), unless the <tt>with_usec</tt> argument
|
81
|
+
# is set to <tt>true</tt>.
|
82
|
+
#
|
79
83
|
# Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
|
80
84
|
# travel 1.day
|
81
85
|
# Time.current # => Sun, 10 Nov 2013 15:34:49 EST -05:00
|
@@ -90,11 +94,11 @@ module ActiveSupport
|
|
90
94
|
# User.create.created_at # => Sun, 10 Nov 2013 15:34:49 EST -05:00
|
91
95
|
# end
|
92
96
|
# Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
|
93
|
-
def travel(duration, &block)
|
94
|
-
travel_to Time.now + duration, &block
|
97
|
+
def travel(duration, with_usec: false, &block)
|
98
|
+
travel_to Time.now + duration, with_usec: with_usec, &block
|
95
99
|
end
|
96
100
|
|
97
|
-
# Changes current time to the given time by stubbing +Time.now+,
|
101
|
+
# Changes current time to the given time by stubbing +Time.now+, +Time.new+,
|
98
102
|
# +Date.today+, and +DateTime.now+ to return the time or date passed into this method.
|
99
103
|
# The stubs are automatically removed at the end of the test.
|
100
104
|
#
|
@@ -115,7 +119,8 @@ module ActiveSupport
|
|
115
119
|
#
|
116
120
|
# Note that the usec for the time passed will be set to 0 to prevent rounding
|
117
121
|
# errors with external services, like MySQL (which will round instead of floor,
|
118
|
-
# leading to off-by-one-second errors)
|
122
|
+
# leading to off-by-one-second errors), unless the <tt>with_usec</tt> argument
|
123
|
+
# is set to <tt>true</tt>.
|
119
124
|
#
|
120
125
|
# This method also accepts a block, which will return the current time back to its original
|
121
126
|
# state at the end of the block:
|
@@ -125,7 +130,7 @@ module ActiveSupport
|
|
125
130
|
# Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
|
126
131
|
# end
|
127
132
|
# Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
|
128
|
-
def travel_to(date_or_time)
|
133
|
+
def travel_to(date_or_time, with_usec: false)
|
129
134
|
if block_given? && in_block
|
130
135
|
travel_to_nested_block_call = <<~MSG
|
131
136
|
|
@@ -159,13 +164,30 @@ module ActiveSupport
|
|
159
164
|
elsif date_or_time.is_a?(String)
|
160
165
|
now = Time.zone.parse(date_or_time)
|
161
166
|
else
|
162
|
-
now = date_or_time
|
167
|
+
now = date_or_time
|
168
|
+
now = now.to_time unless now.is_a?(Time)
|
169
|
+
now = now.change(usec: 0) unless with_usec
|
170
|
+
end
|
171
|
+
|
172
|
+
# +now+ must be in local system timezone, because +Time.at(now)+
|
173
|
+
# and +now.to_date+ (see stubs below) will use +now+'s timezone too!
|
174
|
+
now = now.getlocal
|
175
|
+
|
176
|
+
stubs = simple_stubs
|
177
|
+
stubbed_time = Time.now if stubs.stubbing(Time, :now)
|
178
|
+
stubs.stub_object(Time, :now) { at(now) }
|
179
|
+
|
180
|
+
stubs.stub_object(Time, :new) do |*args, **options|
|
181
|
+
if args.empty? && options.empty?
|
182
|
+
at(now)
|
183
|
+
else
|
184
|
+
stub = stubs.stubbing(Time, :new)
|
185
|
+
Time.send(stub.original_method, *args, **options)
|
186
|
+
end
|
163
187
|
end
|
164
188
|
|
165
|
-
|
166
|
-
|
167
|
-
simple_stubs.stub_object(Date, :today) { jd(now.to_date.jd) }
|
168
|
-
simple_stubs.stub_object(DateTime, :now) { jd(now.to_date.jd, now.hour, now.min, now.sec, Rational(now.utc_offset, 86400)) }
|
189
|
+
stubs.stub_object(Date, :today) { jd(now.to_date.jd) }
|
190
|
+
stubs.stub_object(DateTime, :now) { jd(now.to_date.jd, now.hour, now.min, now.sec, Rational(now.utc_offset, 86400)) }
|
169
191
|
|
170
192
|
if block_given?
|
171
193
|
begin
|
@@ -215,7 +237,7 @@ module ActiveSupport
|
|
215
237
|
end
|
216
238
|
alias_method :unfreeze_time, :travel_back
|
217
239
|
|
218
|
-
# Calls +travel_to+ with +Time.now+.
|
240
|
+
# Calls +travel_to+ with +Time.now+. Forwards optional <tt>with_usec</tt> argument.
|
219
241
|
#
|
220
242
|
# Time.current # => Sun, 09 Jul 2017 15:34:49 EST -05:00
|
221
243
|
# freeze_time
|
@@ -231,8 +253,8 @@ module ActiveSupport
|
|
231
253
|
# User.create.created_at # => Sun, 09 Jul 2017 15:34:49 EST -05:00
|
232
254
|
# end
|
233
255
|
# Time.current # => Sun, 09 Jul 2017 15:34:50 EST -05:00
|
234
|
-
def freeze_time(&block)
|
235
|
-
travel_to Time.now, &block
|
256
|
+
def freeze_time(with_usec: false, &block)
|
257
|
+
travel_to Time.now, with_usec: with_usec, &block
|
236
258
|
end
|
237
259
|
|
238
260
|
private
|
@@ -8,6 +8,8 @@ require "active_support/core_ext/object/acts_like"
|
|
8
8
|
require "active_support/core_ext/date_and_time/compatibility"
|
9
9
|
|
10
10
|
module ActiveSupport
|
11
|
+
# = Active Support \Time With Zone
|
12
|
+
#
|
11
13
|
# A Time-like class that can represent a time in any time zone. Necessary
|
12
14
|
# because standard Ruby Time instances are limited to UTC and the
|
13
15
|
# system's <tt>ENV['TZ']</tt> zone.
|
@@ -40,18 +42,6 @@ module ActiveSupport
|
|
40
42
|
# t.is_a?(Time) # => true
|
41
43
|
# t.is_a?(ActiveSupport::TimeWithZone) # => true
|
42
44
|
class TimeWithZone
|
43
|
-
# Report class name as 'Time' to thwart type checking.
|
44
|
-
def self.name
|
45
|
-
ActiveSupport::Deprecation.warn(<<~EOM)
|
46
|
-
ActiveSupport::TimeWithZone.name has been deprecated and
|
47
|
-
from Rails 7.1 will use the default Ruby implementation.
|
48
|
-
You can set `config.active_support.remove_deprecated_time_with_zone_name = true`
|
49
|
-
to enable the new behavior now.
|
50
|
-
EOM
|
51
|
-
|
52
|
-
"Time"
|
53
|
-
end
|
54
|
-
|
55
45
|
PRECISIONS = Hash.new { |h, n| h[n] = "%FT%T.%#{n}N" }
|
56
46
|
PRECISIONS[0] = "%FT%T"
|
57
47
|
|
@@ -78,7 +68,7 @@ module ActiveSupport
|
|
78
68
|
alias_method :getutc, :utc
|
79
69
|
alias_method :gmtime, :utc
|
80
70
|
|
81
|
-
# Returns the underlying
|
71
|
+
# Returns the underlying +TZInfo::TimezonePeriod+.
|
82
72
|
def period
|
83
73
|
@period ||= time_zone.period_for_utc(@utc)
|
84
74
|
end
|
@@ -95,7 +85,7 @@ module ActiveSupport
|
|
95
85
|
end
|
96
86
|
alias_method :getlocal, :localtime
|
97
87
|
|
98
|
-
# Returns true if the current time is within Daylight Savings Time for the
|
88
|
+
# Returns true if the current time is within Daylight Savings \Time for the
|
99
89
|
# specified time zone.
|
100
90
|
#
|
101
91
|
# Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
|
@@ -218,7 +208,7 @@ module ActiveSupport
|
|
218
208
|
# Accepts an optional <tt>format</tt>:
|
219
209
|
# * <tt>:default</tt> - default value, mimics Ruby Time#to_s format.
|
220
210
|
# * <tt>:db</tt> - format outputs time in UTC :db time. See Time#to_fs(:db).
|
221
|
-
# * Any key in
|
211
|
+
# * Any key in +Time::DATE_FORMATS+ can be used. See active_support/core_ext/time/conversions.rb.
|
222
212
|
def to_fs(format = :default)
|
223
213
|
if format == :db
|
224
214
|
utc.to_fs(format)
|
@@ -342,7 +332,7 @@ module ActiveSupport
|
|
342
332
|
#
|
343
333
|
def -(other)
|
344
334
|
if other.acts_like?(:time)
|
345
|
-
|
335
|
+
getutc - other.getutc
|
346
336
|
elsif duration_of_variable_length?(other)
|
347
337
|
method_missing(:-, other)
|
348
338
|
else
|
@@ -385,8 +375,8 @@ module ActiveSupport
|
|
385
375
|
#
|
386
376
|
# t = Time.zone.now # => Fri, 14 Apr 2017 11:45:15.116992711 EST -05:00
|
387
377
|
# t.change(year: 2020) # => Tue, 14 Apr 2020 11:45:15.116992711 EST -05:00
|
388
|
-
# t.change(hour: 12) # => Fri, 14 Apr 2017 12:00:00.
|
389
|
-
# t.change(min: 30) # => Fri, 14 Apr 2017 11:30:00.
|
378
|
+
# t.change(hour: 12) # => Fri, 14 Apr 2017 12:00:00.000000000 EST -05:00
|
379
|
+
# t.change(min: 30) # => Fri, 14 Apr 2017 11:30:00.000000000 EST -05:00
|
390
380
|
# t.change(offset: "-10:00") # => Fri, 14 Apr 2017 11:45:15.116992711 HST -10:00
|
391
381
|
# t.change(zone: "Hawaii") # => Fri, 14 Apr 2017 11:45:15.116992711 HST -10:00
|
392
382
|
def change(options)
|
@@ -516,6 +506,10 @@ module ActiveSupport
|
|
516
506
|
false
|
517
507
|
end
|
518
508
|
|
509
|
+
def present? # :nodoc:
|
510
|
+
true
|
511
|
+
end
|
512
|
+
|
519
513
|
def freeze
|
520
514
|
# preload instance variables before freezing
|
521
515
|
period; utc; time; to_datetime; to_time
|