activesupport 5.1.7 → 5.2.7

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.

Files changed (242) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +424 -512
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +3 -3
  5. data/lib/active_support/all.rb +2 -0
  6. data/lib/active_support/array_inquirer.rb +2 -0
  7. data/lib/active_support/backtrace_cleaner.rb +2 -0
  8. data/lib/active_support/benchmarkable.rb +2 -0
  9. data/lib/active_support/builder.rb +2 -0
  10. data/lib/active_support/cache/file_store.rb +5 -4
  11. data/lib/active_support/cache/mem_cache_store.rb +39 -38
  12. data/lib/active_support/cache/memory_store.rb +2 -0
  13. data/lib/active_support/cache/null_store.rb +2 -0
  14. data/lib/active_support/cache/redis_cache_store.rb +466 -0
  15. data/lib/active_support/cache/strategy/local_cache.rb +33 -2
  16. data/lib/active_support/cache/strategy/local_cache_middleware.rb +2 -0
  17. data/lib/active_support/cache.rb +197 -83
  18. data/lib/active_support/callbacks.rb +28 -39
  19. data/lib/active_support/concern.rb +10 -4
  20. data/lib/active_support/concurrency/share_lock.rb +2 -0
  21. data/lib/active_support/configurable.rb +2 -0
  22. data/lib/active_support/core_ext/array/access.rb +4 -2
  23. data/lib/active_support/core_ext/array/conversions.rb +2 -0
  24. data/lib/active_support/core_ext/array/extract_options.rb +2 -0
  25. data/lib/active_support/core_ext/array/grouping.rb +2 -0
  26. data/lib/active_support/core_ext/array/inquiry.rb +2 -0
  27. data/lib/active_support/core_ext/array/prepend_and_append.rb +4 -2
  28. data/lib/active_support/core_ext/array/wrap.rb +2 -0
  29. data/lib/active_support/core_ext/array.rb +2 -0
  30. data/lib/active_support/core_ext/benchmark.rb +2 -0
  31. data/lib/active_support/core_ext/big_decimal/conversions.rb +2 -0
  32. data/lib/active_support/core_ext/big_decimal.rb +2 -0
  33. data/lib/active_support/core_ext/class/attribute.rb +34 -16
  34. data/lib/active_support/core_ext/class/attribute_accessors.rb +2 -0
  35. data/lib/active_support/core_ext/class/subclasses.rb +1 -2
  36. data/lib/active_support/core_ext/class.rb +2 -0
  37. data/lib/active_support/core_ext/date/acts_like.rb +2 -0
  38. data/lib/active_support/core_ext/date/blank.rb +2 -0
  39. data/lib/active_support/core_ext/date/calculations.rb +2 -0
  40. data/lib/active_support/core_ext/date/conversions.rb +10 -9
  41. data/lib/active_support/core_ext/date/zones.rb +2 -0
  42. data/lib/active_support/core_ext/date.rb +2 -0
  43. data/lib/active_support/core_ext/date_and_time/calculations.rb +50 -16
  44. data/lib/active_support/core_ext/date_and_time/compatibility.rb +3 -1
  45. data/lib/active_support/core_ext/date_and_time/zones.rb +2 -0
  46. data/lib/active_support/core_ext/date_time/acts_like.rb +2 -0
  47. data/lib/active_support/core_ext/date_time/blank.rb +2 -0
  48. data/lib/active_support/core_ext/date_time/calculations.rb +2 -0
  49. data/lib/active_support/core_ext/date_time/compatibility.rb +7 -5
  50. data/lib/active_support/core_ext/date_time/conversions.rb +2 -0
  51. data/lib/active_support/core_ext/date_time.rb +2 -0
  52. data/lib/active_support/core_ext/digest/uuid.rb +3 -1
  53. data/lib/active_support/core_ext/digest.rb +3 -0
  54. data/lib/active_support/core_ext/enumerable.rb +8 -1
  55. data/lib/active_support/core_ext/file/atomic.rb +3 -1
  56. data/lib/active_support/core_ext/file.rb +2 -0
  57. data/lib/active_support/core_ext/hash/compact.rb +2 -0
  58. data/lib/active_support/core_ext/hash/conversions.rb +4 -2
  59. data/lib/active_support/core_ext/hash/deep_merge.rb +8 -12
  60. data/lib/active_support/core_ext/hash/except.rb +2 -0
  61. data/lib/active_support/core_ext/hash/indifferent_access.rb +2 -0
  62. data/lib/active_support/core_ext/hash/keys.rb +2 -0
  63. data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
  64. data/lib/active_support/core_ext/hash/slice.rb +4 -4
  65. data/lib/active_support/core_ext/hash/transform_values.rb +2 -0
  66. data/lib/active_support/core_ext/hash.rb +2 -0
  67. data/lib/active_support/core_ext/integer/inflections.rb +2 -0
  68. data/lib/active_support/core_ext/integer/multiple.rb +2 -0
  69. data/lib/active_support/core_ext/integer/time.rb +7 -14
  70. data/lib/active_support/core_ext/integer.rb +2 -0
  71. data/lib/active_support/core_ext/kernel/agnostics.rb +2 -0
  72. data/lib/active_support/core_ext/kernel/concern.rb +2 -0
  73. data/lib/active_support/core_ext/kernel/reporting.rb +2 -0
  74. data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
  75. data/lib/active_support/core_ext/kernel.rb +2 -0
  76. data/lib/active_support/core_ext/load_error.rb +2 -7
  77. data/lib/active_support/core_ext/marshal.rb +2 -0
  78. data/lib/active_support/core_ext/module/aliasing.rb +2 -0
  79. data/lib/active_support/core_ext/module/anonymous.rb +2 -0
  80. data/lib/active_support/core_ext/module/attr_internal.rb +2 -0
  81. data/lib/active_support/core_ext/module/attribute_accessors.rb +21 -24
  82. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +2 -0
  83. data/lib/active_support/core_ext/module/concerning.rb +7 -8
  84. data/lib/active_support/core_ext/module/delegation.rb +31 -29
  85. data/lib/active_support/core_ext/module/deprecation.rb +2 -0
  86. data/lib/active_support/core_ext/module/introspection.rb +2 -0
  87. data/lib/active_support/core_ext/module/reachable.rb +3 -0
  88. data/lib/active_support/core_ext/module/redefine_method.rb +49 -0
  89. data/lib/active_support/core_ext/module/remove_method.rb +5 -23
  90. data/lib/active_support/core_ext/module.rb +3 -0
  91. data/lib/active_support/core_ext/name_error.rb +7 -0
  92. data/lib/active_support/core_ext/numeric/bytes.rb +2 -0
  93. data/lib/active_support/core_ext/numeric/conversions.rb +9 -7
  94. data/lib/active_support/core_ext/numeric/inquiry.rb +2 -0
  95. data/lib/active_support/core_ext/numeric/time.rb +7 -15
  96. data/lib/active_support/core_ext/numeric.rb +2 -0
  97. data/lib/active_support/core_ext/object/acts_like.rb +12 -1
  98. data/lib/active_support/core_ext/object/blank.rb +12 -1
  99. data/lib/active_support/core_ext/object/conversions.rb +2 -0
  100. data/lib/active_support/core_ext/object/deep_dup.rb +2 -0
  101. data/lib/active_support/core_ext/object/duplicable.rb +10 -8
  102. data/lib/active_support/core_ext/object/inclusion.rb +2 -0
  103. data/lib/active_support/core_ext/object/instance_variables.rb +2 -0
  104. data/lib/active_support/core_ext/object/json.rb +8 -0
  105. data/lib/active_support/core_ext/object/to_param.rb +2 -0
  106. data/lib/active_support/core_ext/object/to_query.rb +2 -0
  107. data/lib/active_support/core_ext/object/try.rb +2 -0
  108. data/lib/active_support/core_ext/object/with_options.rb +3 -1
  109. data/lib/active_support/core_ext/object.rb +2 -0
  110. data/lib/active_support/core_ext/range/compare_range.rb +61 -0
  111. data/lib/active_support/core_ext/range/conversions.rb +9 -1
  112. data/lib/active_support/core_ext/range/each.rb +5 -1
  113. data/lib/active_support/core_ext/range/include_range.rb +2 -22
  114. data/lib/active_support/core_ext/range/include_time_with_zone.rb +23 -0
  115. data/lib/active_support/core_ext/range/overlaps.rb +2 -0
  116. data/lib/active_support/core_ext/range.rb +4 -1
  117. data/lib/active_support/core_ext/regexp.rb +2 -0
  118. data/lib/active_support/core_ext/securerandom.rb +2 -0
  119. data/lib/active_support/core_ext/string/access.rb +2 -0
  120. data/lib/active_support/core_ext/string/behavior.rb +2 -0
  121. data/lib/active_support/core_ext/string/conversions.rb +2 -0
  122. data/lib/active_support/core_ext/string/exclude.rb +2 -0
  123. data/lib/active_support/core_ext/string/filters.rb +2 -0
  124. data/lib/active_support/core_ext/string/indent.rb +2 -0
  125. data/lib/active_support/core_ext/string/inflections.rb +26 -12
  126. data/lib/active_support/core_ext/string/inquiry.rb +2 -0
  127. data/lib/active_support/core_ext/string/multibyte.rb +4 -0
  128. data/lib/active_support/core_ext/string/output_safety.rb +6 -7
  129. data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -0
  130. data/lib/active_support/core_ext/string/strip.rb +2 -0
  131. data/lib/active_support/core_ext/string/zones.rb +2 -0
  132. data/lib/active_support/core_ext/string.rb +2 -0
  133. data/lib/active_support/core_ext/time/acts_like.rb +2 -0
  134. data/lib/active_support/core_ext/time/calculations.rb +23 -15
  135. data/lib/active_support/core_ext/time/compatibility.rb +4 -2
  136. data/lib/active_support/core_ext/time/conversions.rb +2 -0
  137. data/lib/active_support/core_ext/time/zones.rb +6 -4
  138. data/lib/active_support/core_ext/time.rb +2 -0
  139. data/lib/active_support/core_ext/uri.rb +6 -6
  140. data/lib/active_support/core_ext.rb +3 -1
  141. data/lib/active_support/current_attributes.rb +195 -0
  142. data/lib/active_support/dependencies/autoload.rb +2 -0
  143. data/lib/active_support/dependencies/interlock.rb +2 -0
  144. data/lib/active_support/dependencies.rb +25 -26
  145. data/lib/active_support/deprecation/behaviors.rb +28 -9
  146. data/lib/active_support/deprecation/constant_accessor.rb +4 -2
  147. data/lib/active_support/deprecation/instance_delegator.rb +2 -0
  148. data/lib/active_support/deprecation/method_wrappers.rb +30 -17
  149. data/lib/active_support/deprecation/proxy_wrappers.rb +5 -2
  150. data/lib/active_support/deprecation/reporting.rb +5 -3
  151. data/lib/active_support/deprecation.rb +4 -2
  152. data/lib/active_support/descendants_tracker.rb +2 -0
  153. data/lib/active_support/digest.rb +20 -0
  154. data/lib/active_support/duration/iso8601_parser.rb +4 -2
  155. data/lib/active_support/duration/iso8601_serializer.rb +4 -2
  156. data/lib/active_support/duration.rb +22 -14
  157. data/lib/active_support/encrypted_configuration.rb +49 -0
  158. data/lib/active_support/encrypted_file.rb +99 -0
  159. data/lib/active_support/evented_file_update_checker.rb +2 -0
  160. data/lib/active_support/execution_wrapper.rb +18 -13
  161. data/lib/active_support/executor.rb +2 -0
  162. data/lib/active_support/file_update_checker.rb +2 -0
  163. data/lib/active_support/gem_version.rb +3 -1
  164. data/lib/active_support/gzip.rb +2 -0
  165. data/lib/active_support/hash_with_indifferent_access.rb +55 -1
  166. data/lib/active_support/i18n.rb +3 -1
  167. data/lib/active_support/i18n_railtie.rb +4 -6
  168. data/lib/active_support/inflections.rb +2 -0
  169. data/lib/active_support/inflector/inflections.rb +20 -4
  170. data/lib/active_support/inflector/methods.rb +43 -24
  171. data/lib/active_support/inflector/transliterate.rb +17 -8
  172. data/lib/active_support/inflector.rb +2 -0
  173. data/lib/active_support/json/decoding.rb +2 -0
  174. data/lib/active_support/json/encoding.rb +2 -0
  175. data/lib/active_support/json.rb +2 -0
  176. data/lib/active_support/key_generator.rb +3 -1
  177. data/lib/active_support/lazy_load_hooks.rb +2 -0
  178. data/lib/active_support/log_subscriber/test_helper.rb +2 -0
  179. data/lib/active_support/log_subscriber.rb +3 -2
  180. data/lib/active_support/logger.rb +2 -0
  181. data/lib/active_support/logger_silence.rb +3 -2
  182. data/lib/active_support/logger_thread_safe_level.rb +4 -1
  183. data/lib/active_support/message_encryptor.rb +95 -22
  184. data/lib/active_support/message_verifier.rb +78 -7
  185. data/lib/active_support/messages/metadata.rb +71 -0
  186. data/lib/active_support/messages/rotation_configuration.rb +22 -0
  187. data/lib/active_support/messages/rotator.rb +56 -0
  188. data/lib/active_support/multibyte/chars.rb +2 -0
  189. data/lib/active_support/multibyte/unicode.rb +4 -2
  190. data/lib/active_support/multibyte.rb +2 -0
  191. data/lib/active_support/notifications/fanout.rb +4 -2
  192. data/lib/active_support/notifications/instrumenter.rb +2 -0
  193. data/lib/active_support/notifications.rb +2 -0
  194. data/lib/active_support/number_helper/number_converter.rb +2 -0
  195. data/lib/active_support/number_helper/number_to_currency_converter.rb +2 -0
  196. data/lib/active_support/number_helper/number_to_delimited_converter.rb +2 -0
  197. data/lib/active_support/number_helper/number_to_human_converter.rb +2 -0
  198. data/lib/active_support/number_helper/number_to_human_size_converter.rb +2 -0
  199. data/lib/active_support/number_helper/number_to_percentage_converter.rb +2 -0
  200. data/lib/active_support/number_helper/number_to_phone_converter.rb +3 -1
  201. data/lib/active_support/number_helper/number_to_rounded_converter.rb +2 -20
  202. data/lib/active_support/number_helper/rounding_helper.rb +6 -4
  203. data/lib/active_support/number_helper.rb +2 -0
  204. data/lib/active_support/option_merger.rb +2 -0
  205. data/lib/active_support/ordered_hash.rb +2 -0
  206. data/lib/active_support/ordered_options.rb +5 -3
  207. data/lib/active_support/per_thread_registry.rb +2 -0
  208. data/lib/active_support/proxy_object.rb +2 -0
  209. data/lib/active_support/rails.rb +2 -0
  210. data/lib/active_support/railtie.rb +37 -8
  211. data/lib/active_support/reloader.rb +8 -6
  212. data/lib/active_support/rescuable.rb +3 -2
  213. data/lib/active_support/security_utils.rb +15 -11
  214. data/lib/active_support/string_inquirer.rb +2 -0
  215. data/lib/active_support/subscriber.rb +8 -2
  216. data/lib/active_support/tagged_logging.rb +2 -0
  217. data/lib/active_support/test_case.rb +3 -2
  218. data/lib/active_support/testing/assertions.rb +31 -14
  219. data/lib/active_support/testing/autorun.rb +2 -0
  220. data/lib/active_support/testing/constant_lookup.rb +2 -0
  221. data/lib/active_support/testing/declarative.rb +2 -0
  222. data/lib/active_support/testing/deprecation.rb +2 -0
  223. data/lib/active_support/testing/file_fixtures.rb +2 -0
  224. data/lib/active_support/testing/isolation.rb +3 -1
  225. data/lib/active_support/testing/method_call_assertions.rb +2 -0
  226. data/lib/active_support/testing/setup_and_teardown.rb +12 -7
  227. data/lib/active_support/testing/stream.rb +2 -0
  228. data/lib/active_support/testing/tagged_logging.rb +2 -0
  229. data/lib/active_support/testing/time_helpers.rb +33 -3
  230. data/lib/active_support/time.rb +2 -0
  231. data/lib/active_support/time_with_zone.rb +38 -0
  232. data/lib/active_support/values/time_zone.rb +20 -8
  233. data/lib/active_support/version.rb +2 -0
  234. data/lib/active_support/xml_mini/jdom.rb +4 -2
  235. data/lib/active_support/xml_mini/libxml.rb +3 -1
  236. data/lib/active_support/xml_mini/libxmlsax.rb +4 -2
  237. data/lib/active_support/xml_mini/nokogiri.rb +3 -1
  238. data/lib/active_support/xml_mini/nokogirisax.rb +3 -1
  239. data/lib/active_support/xml_mini/rexml.rb +3 -1
  240. data/lib/active_support/xml_mini.rb +4 -2
  241. data/lib/active_support.rb +5 -13
  242. metadata +17 -5
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/object/blank"
2
4
 
3
5
  module ActiveSupport
@@ -22,7 +24,7 @@ module ActiveSupport
22
24
  # To raise an exception when the value is blank, append a
23
25
  # bang to the key name, like:
24
26
  #
25
- # h.dog! # => raises KeyError: key not found: :dog
27
+ # h.dog! # => raises KeyError: :dog is blank
26
28
  #
27
29
  class OrderedOptions < Hash
28
30
  alias_method :_get, :[] # preserve the original #[] method
@@ -37,14 +39,14 @@ module ActiveSupport
37
39
  end
38
40
 
39
41
  def method_missing(name, *args)
40
- name_string = name.to_s
42
+ name_string = name.to_s.dup
41
43
  if name_string.chomp!("=")
42
44
  self[name_string] = args.first
43
45
  else
44
46
  bangs = name_string.chomp!("!")
45
47
 
46
48
  if bangs
47
- fetch(name_string.to_sym).presence || raise(KeyError.new("#{name_string} is blank."))
49
+ self[name_string].presence || raise(KeyError.new(":#{name_string} is blank"))
48
50
  else
49
51
  self[name_string]
50
52
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/module/delegation"
2
4
 
3
5
  module ActiveSupport
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveSupport
2
4
  # A class with no predefined methods that behaves similarly to Builder's
3
5
  # BlankSlate. Used for proxy classes.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # This is private interface.
2
4
  #
3
5
  # Rails components cherry pick from Active Support as needed, but there are a
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support"
2
4
  require "active_support/i18n_railtie"
3
5
 
@@ -7,6 +9,21 @@ module ActiveSupport
7
9
 
8
10
  config.eager_load_namespaces << ActiveSupport
9
11
 
12
+ initializer "active_support.set_authenticated_message_encryption" do |app|
13
+ config.after_initialize do
14
+ unless app.config.active_support.use_authenticated_message_encryption.nil?
15
+ ActiveSupport::MessageEncryptor.use_authenticated_message_encryption =
16
+ app.config.active_support.use_authenticated_message_encryption
17
+ end
18
+ end
19
+ end
20
+
21
+ initializer "active_support.reset_all_current_attributes_instances" do |app|
22
+ app.reloader.before_class_unload { ActiveSupport::CurrentAttributes.clear_all }
23
+ app.executor.to_run { ActiveSupport::CurrentAttributes.reset_all }
24
+ app.executor.to_complete { ActiveSupport::CurrentAttributes.reset_all }
25
+ end
26
+
10
27
  initializer "active_support.deprecation_behavior" do |app|
11
28
  if deprecation = app.config.active_support.deprecation
12
29
  ActiveSupport::Deprecation.behavior = deprecation
@@ -22,14 +39,7 @@ module ActiveSupport
22
39
  raise e.exception "tzinfo-data is not present. Please add gem 'tzinfo-data' to your Gemfile and run bundle install"
23
40
  end
24
41
  require "active_support/core_ext/time/zones"
25
- zone_default = Time.find_zone!(app.config.time_zone)
26
-
27
- unless zone_default
28
- raise "Value assigned to config.time_zone not recognized. " \
29
- 'Run "rake time:zones:all" for a time zone names list.'
30
- end
31
-
32
- Time.zone_default = zone_default
42
+ Time.zone_default = Time.find_zone!(app.config.time_zone)
33
43
  end
34
44
 
35
45
  # Sets the default week start
@@ -41,11 +51,30 @@ module ActiveSupport
41
51
  Date.beginning_of_week_default = beginning_of_week_default
42
52
  end
43
53
 
54
+ initializer "active_support.require_master_key" do |app|
55
+ if app.config.respond_to?(:require_master_key) && app.config.require_master_key
56
+ begin
57
+ app.credentials.key
58
+ rescue ActiveSupport::EncryptedFile::MissingKeyError => error
59
+ $stderr.puts error.message
60
+ exit 1
61
+ end
62
+ end
63
+ end
64
+
44
65
  initializer "active_support.set_configs" do |app|
45
66
  app.config.active_support.each do |k, v|
46
67
  k = "#{k}="
47
68
  ActiveSupport.send(k, v) if ActiveSupport.respond_to? k
48
69
  end
49
70
  end
71
+
72
+ initializer "active_support.set_hash_digest_class" do |app|
73
+ config.after_initialize do
74
+ if app.config.active_support.use_sha1_digests
75
+ ActiveSupport::Digest.hash_digest_class = ::Digest::SHA1
76
+ end
77
+ end
78
+ end
50
79
  end
51
80
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/execution_wrapper"
2
4
 
3
5
  module ActiveSupport
@@ -26,14 +28,17 @@ module ActiveSupport
26
28
 
27
29
  define_callbacks :class_unload
28
30
 
31
+ # Registers a callback that will run once at application startup and every time the code is reloaded.
29
32
  def self.to_prepare(*args, &block)
30
33
  set_callback(:prepare, *args, &block)
31
34
  end
32
35
 
36
+ # Registers a callback that will run immediately before the classes are unloaded.
33
37
  def self.before_class_unload(*args, &block)
34
38
  set_callback(:class_unload, *args, &block)
35
39
  end
36
40
 
41
+ # Registers a callback that will run immediately after the classes are unloaded.
37
42
  def self.after_class_unload(*args, &block)
38
43
  set_callback(:class_unload, :after, *args, &block)
39
44
  end
@@ -54,7 +59,7 @@ module ActiveSupport
54
59
  prepare!
55
60
  end
56
61
 
57
- def self.run! # :nodoc:
62
+ def self.run!(reset: false) # :nodoc:
58
63
  if check!
59
64
  super
60
65
  else
@@ -69,11 +74,8 @@ module ActiveSupport
69
74
  end
70
75
  end
71
76
 
72
- class_attribute :executor
73
- class_attribute :check
74
-
75
- self.executor = Executor
76
- self.check = lambda { false }
77
+ class_attribute :executor, default: Executor
78
+ class_attribute :check, default: lambda { false }
77
79
 
78
80
  def self.check! # :nodoc:
79
81
  @should_reload ||= check.call
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/concern"
2
4
  require "active_support/core_ext/class/attribute"
3
5
  require "active_support/core_ext/string/inflections"
@@ -8,8 +10,7 @@ module ActiveSupport
8
10
  extend Concern
9
11
 
10
12
  included do
11
- class_attribute :rescue_handlers
12
- self.rescue_handlers = []
13
+ class_attribute :rescue_handlers, default: []
13
14
  end
14
15
 
15
16
  module ClassMethods
@@ -1,15 +1,15 @@
1
- require "digest"
1
+ # frozen_string_literal: true
2
+
3
+ require "digest/sha2"
2
4
 
3
5
  module ActiveSupport
4
6
  module SecurityUtils
5
- # Constant time string comparison.
7
+ # Constant time string comparison, for fixed length strings.
6
8
  #
7
9
  # The values compared should be of fixed length, such as strings
8
- # that have already been processed by HMAC. This should not be used
9
- # on variable length plaintext strings because it could leak length info
10
- # via timing attacks.
11
- def secure_compare(a, b)
12
- return false unless a.bytesize == b.bytesize
10
+ # that have already been processed by HMAC. Raises in case of length mismatch.
11
+ def fixed_length_secure_compare(a, b)
12
+ raise ArgumentError, "string length mismatch." unless a.bytesize == b.bytesize
13
13
 
14
14
  l = a.unpack "C#{a.bytesize}"
15
15
 
@@ -17,11 +17,15 @@ module ActiveSupport
17
17
  b.each_byte { |byte| res |= byte ^ l.shift }
18
18
  res == 0
19
19
  end
20
- module_function :secure_compare
20
+ module_function :fixed_length_secure_compare
21
21
 
22
- def variable_size_secure_compare(a, b) # :nodoc:
23
- secure_compare(::Digest::SHA256.hexdigest(a), ::Digest::SHA256.hexdigest(b))
22
+ # Constant time string comparison, for variable length strings.
23
+ #
24
+ # The values are first processed by SHA256, so that we don't leak length info
25
+ # via timing attacks.
26
+ def secure_compare(a, b)
27
+ fixed_length_secure_compare(::Digest::SHA256.hexdigest(a), ::Digest::SHA256.hexdigest(b)) && a == b
24
28
  end
25
- module_function :variable_size_secure_compare
29
+ module_function :secure_compare
26
30
  end
27
31
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveSupport
2
4
  # Wrapping a string in this class gives you a prettier way to test
3
5
  # for equality. The value returned by <tt>Rails.env</tt> is wrapped
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/per_thread_registry"
2
4
  require "active_support/notifications"
3
5
 
@@ -82,7 +84,7 @@ module ActiveSupport
82
84
  end
83
85
 
84
86
  def start(name, id, payload)
85
- e = ActiveSupport::Notifications::Event.new(name, Time.now, nil, id, payload)
87
+ e = ActiveSupport::Notifications::Event.new(name, now, nil, id, payload)
86
88
  parent = event_stack.last
87
89
  parent << e if parent
88
90
 
@@ -90,7 +92,7 @@ module ActiveSupport
90
92
  end
91
93
 
92
94
  def finish(name, id, payload)
93
- finished = Time.now
95
+ finished = now
94
96
  event = event_stack.pop
95
97
  event.end = finished
96
98
  event.payload.merge!(payload)
@@ -104,6 +106,10 @@ module ActiveSupport
104
106
  def event_stack
105
107
  SubscriberQueueRegistry.instance.get_queue(@queue_key)
106
108
  end
109
+
110
+ def now
111
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
112
+ end
107
113
  end
108
114
 
109
115
  # This is a registry for all the event stacks kept for subscribers.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/module/delegation"
2
4
  require "active_support/core_ext/object/blank"
3
5
  require "logger"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  gem "minitest" # make sure we get the gem, not stdlib
2
4
  require "minitest"
3
5
  require "active_support/testing/tagged_logging"
@@ -9,7 +11,6 @@ require "active_support/testing/isolation"
9
11
  require "active_support/testing/constant_lookup"
10
12
  require "active_support/testing/time_helpers"
11
13
  require "active_support/testing/file_fixtures"
12
- require "active_support/core_ext/kernel/reporting"
13
14
 
14
15
  module ActiveSupport
15
16
  class TestCase < ::Minitest::Test
@@ -43,7 +44,7 @@ module ActiveSupport
43
44
  alias_method :method_name, :name
44
45
 
45
46
  include ActiveSupport::Testing::TaggedLogging
46
- include ActiveSupport::Testing::SetupAndTeardown
47
+ prepend ActiveSupport::Testing::SetupAndTeardown
47
48
  include ActiveSupport::Testing::Assertions
48
49
  include ActiveSupport::Testing::Deprecation
49
50
  include ActiveSupport::Testing::TimeHelpers
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveSupport
2
4
  module Testing
3
5
  module Assertions
@@ -56,6 +58,12 @@ module ActiveSupport
56
58
  # post :create, params: { article: {...} }
57
59
  # end
58
60
  #
61
+ # A hash of expressions/numeric differences can also be passed in and evaluated.
62
+ #
63
+ # assert_difference ->{ Article.count } => 1, ->{ Notification.count } => 2 do
64
+ # post :create, params: { article: {...} }
65
+ # end
66
+ #
59
67
  # A lambda or a list of lambdas can be passed in and evaluated:
60
68
  #
61
69
  # assert_difference ->{ Article.count }, 2 do
@@ -71,20 +79,28 @@ module ActiveSupport
71
79
  # assert_difference 'Article.count', -1, 'An Article should be destroyed' do
72
80
  # post :delete, params: { id: ... }
73
81
  # end
74
- def assert_difference(expression, difference = 1, message = nil, &block)
75
- expressions = Array(expression)
76
-
77
- exps = expressions.map { |e|
82
+ def assert_difference(expression, *args, &block)
83
+ expressions =
84
+ if expression.is_a?(Hash)
85
+ message = args[0]
86
+ expression
87
+ else
88
+ difference = args[0] || 1
89
+ message = args[1]
90
+ Hash[Array(expression).map { |e| [e, difference] }]
91
+ end
92
+
93
+ exps = expressions.keys.map { |e|
78
94
  e.respond_to?(:call) ? e : lambda { eval(e, block.binding) }
79
95
  }
80
96
  before = exps.map(&:call)
81
97
 
82
98
  retval = yield
83
99
 
84
- expressions.zip(exps).each_with_index do |(code, e), i|
85
- error = "#{code.inspect} didn't change by #{difference}"
100
+ expressions.zip(exps, before) do |(code, diff), exp, before_value|
101
+ error = "#{code.inspect} didn't change by #{diff}"
86
102
  error = "#{message}.\n#{error}" if message
87
- assert_equal(before[i] + difference, e.call, error)
103
+ assert_equal(before_value + diff, exp.call, error)
88
104
  end
89
105
 
90
106
  retval
@@ -154,11 +170,12 @@ module ActiveSupport
154
170
 
155
171
  after = exp.call
156
172
 
157
- if to == UNTRACKED
158
- error = "#{expression.inspect} didn't changed"
159
- error = "#{message}.\n#{error}" if message
160
- assert_not_equal before, after, error
161
- else
173
+ error = "#{expression.inspect} didn't change"
174
+ error = "#{error}. It was already #{to}" if before == to
175
+ error = "#{message}.\n#{error}" if message
176
+ assert before != after, error
177
+
178
+ unless to == UNTRACKED
162
179
  error = "#{expression.inspect} didn't change to #{to}"
163
180
  error = "#{message}.\n#{error}" if message
164
181
  assert to === after, error
@@ -167,7 +184,7 @@ module ActiveSupport
167
184
  retval
168
185
  end
169
186
 
170
- # Assertion that the result of evaluating an expression is changed before
187
+ # Assertion that the result of evaluating an expression is not changed before
171
188
  # and after invoking the passed in block.
172
189
  #
173
190
  # assert_no_changes 'Status.all_good?' do
@@ -188,7 +205,7 @@ module ActiveSupport
188
205
 
189
206
  error = "#{expression.inspect} did change to #{after}"
190
207
  error = "#{message}.\n#{error}" if message
191
- assert_equal before, after, error
208
+ assert before == after, error
192
209
 
193
210
  retval
194
211
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  gem "minitest"
2
4
 
3
5
  require "minitest"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/concern"
2
4
  require "active_support/inflector"
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveSupport
2
4
  module Testing
3
5
  module Declarative
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/deprecation"
2
4
  require "active_support/core_ext/regexp"
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveSupport
2
4
  module Testing
3
5
  # Adds simple access to sample files called file fixtures.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveSupport
2
4
  module Testing
3
5
  module Isolation
@@ -54,7 +56,7 @@ module ActiveSupport
54
56
  write.close
55
57
  result = read.read
56
58
  Process.wait2(pid)
57
- return result.unpack("m")[0]
59
+ result.unpack("m")[0]
58
60
  end
59
61
  end
60
62
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "minitest/mock"
2
4
 
3
5
  module ActiveSupport
@@ -1,4 +1,5 @@
1
- require "active_support/concern"
1
+ # frozen_string_literal: true
2
+
2
3
  require "active_support/callbacks"
3
4
 
4
5
  module ActiveSupport
@@ -17,11 +18,10 @@ module ActiveSupport
17
18
  # end
18
19
  # end
19
20
  module SetupAndTeardown
20
- extend ActiveSupport::Concern
21
-
22
- included do
23
- include ActiveSupport::Callbacks
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
- run_callbacks :teardown
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
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveSupport
2
4
  module Testing
3
5
  module Stream #:nodoc:
@@ -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
@@ -1,3 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/module/redefine_method"
1
4
  require "active_support/core_ext/string/strip" # for strip_heredoc
2
5
  require "active_support/core_ext/time/calculations"
3
6
  require "concurrent/map"
@@ -41,7 +44,7 @@ module ActiveSupport
41
44
 
42
45
  def unstub_object(stub)
43
46
  singleton_class = stub.object.singleton_class
44
- singleton_class.send :undef_method, stub.method_name
47
+ singleton_class.send :silence_redefinition_of_method, stub.method_name
45
48
  singleton_class.send :alias_method, stub.method_name, stub.original_method
46
49
  singleton_class.send :undef_method, stub.original_method
47
50
  end
@@ -49,8 +52,14 @@ module ActiveSupport
49
52
 
50
53
  # Contains helpers that help you test passage of time.
51
54
  module TimeHelpers
55
+ def after_teardown
56
+ travel_back
57
+ super
58
+ end
59
+
52
60
  # Changes current time to the time in the future or in the past by a given time difference by
53
- # stubbing +Time.now+, +Date.today+, and +DateTime.now+.
61
+ # stubbing +Time.now+, +Date.today+, and +DateTime.now+. The stubs are automatically removed
62
+ # at the end of the test.
54
63
  #
55
64
  # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
56
65
  # travel 1.day
@@ -72,6 +81,7 @@ module ActiveSupport
72
81
 
73
82
  # Changes current time to the given time by stubbing +Time.now+,
74
83
  # +Date.today+, and +DateTime.now+ to return the time or date passed into this method.
84
+ # The stubs are automatically removed at the end of the test.
75
85
  #
76
86
  # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
77
87
  # travel_to Time.zone.local(2004, 11, 24, 01, 04, 44)
@@ -149,7 +159,7 @@ module ActiveSupport
149
159
  end
150
160
 
151
161
  # Returns the current time back to its original state, by removing the stubs added by
152
- # `travel` and `travel_to`.
162
+ # +travel+ and +travel_to+.
153
163
  #
154
164
  # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
155
165
  # travel_to Time.zone.local(2004, 11, 24, 01, 04, 44)
@@ -160,6 +170,26 @@ module ActiveSupport
160
170
  simple_stubs.unstub_all!
161
171
  end
162
172
 
173
+ # Calls +travel_to+ with +Time.now+.
174
+ #
175
+ # Time.current # => Sun, 09 Jul 2017 15:34:49 EST -05:00
176
+ # freeze_time
177
+ # sleep(1)
178
+ # Time.current # => Sun, 09 Jul 2017 15:34:49 EST -05:00
179
+ #
180
+ # This method also accepts a block, which will return the current time back to its original
181
+ # state at the end of the block:
182
+ #
183
+ # Time.current # => Sun, 09 Jul 2017 15:34:49 EST -05:00
184
+ # freeze_time do
185
+ # sleep(1)
186
+ # User.create.created_at # => Sun, 09 Jul 2017 15:34:49 EST -05:00
187
+ # end
188
+ # Time.current # => Sun, 09 Jul 2017 15:34:50 EST -05:00
189
+ def freeze_time(&block)
190
+ travel_to Time.now, &block
191
+ end
192
+
163
193
  private
164
194
 
165
195
  def simple_stubs
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveSupport
2
4
  autoload :Duration, "active_support/duration"
3
5
  autoload :TimeWithZone, "active_support/time_with_zone"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/duration"
2
4
  require "active_support/values/time_zone"
3
5
  require "active_support/core_ext/object/acts_like"
@@ -330,6 +332,42 @@ module ActiveSupport
330
332
  since(-other)
331
333
  end
332
334
 
335
+ # Returns a new +ActiveSupport::TimeWithZone+ where one or more of the elements have
336
+ # been changed according to the +options+ parameter. The time options (<tt>:hour</tt>,
337
+ # <tt>:min</tt>, <tt>:sec</tt>, <tt>:usec</tt>, <tt>:nsec</tt>) reset cascadingly,
338
+ # so if only the hour is passed, then minute, sec, usec and nsec is set to 0. If the
339
+ # hour and minute is passed, then sec, usec and nsec is set to 0. The +options+
340
+ # parameter takes a hash with any of these keys: <tt>:year</tt>, <tt>:month</tt>,
341
+ # <tt>:day</tt>, <tt>:hour</tt>, <tt>:min</tt>, <tt>:sec</tt>, <tt>:usec</tt>,
342
+ # <tt>:nsec</tt>, <tt>:offset</tt>, <tt>:zone</tt>. Pass either <tt>:usec</tt>
343
+ # or <tt>:nsec</tt>, not both. Similarly, pass either <tt>:zone</tt> or
344
+ # <tt>:offset</tt>, not both.
345
+ #
346
+ # t = Time.zone.now # => Fri, 14 Apr 2017 11:45:15 EST -05:00
347
+ # t.change(year: 2020) # => Tue, 14 Apr 2020 11:45:15 EST -05:00
348
+ # t.change(hour: 12) # => Fri, 14 Apr 2017 12:00:00 EST -05:00
349
+ # t.change(min: 30) # => Fri, 14 Apr 2017 11:30:00 EST -05:00
350
+ # t.change(offset: "-10:00") # => Fri, 14 Apr 2017 11:45:15 HST -10:00
351
+ # t.change(zone: "Hawaii") # => Fri, 14 Apr 2017 11:45:15 HST -10:00
352
+ def change(options)
353
+ if options[:zone] && options[:offset]
354
+ raise ArgumentError, "Can't change both :offset and :zone at the same time: #{options.inspect}"
355
+ end
356
+
357
+ new_time = time.change(options)
358
+
359
+ if options[:zone]
360
+ new_zone = ::Time.find_zone(options[:zone])
361
+ elsif options[:offset]
362
+ new_zone = ::Time.find_zone(new_time.utc_offset)
363
+ end
364
+
365
+ new_zone ||= time_zone
366
+ periods = new_zone.periods_for_local(new_time)
367
+
368
+ self.class.new(nil, new_zone, new_time, periods.include?(period) ? period : nil)
369
+ end
370
+
333
371
  # Uses Date to provide precise Time calculations for years, months, and days
334
372
  # according to the proleptic Gregorian calendar. The result is returned as a
335
373
  # new TimeWithZone object.