activesupport 7.1.6 → 8.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (169) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +256 -1133
  3. data/README.rdoc +1 -1
  4. data/lib/active_support/array_inquirer.rb +1 -1
  5. data/lib/active_support/backtrace_cleaner.rb +81 -3
  6. data/lib/active_support/benchmark.rb +21 -0
  7. data/lib/active_support/benchmarkable.rb +3 -2
  8. data/lib/active_support/broadcast_logger.rb +65 -78
  9. data/lib/active_support/cache/file_store.rb +29 -14
  10. data/lib/active_support/cache/mem_cache_store.rb +42 -102
  11. data/lib/active_support/cache/memory_store.rb +11 -6
  12. data/lib/active_support/cache/null_store.rb +2 -2
  13. data/lib/active_support/cache/redis_cache_store.rb +58 -46
  14. data/lib/active_support/cache/serializer_with_fallback.rb +0 -23
  15. data/lib/active_support/cache/strategy/local_cache.rb +72 -27
  16. data/lib/active_support/cache/strategy/local_cache_middleware.rb +7 -7
  17. data/lib/active_support/cache.rb +146 -86
  18. data/lib/active_support/callbacks.rb +102 -126
  19. data/lib/active_support/class_attribute.rb +33 -0
  20. data/lib/active_support/code_generator.rb +9 -0
  21. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +8 -62
  22. data/lib/active_support/concurrency/share_lock.rb +0 -1
  23. data/lib/active_support/concurrency/thread_monitor.rb +55 -0
  24. data/lib/active_support/configurable.rb +34 -0
  25. data/lib/active_support/configuration_file.rb +15 -6
  26. data/lib/active_support/continuous_integration.rb +145 -0
  27. data/lib/active_support/core_ext/array/conversions.rb +3 -5
  28. data/lib/active_support/core_ext/array.rb +7 -7
  29. data/lib/active_support/core_ext/benchmark.rb +4 -14
  30. data/lib/active_support/core_ext/big_decimal.rb +1 -1
  31. data/lib/active_support/core_ext/class/attribute.rb +26 -19
  32. data/lib/active_support/core_ext/class/subclasses.rb +15 -35
  33. data/lib/active_support/core_ext/class.rb +2 -2
  34. data/lib/active_support/core_ext/date/blank.rb +4 -0
  35. data/lib/active_support/core_ext/date/conversions.rb +2 -2
  36. data/lib/active_support/core_ext/date.rb +5 -5
  37. data/lib/active_support/core_ext/date_and_time/compatibility.rb +1 -9
  38. data/lib/active_support/core_ext/date_time/blank.rb +4 -0
  39. data/lib/active_support/core_ext/date_time/compatibility.rb +3 -5
  40. data/lib/active_support/core_ext/date_time/conversions.rb +4 -6
  41. data/lib/active_support/core_ext/date_time.rb +5 -5
  42. data/lib/active_support/core_ext/digest/uuid.rb +6 -0
  43. data/lib/active_support/core_ext/digest.rb +1 -1
  44. data/lib/active_support/core_ext/enumerable.rb +25 -8
  45. data/lib/active_support/core_ext/erb/util.rb +10 -5
  46. data/lib/active_support/core_ext/file.rb +1 -1
  47. data/lib/active_support/core_ext/hash/deep_merge.rb +1 -0
  48. data/lib/active_support/core_ext/hash/except.rb +0 -12
  49. data/lib/active_support/core_ext/hash/keys.rb +4 -4
  50. data/lib/active_support/core_ext/hash.rb +8 -8
  51. data/lib/active_support/core_ext/integer.rb +3 -3
  52. data/lib/active_support/core_ext/kernel.rb +3 -3
  53. data/lib/active_support/core_ext/module/attr_internal.rb +16 -6
  54. data/lib/active_support/core_ext/module/delegation.rb +20 -163
  55. data/lib/active_support/core_ext/module/deprecation.rb +1 -4
  56. data/lib/active_support/core_ext/module/introspection.rb +3 -0
  57. data/lib/active_support/core_ext/module.rb +11 -11
  58. data/lib/active_support/core_ext/numeric/conversions.rb +3 -3
  59. data/lib/active_support/core_ext/numeric.rb +3 -3
  60. data/lib/active_support/core_ext/object/blank.rb +45 -1
  61. data/lib/active_support/core_ext/object/instance_variables.rb +11 -19
  62. data/lib/active_support/core_ext/object/json.rb +24 -11
  63. data/lib/active_support/core_ext/object/to_query.rb +7 -1
  64. data/lib/active_support/core_ext/object/try.rb +2 -2
  65. data/lib/active_support/core_ext/object/with.rb +5 -3
  66. data/lib/active_support/core_ext/object.rb +13 -13
  67. data/lib/active_support/core_ext/pathname/blank.rb +4 -0
  68. data/lib/active_support/core_ext/pathname.rb +2 -2
  69. data/lib/active_support/core_ext/range/overlap.rb +4 -4
  70. data/lib/active_support/core_ext/range/sole.rb +17 -0
  71. data/lib/active_support/core_ext/range.rb +4 -4
  72. data/lib/active_support/core_ext/securerandom.rb +4 -4
  73. data/lib/active_support/core_ext/string/conversions.rb +1 -1
  74. data/lib/active_support/core_ext/string/filters.rb +4 -4
  75. data/lib/active_support/core_ext/string/multibyte.rb +13 -4
  76. data/lib/active_support/core_ext/string/output_safety.rb +19 -19
  77. data/lib/active_support/core_ext/string.rb +13 -13
  78. data/lib/active_support/core_ext/symbol.rb +1 -1
  79. data/lib/active_support/core_ext/thread/backtrace/location.rb +2 -7
  80. data/lib/active_support/core_ext/time/calculations.rb +25 -30
  81. data/lib/active_support/core_ext/time/compatibility.rb +2 -3
  82. data/lib/active_support/core_ext/time/conversions.rb +2 -2
  83. data/lib/active_support/core_ext/time/zones.rb +1 -1
  84. data/lib/active_support/core_ext/time.rb +5 -5
  85. data/lib/active_support/core_ext.rb +1 -2
  86. data/lib/active_support/current_attributes/test_helper.rb +2 -2
  87. data/lib/active_support/current_attributes.rb +58 -50
  88. data/lib/active_support/delegation.rb +200 -0
  89. data/lib/active_support/dependencies/autoload.rb +0 -12
  90. data/lib/active_support/dependencies/interlock.rb +11 -5
  91. data/lib/active_support/dependencies.rb +6 -2
  92. data/lib/active_support/deprecation/constant_accessor.rb +47 -26
  93. data/lib/active_support/deprecation/proxy_wrappers.rb +9 -12
  94. data/lib/active_support/deprecation/reporting.rb +5 -17
  95. data/lib/active_support/deprecation.rb +8 -5
  96. data/lib/active_support/descendants_tracker.rb +9 -87
  97. data/lib/active_support/duration/iso8601_parser.rb +2 -2
  98. data/lib/active_support/duration/iso8601_serializer.rb +1 -2
  99. data/lib/active_support/duration.rb +25 -16
  100. data/lib/active_support/editor.rb +70 -0
  101. data/lib/active_support/encrypted_configuration.rb +20 -2
  102. data/lib/active_support/encrypted_file.rb +1 -1
  103. data/lib/active_support/error_reporter.rb +121 -6
  104. data/lib/active_support/event_reporter/test_helper.rb +32 -0
  105. data/lib/active_support/event_reporter.rb +592 -0
  106. data/lib/active_support/evented_file_update_checker.rb +5 -3
  107. data/lib/active_support/execution_context.rb +64 -7
  108. data/lib/active_support/execution_wrapper.rb +1 -2
  109. data/lib/active_support/file_update_checker.rb +9 -7
  110. data/lib/active_support/fork_tracker.rb +2 -38
  111. data/lib/active_support/gem_version.rb +2 -2
  112. data/lib/active_support/gzip.rb +1 -0
  113. data/lib/active_support/hash_with_indifferent_access.rb +66 -45
  114. data/lib/active_support/html_safe_translation.rb +3 -0
  115. data/lib/active_support/i18n_railtie.rb +19 -11
  116. data/lib/active_support/inflector/inflections.rb +31 -15
  117. data/lib/active_support/inflector/transliterate.rb +6 -8
  118. data/lib/active_support/isolated_execution_state.rb +12 -17
  119. data/lib/active_support/json/decoding.rb +6 -4
  120. data/lib/active_support/json/encoding.rb +157 -21
  121. data/lib/active_support/lazy_load_hooks.rb +1 -1
  122. data/lib/active_support/log_subscriber.rb +2 -18
  123. data/lib/active_support/logger.rb +15 -2
  124. data/lib/active_support/logger_thread_safe_level.rb +4 -9
  125. data/lib/active_support/message_encryptors.rb +54 -2
  126. data/lib/active_support/message_pack/extensions.rb +20 -2
  127. data/lib/active_support/message_verifier.rb +21 -0
  128. data/lib/active_support/message_verifiers.rb +57 -3
  129. data/lib/active_support/messages/rotation_coordinator.rb +9 -0
  130. data/lib/active_support/messages/rotator.rb +10 -0
  131. data/lib/active_support/multibyte/chars.rb +14 -4
  132. data/lib/active_support/multibyte.rb +4 -0
  133. data/lib/active_support/notifications/fanout.rb +68 -50
  134. data/lib/active_support/notifications/instrumenter.rb +22 -19
  135. data/lib/active_support/notifications.rb +28 -27
  136. data/lib/active_support/number_helper/number_converter.rb +2 -2
  137. data/lib/active_support/number_helper.rb +22 -0
  138. data/lib/active_support/option_merger.rb +2 -2
  139. data/lib/active_support/ordered_options.rb +53 -15
  140. data/lib/active_support/railtie.rb +36 -20
  141. data/lib/active_support/string_inquirer.rb +1 -1
  142. data/lib/active_support/structured_event_subscriber.rb +99 -0
  143. data/lib/active_support/subscriber.rb +1 -5
  144. data/lib/active_support/syntax_error_proxy.rb +3 -0
  145. data/lib/active_support/tagged_logging.rb +5 -1
  146. data/lib/active_support/test_case.rb +63 -6
  147. data/lib/active_support/testing/assertions.rb +113 -27
  148. data/lib/active_support/testing/constant_stubbing.rb +30 -8
  149. data/lib/active_support/testing/deprecation.rb +5 -12
  150. data/lib/active_support/testing/error_reporter_assertions.rb +18 -1
  151. data/lib/active_support/testing/event_reporter_assertions.rb +227 -0
  152. data/lib/active_support/testing/isolation.rb +19 -9
  153. data/lib/active_support/testing/method_call_assertions.rb +2 -16
  154. data/lib/active_support/testing/notification_assertions.rb +92 -0
  155. data/lib/active_support/testing/parallelization/server.rb +18 -2
  156. data/lib/active_support/testing/parallelization/worker.rb +4 -2
  157. data/lib/active_support/testing/parallelization.rb +25 -1
  158. data/lib/active_support/testing/tests_without_assertions.rb +19 -0
  159. data/lib/active_support/testing/time_helpers.rb +11 -6
  160. data/lib/active_support/time_with_zone.rb +39 -26
  161. data/lib/active_support/values/time_zone.rb +26 -17
  162. data/lib/active_support/xml_mini.rb +14 -4
  163. data/lib/active_support.rb +22 -9
  164. metadata +31 -17
  165. data/lib/active_support/core_ext/range/each.rb +0 -24
  166. data/lib/active_support/deprecation/instance_delegator.rb +0 -65
  167. data/lib/active_support/proxy_object.rb +0 -17
  168. data/lib/active_support/ruby_features.rb +0 -7
  169. data/lib/active_support/testing/strict_warnings.rb +0 -39
@@ -31,8 +31,8 @@ module ActiveSupport
31
31
  end
32
32
  end
33
33
 
34
- def respond_to_missing?(*arguments)
35
- @context.respond_to?(*arguments)
34
+ def respond_to_missing?(...)
35
+ @context.respond_to?(...)
36
36
  end
37
37
  end
38
38
  end
@@ -46,18 +46,14 @@ module ActiveSupport
46
46
  super(key.to_sym, *identifiers)
47
47
  end
48
48
 
49
- def method_missing(name, *args)
50
- name_string = +name.to_s
51
- if name_string.chomp!("=")
52
- self[name_string] = args.first
49
+ def method_missing(method, *args)
50
+ if method.end_with?("=")
51
+ self[method.name.chomp("=")] = args.first
52
+ elsif method.end_with?("!")
53
+ name_string = method.name.chomp("!")
54
+ self[name_string].presence || raise(KeyError.new(":#{name_string} is blank"))
53
55
  else
54
- bangs = name_string.chomp!("!")
55
-
56
- if bangs
57
- self[name_string].presence || raise(KeyError.new(":#{name_string} is blank"))
58
- else
59
- self[name_string]
60
- end
56
+ self[method.name]
61
57
  end
62
58
  end
63
59
 
@@ -92,18 +88,60 @@ module ActiveSupport
92
88
  # h.boy # => 'John'
93
89
  class InheritableOptions < OrderedOptions
94
90
  def initialize(parent = nil)
95
- if parent.kind_of?(OrderedOptions)
91
+ @parent = parent
92
+ if @parent.kind_of?(OrderedOptions)
96
93
  # use the faster _get when dealing with OrderedOptions
97
- super() { |h, k| parent._get(k) }
98
- elsif parent
99
- super() { |h, k| parent[k] }
94
+ super() { |h, k| @parent._get(k) }
95
+ elsif @parent
96
+ super() { |h, k| @parent[k] }
100
97
  else
101
98
  super()
99
+ @parent = {}
102
100
  end
103
101
  end
104
102
 
103
+ def to_h
104
+ @parent.merge(self)
105
+ end
106
+
107
+ def ==(other)
108
+ to_h == other.to_h
109
+ end
110
+
111
+ def inspect
112
+ "#<#{self.class.name} #{to_h.inspect}>"
113
+ end
114
+
115
+ def to_s
116
+ to_h.to_s
117
+ end
118
+
119
+ def pretty_print(pp)
120
+ pp.pp_hash(to_h)
121
+ end
122
+
123
+ alias_method :own_key?, :key?
124
+ private :own_key?
125
+
126
+ def key?(key)
127
+ super || @parent.key?(key)
128
+ end
129
+
130
+ def overridden?(key)
131
+ !!(@parent && @parent.key?(key) && own_key?(key.to_sym))
132
+ end
133
+
105
134
  def inheritable_copy
106
135
  self.class.new(self)
107
136
  end
137
+
138
+ def to_a
139
+ entries
140
+ end
141
+
142
+ def each(&block)
143
+ to_h.each(&block)
144
+ self
145
+ end
108
146
  end
109
147
  end
@@ -15,7 +15,7 @@ module ActiveSupport
15
15
 
16
16
  initializer "active_support.isolation_level" do |app|
17
17
  config.after_initialize do
18
- if level = app.config.active_support.delete(:isolation_level)
18
+ if level = app.config.active_support.isolation_level
19
19
  ActiveSupport::IsolatedExecutionState.isolation_level = level
20
20
  end
21
21
  end
@@ -38,19 +38,35 @@ module ActiveSupport
38
38
  end
39
39
  end
40
40
 
41
- initializer "active_support.reset_execution_context" do |app|
42
- app.reloader.before_class_unload { ActiveSupport::ExecutionContext.clear }
43
- app.executor.to_run { ActiveSupport::ExecutionContext.clear }
44
- app.executor.to_complete { ActiveSupport::ExecutionContext.clear }
41
+ initializer "active_support.set_event_reporter_context_store" do |app|
42
+ config.after_initialize do
43
+ if klass = app.config.active_support.event_reporter_context_store
44
+ ActiveSupport::EventReporter.context_store = klass
45
+ end
46
+ end
45
47
  end
46
48
 
47
- initializer "active_support.reset_all_current_attributes_instances" do |app|
48
- app.reloader.before_class_unload { ActiveSupport::CurrentAttributes.clear_all }
49
- app.executor.to_run { ActiveSupport::CurrentAttributes.reset_all }
50
- app.executor.to_complete { ActiveSupport::CurrentAttributes.reset_all }
49
+ initializer "active_support.reset_execution_context" do |app|
50
+ app.reloader.before_class_unload do
51
+ ActiveSupport::CurrentAttributes.clear_all
52
+ ActiveSupport::ExecutionContext.clear
53
+ ActiveSupport.event_reporter.clear_context
54
+ end
55
+
56
+ app.executor.to_run do
57
+ ActiveSupport::ExecutionContext.push
58
+ end
59
+
60
+ app.executor.to_complete do
61
+ ActiveSupport::CurrentAttributes.clear_all
62
+ ActiveSupport::ExecutionContext.pop
63
+ ActiveSupport.event_reporter.clear_context
64
+ end
51
65
 
52
66
  ActiveSupport.on_load(:active_support_test_case) do
53
67
  if app.config.active_support.executor_around_test_case
68
+ ActiveSupport::ExecutionContext.nestable = true
69
+
54
70
  require "active_support/executor/test_helper"
55
71
  include ActiveSupport::Executor::TestHelper
56
72
  else
@@ -63,6 +79,13 @@ module ActiveSupport
63
79
  end
64
80
  end
65
81
 
82
+ initializer "active_support.set_filter_parameters" do |app|
83
+ config.after_initialize do
84
+ ActiveSupport.filter_parameters += Rails.application.config.filter_parameters
85
+ ActiveSupport.event_reporter.reload_payload_filter
86
+ end
87
+ end
88
+
66
89
  initializer "active_support.deprecation_behavior" do |app|
67
90
  if app.config.active_support.report_deprecations == false
68
91
  app.deprecators.silenced = true
@@ -89,10 +112,11 @@ module ActiveSupport
89
112
  begin
90
113
  TZInfo::DataSource.get
91
114
  rescue TZInfo::DataSourceNotFound => e
92
- raise e.exception "tzinfo-data is not present. Please add gem 'tzinfo-data' to your Gemfile and run bundle install"
115
+ raise e.exception('tzinfo-data is not present. Please add gem "tzinfo-data" to your Gemfile and run bundle install')
93
116
  end
94
117
  require "active_support/core_ext/time/zones"
95
118
  Time.zone_default = Time.find_zone!(app.config.time_zone)
119
+ config.eager_load_namespaces << TZInfo
96
120
  end
97
121
 
98
122
  # Sets the default week start
@@ -117,16 +141,8 @@ module ActiveSupport
117
141
 
118
142
  initializer "active_support.set_configs" do |app|
119
143
  app.config.active_support.each do |k, v|
120
- if k == :disable_to_s_conversion
121
- ActiveSupport.deprecator.warn("config.active_support.disable_to_s_conversion is deprecated and will be removed in Rails 7.2.")
122
- elsif k == :remove_deprecated_time_with_zone_name
123
- ActiveSupport.deprecator.warn("config.active_support.remove_deprecated_time_with_zone_name is deprecated and will be removed in Rails 7.2.")
124
- elsif k == :use_rfc4122_namespaced_uuids
125
- ActiveSupport.deprecator.warn("config.active_support.use_rfc4122_namespaced_uuids is deprecated and will be removed in Rails 7.2.")
126
- else
127
- k = "#{k}="
128
- ActiveSupport.public_send(k, v) if ActiveSupport.respond_to? k
129
- end
144
+ k = "#{k}="
145
+ ActiveSupport.public_send(k, v) if ActiveSupport.respond_to? k
130
146
  end
131
147
  end
132
148
 
@@ -24,7 +24,7 @@ module ActiveSupport
24
24
  method_name.end_with?("?") || super
25
25
  end
26
26
 
27
- def method_missing(method_name, *arguments)
27
+ def method_missing(method_name, ...)
28
28
  if method_name.end_with?("?")
29
29
  self == method_name[0..-2]
30
30
  else
@@ -0,0 +1,99 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/subscriber"
4
+
5
+ module ActiveSupport
6
+ # = Active Support Structured Event \Subscriber
7
+ #
8
+ # +ActiveSupport::StructuredEventSubscriber+ consumes ActiveSupport::Notifications
9
+ # in order to emit structured events via +Rails.event+.
10
+ #
11
+ # An example would be the Action Controller structured event subscriber, responsible for
12
+ # emitting request processing events:
13
+ #
14
+ # module ActionController
15
+ # class StructuredEventSubscriber < ActiveSupport::StructuredEventSubscriber
16
+ # attach_to :action_controller
17
+ #
18
+ # def start_processing(event)
19
+ # emit_event("controller.request_started",
20
+ # controller: event.payload[:controller],
21
+ # action: event.payload[:action],
22
+ # format: event.payload[:format]
23
+ # )
24
+ # end
25
+ # end
26
+ # end
27
+ #
28
+ # After configured, whenever a <tt>"start_processing.action_controller"</tt> notification is published,
29
+ # it will properly dispatch the event (+ActiveSupport::Notifications::Event+) to the +start_processing+ method.
30
+ # The subscriber can then emit a structured event via the +emit_event+ method.
31
+ class StructuredEventSubscriber < Subscriber
32
+ class_attribute :debug_methods, instance_accessor: false, default: [] # :nodoc:
33
+
34
+ DEBUG_CHECK = proc { !ActiveSupport.event_reporter.debug_mode? }
35
+
36
+ class << self
37
+ def attach_to(...) # :nodoc:
38
+ result = super
39
+ set_silenced_events
40
+ result
41
+ end
42
+
43
+ private
44
+ def set_silenced_events
45
+ if subscriber
46
+ subscriber.silenced_events = debug_methods.to_h { |method| ["#{method}.#{namespace}", DEBUG_CHECK] }
47
+ end
48
+ end
49
+
50
+ def debug_only(method)
51
+ self.debug_methods << method
52
+ set_silenced_events
53
+ end
54
+ end
55
+
56
+ def initialize
57
+ super
58
+ @silenced_events = {}
59
+ end
60
+
61
+ def silenced?(event)
62
+ ActiveSupport.event_reporter.subscribers.none? || @silenced_events[event]&.call
63
+ end
64
+
65
+ attr_writer :silenced_events # :nodoc:
66
+
67
+ # Emit a structured event via Rails.event.notify.
68
+ #
69
+ # ==== Arguments
70
+ #
71
+ # * +name+ - The event name as a string or symbol
72
+ # * +payload+ - The event payload as a hash or object
73
+ # * +caller_depth+ - Stack depth for source location (default: 1)
74
+ # * +kwargs+ - Additional payload data merged with the payload hash
75
+ def emit_event(name, payload = nil, caller_depth: 1, **kwargs)
76
+ ActiveSupport.event_reporter.notify(name, payload, caller_depth: caller_depth + 1, **kwargs)
77
+ rescue => e
78
+ handle_event_error(name, e)
79
+ end
80
+
81
+ # Like +emit_event+, but only emits when the event reporter is in debug mode
82
+ def emit_debug_event(name, payload = nil, caller_depth: 1, **kwargs)
83
+ ActiveSupport.event_reporter.debug(name, payload, caller_depth: caller_depth + 1, **kwargs)
84
+ rescue => e
85
+ handle_event_error(name, e)
86
+ end
87
+
88
+ def call(event)
89
+ super
90
+ rescue => e
91
+ handle_event_error(event.name, e)
92
+ end
93
+
94
+ private
95
+ def handle_event_error(name, error)
96
+ ActiveSupport.error_reporter.report(error, source: name)
97
+ end
98
+ end
99
+ end
@@ -67,6 +67,7 @@ module ActiveSupport
67
67
 
68
68
  # Adds event subscribers for all new methods added to the class.
69
69
  def method_added(event)
70
+ super
70
71
  # Only public methods are added as subscribers, and only if a notifier
71
72
  # has been set up. This means that subscribers will only be set up for
72
73
  # classes that call #attach_to.
@@ -136,10 +137,5 @@ module ActiveSupport
136
137
  method = event.name[0, event.name.index(".")]
137
138
  send(method, event)
138
139
  end
139
-
140
- def publish_event(event) # :nodoc:
141
- method = event.name[0, event.name.index(".")]
142
- send(method, event)
143
- end
144
140
  end
145
141
  end
@@ -18,6 +18,9 @@ module ActiveSupport
18
18
 
19
19
  def label
20
20
  end
21
+
22
+ def base_label
23
+ end
21
24
  end
22
25
 
23
26
  class BacktraceLocationProxy < DelegateClass(Thread::Backtrace::Location) # :nodoc:
@@ -2,7 +2,6 @@
2
2
 
3
3
  require "active_support/core_ext/module/delegation"
4
4
  require "active_support/core_ext/object/blank"
5
- require "logger"
6
5
  require "active_support/logger"
7
6
 
8
7
  module ActiveSupport
@@ -114,6 +113,11 @@ module ActiveSupport
114
113
  end
115
114
  end
116
115
 
116
+ # Returns an `ActiveSupport::Logger` that has already been wrapped with tagged logging concern.
117
+ def self.logger(*args, **kwargs)
118
+ new ActiveSupport::Logger.new(*args, **kwargs)
119
+ end
120
+
117
121
  def self.new(logger)
118
122
  logger = logger.clone
119
123
 
@@ -3,8 +3,10 @@
3
3
  require "minitest"
4
4
  require "active_support/testing/tagged_logging"
5
5
  require "active_support/testing/setup_and_teardown"
6
+ require "active_support/testing/tests_without_assertions"
6
7
  require "active_support/testing/assertions"
7
8
  require "active_support/testing/error_reporter_assertions"
9
+ require "active_support/testing/event_reporter_assertions"
8
10
  require "active_support/testing/deprecation"
9
11
  require "active_support/testing/declarative"
10
12
  require "active_support/testing/isolation"
@@ -14,13 +16,29 @@ require "active_support/testing/constant_stubbing"
14
16
  require "active_support/testing/file_fixtures"
15
17
  require "active_support/testing/parallelization"
16
18
  require "active_support/testing/parallelize_executor"
19
+ require "active_support/testing/notification_assertions"
17
20
  require "concurrent/utility/processor_counter"
18
21
 
19
22
  module ActiveSupport
20
23
  class TestCase < ::Minitest::Test
21
24
  Assertion = Minitest::Assertion
22
25
 
26
+ # Class variable to store the parallel worker ID
27
+ @@parallel_worker_id = nil
28
+
23
29
  class << self
30
+ # Returns the current parallel worker ID if tests are running in parallel,
31
+ # nil otherwise.
32
+ #
33
+ # ActiveSupport::TestCase.parallel_worker_id # => 2
34
+ def parallel_worker_id
35
+ @@parallel_worker_id
36
+ end
37
+
38
+ def parallel_worker_id=(value) # :nodoc:
39
+ @@parallel_worker_id = value
40
+ end
41
+
24
42
  # Sets the order in which test cases are run.
25
43
  #
26
44
  # ActiveSupport::TestCase.test_order = :random # => :random
@@ -50,8 +68,8 @@ module ActiveSupport
50
68
  # is forked. For each process a new database will be created suffixed
51
69
  # with the worker number.
52
70
  #
53
- # test-database-0
54
- # test-database-1
71
+ # test-database_0
72
+ # test-database_1
55
73
  #
56
74
  # If <tt>ENV["PARALLEL_WORKERS"]</tt> is set the workers argument will be ignored
57
75
  # and the environment variable will be used instead. This is useful for CI
@@ -77,14 +95,45 @@ module ActiveSupport
77
95
  # Because parallelization presents an overhead, it is only enabled when the
78
96
  # number of tests to run is above the +threshold+ param. The default value is
79
97
  # 50, and it's configurable via +config.active_support.test_parallelization_threshold+.
80
- def parallelize(workers: :number_of_processors, with: :processes, threshold: ActiveSupport.test_parallelization_threshold)
81
- workers = Concurrent.physical_processor_count if workers == :number_of_processors
82
- workers = ENV["PARALLEL_WORKERS"].to_i if ENV["PARALLEL_WORKERS"]
98
+ #
99
+ # If you want to skip Rails default creation of one database per process in favor of
100
+ # writing your own implementation, you can set +parallelize_databases+, or configure it
101
+ # via +config.active_support.parallelize_test_databases+.
102
+ #
103
+ # parallelize(workers: :number_of_processors, parallelize_databases: false)
104
+ #
105
+ # Note that your test suite may deadlock if you attempt to use only one database
106
+ # with multiple processes.
107
+ def parallelize(workers: :number_of_processors, with: :processes, threshold: ActiveSupport.test_parallelization_threshold, parallelize_databases: ActiveSupport.parallelize_test_databases)
108
+ case
109
+ when ENV["PARALLEL_WORKERS"]
110
+ workers = ENV["PARALLEL_WORKERS"].to_i
111
+ when workers == :number_of_processors
112
+ workers = (Concurrent.available_processor_count || Concurrent.processor_count).floor
113
+ end
114
+
115
+ if with == :processes
116
+ ActiveSupport.parallelize_test_databases = parallelize_databases
117
+ end
83
118
 
84
119
  Minitest.parallel_executor = ActiveSupport::Testing::ParallelizeExecutor.new(size: workers, with: with, threshold: threshold)
85
120
  end
86
121
 
87
- # Set up hook for parallel testing. This can be used if you have multiple
122
+ # Before fork hook for parallel testing. This can be used to run anything
123
+ # before the processes are forked.
124
+ #
125
+ # In your +test_helper.rb+ add the following:
126
+ #
127
+ # class ActiveSupport::TestCase
128
+ # parallelize_before_fork do
129
+ # # run this before fork
130
+ # end
131
+ # end
132
+ def parallelize_before_fork(&block)
133
+ ActiveSupport::Testing::Parallelization.before_fork_hook(&block)
134
+ end
135
+
136
+ # Setup hook for parallel testing. This can be used if you have multiple
88
137
  # databases or any behavior that needs to be run after the process is forked
89
138
  # but before the tests run.
90
139
  #
@@ -140,10 +189,18 @@ module ActiveSupport
140
189
 
141
190
  alias_method :method_name, :name
142
191
 
192
+ # Returns the current parallel worker ID if tests are running in parallel
193
+ def parallel_worker_id
194
+ self.class.parallel_worker_id
195
+ end
196
+
143
197
  include ActiveSupport::Testing::TaggedLogging
144
198
  prepend ActiveSupport::Testing::SetupAndTeardown
199
+ prepend ActiveSupport::Testing::TestsWithoutAssertions
145
200
  include ActiveSupport::Testing::Assertions
146
201
  include ActiveSupport::Testing::ErrorReporterAssertions
202
+ include ActiveSupport::Testing::EventReporterAssertions
203
+ include ActiveSupport::Testing::NotificationAssertions
147
204
  include ActiveSupport::Testing::Deprecation
148
205
  include ActiveSupport::Testing::ConstantStubbing
149
206
  include ActiveSupport::Testing::TimeHelpers