activesupport 4.2.0 → 5.0.0
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 +630 -220
- data/MIT-LICENSE +2 -2
- data/README.rdoc +2 -3
- data/lib/active_support/array_inquirer.rb +44 -0
- data/lib/active_support/backtrace_cleaner.rb +1 -1
- data/lib/active_support/benchmarkable.rb +1 -1
- data/lib/active_support/cache/file_store.rb +36 -22
- data/lib/active_support/cache/mem_cache_store.rb +63 -54
- data/lib/active_support/cache/memory_store.rb +16 -21
- data/lib/active_support/cache/null_store.rb +1 -4
- data/lib/active_support/cache/strategy/local_cache.rb +31 -20
- data/lib/active_support/cache.rb +73 -89
- data/lib/active_support/callbacks.rb +195 -155
- data/lib/active_support/concern.rb +2 -2
- data/lib/active_support/concurrency/latch.rb +7 -15
- data/lib/active_support/concurrency/share_lock.rb +186 -0
- data/lib/active_support/configurable.rb +1 -0
- data/lib/active_support/core_ext/array/access.rb +27 -1
- data/lib/active_support/core_ext/array/conversions.rb +6 -4
- data/lib/active_support/core_ext/array/grouping.rb +9 -18
- data/lib/active_support/core_ext/array/inquiry.rb +17 -0
- data/lib/active_support/core_ext/array/wrap.rb +5 -4
- data/lib/active_support/core_ext/array.rb +1 -0
- data/lib/active_support/core_ext/big_decimal/conversions.rb +8 -10
- data/lib/active_support/core_ext/class/attribute.rb +10 -9
- data/lib/active_support/core_ext/class/subclasses.rb +3 -4
- data/lib/active_support/core_ext/class.rb +0 -1
- data/lib/active_support/core_ext/date/blank.rb +12 -0
- data/lib/active_support/core_ext/date/calculations.rb +1 -1
- data/lib/active_support/core_ext/date/conversions.rb +13 -6
- data/lib/active_support/core_ext/date.rb +1 -1
- data/lib/active_support/core_ext/date_and_time/calculations.rb +109 -25
- data/lib/active_support/core_ext/date_and_time/compatibility.rb +18 -0
- data/lib/active_support/core_ext/date_and_time/zones.rb +3 -4
- data/lib/active_support/core_ext/date_time/blank.rb +12 -0
- data/lib/active_support/core_ext/date_time/calculations.rb +36 -10
- data/lib/active_support/core_ext/date_time/compatibility.rb +5 -0
- data/lib/active_support/core_ext/date_time/conversions.rb +2 -0
- data/lib/active_support/core_ext/date_time.rb +2 -1
- data/lib/active_support/core_ext/enumerable.rb +49 -5
- data/lib/active_support/core_ext/file/atomic.rb +30 -25
- data/lib/active_support/core_ext/hash/conversions.rb +23 -4
- data/lib/active_support/core_ext/hash/deep_merge.rb +1 -1
- data/lib/active_support/core_ext/hash/except.rb +9 -8
- data/lib/active_support/core_ext/hash/indifferent_access.rb +1 -1
- data/lib/active_support/core_ext/hash/keys.rb +23 -19
- data/lib/active_support/core_ext/hash/slice.rb +1 -1
- data/lib/active_support/core_ext/hash/transform_values.rb +11 -5
- data/lib/active_support/core_ext/integer/time.rb +1 -16
- data/lib/active_support/core_ext/kernel/concern.rb +2 -0
- data/lib/active_support/core_ext/kernel/debugger.rb +3 -10
- data/lib/active_support/core_ext/kernel/reporting.rb +2 -83
- data/lib/active_support/core_ext/kernel.rb +0 -1
- data/lib/active_support/core_ext/load_error.rb +4 -2
- data/lib/active_support/core_ext/marshal.rb +12 -11
- data/lib/active_support/core_ext/module/aliasing.rb +6 -1
- data/lib/active_support/core_ext/module/anonymous.rb +10 -1
- data/lib/active_support/core_ext/module/attr_internal.rb +2 -5
- data/lib/active_support/core_ext/module/attribute_accessors.rb +15 -15
- data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +141 -0
- data/lib/active_support/core_ext/module/concerning.rb +4 -4
- data/lib/active_support/core_ext/module/delegation.rb +35 -25
- data/lib/active_support/core_ext/module/deprecation.rb +2 -2
- data/lib/active_support/core_ext/module/introspection.rb +4 -0
- data/lib/active_support/core_ext/module/method_transplanting.rb +3 -11
- data/lib/active_support/core_ext/module/qualified_const.rb +30 -12
- data/lib/active_support/core_ext/module/remove_method.rb +23 -0
- data/lib/active_support/core_ext/module.rb +1 -0
- data/lib/active_support/core_ext/name_error.rb +15 -2
- data/lib/active_support/core_ext/numeric/bytes.rb +20 -0
- data/lib/active_support/core_ext/numeric/conversions.rb +74 -64
- data/lib/active_support/core_ext/numeric/inquiry.rb +26 -0
- data/lib/active_support/core_ext/numeric/time.rb +24 -19
- data/lib/active_support/core_ext/numeric.rb +1 -0
- data/lib/active_support/core_ext/object/blank.rb +17 -5
- data/lib/active_support/core_ext/object/deep_dup.rb +10 -3
- data/lib/active_support/core_ext/object/duplicable.rb +8 -13
- data/lib/active_support/core_ext/object/inclusion.rb +2 -2
- data/lib/active_support/core_ext/object/instance_variables.rb +1 -1
- data/lib/active_support/core_ext/object/json.rb +15 -7
- data/lib/active_support/core_ext/object/to_query.rb +1 -1
- data/lib/active_support/core_ext/object/try.rb +68 -22
- data/lib/active_support/core_ext/object/with_options.rb +1 -1
- data/lib/active_support/core_ext/object.rb +0 -1
- data/lib/active_support/core_ext/range/conversions.rb +18 -6
- data/lib/active_support/core_ext/range/each.rb +16 -18
- data/lib/active_support/core_ext/range/include_range.rb +20 -20
- data/lib/active_support/core_ext/securerandom.rb +23 -0
- data/lib/active_support/core_ext/string/access.rb +1 -1
- data/lib/active_support/core_ext/string/behavior.rb +1 -1
- data/lib/active_support/core_ext/string/conversions.rb +4 -3
- data/lib/active_support/core_ext/string/filters.rb +5 -5
- data/lib/active_support/core_ext/string/inflections.rb +32 -5
- data/lib/active_support/core_ext/string/multibyte.rb +11 -7
- data/lib/active_support/core_ext/string/output_safety.rb +18 -16
- data/lib/active_support/core_ext/string/strip.rb +3 -6
- data/lib/active_support/core_ext/struct.rb +3 -6
- data/lib/active_support/core_ext/time/calculations.rb +36 -11
- data/lib/active_support/core_ext/time/compatibility.rb +5 -0
- data/lib/active_support/core_ext/time/conversions.rb +4 -2
- data/lib/active_support/core_ext/time/marshal.rb +2 -29
- data/lib/active_support/core_ext/time/zones.rb +36 -4
- data/lib/active_support/core_ext/time.rb +1 -1
- data/lib/active_support/core_ext/uri.rb +1 -3
- data/lib/active_support/core_ext.rb +2 -1
- data/lib/active_support/dependencies/interlock.rb +51 -0
- data/lib/active_support/dependencies.rb +87 -95
- data/lib/active_support/deprecation/behaviors.rb +16 -2
- data/lib/active_support/deprecation/method_wrappers.rb +42 -16
- data/lib/active_support/deprecation/proxy_wrappers.rb +47 -24
- data/lib/active_support/deprecation/reporting.rb +23 -5
- data/lib/active_support/deprecation.rb +1 -1
- data/lib/active_support/duration/iso8601_parser.rb +122 -0
- data/lib/active_support/duration/iso8601_serializer.rb +51 -0
- data/lib/active_support/duration.rb +55 -10
- data/lib/active_support/evented_file_update_checker.rb +194 -0
- data/lib/active_support/execution_wrapper.rb +117 -0
- data/lib/active_support/executor.rb +6 -0
- data/lib/active_support/file_update_checker.rb +23 -3
- data/lib/active_support/gem_version.rb +3 -3
- data/lib/active_support/hash_with_indifferent_access.rb +46 -13
- data/lib/active_support/i18n_railtie.rb +25 -4
- data/lib/active_support/inflector/inflections.rb +36 -5
- data/lib/active_support/inflector/methods.rb +97 -90
- data/lib/active_support/inflector/transliterate.rb +36 -21
- data/lib/active_support/json/decoding.rb +11 -10
- data/lib/active_support/json/encoding.rb +4 -49
- data/lib/active_support/key_generator.rb +7 -9
- data/lib/active_support/locale/en.yml +2 -0
- data/lib/active_support/log_subscriber/test_helper.rb +3 -3
- data/lib/active_support/log_subscriber.rb +1 -1
- data/lib/active_support/logger.rb +50 -1
- data/lib/active_support/logger_silence.rb +8 -4
- data/lib/active_support/logger_thread_safe_level.rb +31 -0
- data/lib/active_support/message_encryptor.rb +4 -4
- data/lib/active_support/message_verifier.rb +70 -8
- data/lib/active_support/multibyte/chars.rb +13 -4
- data/lib/active_support/multibyte/unicode.rb +44 -21
- data/lib/active_support/notifications/fanout.rb +6 -6
- data/lib/active_support/notifications/instrumenter.rb +20 -2
- data/lib/active_support/notifications.rb +2 -2
- data/lib/active_support/number_helper/number_to_currency_converter.rb +7 -9
- data/lib/active_support/number_helper/number_to_delimited_converter.rb +8 -3
- data/lib/active_support/number_helper/number_to_human_converter.rb +6 -4
- data/lib/active_support/number_helper/number_to_human_size_converter.rb +6 -2
- data/lib/active_support/number_helper/number_to_percentage_converter.rb +1 -1
- data/lib/active_support/number_helper/number_to_phone_converter.rb +11 -2
- data/lib/active_support/number_helper/number_to_rounded_converter.rb +30 -25
- data/lib/active_support/number_helper.rb +90 -67
- data/lib/active_support/ordered_hash.rb +1 -1
- data/lib/active_support/ordered_options.rb +15 -1
- data/lib/active_support/per_thread_registry.rb +8 -3
- data/lib/active_support/rails.rb +2 -2
- data/lib/active_support/railtie.rb +6 -1
- data/lib/active_support/reloader.rb +129 -0
- data/lib/active_support/rescuable.rb +93 -47
- data/lib/active_support/security_utils.rb +7 -0
- data/lib/active_support/string_inquirer.rb +1 -1
- data/lib/active_support/subscriber.rb +5 -10
- data/lib/active_support/tagged_logging.rb +3 -1
- data/lib/active_support/test_case.rb +15 -29
- data/lib/active_support/testing/assertions.rb +15 -13
- data/lib/active_support/testing/autorun.rb +8 -1
- data/lib/active_support/testing/deprecation.rb +9 -8
- data/lib/active_support/testing/file_fixtures.rb +34 -0
- data/lib/active_support/testing/isolation.rb +22 -8
- data/lib/active_support/testing/method_call_assertions.rb +41 -0
- data/lib/active_support/testing/stream.rb +42 -0
- data/lib/active_support/testing/time_helpers.rb +13 -10
- data/lib/active_support/time_with_zone.rb +135 -46
- data/lib/active_support/values/time_zone.rb +95 -47
- data/lib/active_support/values/unicode_tables.dat +0 -0
- data/lib/active_support/xml_mini/jdom.rb +7 -6
- data/lib/active_support/xml_mini/libxml.rb +2 -2
- data/lib/active_support/xml_mini/nokogiri.rb +2 -2
- data/lib/active_support/xml_mini/rexml.rb +7 -8
- data/lib/active_support/xml_mini.rb +22 -14
- data/lib/active_support.rb +20 -6
- metadata +32 -35
- data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +0 -14
- 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/object/itself.rb +0 -15
- data/lib/active_support/core_ext/thread.rb +0 -86
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'active_support/concern'
|
2
2
|
require 'active_support/core_ext/class/attribute'
|
3
3
|
require 'active_support/core_ext/string/inflections'
|
4
|
-
require 'active_support/core_ext/array/extract_options'
|
5
4
|
|
6
5
|
module ActiveSupport
|
7
6
|
# Rescuable module adds support for easier exception handling.
|
@@ -48,72 +47,119 @@ module ActiveSupport
|
|
48
47
|
# end
|
49
48
|
#
|
50
49
|
# Exceptions raised inside exception handlers are not propagated up.
|
51
|
-
def rescue_from(*klasses, &block)
|
52
|
-
|
53
|
-
|
54
|
-
unless options.has_key?(:with)
|
50
|
+
def rescue_from(*klasses, with: nil, &block)
|
51
|
+
unless with
|
55
52
|
if block_given?
|
56
|
-
|
53
|
+
with = block
|
57
54
|
else
|
58
|
-
raise ArgumentError,
|
55
|
+
raise ArgumentError, 'Need a handler. Pass the with: keyword argument or provide a block.'
|
59
56
|
end
|
60
57
|
end
|
61
58
|
|
62
59
|
klasses.each do |klass|
|
63
|
-
key = if klass.is_a?(
|
60
|
+
key = if klass.is_a?(Module) && klass.respond_to?(:===)
|
64
61
|
klass.name
|
65
62
|
elsif klass.is_a?(String)
|
66
63
|
klass
|
67
64
|
else
|
68
|
-
raise ArgumentError, "#{klass}
|
65
|
+
raise ArgumentError, "#{klass.inspect} must be an Exception class or a String referencing an Exception class"
|
69
66
|
end
|
70
67
|
|
71
|
-
#
|
72
|
-
self.rescue_handlers += [[key,
|
68
|
+
# Put the new handler at the end because the list is read in reverse.
|
69
|
+
self.rescue_handlers += [[key, with]]
|
73
70
|
end
|
74
71
|
end
|
75
|
-
end
|
76
72
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
73
|
+
# Matches an exception to a handler based on the exception class.
|
74
|
+
#
|
75
|
+
# If no handler matches the exception, check for a handler matching the
|
76
|
+
# (optional) exception.cause. If no handler matches the exception or its
|
77
|
+
# cause, this returns nil so you can deal with unhandled exceptions.
|
78
|
+
# Be sure to re-raise unhandled exceptions if this is what you expect.
|
79
|
+
#
|
80
|
+
# begin
|
81
|
+
# …
|
82
|
+
# rescue => exception
|
83
|
+
# rescue_with_handler(exception) || raise
|
84
|
+
# end
|
85
|
+
#
|
86
|
+
# Returns the exception if it was handled and nil if it was not.
|
87
|
+
def rescue_with_handler(exception, object: self)
|
88
|
+
if handler = handler_for_rescue(exception, object: object)
|
89
|
+
handler.call exception
|
90
|
+
exception
|
91
|
+
end
|
82
92
|
end
|
83
|
-
end
|
84
93
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
# itself when rescue_from CONSTANT is executed.
|
102
|
-
klass = self.class.const_get(klass_name) rescue nil
|
103
|
-
klass ||= klass_name.constantize rescue nil
|
104
|
-
exception.is_a?(klass) if klass
|
94
|
+
def handler_for_rescue(exception, object: self) #:nodoc:
|
95
|
+
case rescuer = find_rescue_handler(exception)
|
96
|
+
when Symbol
|
97
|
+
method = object.method(rescuer)
|
98
|
+
if method.arity == 0
|
99
|
+
-> e { method.call }
|
100
|
+
else
|
101
|
+
method
|
102
|
+
end
|
103
|
+
when Proc
|
104
|
+
if rescuer.arity == 0
|
105
|
+
-> e { object.instance_exec(&rescuer) }
|
106
|
+
else
|
107
|
+
-> e { object.instance_exec(e, &rescuer) }
|
108
|
+
end
|
109
|
+
end
|
105
110
|
end
|
106
111
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
112
|
+
private
|
113
|
+
def find_rescue_handler(exception)
|
114
|
+
if exception
|
115
|
+
# Handlers are in order of declaration but the most recently declared
|
116
|
+
# is the highest priority match, so we search for matching handlers
|
117
|
+
# in reverse.
|
118
|
+
_, handler = rescue_handlers.reverse_each.detect do |class_or_name, _|
|
119
|
+
if klass = constantize_rescue_handler_class(class_or_name)
|
120
|
+
klass === exception
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
handler || find_rescue_handler(exception.cause)
|
125
|
+
end
|
115
126
|
end
|
116
|
-
|
127
|
+
|
128
|
+
def constantize_rescue_handler_class(class_or_name)
|
129
|
+
case class_or_name
|
130
|
+
when String, Symbol
|
131
|
+
begin
|
132
|
+
# Try a lexical lookup first since we support
|
133
|
+
#
|
134
|
+
# class Super
|
135
|
+
# rescue_from 'Error', with: …
|
136
|
+
# end
|
137
|
+
#
|
138
|
+
# class Sub
|
139
|
+
# class Error < StandardError; end
|
140
|
+
# end
|
141
|
+
#
|
142
|
+
# so an Error raised in Sub will hit the 'Error' handler.
|
143
|
+
const_get class_or_name
|
144
|
+
rescue NameError
|
145
|
+
class_or_name.safe_constantize
|
146
|
+
end
|
147
|
+
else
|
148
|
+
class_or_name
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
# Delegates to the class method, but uses the instance as the subject for
|
154
|
+
# rescue_from handlers (method calls, instance_exec blocks).
|
155
|
+
def rescue_with_handler(exception)
|
156
|
+
self.class.rescue_with_handler exception, object: self
|
157
|
+
end
|
158
|
+
|
159
|
+
# Internal handler lookup. Delegates to class method. Some libraries call
|
160
|
+
# this directly, so keeping it around for compatibility.
|
161
|
+
def handler_for_rescue(exception) #:nodoc:
|
162
|
+
self.class.handler_for_rescue exception, object: self
|
117
163
|
end
|
118
164
|
end
|
119
165
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'digest'
|
2
|
+
|
1
3
|
module ActiveSupport
|
2
4
|
module SecurityUtils
|
3
5
|
# Constant time string comparison.
|
@@ -16,5 +18,10 @@ module ActiveSupport
|
|
16
18
|
res == 0
|
17
19
|
end
|
18
20
|
module_function :secure_compare
|
21
|
+
|
22
|
+
def variable_size_secure_compare(a, b) # :nodoc:
|
23
|
+
secure_compare(::Digest::SHA256.hexdigest(a), ::Digest::SHA256.hexdigest(b))
|
24
|
+
end
|
25
|
+
module_function :variable_size_secure_compare
|
19
26
|
end
|
20
27
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module ActiveSupport
|
2
2
|
# Wrapping a string in this class gives you a prettier way to test
|
3
3
|
# for equality. The value returned by <tt>Rails.env</tt> is wrapped
|
4
|
-
# in a StringInquirer object so instead of calling this:
|
4
|
+
# in a StringInquirer object, so instead of calling this:
|
5
5
|
#
|
6
6
|
# Rails.env == 'production'
|
7
7
|
#
|
@@ -5,24 +5,19 @@ module ActiveSupport
|
|
5
5
|
# ActiveSupport::Notifications. The subscriber dispatches notifications to
|
6
6
|
# a registered object based on its given namespace.
|
7
7
|
#
|
8
|
-
# An example would be Active Record subscriber responsible for collecting
|
8
|
+
# An example would be an Active Record subscriber responsible for collecting
|
9
9
|
# statistics about queries:
|
10
10
|
#
|
11
11
|
# module ActiveRecord
|
12
12
|
# class StatsSubscriber < ActiveSupport::Subscriber
|
13
|
+
# attach_to :active_record
|
14
|
+
#
|
13
15
|
# def sql(event)
|
14
16
|
# Statsd.timing("sql.#{event.payload[:name]}", event.duration)
|
15
17
|
# end
|
16
18
|
# end
|
17
19
|
# end
|
18
20
|
#
|
19
|
-
# And it's finally registered as:
|
20
|
-
#
|
21
|
-
# ActiveRecord::StatsSubscriber.attach_to :active_record
|
22
|
-
#
|
23
|
-
# Since we need to know all instance methods before attaching the log
|
24
|
-
# subscriber, the line above should be called after your subscriber definition.
|
25
|
-
#
|
26
21
|
# After configured, whenever a "sql.active_record" notification is published,
|
27
22
|
# it will properly dispatch the event (ActiveSupport::Notifications::Event) to
|
28
23
|
# the +sql+ method.
|
@@ -66,7 +61,7 @@ module ActiveSupport
|
|
66
61
|
|
67
62
|
pattern = "#{event}.#{namespace}"
|
68
63
|
|
69
|
-
#
|
64
|
+
# Don't add multiple subscribers (eg. if methods are redefined).
|
70
65
|
return if subscriber.patterns.include?(pattern)
|
71
66
|
|
72
67
|
subscriber.patterns << pattern
|
@@ -96,7 +91,7 @@ module ActiveSupport
|
|
96
91
|
event.end = finished
|
97
92
|
event.payload.merge!(payload)
|
98
93
|
|
99
|
-
method = name.split('.').first
|
94
|
+
method = name.split('.'.freeze).first
|
100
95
|
send(method, event)
|
101
96
|
end
|
102
97
|
|
@@ -43,7 +43,9 @@ module ActiveSupport
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def current_tags
|
46
|
-
|
46
|
+
# We use our object ID here to avoid conflicting with other instances
|
47
|
+
thread_key = @thread_key ||= "activesupport_tagged_logging_tags:#{object_id}".freeze
|
48
|
+
Thread.current[thread_key] ||= []
|
47
49
|
end
|
48
50
|
|
49
51
|
private
|
@@ -8,8 +8,8 @@ require 'active_support/testing/declarative'
|
|
8
8
|
require 'active_support/testing/isolation'
|
9
9
|
require 'active_support/testing/constant_lookup'
|
10
10
|
require 'active_support/testing/time_helpers'
|
11
|
+
require 'active_support/testing/file_fixtures'
|
11
12
|
require 'active_support/core_ext/kernel/reporting'
|
12
|
-
require 'active_support/deprecation'
|
13
13
|
|
14
14
|
module ActiveSupport
|
15
15
|
class TestCase < ::Minitest::Test
|
@@ -31,36 +31,13 @@ module ActiveSupport
|
|
31
31
|
|
32
32
|
# Returns the order in which test cases are run.
|
33
33
|
#
|
34
|
-
# ActiveSupport::TestCase.test_order # => :
|
34
|
+
# ActiveSupport::TestCase.test_order # => :random
|
35
35
|
#
|
36
36
|
# Possible values are +:random+, +:parallel+, +:alpha+, +:sorted+.
|
37
|
-
# Defaults to +:
|
37
|
+
# Defaults to +:random+.
|
38
38
|
def test_order
|
39
|
-
test_order
|
40
|
-
|
41
|
-
if test_order.nil?
|
42
|
-
ActiveSupport::Deprecation.warn "You did not specify a value for the " \
|
43
|
-
"configuration option `active_support.test_order`. In Rails 5, " \
|
44
|
-
"the default value of this option will change from `:sorted` to " \
|
45
|
-
"`:random`.\n" \
|
46
|
-
"To disable this warning and keep the current behavior, you can add " \
|
47
|
-
"the following line to your `config/environments/test.rb`:\n" \
|
48
|
-
"\n" \
|
49
|
-
" Rails.application.configure do\n" \
|
50
|
-
" config.active_support.test_order = :sorted\n" \
|
51
|
-
" end\n" \
|
52
|
-
"\n" \
|
53
|
-
"Alternatively, you can opt into the future behavior by setting this " \
|
54
|
-
"option to `:random`."
|
55
|
-
|
56
|
-
test_order = :sorted
|
57
|
-
self.test_order = test_order
|
58
|
-
end
|
59
|
-
|
60
|
-
test_order
|
39
|
+
ActiveSupport.test_order ||= :random
|
61
40
|
end
|
62
|
-
|
63
|
-
alias :my_tests_are_order_dependent! :i_suck_and_my_tests_are_order_dependent!
|
64
41
|
end
|
65
42
|
|
66
43
|
alias_method :method_name, :name
|
@@ -70,6 +47,7 @@ module ActiveSupport
|
|
70
47
|
include ActiveSupport::Testing::Assertions
|
71
48
|
include ActiveSupport::Testing::Deprecation
|
72
49
|
include ActiveSupport::Testing::TimeHelpers
|
50
|
+
include ActiveSupport::Testing::FileFixtures
|
73
51
|
extend ActiveSupport::Testing::Declarative
|
74
52
|
|
75
53
|
# test/unit backwards compatibility methods
|
@@ -88,12 +66,20 @@ module ActiveSupport
|
|
88
66
|
alias :assert_not_respond_to :refute_respond_to
|
89
67
|
alias :assert_not_same :refute_same
|
90
68
|
|
91
|
-
|
69
|
+
|
70
|
+
# Assertion that the block should not raise an exception.
|
71
|
+
#
|
72
|
+
# Passes if evaluated code in the yielded block raises no exception.
|
92
73
|
#
|
93
74
|
# assert_nothing_raised do
|
94
|
-
#
|
75
|
+
# perform_service(param: 'no_exception')
|
95
76
|
# end
|
96
77
|
def assert_nothing_raised(*args)
|
78
|
+
if args.present?
|
79
|
+
ActiveSupport::Deprecation.warn(
|
80
|
+
"Passing arguments to assert_nothing_raised " \
|
81
|
+
"is deprecated and will be removed in Rails 5.1.")
|
82
|
+
end
|
97
83
|
yield
|
98
84
|
end
|
99
85
|
end
|
@@ -3,7 +3,7 @@ require 'active_support/core_ext/object/blank'
|
|
3
3
|
module ActiveSupport
|
4
4
|
module Testing
|
5
5
|
module Assertions
|
6
|
-
#
|
6
|
+
# Asserts that an expression is not truthy. Passes if <tt>object</tt> is
|
7
7
|
# +nil+ or +false+. "Truthy" means "considered true in a conditional"
|
8
8
|
# like <tt>if foo</tt>.
|
9
9
|
#
|
@@ -23,42 +23,42 @@ module ActiveSupport
|
|
23
23
|
# result of what is evaluated in the yielded block.
|
24
24
|
#
|
25
25
|
# assert_difference 'Article.count' do
|
26
|
-
# post :create, article: {...}
|
26
|
+
# post :create, params: { article: {...} }
|
27
27
|
# end
|
28
28
|
#
|
29
29
|
# An arbitrary expression is passed in and evaluated.
|
30
30
|
#
|
31
|
-
# assert_difference '
|
32
|
-
# post :create, comment: {...}
|
31
|
+
# assert_difference 'Article.last.comments(:reload).size' do
|
32
|
+
# post :create, params: { comment: {...} }
|
33
33
|
# end
|
34
34
|
#
|
35
35
|
# An arbitrary positive or negative difference can be specified.
|
36
36
|
# The default is <tt>1</tt>.
|
37
37
|
#
|
38
38
|
# assert_difference 'Article.count', -1 do
|
39
|
-
# post :delete, id: ...
|
39
|
+
# post :delete, params: { id: ... }
|
40
40
|
# end
|
41
41
|
#
|
42
42
|
# An array of expressions can also be passed in and evaluated.
|
43
43
|
#
|
44
44
|
# assert_difference [ 'Article.count', 'Post.count' ], 2 do
|
45
|
-
# post :create, article: {...}
|
45
|
+
# post :create, params: { article: {...} }
|
46
46
|
# end
|
47
47
|
#
|
48
48
|
# A lambda or a list of lambdas can be passed in and evaluated:
|
49
49
|
#
|
50
50
|
# assert_difference ->{ Article.count }, 2 do
|
51
|
-
# post :create, article: {...}
|
51
|
+
# post :create, params: { article: {...} }
|
52
52
|
# end
|
53
53
|
#
|
54
54
|
# assert_difference [->{ Article.count }, ->{ Post.count }], 2 do
|
55
|
-
# post :create, article: {...}
|
55
|
+
# post :create, params: { article: {...} }
|
56
56
|
# end
|
57
57
|
#
|
58
58
|
# An error message can be specified.
|
59
59
|
#
|
60
60
|
# assert_difference 'Article.count', -1, 'An Article should be destroyed' do
|
61
|
-
# post :delete, id: ...
|
61
|
+
# post :delete, params: { id: ... }
|
62
62
|
# end
|
63
63
|
def assert_difference(expression, difference = 1, message = nil, &block)
|
64
64
|
expressions = Array(expression)
|
@@ -66,28 +66,30 @@ module ActiveSupport
|
|
66
66
|
exps = expressions.map { |e|
|
67
67
|
e.respond_to?(:call) ? e : lambda { eval(e, block.binding) }
|
68
68
|
}
|
69
|
-
before = exps.map
|
69
|
+
before = exps.map(&:call)
|
70
70
|
|
71
|
-
yield
|
71
|
+
retval = yield
|
72
72
|
|
73
73
|
expressions.zip(exps).each_with_index do |(code, e), i|
|
74
74
|
error = "#{code.inspect} didn't change by #{difference}"
|
75
75
|
error = "#{message}.\n#{error}" if message
|
76
76
|
assert_equal(before[i] + difference, e.call, error)
|
77
77
|
end
|
78
|
+
|
79
|
+
retval
|
78
80
|
end
|
79
81
|
|
80
82
|
# Assertion that the numeric result of evaluating an expression is not
|
81
83
|
# changed before and after invoking the passed in block.
|
82
84
|
#
|
83
85
|
# assert_no_difference 'Article.count' do
|
84
|
-
# post :create, article: invalid_attributes
|
86
|
+
# post :create, params: { article: invalid_attributes }
|
85
87
|
# end
|
86
88
|
#
|
87
89
|
# An error message can be specified.
|
88
90
|
#
|
89
91
|
# assert_no_difference 'Article.count', 'An Article should not be created' do
|
90
|
-
# post :create, article: invalid_attributes
|
92
|
+
# post :create, params: { article: invalid_attributes }
|
91
93
|
# end
|
92
94
|
def assert_no_difference(expression, message = nil, &block)
|
93
95
|
assert_difference expression, 0, message, &block
|
@@ -3,8 +3,8 @@ require 'active_support/deprecation'
|
|
3
3
|
module ActiveSupport
|
4
4
|
module Testing
|
5
5
|
module Deprecation #:nodoc:
|
6
|
-
def assert_deprecated(match = nil, &block)
|
7
|
-
result, warnings = collect_deprecations(&block)
|
6
|
+
def assert_deprecated(match = nil, deprecator = nil, &block)
|
7
|
+
result, warnings = collect_deprecations(deprecator, &block)
|
8
8
|
assert !warnings.empty?, "Expected a deprecation warning within the block but received none"
|
9
9
|
if match
|
10
10
|
match = Regexp.new(Regexp.escape(match)) unless match.is_a?(Regexp)
|
@@ -13,22 +13,23 @@ module ActiveSupport
|
|
13
13
|
result
|
14
14
|
end
|
15
15
|
|
16
|
-
def assert_not_deprecated(&block)
|
17
|
-
result, deprecations = collect_deprecations(&block)
|
16
|
+
def assert_not_deprecated(deprecator = nil, &block)
|
17
|
+
result, deprecations = collect_deprecations(deprecator, &block)
|
18
18
|
assert deprecations.empty?, "Expected no deprecation warning within the block but received #{deprecations.size}: \n #{deprecations * "\n "}"
|
19
19
|
result
|
20
20
|
end
|
21
21
|
|
22
|
-
def collect_deprecations
|
23
|
-
|
22
|
+
def collect_deprecations(deprecator = nil)
|
23
|
+
deprecator ||= ActiveSupport::Deprecation
|
24
|
+
old_behavior = deprecator.behavior
|
24
25
|
deprecations = []
|
25
|
-
|
26
|
+
deprecator.behavior = Proc.new do |message, callstack|
|
26
27
|
deprecations << message
|
27
28
|
end
|
28
29
|
result = yield
|
29
30
|
[result, deprecations]
|
30
31
|
ensure
|
31
|
-
|
32
|
+
deprecator.behavior = old_behavior
|
32
33
|
end
|
33
34
|
end
|
34
35
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module ActiveSupport
|
2
|
+
module Testing
|
3
|
+
# Adds simple access to sample files called file fixtures.
|
4
|
+
# File fixtures are normal files stored in
|
5
|
+
# <tt>ActiveSupport::TestCase.file_fixture_path</tt>.
|
6
|
+
#
|
7
|
+
# File fixtures are represented as +Pathname+ objects.
|
8
|
+
# This makes it easy to extract specific information:
|
9
|
+
#
|
10
|
+
# file_fixture("example.txt").read # get the file's content
|
11
|
+
# file_fixture("example.mp3").size # get the file size
|
12
|
+
module FileFixtures
|
13
|
+
extend ActiveSupport::Concern
|
14
|
+
|
15
|
+
included do
|
16
|
+
class_attribute :file_fixture_path, instance_writer: false
|
17
|
+
end
|
18
|
+
|
19
|
+
# Returns a +Pathname+ to the fixture file named +fixture_name+.
|
20
|
+
#
|
21
|
+
# Raises +ArgumentError+ if +fixture_name+ can't be found.
|
22
|
+
def file_fixture(fixture_name)
|
23
|
+
path = Pathname.new(File.join(file_fixture_path, fixture_name))
|
24
|
+
|
25
|
+
if path.exist?
|
26
|
+
path
|
27
|
+
else
|
28
|
+
msg = "the directory '%s' does not contain a file named '%s'"
|
29
|
+
raise ArgumentError, msg % [file_fixture_path, fixture_name]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'rbconfig'
|
2
|
-
|
3
1
|
module ActiveSupport
|
4
2
|
module Testing
|
5
3
|
module Isolation
|
@@ -12,7 +10,7 @@ module ActiveSupport
|
|
12
10
|
end
|
13
11
|
|
14
12
|
def self.forking_env?
|
15
|
-
!ENV["NO_FORK"] && (
|
13
|
+
!ENV["NO_FORK"] && Process.respond_to?(:fork)
|
16
14
|
end
|
17
15
|
|
18
16
|
@@class_setup_mutex = Mutex.new
|
@@ -43,7 +41,23 @@ module ActiveSupport
|
|
43
41
|
pid = fork do
|
44
42
|
read.close
|
45
43
|
yield
|
46
|
-
|
44
|
+
begin
|
45
|
+
if error?
|
46
|
+
failures.map! { |e|
|
47
|
+
begin
|
48
|
+
Marshal.dump e
|
49
|
+
e
|
50
|
+
rescue TypeError
|
51
|
+
ex = Exception.new e.message
|
52
|
+
ex.set_backtrace e.backtrace
|
53
|
+
Minitest::UnexpectedError.new ex
|
54
|
+
end
|
55
|
+
}
|
56
|
+
end
|
57
|
+
result = Marshal.dump(self.dup)
|
58
|
+
end
|
59
|
+
|
60
|
+
write.puts [result].pack("m")
|
47
61
|
exit!
|
48
62
|
end
|
49
63
|
|
@@ -71,17 +85,17 @@ module ActiveSupport
|
|
71
85
|
else
|
72
86
|
Tempfile.open("isolation") do |tmpfile|
|
73
87
|
env = {
|
74
|
-
ISOLATION_TEST
|
75
|
-
ISOLATION_OUTPUT
|
88
|
+
'ISOLATION_TEST' => self.class.name,
|
89
|
+
'ISOLATION_OUTPUT' => tmpfile.path
|
76
90
|
}
|
77
91
|
|
78
92
|
load_paths = $-I.map {|p| "-I\"#{File.expand_path(p)}\"" }.join(" ")
|
79
93
|
orig_args = ORIG_ARGV.join(" ")
|
80
94
|
test_opts = "-n#{self.class.name}##{self.name}"
|
81
|
-
command = "#{Gem.ruby} #{load_paths} #{$0} #{orig_args} #{test_opts}"
|
95
|
+
command = "#{Gem.ruby} #{load_paths} #{$0} '#{orig_args}' #{test_opts}"
|
82
96
|
|
83
97
|
# IO.popen lets us pass env in a cross-platform way
|
84
|
-
child = IO.popen(
|
98
|
+
child = IO.popen(env, command)
|
85
99
|
|
86
100
|
begin
|
87
101
|
Process.wait(child.pid)
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'minitest/mock'
|
2
|
+
|
3
|
+
module ActiveSupport
|
4
|
+
module Testing
|
5
|
+
module MethodCallAssertions # :nodoc:
|
6
|
+
private
|
7
|
+
def assert_called(object, method_name, message = nil, times: 1, returns: nil)
|
8
|
+
times_called = 0
|
9
|
+
|
10
|
+
object.stub(method_name, proc { times_called += 1; returns }) { yield }
|
11
|
+
|
12
|
+
error = "Expected #{method_name} to be called #{times} times, " \
|
13
|
+
"but was called #{times_called} times"
|
14
|
+
error = "#{message}.\n#{error}" if message
|
15
|
+
assert_equal times, times_called, error
|
16
|
+
end
|
17
|
+
|
18
|
+
def assert_called_with(object, method_name, args = [], returns: nil)
|
19
|
+
mock = Minitest::Mock.new
|
20
|
+
|
21
|
+
if args.all? { |arg| arg.is_a?(Array) }
|
22
|
+
args.each { |arg| mock.expect(:call, returns, arg) }
|
23
|
+
else
|
24
|
+
mock.expect(:call, returns, args)
|
25
|
+
end
|
26
|
+
|
27
|
+
object.stub(method_name, mock) { yield }
|
28
|
+
|
29
|
+
mock.verify
|
30
|
+
end
|
31
|
+
|
32
|
+
def assert_not_called(object, method_name, message = nil, &block)
|
33
|
+
assert_called(object, method_name, message, times: 0, &block)
|
34
|
+
end
|
35
|
+
|
36
|
+
def stub_any_instance(klass, instance: klass.new)
|
37
|
+
klass.stub(:new, instance) { yield instance }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module ActiveSupport
|
2
|
+
module Testing
|
3
|
+
module Stream #:nodoc:
|
4
|
+
private
|
5
|
+
|
6
|
+
def silence_stream(stream)
|
7
|
+
old_stream = stream.dup
|
8
|
+
stream.reopen(IO::NULL)
|
9
|
+
stream.sync = true
|
10
|
+
yield
|
11
|
+
ensure
|
12
|
+
stream.reopen(old_stream)
|
13
|
+
old_stream.close
|
14
|
+
end
|
15
|
+
|
16
|
+
def quietly
|
17
|
+
silence_stream(STDOUT) do
|
18
|
+
silence_stream(STDERR) do
|
19
|
+
yield
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def capture(stream)
|
25
|
+
stream = stream.to_s
|
26
|
+
captured_stream = Tempfile.new(stream)
|
27
|
+
stream_io = eval("$#{stream}")
|
28
|
+
origin_stream = stream_io.dup
|
29
|
+
stream_io.reopen(captured_stream)
|
30
|
+
|
31
|
+
yield
|
32
|
+
|
33
|
+
stream_io.rewind
|
34
|
+
return captured_stream.read
|
35
|
+
ensure
|
36
|
+
captured_stream.close
|
37
|
+
captured_stream.unlink
|
38
|
+
stream_io.reopen(origin_stream)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|