activesupport 4.0.13 → 5.2.5

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 (264) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +412 -444
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +8 -4
  5. data/lib/active_support/all.rb +5 -3
  6. data/lib/active_support/array_inquirer.rb +48 -0
  7. data/lib/active_support/backtrace_cleaner.rb +14 -12
  8. data/lib/active_support/benchmarkable.rb +6 -14
  9. data/lib/active_support/builder.rb +3 -1
  10. data/lib/active_support/cache/file_store.rb +67 -51
  11. data/lib/active_support/cache/mem_cache_store.rb +95 -97
  12. data/lib/active_support/cache/memory_store.rb +28 -30
  13. data/lib/active_support/cache/null_store.rb +7 -8
  14. data/lib/active_support/cache/redis_cache_store.rb +466 -0
  15. data/lib/active_support/cache/strategy/local_cache.rb +70 -56
  16. data/lib/active_support/cache/strategy/local_cache_middleware.rb +45 -0
  17. data/lib/active_support/cache.rb +331 -206
  18. data/lib/active_support/callbacks.rb +697 -426
  19. data/lib/active_support/concern.rb +32 -10
  20. data/lib/active_support/concurrency/load_interlock_aware_monitor.rb +17 -0
  21. data/lib/active_support/concurrency/share_lock.rb +227 -0
  22. data/lib/active_support/configurable.rb +8 -5
  23. data/lib/active_support/core_ext/array/access.rb +39 -1
  24. data/lib/active_support/core_ext/array/conversions.rb +24 -35
  25. data/lib/active_support/core_ext/array/extract_options.rb +2 -0
  26. data/lib/active_support/core_ext/array/grouping.rb +23 -13
  27. data/lib/active_support/core_ext/array/inquiry.rb +19 -0
  28. data/lib/active_support/core_ext/array/prepend_and_append.rb +7 -5
  29. data/lib/active_support/core_ext/array/wrap.rb +7 -4
  30. data/lib/active_support/core_ext/array.rb +9 -7
  31. data/lib/active_support/core_ext/benchmark.rb +3 -1
  32. data/lib/active_support/core_ext/big_decimal/conversions.rb +9 -26
  33. data/lib/active_support/core_ext/big_decimal.rb +3 -1
  34. data/lib/active_support/core_ext/class/attribute.rb +41 -23
  35. data/lib/active_support/core_ext/class/attribute_accessors.rb +5 -169
  36. data/lib/active_support/core_ext/class/subclasses.rb +20 -8
  37. data/lib/active_support/core_ext/class.rb +4 -4
  38. data/lib/active_support/core_ext/date/acts_like.rb +3 -1
  39. data/lib/active_support/core_ext/date/blank.rb +14 -0
  40. data/lib/active_support/core_ext/date/calculations.rb +21 -9
  41. data/lib/active_support/core_ext/date/conversions.rb +32 -22
  42. data/lib/active_support/core_ext/date/zones.rb +5 -34
  43. data/lib/active_support/core_ext/date.rb +6 -4
  44. data/lib/active_support/core_ext/date_and_time/calculations.rb +199 -57
  45. data/lib/active_support/core_ext/date_and_time/compatibility.rb +16 -0
  46. data/lib/active_support/core_ext/date_and_time/zones.rb +41 -0
  47. data/lib/active_support/core_ext/date_time/acts_like.rb +4 -2
  48. data/lib/active_support/core_ext/date_time/blank.rb +14 -0
  49. data/lib/active_support/core_ext/date_time/calculations.rb +78 -37
  50. data/lib/active_support/core_ext/date_time/compatibility.rb +18 -0
  51. data/lib/active_support/core_ext/date_time/conversions.rb +19 -13
  52. data/lib/active_support/core_ext/date_time.rb +7 -4
  53. data/lib/active_support/core_ext/digest/uuid.rb +53 -0
  54. data/lib/active_support/core_ext/digest.rb +3 -0
  55. data/lib/active_support/core_ext/enumerable.rb +113 -29
  56. data/lib/active_support/core_ext/file/atomic.rb +38 -31
  57. data/lib/active_support/core_ext/file.rb +3 -1
  58. data/lib/active_support/core_ext/hash/compact.rb +29 -0
  59. data/lib/active_support/core_ext/hash/conversions.rb +71 -49
  60. data/lib/active_support/core_ext/hash/deep_merge.rb +9 -13
  61. data/lib/active_support/core_ext/hash/except.rb +12 -3
  62. data/lib/active_support/core_ext/hash/indifferent_access.rb +5 -3
  63. data/lib/active_support/core_ext/hash/keys.rb +50 -38
  64. data/lib/active_support/core_ext/hash/reverse_merge.rb +5 -2
  65. data/lib/active_support/core_ext/hash/slice.rb +12 -6
  66. data/lib/active_support/core_ext/hash/transform_values.rb +32 -0
  67. data/lib/active_support/core_ext/hash.rb +11 -8
  68. data/lib/active_support/core_ext/integer/inflections.rb +3 -1
  69. data/lib/active_support/core_ext/integer/multiple.rb +2 -0
  70. data/lib/active_support/core_ext/integer/time.rb +11 -33
  71. data/lib/active_support/core_ext/integer.rb +5 -3
  72. data/lib/active_support/core_ext/kernel/agnostics.rb +2 -0
  73. data/lib/active_support/core_ext/kernel/concern.rb +14 -0
  74. data/lib/active_support/core_ext/kernel/reporting.rb +5 -74
  75. data/lib/active_support/core_ext/kernel/singleton_class.rb +2 -0
  76. data/lib/active_support/core_ext/kernel.rb +6 -4
  77. data/lib/active_support/core_ext/load_error.rb +5 -21
  78. data/lib/active_support/core_ext/marshal.rb +13 -10
  79. data/lib/active_support/core_ext/module/aliasing.rb +6 -44
  80. data/lib/active_support/core_ext/module/anonymous.rb +12 -1
  81. data/lib/active_support/core_ext/module/attr_internal.rb +8 -8
  82. data/lib/active_support/core_ext/module/attribute_accessors.rb +170 -21
  83. data/lib/active_support/core_ext/module/attribute_accessors_per_thread.rb +150 -0
  84. data/lib/active_support/core_ext/module/concerning.rb +134 -0
  85. data/lib/active_support/core_ext/module/delegation.rb +135 -45
  86. data/lib/active_support/core_ext/module/deprecation.rb +3 -3
  87. data/lib/active_support/core_ext/module/introspection.rb +9 -25
  88. data/lib/active_support/core_ext/module/reachable.rb +5 -2
  89. data/lib/active_support/core_ext/module/redefine_method.rb +49 -0
  90. data/lib/active_support/core_ext/module/remove_method.rb +8 -3
  91. data/lib/active_support/core_ext/module.rb +14 -10
  92. data/lib/active_support/core_ext/name_error.rb +22 -2
  93. data/lib/active_support/core_ext/numeric/bytes.rb +22 -0
  94. data/lib/active_support/core_ext/numeric/conversions.rb +79 -74
  95. data/lib/active_support/core_ext/numeric/inquiry.rb +28 -0
  96. data/lib/active_support/core_ext/numeric/time.rb +37 -50
  97. data/lib/active_support/core_ext/numeric.rb +6 -3
  98. data/lib/active_support/core_ext/object/acts_like.rb +12 -1
  99. data/lib/active_support/core_ext/object/blank.rb +70 -19
  100. data/lib/active_support/core_ext/object/conversions.rb +6 -4
  101. data/lib/active_support/core_ext/object/deep_dup.rb +19 -10
  102. data/lib/active_support/core_ext/object/duplicable.rb +100 -34
  103. data/lib/active_support/core_ext/object/inclusion.rb +18 -15
  104. data/lib/active_support/core_ext/object/instance_variables.rb +3 -1
  105. data/lib/active_support/core_ext/object/json.rb +227 -0
  106. data/lib/active_support/core_ext/object/to_param.rb +3 -1
  107. data/lib/active_support/core_ext/object/to_query.rb +21 -8
  108. data/lib/active_support/core_ext/object/try.rb +94 -24
  109. data/lib/active_support/core_ext/object/with_options.rb +45 -5
  110. data/lib/active_support/core_ext/object.rb +14 -12
  111. data/lib/active_support/core_ext/range/compare_range.rb +61 -0
  112. data/lib/active_support/core_ext/range/conversions.rb +27 -7
  113. data/lib/active_support/core_ext/range/each.rb +19 -17
  114. data/lib/active_support/core_ext/range/include_range.rb +2 -22
  115. data/lib/active_support/core_ext/range/include_time_with_zone.rb +23 -0
  116. data/lib/active_support/core_ext/range/overlaps.rb +2 -0
  117. data/lib/active_support/core_ext/range.rb +7 -4
  118. data/lib/active_support/core_ext/regexp.rb +6 -0
  119. data/lib/active_support/core_ext/securerandom.rb +25 -0
  120. data/lib/active_support/core_ext/string/access.rb +41 -39
  121. data/lib/active_support/core_ext/string/behavior.rb +3 -1
  122. data/lib/active_support/core_ext/string/conversions.rb +17 -13
  123. data/lib/active_support/core_ext/string/exclude.rb +5 -3
  124. data/lib/active_support/core_ext/string/filters.rb +55 -6
  125. data/lib/active_support/core_ext/string/indent.rb +6 -4
  126. data/lib/active_support/core_ext/string/inflections.rb +66 -24
  127. data/lib/active_support/core_ext/string/inquiry.rb +3 -1
  128. data/lib/active_support/core_ext/string/multibyte.rb +15 -7
  129. data/lib/active_support/core_ext/string/output_safety.rb +114 -54
  130. data/lib/active_support/core_ext/string/starts_ends_with.rb +2 -0
  131. data/lib/active_support/core_ext/string/strip.rb +4 -5
  132. data/lib/active_support/core_ext/string/zones.rb +4 -1
  133. data/lib/active_support/core_ext/string.rb +15 -13
  134. data/lib/active_support/core_ext/time/acts_like.rb +3 -1
  135. data/lib/active_support/core_ext/time/calculations.rb +123 -110
  136. data/lib/active_support/core_ext/time/compatibility.rb +16 -0
  137. data/lib/active_support/core_ext/time/conversions.rb +23 -14
  138. data/lib/active_support/core_ext/time/zones.rb +42 -26
  139. data/lib/active_support/core_ext/time.rb +7 -5
  140. data/lib/active_support/core_ext/uri.rb +6 -8
  141. data/lib/active_support/core_ext.rb +3 -2
  142. data/lib/active_support/current_attributes.rb +195 -0
  143. data/lib/active_support/dependencies/autoload.rb +3 -1
  144. data/lib/active_support/dependencies/interlock.rb +57 -0
  145. data/lib/active_support/dependencies.rb +196 -166
  146. data/lib/active_support/deprecation/behaviors.rb +48 -15
  147. data/lib/active_support/deprecation/constant_accessor.rb +52 -0
  148. data/lib/active_support/deprecation/instance_delegator.rb +17 -2
  149. data/lib/active_support/deprecation/method_wrappers.rb +66 -20
  150. data/lib/active_support/deprecation/proxy_wrappers.rb +56 -28
  151. data/lib/active_support/deprecation/reporting.rb +32 -12
  152. data/lib/active_support/deprecation.rb +14 -11
  153. data/lib/active_support/descendants_tracker.rb +2 -0
  154. data/lib/active_support/digest.rb +20 -0
  155. data/lib/active_support/duration/iso8601_parser.rb +125 -0
  156. data/lib/active_support/duration/iso8601_serializer.rb +55 -0
  157. data/lib/active_support/duration.rb +354 -34
  158. data/lib/active_support/encrypted_configuration.rb +49 -0
  159. data/lib/active_support/encrypted_file.rb +99 -0
  160. data/lib/active_support/evented_file_update_checker.rb +205 -0
  161. data/lib/active_support/execution_wrapper.rb +128 -0
  162. data/lib/active_support/executor.rb +8 -0
  163. data/lib/active_support/file_update_checker.rb +63 -37
  164. data/lib/active_support/gem_version.rb +17 -0
  165. data/lib/active_support/gzip.rb +7 -5
  166. data/lib/active_support/hash_with_indifferent_access.rb +158 -35
  167. data/lib/active_support/i18n.rb +8 -6
  168. data/lib/active_support/i18n_railtie.rb +38 -20
  169. data/lib/active_support/inflections.rb +19 -12
  170. data/lib/active_support/inflector/inflections.rb +79 -30
  171. data/lib/active_support/inflector/methods.rb +197 -129
  172. data/lib/active_support/inflector/transliterate.rb +48 -27
  173. data/lib/active_support/inflector.rb +7 -5
  174. data/lib/active_support/json/decoding.rb +21 -25
  175. data/lib/active_support/json/encoding.rb +84 -292
  176. data/lib/active_support/json.rb +4 -2
  177. data/lib/active_support/key_generator.rb +26 -28
  178. data/lib/active_support/lazy_load_hooks.rb +51 -21
  179. data/lib/active_support/locale/en.yml +2 -0
  180. data/lib/active_support/log_subscriber/test_helper.rb +14 -12
  181. data/lib/active_support/log_subscriber.rb +13 -10
  182. data/lib/active_support/logger.rb +54 -3
  183. data/lib/active_support/logger_silence.rb +12 -7
  184. data/lib/active_support/logger_thread_safe_level.rb +34 -0
  185. data/lib/active_support/message_encryptor.rb +173 -50
  186. data/lib/active_support/message_verifier.rb +159 -22
  187. data/lib/active_support/messages/metadata.rb +71 -0
  188. data/lib/active_support/messages/rotation_configuration.rb +22 -0
  189. data/lib/active_support/messages/rotator.rb +56 -0
  190. data/lib/active_support/multibyte/chars.rb +38 -26
  191. data/lib/active_support/multibyte/unicode.rb +138 -146
  192. data/lib/active_support/multibyte.rb +4 -2
  193. data/lib/active_support/notifications/fanout.rb +23 -16
  194. data/lib/active_support/notifications/instrumenter.rb +29 -8
  195. data/lib/active_support/notifications.rb +22 -13
  196. data/lib/active_support/number_helper/number_converter.rb +184 -0
  197. data/lib/active_support/number_helper/number_to_currency_converter.rb +46 -0
  198. data/lib/active_support/number_helper/number_to_delimited_converter.rb +29 -0
  199. data/lib/active_support/number_helper/number_to_human_converter.rb +68 -0
  200. data/lib/active_support/number_helper/number_to_human_size_converter.rb +59 -0
  201. data/lib/active_support/number_helper/number_to_percentage_converter.rb +14 -0
  202. data/lib/active_support/number_helper/number_to_phone_converter.rb +58 -0
  203. data/lib/active_support/number_helper/number_to_rounded_converter.rb +54 -0
  204. data/lib/active_support/number_helper/rounding_helper.rb +66 -0
  205. data/lib/active_support/number_helper.rb +125 -391
  206. data/lib/active_support/option_merger.rb +3 -1
  207. data/lib/active_support/ordered_hash.rb +6 -4
  208. data/lib/active_support/ordered_options.rb +31 -5
  209. data/lib/active_support/per_thread_registry.rb +19 -11
  210. data/lib/active_support/proxy_object.rb +2 -0
  211. data/lib/active_support/rails.rb +16 -8
  212. data/lib/active_support/railtie.rb +43 -9
  213. data/lib/active_support/reloader.rb +131 -0
  214. data/lib/active_support/rescuable.rb +108 -53
  215. data/lib/active_support/security_utils.rb +31 -0
  216. data/lib/active_support/string_inquirer.rb +11 -3
  217. data/lib/active_support/subscriber.rb +54 -17
  218. data/lib/active_support/tagged_logging.rb +14 -11
  219. data/lib/active_support/test_case.rb +42 -37
  220. data/lib/active_support/testing/assertions.rb +126 -39
  221. data/lib/active_support/testing/autorun.rb +5 -3
  222. data/lib/active_support/testing/constant_lookup.rb +3 -6
  223. data/lib/active_support/testing/declarative.rb +10 -22
  224. data/lib/active_support/testing/deprecation.rb +14 -10
  225. data/lib/active_support/testing/file_fixtures.rb +36 -0
  226. data/lib/active_support/testing/isolation.rb +55 -86
  227. data/lib/active_support/testing/method_call_assertions.rb +43 -0
  228. data/lib/active_support/testing/setup_and_teardown.rb +30 -10
  229. data/lib/active_support/testing/stream.rb +44 -0
  230. data/lib/active_support/testing/tagged_logging.rb +5 -3
  231. data/lib/active_support/testing/time_helpers.rb +200 -0
  232. data/lib/active_support/time.rb +13 -13
  233. data/lib/active_support/time_with_zone.rb +223 -73
  234. data/lib/active_support/values/time_zone.rb +261 -126
  235. data/lib/active_support/values/unicode_tables.dat +0 -0
  236. data/lib/active_support/version.rb +6 -7
  237. data/lib/active_support/xml_mini/jdom.rb +116 -113
  238. data/lib/active_support/xml_mini/libxml.rb +17 -16
  239. data/lib/active_support/xml_mini/libxmlsax.rb +16 -18
  240. data/lib/active_support/xml_mini/nokogiri.rb +15 -15
  241. data/lib/active_support/xml_mini/nokogirisax.rb +15 -16
  242. data/lib/active_support/xml_mini/rexml.rb +17 -16
  243. data/lib/active_support/xml_mini.rb +69 -51
  244. data/lib/active_support.rb +29 -3
  245. metadata +84 -54
  246. data/lib/active_support/basic_object.rb +0 -11
  247. data/lib/active_support/buffered_logger.rb +0 -21
  248. data/lib/active_support/concurrency/latch.rb +0 -27
  249. data/lib/active_support/core_ext/array/uniq_by.rb +0 -19
  250. data/lib/active_support/core_ext/class/delegating_attributes.rb +0 -40
  251. data/lib/active_support/core_ext/date_time/zones.rb +0 -24
  252. data/lib/active_support/core_ext/hash/diff.rb +0 -14
  253. data/lib/active_support/core_ext/kernel/debugger.rb +0 -10
  254. data/lib/active_support/core_ext/logger.rb +0 -67
  255. data/lib/active_support/core_ext/module/qualified_const.rb +0 -52
  256. data/lib/active_support/core_ext/object/to_json.rb +0 -27
  257. data/lib/active_support/core_ext/proc.rb +0 -17
  258. data/lib/active_support/core_ext/string/encoding.rb +0 -8
  259. data/lib/active_support/core_ext/struct.rb +0 -6
  260. data/lib/active_support/core_ext/thread.rb +0 -79
  261. data/lib/active_support/core_ext/time/marshal.rb +0 -30
  262. data/lib/active_support/file_watcher.rb +0 -36
  263. data/lib/active_support/json/variable.rb +0 -18
  264. data/lib/active_support/testing/pending.rb +0 -14
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveSupport
4
+ module Testing
5
+ # Adds simple access to sample files called file fixtures.
6
+ # File fixtures are normal files stored in
7
+ # <tt>ActiveSupport::TestCase.file_fixture_path</tt>.
8
+ #
9
+ # File fixtures are represented as +Pathname+ objects.
10
+ # This makes it easy to extract specific information:
11
+ #
12
+ # file_fixture("example.txt").read # get the file's content
13
+ # file_fixture("example.mp3").size # get the file size
14
+ module FileFixtures
15
+ extend ActiveSupport::Concern
16
+
17
+ included do
18
+ class_attribute :file_fixture_path, instance_writer: false
19
+ end
20
+
21
+ # Returns a +Pathname+ to the fixture file named +fixture_name+.
22
+ #
23
+ # Raises +ArgumentError+ if +fixture_name+ can't be found.
24
+ def file_fixture(fixture_name)
25
+ path = Pathname.new(File.join(file_fixture_path, fixture_name))
26
+
27
+ if path.exist?
28
+ path
29
+ else
30
+ msg = "the directory '%s' does not contain a file named '%s'"
31
+ raise ArgumentError, msg % [file_fixture_path, fixture_name]
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -1,105 +1,62 @@
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
8
  def self.included(klass) #:nodoc:
53
- klass.extend(Module.new {
54
- def test_methods
55
- ParallelEach.new super
56
- end
57
- })
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.unpack("m")[0]
103
60
  end
104
61
  end
105
62
 
@@ -112,22 +69,34 @@ module ActiveSupport
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
125
-
126
- load_paths = $-I.map {|p| "-I\"#{File.expand_path(p)}\"" }.join(" ")
127
- `#{Gem.ruby} #{load_paths} #{$0} #{ORIG_ARGV.join(" ")} -t\"#{self.class}\"`
128
-
129
- ENV.delete("ISOLATION_TEST")
130
- ENV.delete("ISOLATION_OUTPUT")
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
92
+
93
+ child = IO.popen([env, Gem.ruby, *load_path_args, $0, *ORIG_ARGV, test_opts])
94
+
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
101
  return tmpfile.read.unpack("m")[0]
133
102
  end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "minitest/mock"
4
+
5
+ module ActiveSupport
6
+ module Testing
7
+ module MethodCallAssertions # :nodoc:
8
+ private
9
+ def assert_called(object, method_name, message = nil, times: 1, returns: nil)
10
+ times_called = 0
11
+
12
+ object.stub(method_name, proc { times_called += 1; returns }) { yield }
13
+
14
+ error = "Expected #{method_name} to be called #{times} times, " \
15
+ "but was called #{times_called} times"
16
+ error = "#{message}.\n#{error}" if message
17
+ assert_equal times, times_called, error
18
+ end
19
+
20
+ def assert_called_with(object, method_name, args = [], returns: nil)
21
+ mock = Minitest::Mock.new
22
+
23
+ if args.all? { |arg| arg.is_a?(Array) }
24
+ args.each { |arg| mock.expect(:call, returns, arg) }
25
+ else
26
+ mock.expect(:call, returns, args)
27
+ end
28
+
29
+ object.stub(method_name, mock) { yield }
30
+
31
+ mock.verify
32
+ end
33
+
34
+ def assert_not_called(object, method_name, message = nil, &block)
35
+ assert_called(object, method_name, message, times: 0, &block)
36
+ end
37
+
38
+ def stub_any_instance(klass, instance: klass.new)
39
+ klass.stub(:new, instance) { yield instance }
40
+ end
41
+ end
42
+ end
43
+ end
@@ -1,33 +1,53 @@
1
- require 'active_support/concern'
2
- require 'active_support/callbacks'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/callbacks"
3
4
 
4
5
  module ActiveSupport
5
6
  module Testing
7
+ # Adds support for +setup+ and +teardown+ callbacks.
8
+ # These callbacks serve as a replacement to overwriting the
9
+ # <tt>#setup</tt> and <tt>#teardown</tt> methods of your TestCase.
10
+ #
11
+ # class ExampleTest < ActiveSupport::TestCase
12
+ # setup do
13
+ # # ...
14
+ # end
15
+ #
16
+ # teardown do
17
+ # # ...
18
+ # end
19
+ # end
6
20
  module SetupAndTeardown
7
- extend ActiveSupport::Concern
8
-
9
- included do
10
- include ActiveSupport::Callbacks
11
- define_callbacks :setup, :teardown
21
+ def self.prepended(klass)
22
+ klass.include ActiveSupport::Callbacks
23
+ klass.define_callbacks :setup, :teardown
24
+ klass.extend ClassMethods
12
25
  end
13
26
 
14
27
  module ClassMethods
28
+ # Add a callback, which runs before <tt>TestCase#setup</tt>.
15
29
  def setup(*args, &block)
16
30
  set_callback(:setup, :before, *args, &block)
17
31
  end
18
32
 
33
+ # Add a callback, which runs after <tt>TestCase#teardown</tt>.
19
34
  def teardown(*args, &block)
20
35
  set_callback(:teardown, :after, *args, &block)
21
36
  end
22
37
  end
23
38
 
24
- def before_setup
39
+ def before_setup # :nodoc:
25
40
  super
26
41
  run_callbacks :setup
27
42
  end
28
43
 
29
- def after_teardown
30
- run_callbacks :teardown
44
+ def after_teardown # :nodoc:
45
+ begin
46
+ run_callbacks :teardown
47
+ rescue => e
48
+ self.failures << Minitest::UnexpectedError.new(e)
49
+ end
50
+
31
51
  super
32
52
  end
33
53
  end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveSupport
4
+ module Testing
5
+ module Stream #:nodoc:
6
+ private
7
+
8
+ def silence_stream(stream)
9
+ old_stream = stream.dup
10
+ stream.reopen(IO::NULL)
11
+ stream.sync = true
12
+ yield
13
+ ensure
14
+ stream.reopen(old_stream)
15
+ old_stream.close
16
+ end
17
+
18
+ def quietly
19
+ silence_stream(STDOUT) do
20
+ silence_stream(STDERR) do
21
+ yield
22
+ end
23
+ end
24
+ end
25
+
26
+ def capture(stream)
27
+ stream = stream.to_s
28
+ captured_stream = Tempfile.new(stream)
29
+ stream_io = eval("$#{stream}")
30
+ origin_stream = stream_io.dup
31
+ stream_io.reopen(captured_stream)
32
+
33
+ yield
34
+
35
+ stream_io.rewind
36
+ return captured_stream.read
37
+ ensure
38
+ captured_stream.close
39
+ captured_stream.unlink
40
+ stream_io.reopen(origin_stream)
41
+ end
42
+ end
43
+ end
44
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveSupport
2
4
  module Testing
3
5
  # Logs a "PostsControllerTest: test name" heading before each test to
@@ -6,9 +8,9 @@ module ActiveSupport
6
8
  attr_writer :tagged_logger
7
9
 
8
10
  def before_setup
9
- if tagged_logger
10
- heading = "#{self.class}: #{__name__}"
11
- divider = '-' * heading.size
11
+ if tagged_logger && tagged_logger.info?
12
+ heading = "#{self.class}: #{name}"
13
+ divider = "-" * heading.size
12
14
  tagged_logger.info divider
13
15
  tagged_logger.info heading
14
16
  tagged_logger.info divider
@@ -0,0 +1,200 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/module/redefine_method"
4
+ require "active_support/core_ext/string/strip" # for strip_heredoc
5
+ require "active_support/core_ext/time/calculations"
6
+ require "concurrent/map"
7
+
8
+ module ActiveSupport
9
+ module Testing
10
+ class SimpleStubs # :nodoc:
11
+ Stub = Struct.new(:object, :method_name, :original_method)
12
+
13
+ def initialize
14
+ @stubs = Concurrent::Map.new { |h, k| h[k] = {} }
15
+ end
16
+
17
+ def stub_object(object, method_name, &block)
18
+ if stub = stubbing(object, method_name)
19
+ unstub_object(stub)
20
+ end
21
+
22
+ new_name = "__simple_stub__#{method_name}"
23
+
24
+ @stubs[object.object_id][method_name] = Stub.new(object, method_name, new_name)
25
+
26
+ object.singleton_class.send :alias_method, new_name, method_name
27
+ object.define_singleton_method(method_name, &block)
28
+ end
29
+
30
+ def unstub_all!
31
+ @stubs.each_value do |object_stubs|
32
+ object_stubs.each_value do |stub|
33
+ unstub_object(stub)
34
+ end
35
+ end
36
+ @stubs.clear
37
+ end
38
+
39
+ def stubbing(object, method_name)
40
+ @stubs[object.object_id][method_name]
41
+ end
42
+
43
+ private
44
+
45
+ def unstub_object(stub)
46
+ singleton_class = stub.object.singleton_class
47
+ singleton_class.send :silence_redefinition_of_method, stub.method_name
48
+ singleton_class.send :alias_method, stub.method_name, stub.original_method
49
+ singleton_class.send :undef_method, stub.original_method
50
+ end
51
+ end
52
+
53
+ # Contains helpers that help you test passage of time.
54
+ module TimeHelpers
55
+ def after_teardown
56
+ travel_back
57
+ super
58
+ end
59
+
60
+ # Changes current time to the time in the future or in the past by a given time difference by
61
+ # stubbing +Time.now+, +Date.today+, and +DateTime.now+. The stubs are automatically removed
62
+ # at the end of the test.
63
+ #
64
+ # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
65
+ # travel 1.day
66
+ # Time.current # => Sun, 10 Nov 2013 15:34:49 EST -05:00
67
+ # Date.current # => Sun, 10 Nov 2013
68
+ # DateTime.current # => Sun, 10 Nov 2013 15:34:49 -0500
69
+ #
70
+ # This method also accepts a block, which will return the current time back to its original
71
+ # state at the end of the block:
72
+ #
73
+ # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
74
+ # travel 1.day do
75
+ # User.create.created_at # => Sun, 10 Nov 2013 15:34:49 EST -05:00
76
+ # end
77
+ # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
78
+ def travel(duration, &block)
79
+ travel_to Time.now + duration, &block
80
+ end
81
+
82
+ # Changes current time to the given time by stubbing +Time.now+,
83
+ # +Date.today+, and +DateTime.now+ to return the time or date passed into this method.
84
+ # The stubs are automatically removed at the end of the test.
85
+ #
86
+ # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
87
+ # travel_to Time.zone.local(2004, 11, 24, 01, 04, 44)
88
+ # Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
89
+ # Date.current # => Wed, 24 Nov 2004
90
+ # DateTime.current # => Wed, 24 Nov 2004 01:04:44 -0500
91
+ #
92
+ # Dates are taken as their timestamp at the beginning of the day in the
93
+ # application time zone. <tt>Time.current</tt> returns said timestamp,
94
+ # and <tt>Time.now</tt> its equivalent in the system time zone. Similarly,
95
+ # <tt>Date.current</tt> returns a date equal to the argument, and
96
+ # <tt>Date.today</tt> the date according to <tt>Time.now</tt>, which may
97
+ # be different. (Note that you rarely want to deal with <tt>Time.now</tt>,
98
+ # or <tt>Date.today</tt>, in order to honor the application time zone
99
+ # please always use <tt>Time.current</tt> and <tt>Date.current</tt>.)
100
+ #
101
+ # Note that the usec for the time passed will be set to 0 to prevent rounding
102
+ # errors with external services, like MySQL (which will round instead of floor,
103
+ # leading to off-by-one-second errors).
104
+ #
105
+ # This method also accepts a block, which will return the current time back to its original
106
+ # state at the end of the block:
107
+ #
108
+ # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
109
+ # travel_to Time.zone.local(2004, 11, 24, 01, 04, 44) do
110
+ # Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
111
+ # end
112
+ # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
113
+ def travel_to(date_or_time)
114
+ if block_given? && simple_stubs.stubbing(Time, :now)
115
+ travel_to_nested_block_call = <<-MSG.strip_heredoc
116
+
117
+ Calling `travel_to` with a block, when we have previously already made a call to `travel_to`, can lead to confusing time stubbing.
118
+
119
+ Instead of:
120
+
121
+ travel_to 2.days.from_now do
122
+ # 2 days from today
123
+ travel_to 3.days.from_now do
124
+ # 5 days from today
125
+ end
126
+ end
127
+
128
+ preferred way to achieve above is:
129
+
130
+ travel 2.days do
131
+ # 2 days from today
132
+ end
133
+
134
+ travel 5.days do
135
+ # 5 days from today
136
+ end
137
+
138
+ MSG
139
+ raise travel_to_nested_block_call
140
+ end
141
+
142
+ if date_or_time.is_a?(Date) && !date_or_time.is_a?(DateTime)
143
+ now = date_or_time.midnight.to_time
144
+ else
145
+ now = date_or_time.to_time.change(usec: 0)
146
+ end
147
+
148
+ simple_stubs.stub_object(Time, :now) { at(now.to_i) }
149
+ simple_stubs.stub_object(Date, :today) { jd(now.to_date.jd) }
150
+ simple_stubs.stub_object(DateTime, :now) { jd(now.to_date.jd, now.hour, now.min, now.sec, Rational(now.utc_offset, 86400)) }
151
+
152
+ if block_given?
153
+ begin
154
+ yield
155
+ ensure
156
+ travel_back
157
+ end
158
+ end
159
+ end
160
+
161
+ # Returns the current time back to its original state, by removing the stubs added by
162
+ # +travel+ and +travel_to+.
163
+ #
164
+ # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
165
+ # travel_to Time.zone.local(2004, 11, 24, 01, 04, 44)
166
+ # Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
167
+ # travel_back
168
+ # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
169
+ def travel_back
170
+ simple_stubs.unstub_all!
171
+ end
172
+
173
+ # Calls +travel_to+ with +Time.now+.
174
+ #
175
+ # Time.current # => Sun, 09 Jul 2017 15:34:49 EST -05:00
176
+ # freeze_time
177
+ # sleep(1)
178
+ # Time.current # => Sun, 09 Jul 2017 15:34:49 EST -05:00
179
+ #
180
+ # This method also accepts a block, which will return the current time back to its original
181
+ # state at the end of the block:
182
+ #
183
+ # Time.current # => Sun, 09 Jul 2017 15:34:49 EST -05:00
184
+ # freeze_time do
185
+ # sleep(1)
186
+ # User.create.created_at # => Sun, 09 Jul 2017 15:34:49 EST -05:00
187
+ # end
188
+ # Time.current # => Sun, 09 Jul 2017 15:34:50 EST -05:00
189
+ def freeze_time(&block)
190
+ travel_to Time.now, &block
191
+ end
192
+
193
+ private
194
+
195
+ def simple_stubs
196
+ @simple_stubs ||= SimpleStubs.new
197
+ end
198
+ end
199
+ end
200
+ end
@@ -1,20 +1,20 @@
1
- require 'active_support'
1
+ # frozen_string_literal: true
2
2
 
3
3
  module ActiveSupport
4
- autoload :Duration, 'active_support/duration'
5
- autoload :TimeWithZone, 'active_support/time_with_zone'
6
- autoload :TimeZone, 'active_support/values/time_zone'
4
+ autoload :Duration, "active_support/duration"
5
+ autoload :TimeWithZone, "active_support/time_with_zone"
6
+ autoload :TimeZone, "active_support/values/time_zone"
7
7
  end
8
8
 
9
- require 'date'
10
- require 'time'
9
+ require "date"
10
+ require "time"
11
11
 
12
- require 'active_support/core_ext/time'
13
- require 'active_support/core_ext/date'
14
- require 'active_support/core_ext/date_time'
12
+ require "active_support/core_ext/time"
13
+ require "active_support/core_ext/date"
14
+ require "active_support/core_ext/date_time"
15
15
 
16
- require 'active_support/core_ext/integer/time'
17
- require 'active_support/core_ext/numeric/time'
16
+ require "active_support/core_ext/integer/time"
17
+ require "active_support/core_ext/numeric/time"
18
18
 
19
- require 'active_support/core_ext/string/conversions'
20
- require 'active_support/core_ext/string/zones'
19
+ require "active_support/core_ext/string/conversions"
20
+ require "active_support/core_ext/string/zones"