activesupport 4.2.11.1 → 6.1.7.3
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 +464 -391
- data/MIT-LICENSE +2 -2
- data/README.rdoc +7 -7
- data/lib/active_support/actionable_error.rb +48 -0
- data/lib/active_support/all.rb +5 -3
- data/lib/active_support/array_inquirer.rb +50 -0
- data/lib/active_support/backtrace_cleaner.rb +34 -6
- data/lib/active_support/benchmarkable.rb +6 -4
- data/lib/active_support/builder.rb +3 -1
- data/lib/active_support/cache/file_store.rb +61 -55
- data/lib/active_support/cache/mem_cache_store.rb +115 -100
- data/lib/active_support/cache/memory_store.rb +81 -58
- data/lib/active_support/cache/null_store.rb +11 -7
- data/lib/active_support/cache/redis_cache_store.rb +493 -0
- data/lib/active_support/cache/strategy/local_cache.rb +90 -42
- data/lib/active_support/cache/strategy/local_cache_middleware.rb +10 -9
- data/lib/active_support/cache.rb +386 -225
- data/lib/active_support/callbacks.rb +661 -594
- data/lib/active_support/concern.rb +80 -7
- data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +35 -0
- data/lib/active_support/concurrency/share_lock.rb +226 -0
- data/lib/active_support/configurable.rb +16 -17
- data/lib/active_support/configuration_file.rb +51 -0
- data/lib/active_support/core_ext/array/access.rb +41 -1
- data/lib/active_support/core_ext/array/conversions.rb +24 -20
- data/lib/active_support/core_ext/array/extract.rb +21 -0
- data/lib/active_support/core_ext/array/extract_options.rb +2 -0
- data/lib/active_support/core_ext/array/grouping.rb +11 -18
- data/lib/active_support/core_ext/array/inquiry.rb +19 -0
- data/lib/active_support/core_ext/array/wrap.rb +7 -4
- data/lib/active_support/core_ext/array.rb +9 -6
- data/lib/active_support/core_ext/benchmark.rb +5 -3
- data/lib/active_support/core_ext/big_decimal/conversions.rb +10 -12
- data/lib/active_support/core_ext/big_decimal.rb +3 -1
- data/lib/active_support/core_ext/class/attribute.rb +52 -48
- data/lib/active_support/core_ext/class/attribute_accessors.rb +3 -1
- data/lib/active_support/core_ext/class/subclasses.rb +18 -25
- data/lib/active_support/core_ext/class.rb +4 -3
- data/lib/active_support/core_ext/date/acts_like.rb +3 -1
- data/lib/active_support/core_ext/date/blank.rb +14 -0
- data/lib/active_support/core_ext/date/calculations.rb +17 -14
- data/lib/active_support/core_ext/date/conversions.rb +27 -24
- data/lib/active_support/core_ext/date/zones.rb +4 -2
- data/lib/active_support/core_ext/date.rb +6 -4
- data/lib/active_support/core_ext/date_and_time/calculations.rb +167 -65
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +19 -3
- data/lib/active_support/core_ext/date_and_time/zones.rb +12 -13
- data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
- data/lib/active_support/core_ext/date_time/blank.rb +14 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +37 -19
- data/lib/active_support/core_ext/date_time/compatibility.rb +8 -6
- data/lib/active_support/core_ext/date_time/conversions.rb +16 -13
- data/lib/active_support/core_ext/date_time.rb +7 -5
- data/lib/active_support/core_ext/digest/uuid.rb +8 -5
- data/lib/active_support/core_ext/digest.rb +3 -0
- data/lib/active_support/core_ext/enumerable.rb +186 -22
- data/lib/active_support/core_ext/file/atomic.rb +38 -31
- data/lib/active_support/core_ext/file.rb +3 -1
- data/lib/active_support/core_ext/hash/conversions.rb +62 -41
- data/lib/active_support/core_ext/hash/deep_merge.rb +9 -13
- data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
- data/lib/active_support/core_ext/hash/except.rb +13 -10
- data/lib/active_support/core_ext/hash/indifferent_access.rb +4 -3
- data/lib/active_support/core_ext/hash/keys.rb +20 -43
- data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
- data/lib/active_support/core_ext/hash/slice.rb +8 -29
- data/lib/active_support/core_ext/hash.rb +10 -9
- data/lib/active_support/core_ext/integer/inflections.rb +3 -1
- data/lib/active_support/core_ext/integer/multiple.rb +3 -1
- data/lib/active_support/core_ext/integer/time.rb +11 -18
- data/lib/active_support/core_ext/integer.rb +5 -3
- data/lib/active_support/core_ext/kernel/concern.rb +5 -1
- data/lib/active_support/core_ext/kernel/reporting.rb +4 -84
- data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
- data/lib/active_support/core_ext/kernel.rb +5 -5
- data/lib/active_support/core_ext/load_error.rb +3 -22
- data/lib/active_support/core_ext/marshal.rb +10 -8
- data/lib/active_support/core_ext/module/aliasing.rb +6 -44
- data/lib/active_support/core_ext/module/anonymous.rb +12 -1
- data/lib/active_support/core_ext/module/attr_internal.rb +8 -9
- data/lib/active_support/core_ext/module/attribute_accessors.rb +63 -69
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +148 -0
- data/lib/active_support/core_ext/module/concerning.rb +19 -14
- data/lib/active_support/core_ext/module/delegation.rb +164 -51
- data/lib/active_support/core_ext/module/deprecation.rb +4 -2
- data/lib/active_support/core_ext/module/introspection.rb +23 -22
- data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
- data/lib/active_support/core_ext/module/remove_method.rb +8 -3
- data/lib/active_support/core_ext/module.rb +13 -11
- data/lib/active_support/core_ext/name_error.rb +51 -4
- data/lib/active_support/core_ext/numeric/bytes.rb +22 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +133 -136
- data/lib/active_support/core_ext/numeric/time.rb +35 -23
- data/lib/active_support/core_ext/numeric.rb +5 -3
- data/lib/active_support/core_ext/object/acts_like.rb +12 -1
- data/lib/active_support/core_ext/object/blank.rb +27 -3
- data/lib/active_support/core_ext/object/conversions.rb +6 -4
- data/lib/active_support/core_ext/object/deep_dup.rb +13 -4
- data/lib/active_support/core_ext/object/duplicable.rb +13 -93
- data/lib/active_support/core_ext/object/inclusion.rb +5 -3
- data/lib/active_support/core_ext/object/instance_variables.rb +3 -1
- data/lib/active_support/core_ext/object/json.rb +63 -21
- data/lib/active_support/core_ext/object/to_param.rb +3 -1
- data/lib/active_support/core_ext/object/to_query.rb +10 -5
- data/lib/active_support/core_ext/object/try.rb +81 -23
- data/lib/active_support/core_ext/object/with_options.rb +16 -3
- data/lib/active_support/core_ext/object.rb +14 -13
- data/lib/active_support/core_ext/range/compare_range.rb +82 -0
- data/lib/active_support/core_ext/range/conversions.rb +37 -15
- data/lib/active_support/core_ext/range/each.rb +18 -17
- data/lib/active_support/core_ext/range/include_time_with_zone.rb +28 -0
- data/lib/active_support/core_ext/range/overlaps.rb +2 -0
- data/lib/active_support/core_ext/range.rb +7 -4
- data/lib/active_support/core_ext/regexp.rb +10 -1
- data/lib/active_support/core_ext/securerandom.rb +45 -0
- data/lib/active_support/core_ext/string/access.rb +9 -18
- data/lib/active_support/core_ext/string/behavior.rb +3 -1
- data/lib/active_support/core_ext/string/conversions.rb +8 -4
- data/lib/active_support/core_ext/string/exclude.rb +2 -0
- data/lib/active_support/core_ext/string/filters.rb +48 -6
- data/lib/active_support/core_ext/string/indent.rb +6 -4
- data/lib/active_support/core_ext/string/inflections.rb +102 -26
- data/lib/active_support/core_ext/string/inquiry.rb +4 -1
- data/lib/active_support/core_ext/string/multibyte.rb +18 -9
- data/lib/active_support/core_ext/string/output_safety.rb +125 -40
- data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -2
- data/lib/active_support/core_ext/string/strip.rb +6 -5
- data/lib/active_support/core_ext/string/zones.rb +4 -2
- data/lib/active_support/core_ext/string.rb +15 -13
- data/lib/active_support/core_ext/symbol/starts_ends_with.rb +14 -0
- data/lib/active_support/core_ext/symbol.rb +3 -0
- data/lib/active_support/core_ext/time/acts_like.rb +3 -1
- data/lib/active_support/core_ext/time/calculations.rb +137 -53
- data/lib/active_support/core_ext/time/compatibility.rb +4 -2
- data/lib/active_support/core_ext/time/conversions.rb +22 -13
- data/lib/active_support/core_ext/time/zones.rb +41 -7
- data/lib/active_support/core_ext/time.rb +7 -6
- data/lib/active_support/core_ext/uri.rb +11 -8
- data/lib/active_support/core_ext.rb +3 -1
- data/lib/active_support/current_attributes/test_helper.rb +13 -0
- data/lib/active_support/current_attributes.rb +210 -0
- data/lib/active_support/dependencies/autoload.rb +2 -0
- data/lib/active_support/dependencies/interlock.rb +57 -0
- data/lib/active_support/dependencies/zeitwerk_integration.rb +120 -0
- data/lib/active_support/dependencies.rb +241 -175
- data/lib/active_support/deprecation/behaviors.rb +58 -12
- data/lib/active_support/deprecation/constant_accessor.rb +52 -0
- data/lib/active_support/deprecation/disallowed.rb +56 -0
- data/lib/active_support/deprecation/instance_delegator.rb +16 -2
- data/lib/active_support/deprecation/method_wrappers.rb +62 -21
- data/lib/active_support/deprecation/proxy_wrappers.rb +81 -30
- data/lib/active_support/deprecation/reporting.rb +81 -18
- data/lib/active_support/deprecation.rb +17 -9
- data/lib/active_support/descendants_tracker.rb +61 -9
- data/lib/active_support/digest.rb +22 -0
- data/lib/active_support/duration/iso8601_parser.rb +123 -0
- data/lib/active_support/duration/iso8601_serializer.rb +59 -0
- data/lib/active_support/duration.rb +364 -39
- data/lib/active_support/encrypted_configuration.rb +45 -0
- data/lib/active_support/encrypted_file.rb +117 -0
- data/lib/active_support/environment_inquirer.rb +20 -0
- data/lib/active_support/evented_file_update_checker.rb +170 -0
- data/lib/active_support/execution_wrapper.rb +132 -0
- data/lib/active_support/executor.rb +8 -0
- data/lib/active_support/file_update_checker.rb +62 -37
- data/lib/active_support/fork_tracker.rb +64 -0
- data/lib/active_support/gem_version.rb +7 -5
- data/lib/active_support/gzip.rb +7 -5
- data/lib/active_support/hash_with_indifferent_access.rb +171 -48
- data/lib/active_support/i18n.rb +9 -6
- data/lib/active_support/i18n_railtie.rb +47 -16
- data/lib/active_support/inflections.rb +13 -11
- data/lib/active_support/inflector/inflections.rb +58 -14
- data/lib/active_support/inflector/methods.rb +186 -169
- data/lib/active_support/inflector/transliterate.rb +83 -33
- data/lib/active_support/inflector.rb +7 -5
- data/lib/active_support/json/decoding.rb +32 -30
- data/lib/active_support/json/encoding.rb +22 -61
- data/lib/active_support/json.rb +4 -2
- data/lib/active_support/key_generator.rb +11 -43
- data/lib/active_support/lazy_load_hooks.rb +53 -20
- data/lib/active_support/locale/en.rb +33 -0
- data/lib/active_support/locale/en.yml +9 -3
- data/lib/active_support/log_subscriber/test_helper.rb +14 -12
- data/lib/active_support/log_subscriber.rb +52 -19
- data/lib/active_support/logger.rb +10 -24
- data/lib/active_support/logger_silence.rb +14 -20
- data/lib/active_support/logger_thread_safe_level.rb +56 -10
- data/lib/active_support/message_encryptor.rb +167 -57
- data/lib/active_support/message_verifier.rb +151 -18
- data/lib/active_support/messages/metadata.rb +80 -0
- data/lib/active_support/messages/rotation_configuration.rb +23 -0
- data/lib/active_support/messages/rotator.rb +57 -0
- data/lib/active_support/multibyte/chars.rb +35 -80
- data/lib/active_support/multibyte/unicode.rb +22 -330
- data/lib/active_support/multibyte.rb +4 -2
- data/lib/active_support/notifications/fanout.rb +125 -23
- data/lib/active_support/notifications/instrumenter.rb +98 -16
- data/lib/active_support/notifications.rb +82 -14
- data/lib/active_support/number_helper/number_converter.rb +17 -16
- data/lib/active_support/number_helper/number_to_currency_converter.rb +9 -14
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +11 -4
- data/lib/active_support/number_helper/number_to_human_converter.rb +14 -11
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +12 -10
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +5 -1
- data/lib/active_support/number_helper/number_to_phone_converter.rb +15 -5
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +29 -57
- data/lib/active_support/number_helper/rounding_helper.rb +50 -0
- data/lib/active_support/number_helper.rb +123 -71
- data/lib/active_support/option_merger.rb +25 -4
- data/lib/active_support/ordered_hash.rb +7 -5
- data/lib/active_support/ordered_options.rb +35 -7
- data/lib/active_support/parameter_filter.rb +133 -0
- data/lib/active_support/per_thread_registry.rb +10 -4
- data/lib/active_support/proxy_object.rb +2 -0
- data/lib/active_support/rails.rb +10 -11
- data/lib/active_support/railtie.rb +66 -10
- data/lib/active_support/reloader.rb +130 -0
- data/lib/active_support/rescuable.rb +112 -57
- data/lib/active_support/secure_compare_rotator.rb +51 -0
- data/lib/active_support/security_utils.rb +26 -15
- data/lib/active_support/string_inquirer.rb +13 -4
- data/lib/active_support/subscriber.rb +80 -31
- data/lib/active_support/tagged_logging.rb +54 -17
- data/lib/active_support/test_case.rb +107 -44
- data/lib/active_support/testing/assertions.rb +158 -20
- data/lib/active_support/testing/autorun.rb +4 -2
- data/lib/active_support/testing/constant_lookup.rb +2 -1
- data/lib/active_support/testing/declarative.rb +3 -1
- data/lib/active_support/testing/deprecation.rb +13 -10
- data/lib/active_support/testing/file_fixtures.rb +38 -0
- data/lib/active_support/testing/isolation.rb +35 -26
- data/lib/active_support/testing/method_call_assertions.rb +70 -0
- data/lib/active_support/testing/parallelization/server.rb +78 -0
- data/lib/active_support/testing/parallelization/worker.rb +100 -0
- data/lib/active_support/testing/parallelization.rb +51 -0
- data/lib/active_support/testing/setup_and_teardown.rb +13 -8
- data/lib/active_support/testing/stream.rb +43 -0
- data/lib/active_support/testing/tagged_logging.rb +3 -1
- data/lib/active_support/testing/time_helpers.rb +121 -20
- data/lib/active_support/time.rb +14 -12
- data/lib/active_support/time_with_zone.rb +215 -51
- data/lib/active_support/values/time_zone.rb +223 -71
- data/lib/active_support/version.rb +3 -1
- data/lib/active_support/xml_mini/jdom.rb +116 -115
- data/lib/active_support/xml_mini/libxml.rb +16 -13
- data/lib/active_support/xml_mini/libxmlsax.rb +15 -14
- data/lib/active_support/xml_mini/nokogiri.rb +14 -12
- data/lib/active_support/xml_mini/nokogirisax.rb +14 -13
- data/lib/active_support/xml_mini/rexml.rb +18 -9
- data/lib/active_support/xml_mini.rb +38 -46
- data/lib/active_support.rb +25 -11
- metadata +100 -43
- data/lib/active_support/concurrency/latch.rb +0 -27
- data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -7
- data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +0 -16
- data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -45
- data/lib/active_support/core_ext/date_time/zones.rb +0 -6
- data/lib/active_support/core_ext/hash/compact.rb +0 -24
- data/lib/active_support/core_ext/hash/transform_values.rb +0 -23
- data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
- data/lib/active_support/core_ext/kernel/debugger.rb +0 -10
- data/lib/active_support/core_ext/module/method_transplanting.rb +0 -13
- data/lib/active_support/core_ext/module/qualified_const.rb +0 -52
- data/lib/active_support/core_ext/module/reachable.rb +0 -8
- data/lib/active_support/core_ext/object/itself.rb +0 -15
- data/lib/active_support/core_ext/range/include_range.rb +0 -23
- data/lib/active_support/core_ext/struct.rb +0 -6
- data/lib/active_support/core_ext/thread.rb +0 -86
- data/lib/active_support/core_ext/time/marshal.rb +0 -30
- data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "minitest/mock"
|
4
|
+
|
5
|
+
module ActiveSupport
|
6
|
+
module Testing
|
7
|
+
module MethodCallAssertions # :nodoc:
|
8
|
+
private
|
9
|
+
def assert_called(object, method_name, message = nil, times: 1, returns: nil)
|
10
|
+
times_called = 0
|
11
|
+
|
12
|
+
object.stub(method_name, proc { times_called += 1; returns }) { yield }
|
13
|
+
|
14
|
+
error = "Expected #{method_name} to be called #{times} times, " \
|
15
|
+
"but was called #{times_called} times"
|
16
|
+
error = "#{message}.\n#{error}" if message
|
17
|
+
assert_equal times, times_called, error
|
18
|
+
end
|
19
|
+
|
20
|
+
def assert_called_with(object, method_name, args, returns: nil)
|
21
|
+
mock = Minitest::Mock.new
|
22
|
+
|
23
|
+
if args.all? { |arg| arg.is_a?(Array) }
|
24
|
+
args.each { |arg| mock.expect(:call, returns, arg) }
|
25
|
+
else
|
26
|
+
mock.expect(:call, returns, args)
|
27
|
+
end
|
28
|
+
|
29
|
+
object.stub(method_name, mock) { yield }
|
30
|
+
|
31
|
+
mock.verify
|
32
|
+
end
|
33
|
+
|
34
|
+
def assert_not_called(object, method_name, message = nil, &block)
|
35
|
+
assert_called(object, method_name, message, times: 0, &block)
|
36
|
+
end
|
37
|
+
|
38
|
+
def assert_called_on_instance_of(klass, method_name, message = nil, times: 1, returns: nil)
|
39
|
+
times_called = 0
|
40
|
+
klass.define_method("stubbed_#{method_name}") do |*|
|
41
|
+
times_called += 1
|
42
|
+
|
43
|
+
returns
|
44
|
+
end
|
45
|
+
|
46
|
+
klass.alias_method "original_#{method_name}", method_name
|
47
|
+
klass.alias_method method_name, "stubbed_#{method_name}"
|
48
|
+
|
49
|
+
yield
|
50
|
+
|
51
|
+
error = "Expected #{method_name} to be called #{times} times, but was called #{times_called} times"
|
52
|
+
error = "#{message}.\n#{error}" if message
|
53
|
+
|
54
|
+
assert_equal times, times_called, error
|
55
|
+
ensure
|
56
|
+
klass.alias_method method_name, "original_#{method_name}"
|
57
|
+
klass.undef_method "original_#{method_name}"
|
58
|
+
klass.undef_method "stubbed_#{method_name}"
|
59
|
+
end
|
60
|
+
|
61
|
+
def assert_not_called_on_instance_of(klass, method_name, message = nil, &block)
|
62
|
+
assert_called_on_instance_of(klass, method_name, message, times: 0, &block)
|
63
|
+
end
|
64
|
+
|
65
|
+
def stub_any_instance(klass, instance: klass.new)
|
66
|
+
klass.stub(:new, instance) { yield instance }
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "drb"
|
4
|
+
require "drb/unix" unless Gem.win_platform?
|
5
|
+
|
6
|
+
module ActiveSupport
|
7
|
+
module Testing
|
8
|
+
class Parallelization # :nodoc:
|
9
|
+
class Server
|
10
|
+
include DRb::DRbUndumped
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@queue = Queue.new
|
14
|
+
@active_workers = Concurrent::Map.new
|
15
|
+
@in_flight = Concurrent::Map.new
|
16
|
+
end
|
17
|
+
|
18
|
+
def record(reporter, result)
|
19
|
+
raise DRb::DRbConnError if result.is_a?(DRb::DRbUnknown)
|
20
|
+
|
21
|
+
@in_flight.delete([result.klass, result.name])
|
22
|
+
|
23
|
+
reporter.synchronize do
|
24
|
+
reporter.record(result)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def <<(o)
|
29
|
+
o[2] = DRbObject.new(o[2]) if o
|
30
|
+
@queue << o
|
31
|
+
end
|
32
|
+
|
33
|
+
def pop
|
34
|
+
if test = @queue.pop
|
35
|
+
@in_flight[[test[0].to_s, test[1]]] = test
|
36
|
+
test
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def start_worker(worker_id)
|
41
|
+
@active_workers[worker_id] = true
|
42
|
+
end
|
43
|
+
|
44
|
+
def stop_worker(worker_id)
|
45
|
+
@active_workers.delete(worker_id)
|
46
|
+
end
|
47
|
+
|
48
|
+
def active_workers?
|
49
|
+
@active_workers.size > 0
|
50
|
+
end
|
51
|
+
|
52
|
+
def shutdown
|
53
|
+
# Wait for initial queue to drain
|
54
|
+
while @queue.length != 0
|
55
|
+
sleep 0.1
|
56
|
+
end
|
57
|
+
|
58
|
+
@queue.close
|
59
|
+
|
60
|
+
# Wait until all workers have finished
|
61
|
+
while active_workers?
|
62
|
+
sleep 0.1
|
63
|
+
end
|
64
|
+
|
65
|
+
@in_flight.values.each do |(klass, name, reporter)|
|
66
|
+
result = Minitest::Result.from(klass.new(name))
|
67
|
+
error = RuntimeError.new("result not reported")
|
68
|
+
error.set_backtrace([""])
|
69
|
+
result.failures << Minitest::UnexpectedError.new(error)
|
70
|
+
reporter.synchronize do
|
71
|
+
reporter.record(result)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveSupport
|
4
|
+
module Testing
|
5
|
+
class Parallelization # :nodoc:
|
6
|
+
class Worker
|
7
|
+
def initialize(number, url)
|
8
|
+
@id = SecureRandom.uuid
|
9
|
+
@number = number
|
10
|
+
@url = url
|
11
|
+
@setup_exception = nil
|
12
|
+
end
|
13
|
+
|
14
|
+
def start
|
15
|
+
fork do
|
16
|
+
set_process_title("(starting)")
|
17
|
+
|
18
|
+
DRb.stop_service
|
19
|
+
|
20
|
+
@queue = DRbObject.new_with_uri(@url)
|
21
|
+
@queue.start_worker(@id)
|
22
|
+
|
23
|
+
begin
|
24
|
+
after_fork
|
25
|
+
rescue => @setup_exception; end
|
26
|
+
|
27
|
+
work_from_queue
|
28
|
+
ensure
|
29
|
+
set_process_title("(stopping)")
|
30
|
+
|
31
|
+
run_cleanup
|
32
|
+
@queue.stop_worker(@id)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def work_from_queue
|
37
|
+
while job = @queue.pop
|
38
|
+
perform_job(job)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def perform_job(job)
|
43
|
+
klass = job[0]
|
44
|
+
method = job[1]
|
45
|
+
reporter = job[2]
|
46
|
+
|
47
|
+
set_process_title("#{klass}##{method}")
|
48
|
+
|
49
|
+
result = klass.with_info_handler reporter do
|
50
|
+
Minitest.run_one_method(klass, method)
|
51
|
+
end
|
52
|
+
|
53
|
+
safe_record(reporter, result)
|
54
|
+
end
|
55
|
+
|
56
|
+
def safe_record(reporter, result)
|
57
|
+
add_setup_exception(result) if @setup_exception
|
58
|
+
|
59
|
+
begin
|
60
|
+
@queue.record(reporter, result)
|
61
|
+
rescue DRb::DRbConnError
|
62
|
+
result.failures.map! do |failure|
|
63
|
+
if failure.respond_to?(:error)
|
64
|
+
# minitest >5.14.0
|
65
|
+
error = DRb::DRbRemoteError.new(failure.error)
|
66
|
+
else
|
67
|
+
error = DRb::DRbRemoteError.new(failure.exception)
|
68
|
+
end
|
69
|
+
Minitest::UnexpectedError.new(error)
|
70
|
+
end
|
71
|
+
@queue.record(reporter, result)
|
72
|
+
end
|
73
|
+
|
74
|
+
set_process_title("(idle)")
|
75
|
+
end
|
76
|
+
|
77
|
+
def after_fork
|
78
|
+
Parallelization.after_fork_hooks.each do |cb|
|
79
|
+
cb.call(@number)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def run_cleanup
|
84
|
+
Parallelization.run_cleanup_hooks.each do |cb|
|
85
|
+
cb.call(@number)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
def add_setup_exception(result)
|
91
|
+
result.failures.prepend Minitest::UnexpectedError.new(@setup_exception)
|
92
|
+
end
|
93
|
+
|
94
|
+
def set_process_title(status)
|
95
|
+
Process.setproctitle("Rails test worker #{@number} - #{status}")
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "drb"
|
4
|
+
require "drb/unix" unless Gem.win_platform?
|
5
|
+
require "active_support/core_ext/module/attribute_accessors"
|
6
|
+
require "active_support/testing/parallelization/server"
|
7
|
+
require "active_support/testing/parallelization/worker"
|
8
|
+
|
9
|
+
module ActiveSupport
|
10
|
+
module Testing
|
11
|
+
class Parallelization # :nodoc:
|
12
|
+
@@after_fork_hooks = []
|
13
|
+
|
14
|
+
def self.after_fork_hook(&blk)
|
15
|
+
@@after_fork_hooks << blk
|
16
|
+
end
|
17
|
+
|
18
|
+
cattr_reader :after_fork_hooks
|
19
|
+
|
20
|
+
@@run_cleanup_hooks = []
|
21
|
+
|
22
|
+
def self.run_cleanup_hook(&blk)
|
23
|
+
@@run_cleanup_hooks << blk
|
24
|
+
end
|
25
|
+
|
26
|
+
cattr_reader :run_cleanup_hooks
|
27
|
+
|
28
|
+
def initialize(worker_count)
|
29
|
+
@worker_count = worker_count
|
30
|
+
@queue_server = Server.new
|
31
|
+
@worker_pool = []
|
32
|
+
@url = DRb.start_service("drbunix:", @queue_server).uri
|
33
|
+
end
|
34
|
+
|
35
|
+
def start
|
36
|
+
@worker_pool = @worker_count.times.map do |worker|
|
37
|
+
Worker.new(worker, @url).start
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def <<(work)
|
42
|
+
@queue_server << work
|
43
|
+
end
|
44
|
+
|
45
|
+
def shutdown
|
46
|
+
@queue_server.shutdown
|
47
|
+
@worker_pool.each { |pid| Process.waitpid pid }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -1,5 +1,6 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/callbacks"
|
3
4
|
|
4
5
|
module ActiveSupport
|
5
6
|
module Testing
|
@@ -17,11 +18,10 @@ module ActiveSupport
|
|
17
18
|
# end
|
18
19
|
# end
|
19
20
|
module SetupAndTeardown
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
define_callbacks :setup, :teardown
|
21
|
+
def self.prepended(klass)
|
22
|
+
klass.include ActiveSupport::Callbacks
|
23
|
+
klass.define_callbacks :setup, :teardown
|
24
|
+
klass.extend ClassMethods
|
25
25
|
end
|
26
26
|
|
27
27
|
module ClassMethods
|
@@ -42,7 +42,12 @@ module ActiveSupport
|
|
42
42
|
end
|
43
43
|
|
44
44
|
def after_teardown # :nodoc:
|
45
|
-
|
45
|
+
begin
|
46
|
+
run_callbacks :teardown
|
47
|
+
rescue => e
|
48
|
+
self.failures << Minitest::UnexpectedError.new(e)
|
49
|
+
end
|
50
|
+
|
46
51
|
super
|
47
52
|
end
|
48
53
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveSupport
|
4
|
+
module Testing
|
5
|
+
module Stream #:nodoc:
|
6
|
+
private
|
7
|
+
def silence_stream(stream)
|
8
|
+
old_stream = stream.dup
|
9
|
+
stream.reopen(IO::NULL)
|
10
|
+
stream.sync = true
|
11
|
+
yield
|
12
|
+
ensure
|
13
|
+
stream.reopen(old_stream)
|
14
|
+
old_stream.close
|
15
|
+
end
|
16
|
+
|
17
|
+
def quietly
|
18
|
+
silence_stream(STDOUT) do
|
19
|
+
silence_stream(STDERR) do
|
20
|
+
yield
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def capture(stream)
|
26
|
+
stream = stream.to_s
|
27
|
+
captured_stream = Tempfile.new(stream)
|
28
|
+
stream_io = eval("$#{stream}")
|
29
|
+
origin_stream = stream_io.dup
|
30
|
+
stream_io.reopen(captured_stream)
|
31
|
+
|
32
|
+
yield
|
33
|
+
|
34
|
+
stream_io.rewind
|
35
|
+
captured_stream.read
|
36
|
+
ensure
|
37
|
+
captured_stream.close
|
38
|
+
captured_stream.unlink
|
39
|
+
stream_io.reopen(origin_stream)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveSupport
|
2
4
|
module Testing
|
3
5
|
# Logs a "PostsControllerTest: test name" heading before each test to
|
@@ -8,7 +10,7 @@ module ActiveSupport
|
|
8
10
|
def before_setup
|
9
11
|
if tagged_logger && tagged_logger.info?
|
10
12
|
heading = "#{self.class}: #{name}"
|
11
|
-
divider =
|
13
|
+
divider = "-" * heading.size
|
12
14
|
tagged_logger.info divider
|
13
15
|
tagged_logger.info heading
|
14
16
|
tagged_logger.info divider
|
@@ -1,48 +1,80 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/module/redefine_method"
|
4
|
+
require "active_support/core_ext/time/calculations"
|
5
|
+
require "concurrent/map"
|
6
|
+
|
1
7
|
module ActiveSupport
|
2
8
|
module Testing
|
9
|
+
# Manages stubs for TimeHelpers
|
3
10
|
class SimpleStubs # :nodoc:
|
4
11
|
Stub = Struct.new(:object, :method_name, :original_method)
|
5
12
|
|
6
13
|
def initialize
|
7
|
-
@stubs = {}
|
14
|
+
@stubs = Concurrent::Map.new { |h, k| h[k] = {} }
|
8
15
|
end
|
9
16
|
|
17
|
+
# Stubs object.method_name with the given block
|
18
|
+
# If the method is already stubbed, remove that stub
|
19
|
+
# so that removing this stub will restore the original implementation.
|
20
|
+
# Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
|
21
|
+
# target = Time.zone.local(2004, 11, 24, 1, 4, 44)
|
22
|
+
# simple_stubs.stub_object(Time, :now) { at(target.to_i) }
|
23
|
+
# Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
|
10
24
|
def stub_object(object, method_name, &block)
|
11
|
-
|
12
|
-
|
13
|
-
if stub = @stubs[key]
|
25
|
+
if stub = stubbing(object, method_name)
|
14
26
|
unstub_object(stub)
|
15
27
|
end
|
16
28
|
|
17
29
|
new_name = "__simple_stub__#{method_name}"
|
18
30
|
|
19
|
-
@stubs[
|
31
|
+
@stubs[object.object_id][method_name] = Stub.new(object, method_name, new_name)
|
20
32
|
|
21
|
-
object.singleton_class.
|
33
|
+
object.singleton_class.alias_method new_name, method_name
|
22
34
|
object.define_singleton_method(method_name, &block)
|
23
35
|
end
|
24
36
|
|
37
|
+
# Remove all object-method stubs held by this instance
|
25
38
|
def unstub_all!
|
26
|
-
@stubs.each_value do |
|
27
|
-
|
39
|
+
@stubs.each_value do |object_stubs|
|
40
|
+
object_stubs.each_value do |stub|
|
41
|
+
unstub_object(stub)
|
42
|
+
end
|
28
43
|
end
|
29
|
-
@stubs
|
44
|
+
@stubs.clear
|
30
45
|
end
|
31
46
|
|
32
|
-
|
47
|
+
# Returns the Stub for object#method_name
|
48
|
+
# (nil if it is not stubbed)
|
49
|
+
def stubbing(object, method_name)
|
50
|
+
@stubs[object.object_id][method_name]
|
51
|
+
end
|
52
|
+
|
53
|
+
# Returns true if any stubs are set, false if there are none
|
54
|
+
def stubbed?
|
55
|
+
!@stubs.empty?
|
56
|
+
end
|
33
57
|
|
58
|
+
private
|
59
|
+
# Restores the original object.method described by the Stub
|
34
60
|
def unstub_object(stub)
|
35
61
|
singleton_class = stub.object.singleton_class
|
36
|
-
singleton_class.
|
37
|
-
singleton_class.
|
38
|
-
singleton_class.
|
62
|
+
singleton_class.silence_redefinition_of_method stub.method_name
|
63
|
+
singleton_class.alias_method stub.method_name, stub.original_method
|
64
|
+
singleton_class.undef_method stub.original_method
|
39
65
|
end
|
40
66
|
end
|
41
67
|
|
42
|
-
#
|
68
|
+
# Contains helpers that help you test passage of time.
|
43
69
|
module TimeHelpers
|
70
|
+
def after_teardown
|
71
|
+
travel_back
|
72
|
+
super
|
73
|
+
end
|
74
|
+
|
44
75
|
# Changes current time to the time in the future or in the past by a given time difference by
|
45
|
-
# stubbing +Time.now+, +Date.today+, and +DateTime.now+.
|
76
|
+
# stubbing +Time.now+, +Date.today+, and +DateTime.now+. The stubs are automatically removed
|
77
|
+
# at the end of the test.
|
46
78
|
#
|
47
79
|
# Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
|
48
80
|
# travel 1.day
|
@@ -64,9 +96,10 @@ module ActiveSupport
|
|
64
96
|
|
65
97
|
# Changes current time to the given time by stubbing +Time.now+,
|
66
98
|
# +Date.today+, and +DateTime.now+ to return the time or date passed into this method.
|
99
|
+
# The stubs are automatically removed at the end of the test.
|
67
100
|
#
|
68
101
|
# Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
|
69
|
-
# travel_to Time.
|
102
|
+
# travel_to Time.zone.local(2004, 11, 24, 1, 4, 44)
|
70
103
|
# Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
|
71
104
|
# Date.current # => Wed, 24 Nov 2004
|
72
105
|
# DateTime.current # => Wed, 24 Nov 2004 01:04:44 -0500
|
@@ -88,11 +121,39 @@ module ActiveSupport
|
|
88
121
|
# state at the end of the block:
|
89
122
|
#
|
90
123
|
# Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
|
91
|
-
# travel_to Time.
|
124
|
+
# travel_to Time.zone.local(2004, 11, 24, 1, 4, 44) do
|
92
125
|
# Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
|
93
126
|
# end
|
94
127
|
# Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
|
95
128
|
def travel_to(date_or_time)
|
129
|
+
if block_given? && simple_stubs.stubbing(Time, :now)
|
130
|
+
travel_to_nested_block_call = <<~MSG
|
131
|
+
|
132
|
+
Calling `travel_to` with a block, when we have previously already made a call to `travel_to`, can lead to confusing time stubbing.
|
133
|
+
|
134
|
+
Instead of:
|
135
|
+
|
136
|
+
travel_to 2.days.from_now do
|
137
|
+
# 2 days from today
|
138
|
+
travel_to 3.days.from_now do
|
139
|
+
# 5 days from today
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
preferred way to achieve above is:
|
144
|
+
|
145
|
+
travel 2.days do
|
146
|
+
# 2 days from today
|
147
|
+
end
|
148
|
+
|
149
|
+
travel 5.days do
|
150
|
+
# 5 days from today
|
151
|
+
end
|
152
|
+
|
153
|
+
MSG
|
154
|
+
raise travel_to_nested_block_call
|
155
|
+
end
|
156
|
+
|
96
157
|
if date_or_time.is_a?(Date) && !date_or_time.is_a?(DateTime)
|
97
158
|
now = date_or_time.midnight.to_time
|
98
159
|
else
|
@@ -113,19 +174,59 @@ module ActiveSupport
|
|
113
174
|
end
|
114
175
|
|
115
176
|
# Returns the current time back to its original state, by removing the stubs added by
|
116
|
-
#
|
177
|
+
# +travel+, +travel_to+, and +freeze_time+.
|
117
178
|
#
|
118
179
|
# Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
|
119
|
-
#
|
180
|
+
#
|
181
|
+
# travel_to Time.zone.local(2004, 11, 24, 1, 4, 44)
|
120
182
|
# Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
|
183
|
+
#
|
121
184
|
# travel_back
|
122
185
|
# Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
|
186
|
+
#
|
187
|
+
# This method also accepts a block, which brings the stubs back at the end of the block:
|
188
|
+
#
|
189
|
+
# Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
|
190
|
+
#
|
191
|
+
# travel_to Time.zone.local(2004, 11, 24, 1, 4, 44)
|
192
|
+
# Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
|
193
|
+
#
|
194
|
+
# travel_back do
|
195
|
+
# Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
|
196
|
+
# end
|
197
|
+
#
|
198
|
+
# Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
|
123
199
|
def travel_back
|
200
|
+
stubbed_time = Time.current if block_given? && simple_stubs.stubbed?
|
201
|
+
|
124
202
|
simple_stubs.unstub_all!
|
203
|
+
yield if block_given?
|
204
|
+
ensure
|
205
|
+
travel_to stubbed_time if stubbed_time
|
125
206
|
end
|
207
|
+
alias_method :unfreeze_time, :travel_back
|
126
208
|
|
127
|
-
|
209
|
+
# Calls +travel_to+ with +Time.now+.
|
210
|
+
#
|
211
|
+
# Time.current # => Sun, 09 Jul 2017 15:34:49 EST -05:00
|
212
|
+
# freeze_time
|
213
|
+
# sleep(1)
|
214
|
+
# Time.current # => Sun, 09 Jul 2017 15:34:49 EST -05:00
|
215
|
+
#
|
216
|
+
# This method also accepts a block, which will return the current time back to its original
|
217
|
+
# state at the end of the block:
|
218
|
+
#
|
219
|
+
# Time.current # => Sun, 09 Jul 2017 15:34:49 EST -05:00
|
220
|
+
# freeze_time do
|
221
|
+
# sleep(1)
|
222
|
+
# User.create.created_at # => Sun, 09 Jul 2017 15:34:49 EST -05:00
|
223
|
+
# end
|
224
|
+
# Time.current # => Sun, 09 Jul 2017 15:34:50 EST -05:00
|
225
|
+
def freeze_time(&block)
|
226
|
+
travel_to Time.now, &block
|
227
|
+
end
|
128
228
|
|
229
|
+
private
|
129
230
|
def simple_stubs
|
130
231
|
@simple_stubs ||= SimpleStubs.new
|
131
232
|
end
|
data/lib/active_support/time.rb
CHANGED
@@ -1,18 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveSupport
|
2
|
-
autoload :Duration,
|
3
|
-
autoload :TimeWithZone,
|
4
|
-
autoload :TimeZone,
|
4
|
+
autoload :Duration, "active_support/duration"
|
5
|
+
autoload :TimeWithZone, "active_support/time_with_zone"
|
6
|
+
autoload :TimeZone, "active_support/values/time_zone"
|
5
7
|
end
|
6
8
|
|
7
|
-
require
|
8
|
-
require
|
9
|
+
require "date"
|
10
|
+
require "time"
|
9
11
|
|
10
|
-
require
|
11
|
-
require
|
12
|
-
require
|
12
|
+
require "active_support/core_ext/time"
|
13
|
+
require "active_support/core_ext/date"
|
14
|
+
require "active_support/core_ext/date_time"
|
13
15
|
|
14
|
-
require
|
15
|
-
require
|
16
|
+
require "active_support/core_ext/integer/time"
|
17
|
+
require "active_support/core_ext/numeric/time"
|
16
18
|
|
17
|
-
require
|
18
|
-
require
|
19
|
+
require "active_support/core_ext/string/conversions"
|
20
|
+
require "active_support/core_ext/string/zones"
|