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,16 +1,27 @@
1
- require 'active_support/core_ext/module/delegation'
2
- require 'active_support/core_ext/object/blank'
3
- require 'logger'
4
- require 'active_support/logger'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/module/delegation"
4
+ require "active_support/core_ext/object/blank"
5
+ require "logger"
6
+ require "active_support/logger"
5
7
 
6
8
  module ActiveSupport
7
9
  # Wraps any standard Logger object to provide tagging capabilities.
8
10
  #
11
+ # May be called with a block:
12
+ #
9
13
  # logger = ActiveSupport::TaggedLogging.new(Logger.new(STDOUT))
10
14
  # logger.tagged('BCX') { logger.info 'Stuff' } # Logs "[BCX] Stuff"
11
15
  # logger.tagged('BCX', "Jason") { logger.info 'Stuff' } # Logs "[BCX] [Jason] Stuff"
12
16
  # logger.tagged('BCX') { logger.tagged('Jason') { logger.info 'Stuff' } } # Logs "[BCX] [Jason] Stuff"
13
17
  #
18
+ # If called without a block, a new logger will be returned with applied tags:
19
+ #
20
+ # logger = ActiveSupport::TaggedLogging.new(Logger.new(STDOUT))
21
+ # logger.tagged("BCX").info "Stuff" # Logs "[BCX] Stuff"
22
+ # logger.tagged("BCX", "Jason").info "Stuff" # Logs "[BCX] [Jason] Stuff"
23
+ # logger.tagged("BCX").tagged("Jason").info "Stuff" # Logs "[BCX] [Jason] Stuff"
24
+ #
14
25
  # This is used by the default Rails.logger as configured by Railties to make
15
26
  # it easy to stamp log lines with subdomains, request ids, and anything else
16
27
  # to aid debugging of multi-user production applications.
@@ -29,9 +40,10 @@ module ActiveSupport
29
40
  end
30
41
 
31
42
  def push_tags(*tags)
32
- tags.flatten.reject(&:blank?).tap do |new_tags|
33
- current_tags.concat new_tags
34
- end
43
+ tags.flatten!
44
+ tags.reject!(&:blank?)
45
+ current_tags.concat tags
46
+ tags
35
47
  end
36
48
 
37
49
  def pop_tags(size = 1)
@@ -43,21 +55,39 @@ module ActiveSupport
43
55
  end
44
56
 
45
57
  def current_tags
46
- Thread.current[:activesupport_tagged_logging_tags] ||= []
58
+ # We use our object ID here to avoid conflicting with other instances
59
+ thread_key = @thread_key ||= "activesupport_tagged_logging_tags:#{object_id}"
60
+ IsolatedExecutionState[thread_key] ||= []
47
61
  end
48
62
 
49
- private
50
- def tags_text
51
- tags = current_tags
52
- if tags.any?
53
- tags.collect { |tag| "[#{tag}] " }.join
54
- end
63
+ def tags_text
64
+ tags = current_tags
65
+ if tags.one?
66
+ "[#{tags[0]}] "
67
+ elsif tags.any?
68
+ tags.collect { |tag| "[#{tag}] " }.join
55
69
  end
70
+ end
71
+ end
72
+
73
+ module LocalTagStorage # :nodoc:
74
+ attr_accessor :current_tags
75
+
76
+ def self.extended(base)
77
+ base.current_tags = []
78
+ end
56
79
  end
57
80
 
58
81
  def self.new(logger)
59
- # Ensure we set a default formatter so we aren't extending nil!
60
- logger.formatter ||= ActiveSupport::Logger::SimpleFormatter.new
82
+ logger = logger.clone
83
+
84
+ if logger.formatter
85
+ logger.formatter = logger.formatter.dup
86
+ else
87
+ # Ensure we set a default formatter so we aren't extending nil!
88
+ logger.formatter = ActiveSupport::Logger::SimpleFormatter.new
89
+ end
90
+
61
91
  logger.formatter.extend Formatter
62
92
  logger.extend(self)
63
93
  end
@@ -65,7 +95,14 @@ module ActiveSupport
65
95
  delegate :push_tags, :pop_tags, :clear_tags!, to: :formatter
66
96
 
67
97
  def tagged(*tags)
68
- formatter.tagged(*tags) { yield self }
98
+ if block_given?
99
+ formatter.tagged(*tags) { yield self }
100
+ else
101
+ logger = ActiveSupport::TaggedLogging.new(self)
102
+ logger.formatter.extend LocalTagStorage
103
+ logger.push_tags(*formatter.current_tags, *tags)
104
+ logger
105
+ end
69
106
  end
70
107
 
71
108
  def flush
@@ -1,42 +1,133 @@
1
- gem 'minitest' # make sure we get the gem, not stdlib
2
- require 'minitest/unit'
3
- require 'active_support/testing/tagged_logging'
4
- require 'active_support/testing/setup_and_teardown'
5
- require 'active_support/testing/assertions'
6
- require 'active_support/testing/deprecation'
7
- require 'active_support/testing/pending'
8
- require 'active_support/testing/declarative'
9
- require 'active_support/testing/isolation'
10
- require 'active_support/testing/constant_lookup'
11
- require 'active_support/core_ext/kernel/reporting'
12
- require 'active_support/deprecation'
1
+ # frozen_string_literal: true
13
2
 
14
- begin
15
- silence_warnings { require 'mocha/setup' }
16
- rescue LoadError
17
- end
3
+ gem "minitest" # make sure we get the gem, not stdlib
4
+ require "minitest"
5
+ require "active_support/testing/tagged_logging"
6
+ require "active_support/testing/setup_and_teardown"
7
+ require "active_support/testing/assertions"
8
+ require "active_support/testing/deprecation"
9
+ require "active_support/testing/declarative"
10
+ require "active_support/testing/isolation"
11
+ require "active_support/testing/constant_lookup"
12
+ require "active_support/testing/time_helpers"
13
+ require "active_support/testing/file_fixtures"
14
+ require "active_support/testing/parallelization"
15
+ require "active_support/testing/parallelize_executor"
16
+ require "concurrent/utility/processor_counter"
18
17
 
19
18
  module ActiveSupport
20
- class TestCase < ::MiniTest::Unit::TestCase
21
- Assertion = MiniTest::Assertion
22
- alias_method :method_name, :__name__
19
+ class TestCase < ::Minitest::Test
20
+ Assertion = Minitest::Assertion
23
21
 
24
- $tags = {}
25
- def self.for_tag(tag)
26
- yield if $tags[tag]
27
- end
22
+ class << self
23
+ # Sets the order in which test cases are run.
24
+ #
25
+ # ActiveSupport::TestCase.test_order = :random # => :random
26
+ #
27
+ # Valid values are:
28
+ # * +:random+ (to run tests in random order)
29
+ # * +:parallel+ (to run tests in parallel)
30
+ # * +:sorted+ (to run tests alphabetically by method name)
31
+ # * +:alpha+ (equivalent to +:sorted+)
32
+ def test_order=(new_order)
33
+ ActiveSupport.test_order = new_order
34
+ end
35
+
36
+ # Returns the order in which test cases are run.
37
+ #
38
+ # ActiveSupport::TestCase.test_order # => :random
39
+ #
40
+ # Possible values are +:random+, +:parallel+, +:alpha+, +:sorted+.
41
+ # Defaults to +:random+.
42
+ def test_order
43
+ ActiveSupport.test_order ||= :random
44
+ end
45
+
46
+ # Parallelizes the test suite.
47
+ #
48
+ # Takes a +workers+ argument that controls how many times the process
49
+ # is forked. For each process a new database will be created suffixed
50
+ # with the worker number.
51
+ #
52
+ # test-database-0
53
+ # test-database-1
54
+ #
55
+ # If <tt>ENV["PARALLEL_WORKERS"]</tt> is set the workers argument will be ignored
56
+ # and the environment variable will be used instead. This is useful for CI
57
+ # environments, or other environments where you may need more workers than
58
+ # you do for local testing.
59
+ #
60
+ # If the number of workers is set to +1+ or fewer, the tests will not be
61
+ # parallelized.
62
+ #
63
+ # If +workers+ is set to +:number_of_processors+, the number of workers will be
64
+ # set to the actual core count on the machine you are on.
65
+ #
66
+ # The default parallelization method is to fork processes. If you'd like to
67
+ # use threads instead you can pass <tt>with: :threads</tt> to the +parallelize+
68
+ # method. Note the threaded parallelization does not create multiple
69
+ # database and will not work with system tests at this time.
70
+ #
71
+ # parallelize(workers: :number_of_processors, with: :threads)
72
+ #
73
+ # The threaded parallelization uses minitest's parallel executor directly.
74
+ # The processes parallelization uses a Ruby DRb server.
75
+ #
76
+ # Because parallelization presents an overhead, it is only enabled when the
77
+ # number of tests to run is above the +threshold+ param. The default value is
78
+ # 50, and it's configurable via +config.active_support.test_parallelization_threshold+.
79
+ def parallelize(workers: :number_of_processors, with: :processes, threshold: ActiveSupport.test_parallelization_threshold)
80
+ workers = Concurrent.physical_processor_count if workers == :number_of_processors
81
+ workers = ENV["PARALLEL_WORKERS"].to_i if ENV["PARALLEL_WORKERS"]
82
+
83
+ return if workers <= 1
28
84
 
29
- # FIXME: we have tests that depend on run order, we should fix that and
30
- # remove this method.
31
- def self.test_order # :nodoc:
32
- :sorted
85
+ Minitest.parallel_executor = ActiveSupport::Testing::ParallelizeExecutor.new(size: workers, with: with, threshold: threshold)
86
+ end
87
+
88
+ # Set up hook for parallel testing. This can be used if you have multiple
89
+ # databases or any behavior that needs to be run after the process is forked
90
+ # but before the tests run.
91
+ #
92
+ # Note: this feature is not available with the threaded parallelization.
93
+ #
94
+ # In your +test_helper.rb+ add the following:
95
+ #
96
+ # class ActiveSupport::TestCase
97
+ # parallelize_setup do
98
+ # # create databases
99
+ # end
100
+ # end
101
+ def parallelize_setup(&block)
102
+ ActiveSupport::Testing::Parallelization.after_fork_hook(&block)
103
+ end
104
+
105
+ # Clean up hook for parallel testing. This can be used to drop databases
106
+ # if your app uses multiple write/read databases or other clean up before
107
+ # the tests finish. This runs before the forked process is closed.
108
+ #
109
+ # Note: this feature is not available with the threaded parallelization.
110
+ #
111
+ # In your +test_helper.rb+ add the following:
112
+ #
113
+ # class ActiveSupport::TestCase
114
+ # parallelize_teardown do
115
+ # # drop databases
116
+ # end
117
+ # end
118
+ def parallelize_teardown(&block)
119
+ ActiveSupport::Testing::Parallelization.run_cleanup_hook(&block)
120
+ end
33
121
  end
34
122
 
123
+ alias_method :method_name, :name
124
+
35
125
  include ActiveSupport::Testing::TaggedLogging
36
- include ActiveSupport::Testing::SetupAndTeardown
126
+ prepend ActiveSupport::Testing::SetupAndTeardown
37
127
  include ActiveSupport::Testing::Assertions
38
128
  include ActiveSupport::Testing::Deprecation
39
- include ActiveSupport::Testing::Pending
129
+ include ActiveSupport::Testing::TimeHelpers
130
+ include ActiveSupport::Testing::FileFixtures
40
131
  extend ActiveSupport::Testing::Declarative
41
132
 
42
133
  # test/unit backwards compatibility methods
@@ -55,13 +146,6 @@ module ActiveSupport
55
146
  alias :assert_not_respond_to :refute_respond_to
56
147
  alias :assert_not_same :refute_same
57
148
 
58
- # Fails if the block raises an exception.
59
- #
60
- # assert_nothing_raised do
61
- # ...
62
- # end
63
- def assert_nothing_raised(*args)
64
- yield
65
- end
149
+ ActiveSupport.run_load_hooks(:active_support_test_case, self)
66
150
  end
67
151
  end
@@ -1,15 +1,19 @@
1
- require 'active_support/core_ext/object/blank'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/enumerable"
2
4
 
3
5
  module ActiveSupport
4
6
  module Testing
5
7
  module Assertions
6
- # Assert that an expression is not truthy. Passes if <tt>object</tt> is
8
+ UNTRACKED = Object.new # :nodoc:
9
+
10
+ # Asserts that an expression is not truthy. Passes if <tt>object</tt> is
7
11
  # +nil+ or +false+. "Truthy" means "considered true in a conditional"
8
12
  # like <tt>if foo</tt>.
9
13
  #
10
14
  # assert_not nil # => true
11
15
  # assert_not false # => true
12
- # assert_not 'foo' # => 'foo' is not nil or false
16
+ # assert_not 'foo' # => Expected "foo" to be nil or false
13
17
  #
14
18
  # An error message can be specified.
15
19
  #
@@ -19,109 +23,243 @@ module ActiveSupport
19
23
  assert !object, message
20
24
  end
21
25
 
26
+ # Assertion that the block should not raise an exception.
27
+ #
28
+ # Passes if evaluated code in the yielded block raises no exception.
29
+ #
30
+ # assert_nothing_raised do
31
+ # perform_service(param: 'no_exception')
32
+ # end
33
+ def assert_nothing_raised
34
+ yield
35
+ rescue => error
36
+ raise Minitest::UnexpectedError.new(error)
37
+ end
38
+
22
39
  # Test numeric difference between the return value of an expression as a
23
40
  # result of what is evaluated in the yielded block.
24
41
  #
25
42
  # assert_difference 'Article.count' do
26
- # post :create, article: {...}
43
+ # post :create, params: { article: {...} }
27
44
  # end
28
45
  #
29
46
  # An arbitrary expression is passed in and evaluated.
30
47
  #
31
- # assert_difference 'assigns(:article).comments(:reload).size' do
32
- # post :create, comment: {...}
48
+ # assert_difference 'Article.last.comments(:reload).size' do
49
+ # post :create, params: { comment: {...} }
33
50
  # end
34
51
  #
35
52
  # An arbitrary positive or negative difference can be specified.
36
53
  # The default is <tt>1</tt>.
37
54
  #
38
55
  # assert_difference 'Article.count', -1 do
39
- # post :delete, id: ...
56
+ # post :delete, params: { id: ... }
40
57
  # end
41
58
  #
42
59
  # An array of expressions can also be passed in and evaluated.
43
60
  #
44
61
  # assert_difference [ 'Article.count', 'Post.count' ], 2 do
45
- # post :create, article: {...}
62
+ # post :create, params: { article: {...} }
63
+ # end
64
+ #
65
+ # A hash of expressions/numeric differences can also be passed in and evaluated.
66
+ #
67
+ # assert_difference ->{ Article.count } => 1, ->{ Notification.count } => 2 do
68
+ # post :create, params: { article: {...} }
46
69
  # end
47
70
  #
48
71
  # A lambda or a list of lambdas can be passed in and evaluated:
49
72
  #
50
73
  # assert_difference ->{ Article.count }, 2 do
51
- # post :create, article: {...}
74
+ # post :create, params: { article: {...} }
52
75
  # end
53
76
  #
54
77
  # assert_difference [->{ Article.count }, ->{ Post.count }], 2 do
55
- # post :create, article: {...}
78
+ # post :create, params: { article: {...} }
56
79
  # end
57
80
  #
58
81
  # An error message can be specified.
59
82
  #
60
83
  # assert_difference 'Article.count', -1, 'An Article should be destroyed' do
61
- # post :delete, id: ...
84
+ # post :delete, params: { id: ... }
62
85
  # end
63
- def assert_difference(expression, difference = 1, message = nil, &block)
64
- expressions = Array(expression)
86
+ def assert_difference(expression, *args, &block)
87
+ expressions =
88
+ if expression.is_a?(Hash)
89
+ message = args[0]
90
+ expression
91
+ else
92
+ difference = args[0] || 1
93
+ message = args[1]
94
+ Array(expression).index_with(difference)
95
+ end
65
96
 
66
- exps = expressions.map { |e|
97
+ exps = expressions.keys.map { |e|
67
98
  e.respond_to?(:call) ? e : lambda { eval(e, block.binding) }
68
99
  }
69
- before = exps.map { |e| e.call }
100
+ before = exps.map(&:call)
70
101
 
71
- yield
102
+ retval = _assert_nothing_raised_or_warn("assert_difference", &block)
72
103
 
73
- expressions.zip(exps).each_with_index do |(code, e), i|
74
- error = "#{code.inspect} didn't change by #{difference}"
104
+ expressions.zip(exps, before) do |(code, diff), exp, before_value|
105
+ error = "#{code.inspect} didn't change by #{diff}"
75
106
  error = "#{message}.\n#{error}" if message
76
- assert_equal(before[i] + difference, e.call, error)
107
+ assert_equal(before_value + diff, exp.call, error)
77
108
  end
109
+
110
+ retval
78
111
  end
79
112
 
80
113
  # Assertion that the numeric result of evaluating an expression is not
81
114
  # changed before and after invoking the passed in block.
82
115
  #
83
116
  # assert_no_difference 'Article.count' do
84
- # post :create, article: invalid_attributes
117
+ # post :create, params: { article: invalid_attributes }
118
+ # end
119
+ #
120
+ # A lambda can be passed in and evaluated.
121
+ #
122
+ # assert_no_difference -> { Article.count } do
123
+ # post :create, params: { article: invalid_attributes }
85
124
  # end
86
125
  #
87
126
  # An error message can be specified.
88
127
  #
89
128
  # assert_no_difference 'Article.count', 'An Article should not be created' do
90
- # post :create, article: invalid_attributes
129
+ # post :create, params: { article: invalid_attributes }
130
+ # end
131
+ #
132
+ # An array of expressions can also be passed in and evaluated.
133
+ #
134
+ # assert_no_difference [ 'Article.count', -> { Post.count } ] do
135
+ # post :create, params: { article: invalid_attributes }
91
136
  # end
92
137
  def assert_no_difference(expression, message = nil, &block)
93
138
  assert_difference expression, 0, message, &block
94
139
  end
95
140
 
96
- # Test if an expression is blank. Passes if <tt>object.blank?</tt>
97
- # is +true+.
141
+ # Assertion that the result of evaluating an expression is changed before
142
+ # and after invoking the passed in block.
143
+ #
144
+ # assert_changes 'Status.all_good?' do
145
+ # post :create, params: { status: { ok: false } }
146
+ # end
147
+ #
148
+ # You can pass the block as a string to be evaluated in the context of
149
+ # the block. A lambda can be passed for the block as well.
150
+ #
151
+ # assert_changes -> { Status.all_good? } do
152
+ # post :create, params: { status: { ok: false } }
153
+ # end
154
+ #
155
+ # The assertion is useful to test side effects. The passed block can be
156
+ # anything that can be converted to string with #to_s.
157
+ #
158
+ # assert_changes :@object do
159
+ # @object = 42
160
+ # end
98
161
  #
99
- # assert_blank [] # => true
100
- # assert_blank [[]] # => [[]] is not blank
162
+ # The keyword arguments :from and :to can be given to specify the
163
+ # expected initial value and the expected value after the block was
164
+ # executed.
165
+ #
166
+ # assert_changes :@object, from: nil, to: :foo do
167
+ # @object = :foo
168
+ # end
101
169
  #
102
170
  # An error message can be specified.
103
171
  #
104
- # assert_blank [], 'this should be blank'
105
- def assert_blank(object, message=nil)
106
- ActiveSupport::Deprecation.warn('"assert_blank" is deprecated. Please use "assert object.blank?" instead')
107
- message ||= "#{object.inspect} is not blank"
108
- assert object.blank?, message
172
+ # assert_changes -> { Status.all_good? }, 'Expected the status to be bad' do
173
+ # post :create, params: { status: { incident: true } }
174
+ # end
175
+ def assert_changes(expression, message = nil, from: UNTRACKED, to: UNTRACKED, &block)
176
+ exp = expression.respond_to?(:call) ? expression : -> { eval(expression.to_s, block.binding) }
177
+
178
+ before = exp.call
179
+ retval = _assert_nothing_raised_or_warn("assert_changes", &block)
180
+
181
+ unless from == UNTRACKED
182
+ error = "Expected change from #{from.inspect}"
183
+ error = "#{message}.\n#{error}" if message
184
+ assert from === before, error
185
+ end
186
+
187
+ after = exp.call
188
+
189
+ error = "#{expression.inspect} didn't change"
190
+ error = "#{error}. It was already #{to}" if before == to
191
+ error = "#{message}.\n#{error}" if message
192
+ refute_equal before, after, error
193
+
194
+ unless to == UNTRACKED
195
+ error = "Expected change to #{to}\n"
196
+ error = "#{message}.\n#{error}" if message
197
+ assert to === after, error
198
+ end
199
+
200
+ retval
109
201
  end
110
202
 
111
- # Test if an expression is not blank. Passes if <tt>object.present?</tt>
112
- # is +true+.
203
+ # Assertion that the result of evaluating an expression is not changed before
204
+ # and after invoking the passed in block.
113
205
  #
114
- # assert_present({ data: 'x' }) # => true
115
- # assert_present({}) # => {} is blank
206
+ # assert_no_changes 'Status.all_good?' do
207
+ # post :create, params: { status: { ok: true } }
208
+ # end
209
+ #
210
+ # Provide the optional keyword argument :from to specify the expected
211
+ # initial value.
212
+ #
213
+ # assert_no_changes -> { Status.all_good? }, from: true do
214
+ # post :create, params: { status: { ok: true } }
215
+ # end
116
216
  #
117
217
  # An error message can be specified.
118
218
  #
119
- # assert_present({ data: 'x' }, 'this should not be blank')
120
- def assert_present(object, message=nil)
121
- ActiveSupport::Deprecation.warn('"assert_present" is deprecated. Please use "assert object.present?" instead')
122
- message ||= "#{object.inspect} is blank"
123
- assert object.present?, message
219
+ # assert_no_changes -> { Status.all_good? }, 'Expected the status to be good' do
220
+ # post :create, params: { status: { ok: false } }
221
+ # end
222
+ def assert_no_changes(expression, message = nil, from: UNTRACKED, &block)
223
+ exp = expression.respond_to?(:call) ? expression : -> { eval(expression.to_s, block.binding) }
224
+
225
+ before = exp.call
226
+ retval = _assert_nothing_raised_or_warn("assert_no_changes", &block)
227
+
228
+ unless from == UNTRACKED
229
+ error = "Expected initial value of #{from.inspect}"
230
+ error = "#{message}.\n#{error}" if message
231
+ assert from === before, error
232
+ end
233
+
234
+ after = exp.call
235
+
236
+ error = "#{expression.inspect} changed"
237
+ error = "#{message}.\n#{error}" if message
238
+
239
+ if before.nil?
240
+ assert_nil after, error
241
+ else
242
+ assert_equal before, after, error
243
+ end
244
+
245
+ retval
124
246
  end
247
+
248
+ private
249
+ def _assert_nothing_raised_or_warn(assertion, &block)
250
+ assert_nothing_raised(&block)
251
+ rescue Minitest::UnexpectedError => e
252
+ if tagged_logger && tagged_logger.warn?
253
+ warning = <<~MSG
254
+ #{self.class} - #{name}: #{e.error.class} raised.
255
+ If you expected this exception, use `assert_raises` as near to the code that raises as possible.
256
+ Other block based assertions (e.g. `#{assertion}`) can be used, as long as `assert_raises` is inside their block.
257
+ MSG
258
+ tagged_logger.warn warning
259
+ end
260
+
261
+ raise
262
+ end
125
263
  end
126
264
  end
127
265
  end
@@ -1,5 +1,7 @@
1
- gem 'minitest'
1
+ # frozen_string_literal: true
2
2
 
3
- require 'minitest/unit'
3
+ gem "minitest"
4
4
 
5
- MiniTest::Unit.autorun
5
+ require "minitest"
6
+
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
 
@@ -36,19 +38,14 @@ module ActiveSupport
36
38
  while names.size > 0 do
37
39
  names.last.sub!(/Test$/, "")
38
40
  begin
39
- constant = names.join("::").constantize
41
+ constant = names.join("::").safe_constantize
40
42
  break(constant) if yield(constant)
41
- rescue NoMethodError # subclass of NameError
42
- raise
43
- rescue NameError
44
- # Constant wasn't found, move on
45
43
  ensure
46
44
  names.pop
47
45
  end
48
46
  end
49
47
  end
50
48
  end
51
-
52
49
  end
53
50
  end
54
51
  end
@@ -1,30 +1,18 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveSupport
2
4
  module Testing
3
5
  module Declarative
4
-
5
- def self.extended(klass) #:nodoc:
6
- klass.class_eval do
7
-
8
- unless method_defined?(:describe)
9
- def self.describe(text)
10
- class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
11
- def self.name
12
- "#{text}"
13
- end
14
- RUBY_EVAL
15
- end
16
- end
17
-
18
- end
19
- end
20
-
21
6
  unless defined?(Spec)
22
- # test "verify something" do
23
- # ...
24
- # end
7
+ # Helper to define a test method using a String. Under the hood, it replaces
8
+ # spaces with underscores and defines the test method.
9
+ #
10
+ # test "verify something" do
11
+ # ...
12
+ # end
25
13
  def test(name, &block)
26
- test_name = "test_#{name.gsub(/\s+/,'_')}".to_sym
27
- defined = instance_method(test_name) rescue false
14
+ test_name = "test_#{name.gsub(/\s+/, '_')}".to_sym
15
+ defined = method_defined? test_name
28
16
  raise "#{test_name} is already defined in #{self}" if defined
29
17
  if block_given?
30
18
  define_method(test_name, &block)