activesupport 4.2.0 → 5.2.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.

Files changed (254) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +366 -232
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +4 -5
  5. data/lib/active_support.rb +17 -7
  6. data/lib/active_support/all.rb +5 -3
  7. data/lib/active_support/array_inquirer.rb +48 -0
  8. data/lib/active_support/backtrace_cleaner.rb +7 -5
  9. data/lib/active_support/benchmarkable.rb +6 -4
  10. data/lib/active_support/builder.rb +3 -1
  11. data/lib/active_support/cache.rb +271 -177
  12. data/lib/active_support/cache/file_store.rb +41 -35
  13. data/lib/active_support/cache/mem_cache_store.rb +97 -88
  14. data/lib/active_support/cache/memory_store.rb +27 -30
  15. data/lib/active_support/cache/null_store.rb +7 -8
  16. data/lib/active_support/cache/redis_cache_store.rb +454 -0
  17. data/lib/active_support/cache/strategy/local_cache.rb +67 -34
  18. data/lib/active_support/cache/strategy/local_cache_middleware.rb +10 -9
  19. data/lib/active_support/callbacks.rb +654 -560
  20. data/lib/active_support/concern.rb +5 -3
  21. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +17 -0
  22. data/lib/active_support/concurrency/share_lock.rb +227 -0
  23. data/lib/active_support/configurable.rb +8 -5
  24. data/lib/active_support/core_ext.rb +3 -1
  25. data/lib/active_support/core_ext/array.rb +9 -6
  26. data/lib/active_support/core_ext/array/access.rb +29 -1
  27. data/lib/active_support/core_ext/array/conversions.rb +22 -18
  28. data/lib/active_support/core_ext/array/extract_options.rb +2 -0
  29. data/lib/active_support/core_ext/array/grouping.rb +11 -18
  30. data/lib/active_support/core_ext/array/inquiry.rb +19 -0
  31. data/lib/active_support/core_ext/array/prepend_and_append.rb +5 -3
  32. data/lib/active_support/core_ext/array/wrap.rb +7 -4
  33. data/lib/active_support/core_ext/benchmark.rb +3 -1
  34. data/lib/active_support/core_ext/big_decimal.rb +3 -1
  35. data/lib/active_support/core_ext/big_decimal/conversions.rb +10 -12
  36. data/lib/active_support/core_ext/class.rb +4 -3
  37. data/lib/active_support/core_ext/class/attribute.rb +41 -22
  38. data/lib/active_support/core_ext/class/attribute_accessors.rb +3 -1
  39. data/lib/active_support/core_ext/class/subclasses.rb +20 -8
  40. data/lib/active_support/core_ext/date.rb +6 -4
  41. data/lib/active_support/core_ext/date/acts_like.rb +3 -1
  42. data/lib/active_support/core_ext/date/blank.rb +14 -0
  43. data/lib/active_support/core_ext/date/calculations.rb +11 -9
  44. data/lib/active_support/core_ext/date/conversions.rb +31 -23
  45. data/lib/active_support/core_ext/date/zones.rb +4 -2
  46. data/lib/active_support/core_ext/date_and_time/calculations.rb +179 -56
  47. data/lib/active_support/core_ext/date_and_time/compatibility.rb +16 -0
  48. data/lib/active_support/core_ext/date_and_time/zones.rb +12 -12
  49. data/lib/active_support/core_ext/date_time.rb +7 -4
  50. data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
  51. data/lib/active_support/core_ext/date_time/blank.rb +14 -0
  52. data/lib/active_support/core_ext/date_time/calculations.rb +58 -20
  53. data/lib/active_support/core_ext/date_time/compatibility.rb +18 -0
  54. data/lib/active_support/core_ext/date_time/conversions.rb +16 -12
  55. data/lib/active_support/core_ext/digest/uuid.rb +7 -5
  56. data/lib/active_support/core_ext/enumerable.rb +107 -28
  57. data/lib/active_support/core_ext/file.rb +3 -1
  58. data/lib/active_support/core_ext/file/atomic.rb +38 -31
  59. data/lib/active_support/core_ext/hash.rb +11 -9
  60. data/lib/active_support/core_ext/hash/compact.rb +24 -15
  61. data/lib/active_support/core_ext/hash/conversions.rb +63 -43
  62. data/lib/active_support/core_ext/hash/deep_merge.rb +9 -13
  63. data/lib/active_support/core_ext/hash/except.rb +11 -8
  64. data/lib/active_support/core_ext/hash/indifferent_access.rb +4 -3
  65. data/lib/active_support/core_ext/hash/keys.rb +33 -27
  66. data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
  67. data/lib/active_support/core_ext/hash/slice.rb +8 -8
  68. data/lib/active_support/core_ext/hash/transform_values.rb +16 -7
  69. data/lib/active_support/core_ext/integer.rb +5 -3
  70. data/lib/active_support/core_ext/integer/inflections.rb +3 -1
  71. data/lib/active_support/core_ext/integer/multiple.rb +2 -0
  72. data/lib/active_support/core_ext/integer/time.rb +11 -33
  73. data/lib/active_support/core_ext/kernel.rb +6 -5
  74. data/lib/active_support/core_ext/kernel/agnostics.rb +2 -0
  75. data/lib/active_support/core_ext/kernel/concern.rb +5 -1
  76. data/lib/active_support/core_ext/kernel/reporting.rb +4 -83
  77. data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
  78. data/lib/active_support/core_ext/load_error.rb +3 -22
  79. data/lib/active_support/core_ext/marshal.rb +13 -10
  80. data/lib/active_support/core_ext/module.rb +14 -11
  81. data/lib/active_support/core_ext/module/aliasing.rb +6 -44
  82. data/lib/active_support/core_ext/module/anonymous.rb +12 -1
  83. data/lib/active_support/core_ext/module/attr_internal.rb +8 -9
  84. data/lib/active_support/core_ext/module/attribute_accessors.rb +43 -40
  85. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +150 -0
  86. data/lib/active_support/core_ext/module/concerning.rb +11 -12
  87. data/lib/active_support/core_ext/module/delegation.rb +121 -39
  88. data/lib/active_support/core_ext/module/deprecation.rb +4 -2
  89. data/lib/active_support/core_ext/module/introspection.rb +9 -9
  90. data/lib/active_support/core_ext/module/reachable.rb +5 -2
  91. data/lib/active_support/core_ext/module/redefine_method.rb +49 -0
  92. data/lib/active_support/core_ext/module/remove_method.rb +8 -3
  93. data/lib/active_support/core_ext/name_error.rb +22 -2
  94. data/lib/active_support/core_ext/numeric.rb +6 -3
  95. data/lib/active_support/core_ext/numeric/bytes.rb +22 -0
  96. data/lib/active_support/core_ext/numeric/conversions.rb +79 -74
  97. data/lib/active_support/core_ext/numeric/inquiry.rb +28 -0
  98. data/lib/active_support/core_ext/numeric/time.rb +35 -38
  99. data/lib/active_support/core_ext/object.rb +14 -13
  100. data/lib/active_support/core_ext/object/acts_like.rb +12 -1
  101. data/lib/active_support/core_ext/object/blank.rb +29 -4
  102. data/lib/active_support/core_ext/object/conversions.rb +6 -4
  103. data/lib/active_support/core_ext/object/deep_dup.rb +13 -4
  104. data/lib/active_support/core_ext/object/duplicable.rb +98 -45
  105. data/lib/active_support/core_ext/object/inclusion.rb +5 -3
  106. data/lib/active_support/core_ext/object/instance_variables.rb +3 -1
  107. data/lib/active_support/core_ext/object/json.rb +49 -19
  108. data/lib/active_support/core_ext/object/to_param.rb +3 -1
  109. data/lib/active_support/core_ext/object/to_query.rb +6 -4
  110. data/lib/active_support/core_ext/object/try.rb +70 -22
  111. data/lib/active_support/core_ext/object/with_options.rb +16 -3
  112. data/lib/active_support/core_ext/range.rb +7 -4
  113. data/lib/active_support/core_ext/range/conversions.rb +27 -7
  114. data/lib/active_support/core_ext/range/each.rb +19 -17
  115. data/lib/active_support/core_ext/range/include_range.rb +21 -19
  116. data/lib/active_support/core_ext/range/include_time_with_zone.rb +23 -0
  117. data/lib/active_support/core_ext/range/overlaps.rb +2 -0
  118. data/lib/active_support/core_ext/regexp.rb +6 -0
  119. data/lib/active_support/core_ext/securerandom.rb +25 -0
  120. data/lib/active_support/core_ext/string.rb +15 -13
  121. data/lib/active_support/core_ext/string/access.rb +9 -7
  122. data/lib/active_support/core_ext/string/behavior.rb +3 -1
  123. data/lib/active_support/core_ext/string/conversions.rb +8 -5
  124. data/lib/active_support/core_ext/string/exclude.rb +2 -0
  125. data/lib/active_support/core_ext/string/filters.rb +10 -8
  126. data/lib/active_support/core_ext/string/indent.rb +6 -4
  127. data/lib/active_support/core_ext/string/inflections.rb +61 -24
  128. data/lib/active_support/core_ext/string/inquiry.rb +3 -1
  129. data/lib/active_support/core_ext/string/multibyte.rb +15 -7
  130. data/lib/active_support/core_ext/string/output_safety.rb +35 -35
  131. data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -0
  132. data/lib/active_support/core_ext/string/strip.rb +4 -5
  133. data/lib/active_support/core_ext/string/zones.rb +4 -2
  134. data/lib/active_support/core_ext/time.rb +7 -5
  135. data/lib/active_support/core_ext/time/acts_like.rb +3 -1
  136. data/lib/active_support/core_ext/time/calculations.rb +101 -51
  137. data/lib/active_support/core_ext/time/compatibility.rb +16 -0
  138. data/lib/active_support/core_ext/time/conversions.rb +20 -13
  139. data/lib/active_support/core_ext/time/zones.rb +41 -7
  140. data/lib/active_support/core_ext/uri.rb +5 -4
  141. data/lib/active_support/current_attributes.rb +195 -0
  142. data/lib/active_support/dependencies.rb +143 -160
  143. data/lib/active_support/dependencies/autoload.rb +2 -0
  144. data/lib/active_support/dependencies/interlock.rb +57 -0
  145. data/lib/active_support/deprecation.rb +12 -9
  146. data/lib/active_support/deprecation/behaviors.rb +41 -12
  147. data/lib/active_support/deprecation/constant_accessor.rb +52 -0
  148. data/lib/active_support/deprecation/instance_delegator.rb +17 -2
  149. data/lib/active_support/deprecation/method_wrappers.rb +54 -21
  150. data/lib/active_support/deprecation/proxy_wrappers.rb +56 -28
  151. data/lib/active_support/deprecation/reporting.rb +32 -12
  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.rb +326 -30
  155. data/lib/active_support/duration/iso8601_parser.rb +125 -0
  156. data/lib/active_support/duration/iso8601_serializer.rb +55 -0
  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 +205 -0
  160. data/lib/active_support/execution_wrapper.rb +128 -0
  161. data/lib/active_support/executor.rb +8 -0
  162. data/lib/active_support/file_update_checker.rb +63 -37
  163. data/lib/active_support/gem_version.rb +4 -2
  164. data/lib/active_support/gzip.rb +7 -5
  165. data/lib/active_support/hash_with_indifferent_access.rb +130 -30
  166. data/lib/active_support/i18n.rb +8 -6
  167. data/lib/active_support/i18n_railtie.rb +34 -14
  168. data/lib/active_support/inflections.rb +13 -11
  169. data/lib/active_support/inflector.rb +7 -5
  170. data/lib/active_support/inflector/inflections.rb +61 -12
  171. data/lib/active_support/inflector/methods.rb +161 -136
  172. data/lib/active_support/inflector/transliterate.rb +48 -27
  173. data/lib/active_support/json.rb +4 -2
  174. data/lib/active_support/json/decoding.rb +16 -13
  175. data/lib/active_support/json/encoding.rb +15 -57
  176. data/lib/active_support/key_generator.rb +25 -25
  177. data/lib/active_support/lazy_load_hooks.rb +50 -20
  178. data/lib/active_support/locale/en.yml +2 -0
  179. data/lib/active_support/log_subscriber.rb +13 -10
  180. data/lib/active_support/log_subscriber/test_helper.rb +14 -12
  181. data/lib/active_support/logger.rb +54 -3
  182. data/lib/active_support/logger_silence.rb +12 -7
  183. data/lib/active_support/logger_thread_safe_level.rb +33 -0
  184. data/lib/active_support/message_encryptor.rb +173 -51
  185. data/lib/active_support/message_verifier.rb +150 -17
  186. data/lib/active_support/messages/metadata.rb +71 -0
  187. data/lib/active_support/messages/rotation_configuration.rb +22 -0
  188. data/lib/active_support/messages/rotator.rb +56 -0
  189. data/lib/active_support/multibyte.rb +4 -2
  190. data/lib/active_support/multibyte/chars.rb +37 -24
  191. data/lib/active_support/multibyte/unicode.rb +100 -96
  192. data/lib/active_support/notifications.rb +11 -7
  193. data/lib/active_support/notifications/fanout.rb +10 -8
  194. data/lib/active_support/notifications/instrumenter.rb +27 -7
  195. data/lib/active_support/number_helper.rb +94 -68
  196. data/lib/active_support/number_helper/number_converter.rb +13 -11
  197. data/lib/active_support/number_helper/number_to_currency_converter.rb +9 -9
  198. data/lib/active_support/number_helper/number_to_delimited_converter.rb +9 -3
  199. data/lib/active_support/number_helper/number_to_human_converter.rb +11 -9
  200. data/lib/active_support/number_helper/number_to_human_size_converter.rb +9 -8
  201. data/lib/active_support/number_helper/number_to_percentage_converter.rb +3 -1
  202. data/lib/active_support/number_helper/number_to_phone_converter.rb +13 -4
  203. data/lib/active_support/number_helper/number_to_rounded_converter.rb +23 -56
  204. data/lib/active_support/number_helper/rounding_helper.rb +66 -0
  205. data/lib/active_support/option_merger.rb +3 -1
  206. data/lib/active_support/ordered_hash.rb +6 -4
  207. data/lib/active_support/ordered_options.rb +22 -4
  208. data/lib/active_support/per_thread_registry.rb +13 -6
  209. data/lib/active_support/proxy_object.rb +2 -0
  210. data/lib/active_support/rails.rb +16 -8
  211. data/lib/active_support/railtie.rb +43 -9
  212. data/lib/active_support/reloader.rb +131 -0
  213. data/lib/active_support/rescuable.rb +108 -53
  214. data/lib/active_support/security_utils.rb +17 -6
  215. data/lib/active_support/string_inquirer.rb +11 -3
  216. data/lib/active_support/subscriber.rb +15 -14
  217. data/lib/active_support/tagged_logging.rb +14 -11
  218. data/lib/active_support/test_case.rb +18 -46
  219. data/lib/active_support/testing/assertions.rb +137 -20
  220. data/lib/active_support/testing/autorun.rb +4 -2
  221. data/lib/active_support/testing/constant_lookup.rb +2 -1
  222. data/lib/active_support/testing/declarative.rb +3 -1
  223. data/lib/active_support/testing/deprecation.rb +14 -10
  224. data/lib/active_support/testing/file_fixtures.rb +36 -0
  225. data/lib/active_support/testing/isolation.rb +34 -25
  226. data/lib/active_support/testing/method_call_assertions.rb +43 -0
  227. data/lib/active_support/testing/setup_and_teardown.rb +12 -3
  228. data/lib/active_support/testing/stream.rb +44 -0
  229. data/lib/active_support/testing/tagged_logging.rb +3 -1
  230. data/lib/active_support/testing/time_helpers.rb +96 -27
  231. data/lib/active_support/time.rb +14 -12
  232. data/lib/active_support/time_with_zone.rb +195 -53
  233. data/lib/active_support/values/time_zone.rb +200 -61
  234. data/lib/active_support/values/unicode_tables.dat +0 -0
  235. data/lib/active_support/version.rb +3 -1
  236. data/lib/active_support/xml_mini.rb +69 -51
  237. data/lib/active_support/xml_mini/jdom.rb +116 -113
  238. data/lib/active_support/xml_mini/libxml.rb +17 -16
  239. data/lib/active_support/xml_mini/libxmlsax.rb +16 -18
  240. data/lib/active_support/xml_mini/nokogiri.rb +15 -15
  241. data/lib/active_support/xml_mini/nokogirisax.rb +15 -16
  242. data/lib/active_support/xml_mini/rexml.rb +17 -16
  243. metadata +55 -43
  244. data/lib/active_support/concurrency/latch.rb +0 -27
  245. data/lib/active_support/core_ext/big_decimal/yaml_conversions.rb +0 -14
  246. data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -45
  247. data/lib/active_support/core_ext/date_time/zones.rb +0 -6
  248. data/lib/active_support/core_ext/kernel/debugger.rb +0 -10
  249. data/lib/active_support/core_ext/module/method_transplanting.rb +0 -11
  250. data/lib/active_support/core_ext/module/qualified_const.rb +0 -52
  251. data/lib/active_support/core_ext/object/itself.rb +0 -15
  252. data/lib/active_support/core_ext/struct.rb +0 -6
  253. data/lib/active_support/core_ext/thread.rb +0 -86
  254. data/lib/active_support/core_ext/time/marshal.rb +0 -30
@@ -1,5 +1,7 @@
1
- gem 'minitest'
1
+ # frozen_string_literal: true
2
2
 
3
- require 'minitest'
3
+ gem "minitest"
4
+
5
+ require "minitest"
4
6
 
5
7
  Minitest.autorun
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/concern"
2
4
  require "active_support/inflector"
3
5
 
@@ -44,7 +46,6 @@ module ActiveSupport
44
46
  end
45
47
  end
46
48
  end
47
-
48
49
  end
49
50
  end
50
51
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveSupport
2
4
  module Testing
3
5
  module Declarative
@@ -9,7 +11,7 @@ module ActiveSupport
9
11
  # ...
10
12
  # end
11
13
  def test(name, &block)
12
- test_name = "test_#{name.gsub(/\s+/,'_')}".to_sym
14
+ test_name = "test_#{name.gsub(/\s+/, '_')}".to_sym
13
15
  defined = method_defined? test_name
14
16
  raise "#{test_name} is already defined in #{self}" if defined
15
17
  if block_given?
@@ -1,34 +1,38 @@
1
- require 'active_support/deprecation'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/deprecation"
4
+ require "active_support/core_ext/regexp"
2
5
 
3
6
  module ActiveSupport
4
7
  module Testing
5
8
  module Deprecation #:nodoc:
6
- def assert_deprecated(match = nil, &block)
7
- result, warnings = collect_deprecations(&block)
9
+ def assert_deprecated(match = nil, deprecator = nil, &block)
10
+ result, warnings = collect_deprecations(deprecator, &block)
8
11
  assert !warnings.empty?, "Expected a deprecation warning within the block but received none"
9
12
  if match
10
13
  match = Regexp.new(Regexp.escape(match)) unless match.is_a?(Regexp)
11
- assert warnings.any? { |w| w =~ match }, "No deprecation warning matched #{match}: #{warnings.join(', ')}"
14
+ assert warnings.any? { |w| match.match?(w) }, "No deprecation warning matched #{match}: #{warnings.join(', ')}"
12
15
  end
13
16
  result
14
17
  end
15
18
 
16
- def assert_not_deprecated(&block)
17
- result, deprecations = collect_deprecations(&block)
19
+ def assert_not_deprecated(deprecator = nil, &block)
20
+ result, deprecations = collect_deprecations(deprecator, &block)
18
21
  assert deprecations.empty?, "Expected no deprecation warning within the block but received #{deprecations.size}: \n #{deprecations * "\n "}"
19
22
  result
20
23
  end
21
24
 
22
- def collect_deprecations
23
- old_behavior = ActiveSupport::Deprecation.behavior
25
+ def collect_deprecations(deprecator = nil)
26
+ deprecator ||= ActiveSupport::Deprecation
27
+ old_behavior = deprecator.behavior
24
28
  deprecations = []
25
- ActiveSupport::Deprecation.behavior = Proc.new do |message, callstack|
29
+ deprecator.behavior = Proc.new do |message, callstack|
26
30
  deprecations << message
27
31
  end
28
32
  result = yield
29
33
  [result, deprecations]
30
34
  ensure
31
- ActiveSupport::Deprecation.behavior = old_behavior
35
+ deprecator.behavior = old_behavior
32
36
  end
33
37
  end
34
38
  end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveSupport
4
+ module Testing
5
+ # Adds simple access to sample files called file fixtures.
6
+ # File fixtures are normal files stored in
7
+ # <tt>ActiveSupport::TestCase.file_fixture_path</tt>.
8
+ #
9
+ # File fixtures are represented as +Pathname+ objects.
10
+ # This makes it easy to extract specific information:
11
+ #
12
+ # file_fixture("example.txt").read # get the file's content
13
+ # file_fixture("example.mp3").size # get the file size
14
+ module FileFixtures
15
+ extend ActiveSupport::Concern
16
+
17
+ included do
18
+ class_attribute :file_fixture_path, instance_writer: false
19
+ end
20
+
21
+ # Returns a +Pathname+ to the fixture file named +fixture_name+.
22
+ #
23
+ # Raises +ArgumentError+ if +fixture_name+ can't be found.
24
+ def file_fixture(fixture_name)
25
+ path = Pathname.new(File.join(file_fixture_path, fixture_name))
26
+
27
+ if path.exist?
28
+ path
29
+ else
30
+ msg = "the directory '%s' does not contain a file named '%s'"
31
+ raise ArgumentError, msg % [file_fixture_path, fixture_name]
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -1,9 +1,9 @@
1
- require 'rbconfig'
1
+ # frozen_string_literal: true
2
2
 
3
3
  module ActiveSupport
4
4
  module Testing
5
5
  module Isolation
6
- require 'thread'
6
+ require "thread"
7
7
 
8
8
  def self.included(klass) #:nodoc:
9
9
  klass.class_eval do
@@ -12,18 +12,7 @@ module ActiveSupport
12
12
  end
13
13
 
14
14
  def self.forking_env?
15
- !ENV["NO_FORK"] && ((RbConfig::CONFIG['host_os'] !~ /mswin|mingw/) && (RUBY_PLATFORM !~ /java/))
16
- end
17
-
18
- @@class_setup_mutex = Mutex.new
19
-
20
- def _run_class_setup # class setup method should only happen in parent
21
- @@class_setup_mutex.synchronize do
22
- unless defined?(@@ran_class_setup) || ENV['ISOLATION_TEST']
23
- self.class.setup if self.class.respond_to?(:setup)
24
- @@ran_class_setup = true
25
- end
26
- end
15
+ !ENV["NO_FORK"] && Process.respond_to?(:fork)
27
16
  end
28
17
 
29
18
  def run
@@ -43,14 +32,31 @@ module ActiveSupport
43
32
  pid = fork do
44
33
  read.close
45
34
  yield
46
- write.puts [Marshal.dump(self.dup)].pack("m")
35
+ begin
36
+ if error?
37
+ failures.map! { |e|
38
+ begin
39
+ Marshal.dump e
40
+ e
41
+ rescue TypeError
42
+ ex = Exception.new e.message
43
+ ex.set_backtrace e.backtrace
44
+ Minitest::UnexpectedError.new ex
45
+ end
46
+ }
47
+ end
48
+ test_result = defined?(Minitest::Result) ? Minitest::Result.from(self) : dup
49
+ result = Marshal.dump(test_result)
50
+ end
51
+
52
+ write.puts [result].pack("m")
47
53
  exit!
48
54
  end
49
55
 
50
56
  write.close
51
57
  result = read.read
52
58
  Process.wait2(pid)
53
- return result.unpack("m")[0]
59
+ result.unpack("m")[0]
54
60
  end
55
61
  end
56
62
 
@@ -64,24 +70,27 @@ module ActiveSupport
64
70
 
65
71
  if ENV["ISOLATION_TEST"]
66
72
  yield
73
+ test_result = defined?(Minitest::Result) ? Minitest::Result.from(self) : dup
67
74
  File.open(ENV["ISOLATION_OUTPUT"], "w") do |file|
68
- file.puts [Marshal.dump(self.dup)].pack("m")
75
+ file.puts [Marshal.dump(test_result)].pack("m")
69
76
  end
70
77
  exit!
71
78
  else
72
79
  Tempfile.open("isolation") do |tmpfile|
73
80
  env = {
74
- ISOLATION_TEST: self.class.name,
75
- ISOLATION_OUTPUT: tmpfile.path
81
+ "ISOLATION_TEST" => self.class.name,
82
+ "ISOLATION_OUTPUT" => tmpfile.path
76
83
  }
77
84
 
78
- load_paths = $-I.map {|p| "-I\"#{File.expand_path(p)}\"" }.join(" ")
79
- orig_args = ORIG_ARGV.join(" ")
80
- test_opts = "-n#{self.class.name}##{self.name}"
81
- command = "#{Gem.ruby} #{load_paths} #{$0} #{orig_args} #{test_opts}"
85
+ test_opts = "-n#{self.class.name}##{name}"
86
+
87
+ load_path_args = []
88
+ $-I.each do |p|
89
+ load_path_args << "-I"
90
+ load_path_args << File.expand_path(p)
91
+ end
82
92
 
83
- # IO.popen lets us pass env in a cross-platform way
84
- child = IO.popen([env, command])
93
+ child = IO.popen([env, Gem.ruby, *load_path_args, $0, *ORIG_ARGV, test_opts])
85
94
 
86
95
  begin
87
96
  Process.wait(child.pid)
@@ -0,0 +1,43 @@
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 stub_any_instance(klass, instance: klass.new)
39
+ klass.stub(:new, instance) { yield instance }
40
+ end
41
+ end
42
+ end
43
+ end
@@ -1,5 +1,7 @@
1
- require 'active_support/concern'
2
- require 'active_support/callbacks'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/concern"
4
+ require "active_support/callbacks"
3
5
 
4
6
  module ActiveSupport
5
7
  module Testing
@@ -42,8 +44,15 @@ module ActiveSupport
42
44
  end
43
45
 
44
46
  def after_teardown # :nodoc:
45
- run_callbacks :teardown
47
+ begin
48
+ run_callbacks :teardown
49
+ rescue => e
50
+ error = e
51
+ end
52
+
46
53
  super
54
+ ensure
55
+ raise error if error
47
56
  end
48
57
  end
49
58
  end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveSupport
4
+ module Testing
5
+ module Stream #:nodoc:
6
+ private
7
+
8
+ def silence_stream(stream)
9
+ old_stream = stream.dup
10
+ stream.reopen(IO::NULL)
11
+ stream.sync = true
12
+ yield
13
+ ensure
14
+ stream.reopen(old_stream)
15
+ old_stream.close
16
+ end
17
+
18
+ def quietly
19
+ silence_stream(STDOUT) do
20
+ silence_stream(STDERR) do
21
+ yield
22
+ end
23
+ end
24
+ end
25
+
26
+ def capture(stream)
27
+ stream = stream.to_s
28
+ captured_stream = Tempfile.new(stream)
29
+ stream_io = eval("$#{stream}")
30
+ origin_stream = stream_io.dup
31
+ stream_io.reopen(captured_stream)
32
+
33
+ yield
34
+
35
+ stream_io.rewind
36
+ return captured_stream.read
37
+ ensure
38
+ captured_stream.close
39
+ captured_stream.unlink
40
+ stream_io.reopen(origin_stream)
41
+ end
42
+ end
43
+ end
44
+ 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 = '-' * heading.size
13
+ divider = "-" * heading.size
12
14
  tagged_logger.info divider
13
15
  tagged_logger.info heading
14
16
  tagged_logger.info divider
@@ -1,53 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/module/redefine_method"
4
+ require "active_support/core_ext/string/strip" # for strip_heredoc
5
+ require "active_support/core_ext/time/calculations"
6
+ require "concurrent/map"
7
+
1
8
  module ActiveSupport
2
9
  module Testing
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
 
10
- def stub_object(object, method_name, return_value)
11
- key = [object.object_id, method_name]
12
-
13
- if stub = @stubs[key]
17
+ def stub_object(object, method_name, &block)
18
+ if stub = stubbing(object, method_name)
14
19
  unstub_object(stub)
15
20
  end
16
21
 
17
22
  new_name = "__simple_stub__#{method_name}"
18
23
 
19
- @stubs[key] = Stub.new(object, method_name, new_name)
24
+ @stubs[object.object_id][method_name] = Stub.new(object, method_name, new_name)
20
25
 
21
26
  object.singleton_class.send :alias_method, new_name, method_name
22
- object.define_singleton_method(method_name) { return_value }
27
+ object.define_singleton_method(method_name, &block)
23
28
  end
24
29
 
25
30
  def unstub_all!
26
- @stubs.each_value do |stub|
27
- unstub_object(stub)
31
+ @stubs.each_value do |object_stubs|
32
+ object_stubs.each_value do |stub|
33
+ unstub_object(stub)
34
+ end
28
35
  end
29
- @stubs = {}
36
+ @stubs.clear
37
+ end
38
+
39
+ def stubbing(object, method_name)
40
+ @stubs[object.object_id][method_name]
30
41
  end
31
42
 
32
43
  private
33
44
 
34
45
  def unstub_object(stub)
35
46
  singleton_class = stub.object.singleton_class
36
- singleton_class.send :undef_method, stub.method_name
47
+ singleton_class.send :silence_redefinition_of_method, stub.method_name
37
48
  singleton_class.send :alias_method, stub.method_name, stub.original_method
38
49
  singleton_class.send :undef_method, stub.original_method
39
50
  end
40
51
  end
41
52
 
42
- # Containing helpers that helps you test passage of time.
53
+ # Contains helpers that help you test passage of time.
43
54
  module TimeHelpers
55
+ def after_teardown
56
+ travel_back
57
+ super
58
+ end
59
+
44
60
  # Changes current time to the time in the future or in the past by a given time difference by
45
- # stubbing +Time.now+ and +Date.today+.
61
+ # stubbing +Time.now+, +Date.today+, and +DateTime.now+. The stubs are automatically removed
62
+ # at the end of the test.
46
63
  #
47
- # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
64
+ # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
48
65
  # travel 1.day
49
- # Time.current # => Sun, 10 Nov 2013 15:34:49 EST -05:00
50
- # Date.current # => Sun, 10 Nov 2013
66
+ # Time.current # => Sun, 10 Nov 2013 15:34:49 EST -05:00
67
+ # Date.current # => Sun, 10 Nov 2013
68
+ # DateTime.current # => Sun, 10 Nov 2013 15:34:49 -0500
51
69
  #
52
70
  # This method also accepts a block, which will return the current time back to its original
53
71
  # state at the end of the block:
@@ -61,13 +79,15 @@ module ActiveSupport
61
79
  travel_to Time.now + duration, &block
62
80
  end
63
81
 
64
- # Changes current time to the given time by stubbing +Time.now+ and
65
- # +Date.today+ to return the time or date passed into this method.
82
+ # Changes current time to the given time by stubbing +Time.now+,
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.
66
85
  #
67
- # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
68
- # travel_to Time.new(2004, 11, 24, 01, 04, 44)
69
- # Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
70
- # Date.current # => Wed, 24 Nov 2004
86
+ # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
87
+ # travel_to Time.zone.local(2004, 11, 24, 01, 04, 44)
88
+ # Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
89
+ # Date.current # => Wed, 24 Nov 2004
90
+ # DateTime.current # => Wed, 24 Nov 2004 01:04:44 -0500
71
91
  #
72
92
  # Dates are taken as their timestamp at the beginning of the day in the
73
93
  # application time zone. <tt>Time.current</tt> returns said timestamp,
@@ -86,19 +106,48 @@ module ActiveSupport
86
106
  # state at the end of the block:
87
107
  #
88
108
  # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
89
- # travel_to Time.new(2004, 11, 24, 01, 04, 44) do
109
+ # travel_to Time.zone.local(2004, 11, 24, 01, 04, 44) do
90
110
  # Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
91
111
  # end
92
112
  # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
93
113
  def travel_to(date_or_time)
114
+ if block_given? && simple_stubs.stubbing(Time, :now)
115
+ travel_to_nested_block_call = <<-MSG.strip_heredoc
116
+
117
+ Calling `travel_to` with a block, when we have previously already made a call to `travel_to`, can lead to confusing time stubbing.
118
+
119
+ Instead of:
120
+
121
+ travel_to 2.days.from_now do
122
+ # 2 days from today
123
+ travel_to 3.days.from_now do
124
+ # 5 days from today
125
+ end
126
+ end
127
+
128
+ preferred way to achieve above is:
129
+
130
+ travel 2.days do
131
+ # 2 days from today
132
+ end
133
+
134
+ travel 5.days do
135
+ # 5 days from today
136
+ end
137
+
138
+ MSG
139
+ raise travel_to_nested_block_call
140
+ end
141
+
94
142
  if date_or_time.is_a?(Date) && !date_or_time.is_a?(DateTime)
95
143
  now = date_or_time.midnight.to_time
96
144
  else
97
145
  now = date_or_time.to_time.change(usec: 0)
98
146
  end
99
147
 
100
- simple_stubs.stub_object(Time, :now, now)
101
- simple_stubs.stub_object(Date, :today, now.to_date)
148
+ simple_stubs.stub_object(Time, :now) { at(now.to_i) }
149
+ simple_stubs.stub_object(Date, :today) { jd(now.to_date.jd) }
150
+ simple_stubs.stub_object(DateTime, :now) { jd(now.to_date.jd, now.hour, now.min, now.sec, Rational(now.utc_offset, 86400)) }
102
151
 
103
152
  if block_given?
104
153
  begin
@@ -110,10 +159,10 @@ module ActiveSupport
110
159
  end
111
160
 
112
161
  # Returns the current time back to its original state, by removing the stubs added by
113
- # `travel` and `travel_to`.
162
+ # +travel+ and +travel_to+.
114
163
  #
115
164
  # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
116
- # travel_to Time.new(2004, 11, 24, 01, 04, 44)
165
+ # travel_to Time.zone.local(2004, 11, 24, 01, 04, 44)
117
166
  # Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
118
167
  # travel_back
119
168
  # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
@@ -121,6 +170,26 @@ module ActiveSupport
121
170
  simple_stubs.unstub_all!
122
171
  end
123
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
+
124
193
  private
125
194
 
126
195
  def simple_stubs