activesupport 4.0.12 → 7.0.2.4

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 (295) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +249 -501
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +10 -5
  5. data/lib/active_support/actionable_error.rb +48 -0
  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 +41 -13
  9. data/lib/active_support/benchmarkable.rb +7 -15
  10. data/lib/active_support/builder.rb +3 -1
  11. data/lib/active_support/cache/file_store.rb +96 -74
  12. data/lib/active_support/cache/mem_cache_store.rb +211 -103
  13. data/lib/active_support/cache/memory_store.rb +90 -58
  14. data/lib/active_support/cache/null_store.rb +19 -7
  15. data/lib/active_support/cache/redis_cache_store.rb +468 -0
  16. data/lib/active_support/cache/strategy/local_cache.rb +86 -83
  17. data/lib/active_support/cache/strategy/local_cache_middleware.rb +45 -0
  18. data/lib/active_support/cache.rb +580 -241
  19. data/lib/active_support/callbacks.rb +812 -425
  20. data/lib/active_support/code_generator.rb +65 -0
  21. data/lib/active_support/concern.rb +103 -14
  22. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +33 -0
  23. data/lib/active_support/concurrency/share_lock.rb +226 -0
  24. data/lib/active_support/configurable.rb +21 -19
  25. data/lib/active_support/configuration_file.rb +51 -0
  26. data/lib/active_support/core_ext/array/access.rb +47 -1
  27. data/lib/active_support/core_ext/array/conversions.rb +35 -44
  28. data/lib/active_support/core_ext/array/deprecated_conversions.rb +25 -0
  29. data/lib/active_support/core_ext/array/extract.rb +21 -0
  30. data/lib/active_support/core_ext/array/extract_options.rb +2 -0
  31. data/lib/active_support/core_ext/array/grouping.rb +26 -16
  32. data/lib/active_support/core_ext/array/inquiry.rb +19 -0
  33. data/lib/active_support/core_ext/array/wrap.rb +7 -4
  34. data/lib/active_support/core_ext/array.rb +10 -7
  35. data/lib/active_support/core_ext/benchmark.rb +5 -3
  36. data/lib/active_support/core_ext/big_decimal/conversions.rb +9 -26
  37. data/lib/active_support/core_ext/big_decimal.rb +3 -1
  38. data/lib/active_support/core_ext/class/attribute.rb +52 -49
  39. data/lib/active_support/core_ext/class/attribute_accessors.rb +5 -169
  40. data/lib/active_support/core_ext/class/subclasses.rb +25 -26
  41. data/lib/active_support/core_ext/class.rb +4 -4
  42. data/lib/active_support/core_ext/date/acts_like.rb +3 -1
  43. data/lib/active_support/core_ext/date/blank.rb +14 -0
  44. data/lib/active_support/core_ext/date/calculations.rb +31 -18
  45. data/lib/active_support/core_ext/date/conversions.rb +43 -32
  46. data/lib/active_support/core_ext/date/deprecated_conversions.rb +26 -0
  47. data/lib/active_support/core_ext/date/zones.rb +5 -34
  48. data/lib/active_support/core_ext/date.rb +7 -4
  49. data/lib/active_support/core_ext/date_and_time/calculations.rb +198 -66
  50. data/lib/active_support/core_ext/date_and_time/compatibility.rb +31 -0
  51. data/lib/active_support/core_ext/date_and_time/zones.rb +40 -0
  52. data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
  53. data/lib/active_support/core_ext/date_time/blank.rb +14 -0
  54. data/lib/active_support/core_ext/date_time/calculations.rb +79 -38
  55. data/lib/active_support/core_ext/date_time/compatibility.rb +18 -0
  56. data/lib/active_support/core_ext/date_time/conversions.rb +31 -26
  57. data/lib/active_support/core_ext/date_time/deprecated_conversions.rb +22 -0
  58. data/lib/active_support/core_ext/date_time.rb +8 -4
  59. data/lib/active_support/core_ext/digest/uuid.rb +79 -0
  60. data/lib/active_support/core_ext/digest.rb +3 -0
  61. data/lib/active_support/core_ext/enumerable.rb +249 -17
  62. data/lib/active_support/core_ext/file/atomic.rb +41 -32
  63. data/lib/active_support/core_ext/file.rb +3 -1
  64. data/lib/active_support/core_ext/hash/conversions.rb +71 -49
  65. data/lib/active_support/core_ext/hash/deep_merge.rb +9 -13
  66. data/lib/active_support/core_ext/hash/deep_transform_values.rb +46 -0
  67. data/lib/active_support/core_ext/hash/except.rb +14 -5
  68. data/lib/active_support/core_ext/hash/indifferent_access.rb +5 -3
  69. data/lib/active_support/core_ext/hash/keys.rb +39 -56
  70. data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
  71. data/lib/active_support/core_ext/hash/slice.rb +8 -23
  72. data/lib/active_support/core_ext/hash.rb +10 -8
  73. data/lib/active_support/core_ext/integer/inflections.rb +3 -1
  74. data/lib/active_support/core_ext/integer/multiple.rb +3 -1
  75. data/lib/active_support/core_ext/integer/time.rb +11 -33
  76. data/lib/active_support/core_ext/integer.rb +5 -3
  77. data/lib/active_support/core_ext/kernel/concern.rb +14 -0
  78. data/lib/active_support/core_ext/kernel/reporting.rb +9 -78
  79. data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
  80. data/lib/active_support/core_ext/kernel.rb +5 -4
  81. data/lib/active_support/core_ext/load_error.rb +5 -21
  82. data/lib/active_support/core_ext/module/aliasing.rb +6 -44
  83. data/lib/active_support/core_ext/module/anonymous.rb +12 -1
  84. data/lib/active_support/core_ext/module/attr_internal.rb +8 -8
  85. data/lib/active_support/core_ext/module/attribute_accessors.rb +186 -44
  86. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +157 -0
  87. data/lib/active_support/core_ext/module/concerning.rb +140 -0
  88. data/lib/active_support/core_ext/module/delegation.rb +172 -45
  89. data/lib/active_support/core_ext/module/deprecation.rb +3 -3
  90. data/lib/active_support/core_ext/module/introspection.rb +23 -38
  91. data/lib/active_support/core_ext/module/redefine_method.rb +40 -0
  92. data/lib/active_support/core_ext/module/remove_method.rb +8 -3
  93. data/lib/active_support/core_ext/module.rb +13 -10
  94. data/lib/active_support/core_ext/name_error.rb +45 -4
  95. data/lib/active_support/core_ext/numeric/bytes.rb +22 -0
  96. data/lib/active_support/core_ext/numeric/conversions.rb +135 -127
  97. data/lib/active_support/core_ext/numeric/deprecated_conversions.rb +60 -0
  98. data/lib/active_support/core_ext/numeric/time.rb +37 -50
  99. data/lib/active_support/core_ext/numeric.rb +6 -3
  100. data/lib/active_support/core_ext/object/acts_like.rb +41 -6
  101. data/lib/active_support/core_ext/object/blank.rb +70 -20
  102. data/lib/active_support/core_ext/object/conversions.rb +6 -4
  103. data/lib/active_support/core_ext/object/deep_dup.rb +19 -10
  104. data/lib/active_support/core_ext/object/duplicable.rb +17 -47
  105. data/lib/active_support/core_ext/object/inclusion.rb +18 -15
  106. data/lib/active_support/core_ext/object/instance_variables.rb +3 -1
  107. data/lib/active_support/core_ext/object/json.rb +244 -0
  108. data/lib/active_support/core_ext/object/to_param.rb +3 -1
  109. data/lib/active_support/core_ext/object/to_query.rb +21 -8
  110. data/lib/active_support/core_ext/object/try.rb +106 -26
  111. data/lib/active_support/core_ext/object/with_options.rb +64 -5
  112. data/lib/active_support/core_ext/object.rb +14 -12
  113. data/lib/active_support/core_ext/pathname/existence.rb +21 -0
  114. data/lib/active_support/core_ext/pathname.rb +3 -0
  115. data/lib/active_support/core_ext/range/compare_range.rb +57 -0
  116. data/lib/active_support/core_ext/range/conversions.rb +37 -15
  117. data/lib/active_support/core_ext/range/deprecated_conversions.rb +26 -0
  118. data/lib/active_support/core_ext/range/each.rb +18 -17
  119. data/lib/active_support/core_ext/range/include_time_with_zone.rb +7 -0
  120. data/lib/active_support/core_ext/range/overlaps.rb +2 -0
  121. data/lib/active_support/core_ext/range.rb +7 -4
  122. data/lib/active_support/core_ext/regexp.rb +10 -1
  123. data/lib/active_support/core_ext/securerandom.rb +45 -0
  124. data/lib/active_support/core_ext/string/access.rb +42 -51
  125. data/lib/active_support/core_ext/string/behavior.rb +3 -1
  126. data/lib/active_support/core_ext/string/conversions.rb +18 -13
  127. data/lib/active_support/core_ext/string/exclude.rb +5 -3
  128. data/lib/active_support/core_ext/string/filters.rb +97 -7
  129. data/lib/active_support/core_ext/string/indent.rb +6 -4
  130. data/lib/active_support/core_ext/string/inflections.rb +106 -25
  131. data/lib/active_support/core_ext/string/inquiry.rb +4 -1
  132. data/lib/active_support/core_ext/string/multibyte.rb +18 -9
  133. data/lib/active_support/core_ext/string/output_safety.rb +227 -54
  134. data/lib/active_support/core_ext/string/starts_ends_with.rb +4 -2
  135. data/lib/active_support/core_ext/string/strip.rb +6 -5
  136. data/lib/active_support/core_ext/string/zones.rb +4 -1
  137. data/lib/active_support/core_ext/string.rb +15 -13
  138. data/lib/active_support/core_ext/symbol/starts_ends_with.rb +6 -0
  139. data/lib/active_support/core_ext/symbol.rb +3 -0
  140. data/lib/active_support/core_ext/time/acts_like.rb +3 -1
  141. data/lib/active_support/core_ext/time/calculations.rb +178 -116
  142. data/lib/active_support/core_ext/time/compatibility.rb +16 -0
  143. data/lib/active_support/core_ext/time/conversions.rb +37 -25
  144. data/lib/active_support/core_ext/time/deprecated_conversions.rb +22 -0
  145. data/lib/active_support/core_ext/time/zones.rb +44 -42
  146. data/lib/active_support/core_ext/time.rb +8 -5
  147. data/lib/active_support/core_ext/uri.rb +4 -25
  148. data/lib/active_support/core_ext.rb +4 -2
  149. data/lib/active_support/current_attributes/test_helper.rb +13 -0
  150. data/lib/active_support/current_attributes.rb +226 -0
  151. data/lib/active_support/dependencies/autoload.rb +3 -1
  152. data/lib/active_support/dependencies/interlock.rb +49 -0
  153. data/lib/active_support/dependencies/require_dependency.rb +28 -0
  154. data/lib/active_support/dependencies.rb +71 -696
  155. data/lib/active_support/deprecation/behaviors.rb +65 -16
  156. data/lib/active_support/deprecation/constant_accessor.rb +52 -0
  157. data/lib/active_support/deprecation/disallowed.rb +56 -0
  158. data/lib/active_support/deprecation/instance_delegator.rb +16 -2
  159. data/lib/active_support/deprecation/method_wrappers.rb +62 -21
  160. data/lib/active_support/deprecation/proxy_wrappers.rb +82 -31
  161. data/lib/active_support/deprecation/reporting.rb +81 -18
  162. data/lib/active_support/deprecation.rb +19 -11
  163. data/lib/active_support/descendants_tracker.rb +192 -34
  164. data/lib/active_support/digest.rb +22 -0
  165. data/lib/active_support/duration/iso8601_parser.rb +123 -0
  166. data/lib/active_support/duration/iso8601_serializer.rb +67 -0
  167. data/lib/active_support/duration.rb +437 -39
  168. data/lib/active_support/encrypted_configuration.rb +56 -0
  169. data/lib/active_support/encrypted_file.rb +117 -0
  170. data/lib/active_support/environment_inquirer.rb +20 -0
  171. data/lib/active_support/error_reporter.rb +117 -0
  172. data/lib/active_support/evented_file_update_checker.rb +170 -0
  173. data/lib/active_support/execution_context/test_helper.rb +13 -0
  174. data/lib/active_support/execution_context.rb +53 -0
  175. data/lib/active_support/execution_wrapper.rb +151 -0
  176. data/lib/active_support/executor/test_helper.rb +7 -0
  177. data/lib/active_support/executor.rb +8 -0
  178. data/lib/active_support/file_update_checker.rb +62 -37
  179. data/lib/active_support/fork_tracker.rb +71 -0
  180. data/lib/active_support/gem_version.rb +17 -0
  181. data/lib/active_support/gzip.rb +7 -5
  182. data/lib/active_support/hash_with_indifferent_access.rb +207 -54
  183. data/lib/active_support/html_safe_translation.rb +43 -0
  184. data/lib/active_support/i18n.rb +10 -6
  185. data/lib/active_support/i18n_railtie.rb +48 -19
  186. data/lib/active_support/inflections.rb +19 -12
  187. data/lib/active_support/inflector/inflections.rb +97 -37
  188. data/lib/active_support/inflector/methods.rb +192 -157
  189. data/lib/active_support/inflector/transliterate.rb +83 -33
  190. data/lib/active_support/inflector.rb +7 -5
  191. data/lib/active_support/isolated_execution_state.rb +64 -0
  192. data/lib/active_support/json/decoding.rb +37 -42
  193. data/lib/active_support/json/encoding.rb +93 -293
  194. data/lib/active_support/json.rb +4 -2
  195. data/lib/active_support/key_generator.rb +30 -47
  196. data/lib/active_support/lazy_load_hooks.rb +54 -21
  197. data/lib/active_support/locale/en.rb +33 -0
  198. data/lib/active_support/locale/en.yml +10 -4
  199. data/lib/active_support/log_subscriber/test_helper.rb +14 -12
  200. data/lib/active_support/log_subscriber.rb +61 -18
  201. data/lib/active_support/logger.rb +40 -4
  202. data/lib/active_support/logger_silence.rb +17 -20
  203. data/lib/active_support/logger_thread_safe_level.rb +69 -0
  204. data/lib/active_support/message_encryptor.rb +178 -55
  205. data/lib/active_support/message_verifier.rb +195 -26
  206. data/lib/active_support/messages/metadata.rb +80 -0
  207. data/lib/active_support/messages/rotation_configuration.rb +23 -0
  208. data/lib/active_support/messages/rotator.rb +57 -0
  209. data/lib/active_support/multibyte/chars.rb +45 -92
  210. data/lib/active_support/multibyte/unicode.rb +44 -377
  211. data/lib/active_support/multibyte.rb +5 -3
  212. data/lib/active_support/notifications/fanout.rb +177 -44
  213. data/lib/active_support/notifications/instrumenter.rb +117 -17
  214. data/lib/active_support/notifications.rb +106 -39
  215. data/lib/active_support/number_helper/number_converter.rb +181 -0
  216. data/lib/active_support/number_helper/number_to_currency_converter.rb +46 -0
  217. data/lib/active_support/number_helper/number_to_delimited_converter.rb +30 -0
  218. data/lib/active_support/number_helper/number_to_human_converter.rb +69 -0
  219. data/lib/active_support/number_helper/number_to_human_size_converter.rb +60 -0
  220. data/lib/active_support/number_helper/number_to_percentage_converter.rb +16 -0
  221. data/lib/active_support/number_helper/number_to_phone_converter.rb +59 -0
  222. data/lib/active_support/number_helper/number_to_rounded_converter.rb +59 -0
  223. data/lib/active_support/number_helper/rounding_helper.rb +46 -0
  224. data/lib/active_support/number_helper.rb +152 -394
  225. data/lib/active_support/option_merger.rb +18 -5
  226. data/lib/active_support/ordered_hash.rb +8 -6
  227. data/lib/active_support/ordered_options.rb +43 -7
  228. data/lib/active_support/parameter_filter.rb +138 -0
  229. data/lib/active_support/per_thread_registry.rb +24 -11
  230. data/lib/active_support/proxy_object.rb +2 -0
  231. data/lib/active_support/rails.rb +10 -11
  232. data/lib/active_support/railtie.rb +118 -12
  233. data/lib/active_support/reloader.rb +130 -0
  234. data/lib/active_support/rescuable.rb +112 -57
  235. data/lib/active_support/ruby_features.rb +7 -0
  236. data/lib/active_support/secure_compare_rotator.rb +51 -0
  237. data/lib/active_support/security_utils.rb +38 -0
  238. data/lib/active_support/string_inquirer.rb +11 -4
  239. data/lib/active_support/subscriber.rb +109 -39
  240. data/lib/active_support/tagged_logging.rb +54 -17
  241. data/lib/active_support/test_case.rb +121 -37
  242. data/lib/active_support/testing/assertions.rb +177 -39
  243. data/lib/active_support/testing/autorun.rb +5 -3
  244. data/lib/active_support/testing/constant_lookup.rb +3 -6
  245. data/lib/active_support/testing/declarative.rb +10 -22
  246. data/lib/active_support/testing/deprecation.rb +65 -11
  247. data/lib/active_support/testing/file_fixtures.rb +38 -0
  248. data/lib/active_support/testing/isolation.rb +56 -87
  249. data/lib/active_support/testing/method_call_assertions.rb +70 -0
  250. data/lib/active_support/testing/parallelization/server.rb +82 -0
  251. data/lib/active_support/testing/parallelization/worker.rb +103 -0
  252. data/lib/active_support/testing/parallelization.rb +55 -0
  253. data/lib/active_support/testing/parallelize_executor.rb +76 -0
  254. data/lib/active_support/testing/setup_and_teardown.rb +30 -10
  255. data/lib/active_support/testing/stream.rb +41 -0
  256. data/lib/active_support/testing/tagged_logging.rb +6 -4
  257. data/lib/active_support/testing/time_helpers.rb +246 -0
  258. data/lib/active_support/time.rb +13 -13
  259. data/lib/active_support/time_with_zone.rb +315 -90
  260. data/lib/active_support/values/time_zone.rb +306 -135
  261. data/lib/active_support/version.rb +6 -7
  262. data/lib/active_support/xml_mini/jdom.rb +117 -115
  263. data/lib/active_support/xml_mini/libxml.rb +22 -21
  264. data/lib/active_support/xml_mini/libxmlsax.rb +17 -19
  265. data/lib/active_support/xml_mini/nokogiri.rb +19 -19
  266. data/lib/active_support/xml_mini/nokogirisax.rb +16 -17
  267. data/lib/active_support/xml_mini/rexml.rb +25 -17
  268. data/lib/active_support/xml_mini.rb +67 -56
  269. data/lib/active_support.rb +58 -3
  270. metadata +125 -66
  271. data/lib/active_support/basic_object.rb +0 -11
  272. data/lib/active_support/buffered_logger.rb +0 -21
  273. data/lib/active_support/concurrency/latch.rb +0 -27
  274. data/lib/active_support/core_ext/array/prepend_and_append.rb +0 -7
  275. data/lib/active_support/core_ext/array/uniq_by.rb +0 -19
  276. data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -40
  277. data/lib/active_support/core_ext/date_time/zones.rb +0 -24
  278. data/lib/active_support/core_ext/hash/diff.rb +0 -14
  279. data/lib/active_support/core_ext/kernel/agnostics.rb +0 -11
  280. data/lib/active_support/core_ext/kernel/debugger.rb +0 -10
  281. data/lib/active_support/core_ext/logger.rb +0 -67
  282. data/lib/active_support/core_ext/marshal.rb +0 -21
  283. data/lib/active_support/core_ext/module/qualified_const.rb +0 -52
  284. data/lib/active_support/core_ext/module/reachable.rb +0 -8
  285. data/lib/active_support/core_ext/object/to_json.rb +0 -27
  286. data/lib/active_support/core_ext/proc.rb +0 -17
  287. data/lib/active_support/core_ext/range/include_range.rb +0 -23
  288. data/lib/active_support/core_ext/string/encoding.rb +0 -8
  289. data/lib/active_support/core_ext/struct.rb +0 -6
  290. data/lib/active_support/core_ext/thread.rb +0 -79
  291. data/lib/active_support/core_ext/time/marshal.rb +0 -30
  292. data/lib/active_support/file_watcher.rb +0 -36
  293. data/lib/active_support/json/variable.rb +0 -18
  294. data/lib/active_support/testing/pending.rb +0 -14
  295. data/lib/active_support/values/unicode_tables.dat +0 -0
@@ -1,34 +1,88 @@
1
- require 'active_support/deprecation'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/deprecation"
2
4
 
3
5
  module ActiveSupport
4
6
  module Testing
5
- module Deprecation #:nodoc:
6
- def assert_deprecated(match = nil, &block)
7
- result, warnings = collect_deprecations(&block)
7
+ module Deprecation
8
+ # Asserts that a matching deprecation warning was emitted by the given deprecator during the execution of the yielded block.
9
+ #
10
+ # assert_deprecated(/foo/, CustomDeprecator) do
11
+ # CustomDeprecator.warn "foo should no longer be used"
12
+ # end
13
+ #
14
+ # The +match+ object may be a +Regexp+, or +String+ appearing in the message.
15
+ #
16
+ # assert_deprecated('foo', CustomDeprecator) do
17
+ # CustomDeprecator.warn "foo should no longer be used"
18
+ # end
19
+ #
20
+ # If the +match+ is omitted (or explicitly +nil+), any deprecation warning will match.
21
+ #
22
+ # assert_deprecated(nil, CustomDeprecator) do
23
+ # CustomDeprecator.warn "foo should no longer be used"
24
+ # end
25
+ #
26
+ # If no +deprecator+ is given, defaults to ActiveSupport::Deprecation.
27
+ #
28
+ # assert_deprecated do
29
+ # ActiveSupport::Deprecation.warn "foo should no longer be used"
30
+ # end
31
+ def assert_deprecated(match = nil, deprecator = nil, &block)
32
+ result, warnings = collect_deprecations(deprecator, &block)
8
33
  assert !warnings.empty?, "Expected a deprecation warning within the block but received none"
9
34
  if match
10
35
  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(', ')}"
36
+ assert warnings.any? { |w| match.match?(w) }, "No deprecation warning matched #{match}: #{warnings.join(', ')}"
12
37
  end
13
38
  result
14
39
  end
15
40
 
16
- def assert_not_deprecated(&block)
17
- result, deprecations = collect_deprecations(&block)
41
+ # Asserts that no deprecation warnings are emitted by the given deprecator during the execution of the yielded block.
42
+ #
43
+ # assert_not_deprecated(CustomDeprecator) do
44
+ # CustomDeprecator.warn "message" # fails assertion
45
+ # end
46
+ #
47
+ # If no +deprecator+ is given, defaults to ActiveSupport::Deprecation.
48
+ #
49
+ # assert_not_deprecated do
50
+ # ActiveSupport::Deprecation.warn "message" # fails assertion
51
+ # end
52
+ #
53
+ # assert_not_deprecated do
54
+ # CustomDeprecator.warn "message" # passes assertion
55
+ # end
56
+ def assert_not_deprecated(deprecator = nil, &block)
57
+ result, deprecations = collect_deprecations(deprecator, &block)
18
58
  assert deprecations.empty?, "Expected no deprecation warning within the block but received #{deprecations.size}: \n #{deprecations * "\n "}"
19
59
  result
20
60
  end
21
61
 
22
- def collect_deprecations
23
- old_behavior = ActiveSupport::Deprecation.behavior
62
+ # Returns an array of all the deprecation warnings emitted by the given
63
+ # +deprecator+ during the execution of the yielded block.
64
+ #
65
+ # collect_deprecations(CustomDeprecator) do
66
+ # CustomDeprecator.warn "message"
67
+ # end # => ["message"]
68
+ #
69
+ # If no +deprecator+ is given, defaults to ActiveSupport::Deprecation.
70
+ #
71
+ # collect_deprecations do
72
+ # CustomDeprecator.warn "custom message"
73
+ # ActiveSupport::Deprecation.warn "message"
74
+ # end # => ["message"]
75
+ def collect_deprecations(deprecator = nil)
76
+ deprecator ||= ActiveSupport::Deprecation
77
+ old_behavior = deprecator.behavior
24
78
  deprecations = []
25
- ActiveSupport::Deprecation.behavior = Proc.new do |message, callstack|
79
+ deprecator.behavior = Proc.new do |message, callstack|
26
80
  deprecations << message
27
81
  end
28
82
  result = yield
29
83
  [result, deprecations]
30
84
  ensure
31
- ActiveSupport::Deprecation.behavior = old_behavior
85
+ deprecator.behavior = old_behavior
32
86
  end
33
87
  end
34
88
  end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/concern"
4
+
5
+ module ActiveSupport
6
+ module Testing
7
+ # Adds simple access to sample files called file fixtures.
8
+ # File fixtures are normal files stored in
9
+ # <tt>ActiveSupport::TestCase.file_fixture_path</tt>.
10
+ #
11
+ # File fixtures are represented as +Pathname+ objects.
12
+ # This makes it easy to extract specific information:
13
+ #
14
+ # file_fixture("example.txt").read # get the file's content
15
+ # file_fixture("example.mp3").size # get the file size
16
+ module FileFixtures
17
+ extend ActiveSupport::Concern
18
+
19
+ included do
20
+ class_attribute :file_fixture_path, instance_writer: false
21
+ end
22
+
23
+ # Returns a +Pathname+ to the fixture file named +fixture_name+.
24
+ #
25
+ # Raises +ArgumentError+ if +fixture_name+ can't be found.
26
+ def file_fixture(fixture_name)
27
+ path = Pathname.new(File.join(file_fixture_path, fixture_name))
28
+
29
+ if path.exist?
30
+ path
31
+ else
32
+ msg = "the directory '%s' does not contain a file named '%s'"
33
+ raise ArgumentError, msg % [file_fixture_path, fixture_name]
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -1,135 +1,104 @@
1
- require 'rbconfig'
2
- require 'minitest/parallel_each'
1
+ # frozen_string_literal: true
3
2
 
4
3
  module ActiveSupport
5
4
  module Testing
6
- class RemoteError < StandardError
7
-
8
- attr_reader :message, :backtrace
9
-
10
- def initialize(exception)
11
- @message = "caught #{exception.class.name}: #{exception.message}"
12
- @backtrace = exception.backtrace
13
- end
14
- end
15
-
16
- class ProxyTestResult
17
- def initialize(calls = [])
18
- @calls = calls
19
- end
20
-
21
- def add_error(e)
22
- e = Test::Unit::Error.new(e.test_name, RemoteError.new(e.exception))
23
- @calls << [:add_error, e]
24
- end
25
-
26
- def __replay__(result)
27
- @calls.each do |name, args|
28
- result.send(name, *args)
29
- end
30
- end
31
-
32
- def marshal_dump
33
- @calls
34
- end
35
-
36
- def marshal_load(calls)
37
- initialize(calls)
38
- end
39
-
40
- def method_missing(name, *args)
41
- @calls << [name, args]
42
- end
43
-
44
- def info_signal
45
- Signal.list['INFO']
46
- end
47
- end
48
-
49
5
  module Isolation
50
- require 'thread'
6
+ require "thread"
51
7
 
52
- def self.included(klass) #:nodoc:
53
- klass.extend(Module.new {
54
- def test_methods
55
- ParallelEach.new super
56
- end
57
- })
8
+ def self.included(klass) # :nodoc:
9
+ klass.class_eval do
10
+ parallelize_me!
11
+ end
58
12
  end
59
13
 
60
14
  def self.forking_env?
61
- !ENV["NO_FORK"] && ((RbConfig::CONFIG['host_os'] !~ /mswin|mingw/) && (RUBY_PLATFORM !~ /java/))
62
- end
63
-
64
- @@class_setup_mutex = Mutex.new
65
-
66
- def _run_class_setup # class setup method should only happen in parent
67
- @@class_setup_mutex.synchronize do
68
- unless defined?(@@ran_class_setup) || ENV['ISOLATION_TEST']
69
- self.class.setup if self.class.respond_to?(:setup)
70
- @@ran_class_setup = true
71
- end
72
- end
15
+ !ENV["NO_FORK"] && Process.respond_to?(:fork)
73
16
  end
74
17
 
75
- def run(runner)
76
- _run_class_setup
77
-
78
- serialized = run_in_isolation do |isolated_runner|
79
- super(isolated_runner)
18
+ def run
19
+ serialized = run_in_isolation do
20
+ super
80
21
  end
81
22
 
82
- retval, proxy = Marshal.load(serialized)
83
- proxy.__replay__(runner)
84
- retval
23
+ Marshal.load(serialized)
85
24
  end
86
25
 
87
26
  module Forking
88
27
  def run_in_isolation(&blk)
89
28
  read, write = IO.pipe
29
+ read.binmode
30
+ write.binmode
90
31
 
91
32
  pid = fork do
92
33
  read.close
93
- proxy = ProxyTestResult.new
94
- retval = yield proxy
95
- write.puts [Marshal.dump([retval, proxy])].pack("m")
34
+ yield
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")
96
53
  exit!
97
54
  end
98
55
 
99
56
  write.close
100
57
  result = read.read
101
58
  Process.wait2(pid)
102
- return result.unpack("m")[0]
59
+ result.unpack1("m")
103
60
  end
104
61
  end
105
62
 
106
63
  module Subprocess
107
64
  ORIG_ARGV = ARGV.dup unless defined?(ORIG_ARGV)
108
65
 
109
- # Crazy H4X to get this working in windows / jruby with
66
+ # Complicated H4X to get this working in windows / jruby with
110
67
  # no forking.
111
68
  def run_in_isolation(&blk)
112
69
  require "tempfile"
113
70
 
114
71
  if ENV["ISOLATION_TEST"]
115
- proxy = ProxyTestResult.new
116
- retval = yield proxy
72
+ yield
73
+ test_result = defined?(Minitest::Result) ? Minitest::Result.from(self) : dup
117
74
  File.open(ENV["ISOLATION_OUTPUT"], "w") do |file|
118
- file.puts [Marshal.dump([retval, proxy])].pack("m")
75
+ file.puts [Marshal.dump(test_result)].pack("m")
119
76
  end
120
77
  exit!
121
78
  else
122
79
  Tempfile.open("isolation") do |tmpfile|
123
- ENV["ISOLATION_TEST"] = @method_name
124
- ENV["ISOLATION_OUTPUT"] = tmpfile.path
80
+ env = {
81
+ "ISOLATION_TEST" => self.class.name,
82
+ "ISOLATION_OUTPUT" => tmpfile.path
83
+ }
84
+
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
125
92
 
126
- load_paths = $-I.map {|p| "-I\"#{File.expand_path(p)}\"" }.join(" ")
127
- `#{Gem.ruby} #{load_paths} #{$0} #{ORIG_ARGV.join(" ")} -t\"#{self.class}\"`
93
+ child = IO.popen([env, Gem.ruby, *load_path_args, $0, *ORIG_ARGV, test_opts])
128
94
 
129
- ENV.delete("ISOLATION_TEST")
130
- ENV.delete("ISOLATION_OUTPUT")
95
+ begin
96
+ Process.wait(child.pid)
97
+ rescue Errno::ECHILD # The child process may exit before we wait
98
+ nil
99
+ end
131
100
 
132
- return tmpfile.read.unpack("m")[0]
101
+ return tmpfile.read.unpack1("m")
133
102
  end
134
103
  end
135
104
  end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "minitest/mock"
4
+
5
+ module ActiveSupport
6
+ module Testing
7
+ module MethodCallAssertions # :nodoc:
8
+ private
9
+ def assert_called(object, method_name, message = nil, times: 1, returns: nil, &block)
10
+ times_called = 0
11
+
12
+ object.stub(method_name, proc { times_called += 1; returns }, &block)
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, &block)
21
+ mock = Minitest::Mock.new
22
+
23
+ if args.all?(Array)
24
+ args.each { |arg| mock.expect(:call, returns, arg) }
25
+ else
26
+ mock.expect(:call, returns, args)
27
+ end
28
+
29
+ object.stub(method_name, mock, &block)
30
+
31
+ mock.verify
32
+ end
33
+
34
+ def assert_not_called(object, method_name, message = nil, &block)
35
+ assert_called(object, method_name, message, times: 0, &block)
36
+ end
37
+
38
+ def assert_called_on_instance_of(klass, method_name, message = nil, times: 1, returns: nil)
39
+ times_called = 0
40
+ klass.define_method("stubbed_#{method_name}") do |*|
41
+ times_called += 1
42
+
43
+ returns
44
+ end
45
+
46
+ klass.alias_method "original_#{method_name}", method_name
47
+ klass.alias_method method_name, "stubbed_#{method_name}"
48
+
49
+ yield
50
+
51
+ error = "Expected #{method_name} to be called #{times} times, but was called #{times_called} times"
52
+ error = "#{message}.\n#{error}" if message
53
+
54
+ assert_equal times, times_called, error
55
+ ensure
56
+ klass.alias_method method_name, "original_#{method_name}"
57
+ klass.undef_method "original_#{method_name}"
58
+ klass.undef_method "stubbed_#{method_name}"
59
+ end
60
+
61
+ def assert_not_called_on_instance_of(klass, method_name, message = nil, &block)
62
+ assert_called_on_instance_of(klass, method_name, message, times: 0, &block)
63
+ end
64
+
65
+ def stub_any_instance(klass, instance: klass.new)
66
+ klass.stub(:new, instance) { yield instance }
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "drb"
4
+ require "drb/unix" unless Gem.win_platform?
5
+
6
+ module ActiveSupport
7
+ module Testing
8
+ class Parallelization # :nodoc:
9
+ class Server
10
+ include DRb::DRbUndumped
11
+
12
+ def initialize
13
+ @queue = Queue.new
14
+ @active_workers = Concurrent::Map.new
15
+ @in_flight = Concurrent::Map.new
16
+ end
17
+
18
+ def record(reporter, result)
19
+ raise DRb::DRbConnError if result.is_a?(DRb::DRbUnknown)
20
+
21
+ @in_flight.delete([result.klass, result.name])
22
+
23
+ reporter.synchronize do
24
+ reporter.record(result)
25
+ end
26
+ end
27
+
28
+ def <<(o)
29
+ o[2] = DRbObject.new(o[2]) if o
30
+ @queue << o
31
+ end
32
+
33
+ def pop
34
+ if test = @queue.pop
35
+ @in_flight[[test[0].to_s, test[1]]] = test
36
+ test
37
+ end
38
+ end
39
+
40
+ def start_worker(worker_id)
41
+ @active_workers[worker_id] = true
42
+ end
43
+
44
+ def stop_worker(worker_id)
45
+ @active_workers.delete(worker_id)
46
+ end
47
+
48
+ def active_workers?
49
+ @active_workers.size > 0
50
+ end
51
+
52
+ def interrupt
53
+ @queue.clear
54
+ end
55
+
56
+ def shutdown
57
+ # Wait for initial queue to drain
58
+ while @queue.length != 0
59
+ sleep 0.1
60
+ end
61
+
62
+ @queue.close
63
+
64
+ # Wait until all workers have finished
65
+ while active_workers?
66
+ sleep 0.1
67
+ end
68
+
69
+ @in_flight.values.each do |(klass, name, reporter)|
70
+ result = Minitest::Result.from(klass.new(name))
71
+ error = RuntimeError.new("result not reported")
72
+ error.set_backtrace([""])
73
+ result.failures << Minitest::UnexpectedError.new(error)
74
+ reporter.synchronize do
75
+ reporter.record(result)
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveSupport
4
+ module Testing
5
+ class Parallelization # :nodoc:
6
+ class Worker
7
+ def initialize(number, url)
8
+ @id = SecureRandom.uuid
9
+ @number = number
10
+ @url = url
11
+ @setup_exception = nil
12
+ end
13
+
14
+ def start
15
+ fork do
16
+ set_process_title("(starting)")
17
+
18
+ DRb.stop_service
19
+
20
+ @queue = DRbObject.new_with_uri(@url)
21
+ @queue.start_worker(@id)
22
+
23
+ begin
24
+ after_fork
25
+ rescue => @setup_exception; end
26
+
27
+ work_from_queue
28
+ ensure
29
+ set_process_title("(stopping)")
30
+
31
+ run_cleanup
32
+ @queue.stop_worker(@id)
33
+ end
34
+ end
35
+
36
+ def work_from_queue
37
+ while job = @queue.pop
38
+ perform_job(job)
39
+ end
40
+ end
41
+
42
+ def perform_job(job)
43
+ klass = job[0]
44
+ method = job[1]
45
+ reporter = job[2]
46
+
47
+ set_process_title("#{klass}##{method}")
48
+
49
+ result = klass.with_info_handler reporter do
50
+ Minitest.run_one_method(klass, method)
51
+ end
52
+
53
+ safe_record(reporter, result)
54
+ end
55
+
56
+ def safe_record(reporter, result)
57
+ add_setup_exception(result) if @setup_exception
58
+
59
+ begin
60
+ @queue.record(reporter, result)
61
+ rescue DRb::DRbConnError
62
+ result.failures.map! do |failure|
63
+ if failure.respond_to?(:error)
64
+ # minitest >5.14.0
65
+ error = DRb::DRbRemoteError.new(failure.error)
66
+ else
67
+ error = DRb::DRbRemoteError.new(failure.exception)
68
+ end
69
+ Minitest::UnexpectedError.new(error)
70
+ end
71
+ @queue.record(reporter, result)
72
+ rescue Interrupt
73
+ @queue.interrupt
74
+ raise
75
+ end
76
+
77
+ set_process_title("(idle)")
78
+ end
79
+
80
+ def after_fork
81
+ Parallelization.after_fork_hooks.each do |cb|
82
+ cb.call(@number)
83
+ end
84
+ end
85
+
86
+ def run_cleanup
87
+ Parallelization.run_cleanup_hooks.each do |cb|
88
+ cb.call(@number)
89
+ end
90
+ end
91
+
92
+ private
93
+ def add_setup_exception(result)
94
+ result.failures.prepend Minitest::UnexpectedError.new(@setup_exception)
95
+ end
96
+
97
+ def set_process_title(status)
98
+ Process.setproctitle("Rails test worker #{@number} - #{status}")
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "drb"
4
+ require "drb/unix" unless Gem.win_platform?
5
+ require "active_support/core_ext/module/attribute_accessors"
6
+ require "active_support/testing/parallelization/server"
7
+ require "active_support/testing/parallelization/worker"
8
+
9
+ module ActiveSupport
10
+ module Testing
11
+ class Parallelization # :nodoc:
12
+ @@after_fork_hooks = []
13
+
14
+ def self.after_fork_hook(&blk)
15
+ @@after_fork_hooks << blk
16
+ end
17
+
18
+ cattr_reader :after_fork_hooks
19
+
20
+ @@run_cleanup_hooks = []
21
+
22
+ def self.run_cleanup_hook(&blk)
23
+ @@run_cleanup_hooks << blk
24
+ end
25
+
26
+ cattr_reader :run_cleanup_hooks
27
+
28
+ def initialize(worker_count)
29
+ @worker_count = worker_count
30
+ @queue_server = Server.new
31
+ @worker_pool = []
32
+ @url = DRb.start_service("drbunix:", @queue_server).uri
33
+ end
34
+
35
+ def start
36
+ @worker_pool = @worker_count.times.map do |worker|
37
+ Worker.new(worker, @url).start
38
+ end
39
+ end
40
+
41
+ def <<(work)
42
+ @queue_server << work
43
+ end
44
+
45
+ def size
46
+ @worker_count
47
+ end
48
+
49
+ def shutdown
50
+ @queue_server.shutdown
51
+ @worker_pool.each { |pid| Process.waitpid pid }
52
+ end
53
+ end
54
+ end
55
+ end