test-unit 3.4.4 → 3.4.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -3
  3. data/Rakefile +0 -9
  4. data/doc/text/getting-started.md +1 -1
  5. data/doc/text/news.md +54 -1
  6. data/lib/test/unit/assertion-failed-error.rb +35 -0
  7. data/lib/test/unit/assertions.rb +93 -17
  8. data/lib/test/unit/autorunner.rb +13 -1
  9. data/lib/test/unit/collector/descendant.rb +1 -0
  10. data/lib/test/unit/collector/dir.rb +4 -2
  11. data/lib/test/unit/collector/load.rb +2 -0
  12. data/lib/test/unit/collector/objectspace.rb +1 -0
  13. data/lib/test/unit/collector.rb +31 -0
  14. data/lib/test/unit/testcase.rb +34 -1
  15. data/lib/test/unit/testsuite.rb +1 -1
  16. data/lib/test/unit/util/memory-usage.rb +47 -0
  17. data/lib/test/unit/version.rb +1 -1
  18. data/lib/test/unit.rb +4 -4
  19. metadata +6 -83
  20. data/test/collector/test-descendant.rb +0 -182
  21. data/test/collector/test-load.rb +0 -475
  22. data/test/collector/test_dir.rb +0 -407
  23. data/test/collector/test_objectspace.rb +0 -102
  24. data/test/fixtures/header-label.csv +0 -3
  25. data/test/fixtures/header-label.tsv +0 -3
  26. data/test/fixtures/header.csv +0 -3
  27. data/test/fixtures/header.tsv +0 -3
  28. data/test/fixtures/no-header.csv +0 -2
  29. data/test/fixtures/no-header.tsv +0 -2
  30. data/test/fixtures/plus.csv +0 -3
  31. data/test/run-test.rb +0 -22
  32. data/test/test-assertions.rb +0 -2281
  33. data/test/test-attribute-matcher.rb +0 -38
  34. data/test/test-attribute.rb +0 -123
  35. data/test/test-code-snippet.rb +0 -79
  36. data/test/test-color-scheme.rb +0 -123
  37. data/test/test-color.rb +0 -47
  38. data/test/test-data.rb +0 -419
  39. data/test/test-diff.rb +0 -518
  40. data/test/test-emacs-runner.rb +0 -60
  41. data/test/test-error.rb +0 -26
  42. data/test/test-failure.rb +0 -33
  43. data/test/test-fault-location-detector.rb +0 -163
  44. data/test/test-fixture.rb +0 -713
  45. data/test/test-notification.rb +0 -33
  46. data/test/test-omission.rb +0 -81
  47. data/test/test-pending.rb +0 -70
  48. data/test/test-priority.rb +0 -184
  49. data/test/test-test-case.rb +0 -1284
  50. data/test/test-test-result.rb +0 -113
  51. data/test/test-test-suite-creator.rb +0 -97
  52. data/test/test-test-suite.rb +0 -151
  53. data/test/testunit-test-util.rb +0 -33
  54. data/test/ui/test_testrunmediator.rb +0 -20
  55. data/test/util/test-method-owner-finder.rb +0 -38
  56. data/test/util/test-output.rb +0 -11
  57. data/test/util/test_backtracefilter.rb +0 -52
  58. data/test/util/test_observable.rb +0 -102
  59. data/test/util/test_procwrapper.rb +0 -36
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4bf06d094c228d2826f3ffd368b7587dad9844cb59429790157c1d00f963e527
4
- data.tar.gz: d5d07e063a929674b11047dee03b185fdf73f926e48aa8830f2f2fa7d4c88b58
3
+ metadata.gz: 6f71beead19a58b6dd15eadbce6ba5f773a25dc5e8a69cdfc5e0b227fe60bfef
4
+ data.tar.gz: c845b3d680a4f8d4d835bbfa3c3d86fdc5b1aa2faa21b9f6ebcb5635628a7e47
5
5
  SHA512:
6
- metadata.gz: 63d7fa4261919b37f31bd412335cc086778622f4ff63e6f645baf7c8440493e3dc2be0206bff51f5a24bb0f5f90122a61db5cbe31b2499360045092069164605
7
- data.tar.gz: 50238b29eda4de9e4ece1c64fe3cd9a583ceeb7cb965c4e6660d39017ded8a27579723dfe206f434ff0bbd71dba9085e4af987d83d6bf76cf3ef16a475f31e4b
6
+ metadata.gz: 52534de6505e9b791d185d52ac4f8cfba7799c3f937f1fabe9a2419cb43cfae0fef1224727e25f8cb1a69fcef220c49a5a42b57c2b580dee7438d0c8ec64e390
7
+ data.tar.gz: 233aca4112351087c13b900cf64261d5d730fa16fe2b7ab9c14a8be81a43e1032849e3fcc90f1589528738879ccb9fa5d117b5328345967e0b17693d55105afc
data/README.md CHANGED
@@ -1,7 +1,8 @@
1
1
  # test-unit
2
2
 
3
- [![](https://badge.fury.io/rb/test-unit.svg)](http://badge.fury.io/rb/test-unit)
4
- [![](https://travis-ci.org/test-unit/test-unit.svg?branch=master)](https://travis-ci.org/test-unit/test-unit)
3
+ [![Gem Version](https://badge.fury.io/rb/test-unit.png)](http://badge.fury.io/rb/test-unit)
4
+ [![Build Status for Ruby 2.1+](https://github.com/test-unit/test-unit/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/test-unit/test-unit/actions/workflows/test.yml?query=branch%3Amaster+)
5
+ [![Build Status for Ruby 1.9 and 2.0](https://travis-ci.com/test-unit/test-unit.svg?branch=master)](https://travis-ci.com/test-unit/test-unit)
5
6
 
6
7
  * http://test-unit.github.io/
7
8
  * https://github.com/test-unit/test-unit
@@ -24,7 +25,7 @@ writing tests, checking results and automated testing in Ruby.
24
25
  to radically change very soon).
25
26
 
26
27
  * test-unit will be improved actively and may break
27
- compatiblity with test-unit 1.2.3. (We will not hope it
28
+ compatibility with test-unit 1.2.3. (We will not hope it
28
29
  if it isn't needed.)
29
30
 
30
31
  * Some features exist as separated gems like GUI test
data/Rakefile CHANGED
@@ -24,7 +24,6 @@ require "packnga"
24
24
  task :default => :test
25
25
 
26
26
  base_dir = File.dirname(__FILE__)
27
- html_base_dir = File.join(base_dir, "doc", "html")
28
27
 
29
28
  helper = Bundler::GemHelper.new(base_dir)
30
29
  def helper.version_tag
@@ -53,14 +52,6 @@ def rake(*arguments)
53
52
  ruby($0, *arguments)
54
53
  end
55
54
 
56
- namespace :html do
57
- desc "Publish HTML to Web site."
58
- task :publish do
59
- # FIXME Do nothing for now
60
- #rsync_to_rubyforge(spec, "#{html_base_dir}/", "")
61
- end
62
- end
63
-
64
55
  task :test do
65
56
  ruby("test/run-test.rb")
66
57
  end
@@ -239,7 +239,7 @@ module Sub
239
239
  end
240
240
  ~~~
241
241
 
242
- ## 7. For more inforomation
242
+ ## 7. For more information
243
243
 
244
244
  Let's read the official document.
245
245
 
data/doc/text/news.md CHANGED
@@ -1,10 +1,63 @@
1
1
  # News
2
2
 
3
+ ## 3.4.8 - 2021-10-11 {#version-3-4-8}
4
+
5
+ ### Improvements
6
+
7
+ * Added support for omitting Ractor tests on Ruby 2.7 or earlier
8
+ automatically.
9
+
10
+ ## 3.4.7 - 2021-09-14 {#version-3-4-7}
11
+
12
+ ### Fixes
13
+
14
+ * Suppressed a warning on Ruby 2.
15
+ [GitHub#205][Patch by Kenichi Kamiya]
16
+
17
+ ### Thanks
18
+
19
+ * Kenichi Kamiya
20
+
21
+ ## 3.4.6 - 2021-09-11 {#version-3-4-6}
22
+
23
+ ### Improvements
24
+
25
+ * Added support for tests that use Ractor. Use
26
+ `Test::Unit::TestCase.ractor` to declare that these tests use
27
+ Ractor.
28
+
29
+ * Added `--debug-on-failure` option.
30
+
31
+ ## 3.4.5 - 2021-09-04 {#version-3-4-5}
32
+
33
+ ### Improvements
34
+
35
+ * Added more metadata to gemspec.
36
+ [GitHub#183][Patch by Kenichi Kamiya]
37
+
38
+ * Removed needless files from gem.
39
+ [GitHub#184][Patch by Kenichi Kamiya]
40
+
41
+ * Updated documents.
42
+ [GitHub#191][GitHub#192][GitHub#193][GitHub#199][GitHub#200]
43
+ [GitHub#201][Patch by Kenichi Kamiya]
44
+
45
+ * Added `assert_nothing_leaked_memory`.
46
+
47
+ ### Fixes
48
+
49
+ * Fixed typos in documents.
50
+ [GitHub#189][GitHub#190][GitHub#195][GitHub#197][Patch by Kenichi Kamiya]
51
+
52
+ ### Thanks
53
+
54
+ * Kenichi Kamiya
55
+
3
56
  ## 3.4.4 - 2021-06-04 {#version-3-4-4}
4
57
 
5
58
  ### Improvements
6
59
 
7
- * Rename `assert_all?` to `assert_all`. `assert_all?` is deprecated
60
+ * Renamed `assert_all?` to `assert_all`. `assert_all?` is deprecated
8
61
  but is available.
9
62
 
10
63
  ## 3.4.3 - 2021-06-04 {#version-3-4-3}
@@ -9,6 +9,17 @@ module Test
9
9
 
10
10
  # Thrown by Test::Unit::Assertions when an assertion fails.
11
11
  class AssertionFailedError < StandardError
12
+ @debug_on_failure = false
13
+ class << self
14
+ def debug_on_failure=(boolean)
15
+ @debug_on_failure = boolean
16
+ end
17
+
18
+ def debug_on_failure?
19
+ @debug_on_failure
20
+ end
21
+ end
22
+
12
23
  attr_accessor :expected, :actual, :user_message
13
24
  attr_accessor :inspected_expected, :inspected_actual
14
25
  def initialize(message=nil, options=nil)
@@ -19,6 +30,30 @@ module Test
19
30
  @inspected_actual = options[:inspected_actual]
20
31
  @user_message = options[:user_message]
21
32
  super(message)
33
+ debug_on_failure
34
+ end
35
+
36
+ private
37
+ def debug_on_failure
38
+ return unless self.class.debug_on_failure?
39
+
40
+ begin
41
+ require "debug"
42
+ rescue LoadError
43
+ return
44
+ end
45
+
46
+ return unless binding.respond_to?(:break)
47
+
48
+ frames = caller(0)
49
+ pre = nil
50
+ Util::BacktraceFilter.filter_backtrace(frames).each do |location|
51
+ frame_index = frames.index(location)
52
+ next if frame_index.nil?
53
+ pre = "frame #{frame_index}"
54
+ break
55
+ end
56
+ binding.break(pre: pre)
22
57
  end
23
58
  end
24
59
  end
@@ -5,6 +5,7 @@
5
5
 
6
6
  require 'test/unit/assertion-failed-error'
7
7
  require 'test/unit/util/backtracefilter'
8
+ require 'test/unit/util/memory-usage'
8
9
  require 'test/unit/util/method-owner-finder'
9
10
  require 'test/unit/diff'
10
11
 
@@ -43,7 +44,7 @@ module Test
43
44
 
44
45
  ##
45
46
  # The assertion upon which all other assertions are based. Passes if the
46
- # block yields true.
47
+ # block yields not false nor nil.
47
48
  #
48
49
  # @example
49
50
  # assert_block "Couldn't do the thing" do
@@ -454,7 +455,7 @@ EOT
454
455
  alias_method :refute_instance_of, :assert_not_instance_of
455
456
 
456
457
  ##
457
- # Passes if `object` is nil.
458
+ # Passes if `object`.nil?.
458
459
  #
459
460
  # @example
460
461
  # assert_nil [1, 2].uniq!
@@ -627,7 +628,7 @@ EOT
627
628
  ##
628
629
  # Compares the `object1` with `object2` using `operator`.
629
630
  #
630
- # Passes if object1.__send__(operator, object2) is true.
631
+ # Passes if object1.__send__(operator, object2) is not false nor nil.
631
632
  #
632
633
  # @example
633
634
  # assert_operator 5, :>=, 4
@@ -647,7 +648,7 @@ EOT
647
648
  ##
648
649
  # Compares the `object1` with `object2` using `operator`.
649
650
  #
650
- # Passes if object1.__send__(operator, object2) is not true.
651
+ # Passes if object1.__send__(operator, object2) is false or nil.
651
652
  #
652
653
  # @example
653
654
  # assert_not_operator(5, :<, 4) # => pass
@@ -787,7 +788,7 @@ EOT
787
788
  alias_method :refute_match, :assert_not_match
788
789
 
789
790
  ##
790
- # Deprecated. Use #assert_not_match instead.
791
+ # @deprecated Use {#assert_not_match} instead.
791
792
  #
792
793
  # Passes if `regexp` !~ `string`
793
794
  #
@@ -1177,7 +1178,7 @@ EOT
1177
1178
 
1178
1179
  public
1179
1180
  ##
1180
- # Passes if the method send returns a true value.
1181
+ # Passes if the method `__send__` returns not false nor nil.
1181
1182
  #
1182
1183
  # `send_array` is composed of:
1183
1184
  # * A receiver
@@ -1217,7 +1218,7 @@ EOT
1217
1218
  end
1218
1219
 
1219
1220
  ##
1220
- # Passes if the method send doesn't return a true value.
1221
+ # Passes if the method `__send__` returns false or nil.
1221
1222
  #
1222
1223
  # `send_array` is composed of:
1223
1224
  # * A receiver
@@ -1267,7 +1268,7 @@ EOT
1267
1268
  assert_block(build_message(message,
1268
1269
  "<true> or <false> expected but was\n<?>",
1269
1270
  actual)) do
1270
- [true, false].include?(actual)
1271
+ true == actual || false == actual
1271
1272
  end
1272
1273
  end
1273
1274
  end
@@ -1283,7 +1284,7 @@ EOT
1283
1284
  assert_block(build_message(message,
1284
1285
  "<true> expected but was\n<?>",
1285
1286
  actual)) do
1286
- actual == true
1287
+ true == actual
1287
1288
  end
1288
1289
  end
1289
1290
  end
@@ -1299,14 +1300,14 @@ EOT
1299
1300
  assert_block(build_message(message,
1300
1301
  "<false> expected but was\n<?>",
1301
1302
  actual)) do
1302
- actual == false
1303
+ false == actual
1303
1304
  end
1304
1305
  end
1305
1306
  end
1306
1307
 
1307
1308
  ##
1308
1309
  # Passes if expression "`expected` `operator`
1309
- # `actual`" is true.
1310
+ # `actual`" is not false nor nil.
1310
1311
  #
1311
1312
  # @example
1312
1313
  # assert_compare(1, "<", 10) # -> pass
@@ -1435,7 +1436,7 @@ EOT
1435
1436
  end
1436
1437
 
1437
1438
  ##
1438
- # Passes if `object`.`predicate` is _true_.
1439
+ # Passes if `object`.`predicate` is not false nor nil.
1439
1440
  #
1440
1441
  # @example
1441
1442
  # assert_predicate([], :empty?) # -> pass
@@ -1457,7 +1458,7 @@ EOT
1457
1458
  end
1458
1459
 
1459
1460
  ##
1460
- # Passes if `object`.`predicate` is not _true_.
1461
+ # Passes if `object`.`predicate` is false or nil.
1461
1462
  #
1462
1463
  # @example
1463
1464
  # assert_not_predicate([1], :empty?) # -> pass
@@ -1686,12 +1687,12 @@ EOT
1686
1687
  # with any `block`.
1687
1688
  #
1688
1689
  # @example Pass patterns
1689
- # assert_all?([1, 2, 3]) {|item| item > 0} # => pass
1690
- # assert_all?([1, 2, 3], &:positive?) # => pass
1691
- # assert_all?([]) {|item| false} # => pass
1690
+ # assert_all([1, 2, 3]) {|item| item > 0} # => pass
1691
+ # assert_all([1, 2, 3], &:positive?) # => pass
1692
+ # assert_all([]) {|item| false} # => pass
1692
1693
  #
1693
1694
  # @example Failure pattern
1694
- # assert_all?([0, 1, 2], &:zero?) # => failure
1695
+ # assert_all([0, 1, 2], &:zero?) # => failure
1695
1696
  #
1696
1697
  # @param [#each] collection The check target.
1697
1698
  # @param [String] message The additional user message. It is
@@ -1729,6 +1730,81 @@ EOT
1729
1730
  # @since 3.4.3
1730
1731
  alias_method :assert_all?, :assert_all
1731
1732
 
1733
+ # @overload assert_nothing_leaked_memory(max_increasable_size, target=:physical, message=nil, &block)
1734
+ #
1735
+ # Asserts that increased memory usage by `block.call` is less
1736
+ # than `max_increasable_size`. `GC.start` is called before and
1737
+ # after `block.call`.
1738
+ #
1739
+ # This assertion may be fragile. Because memory usage is
1740
+ # depends on the current Ruby process's memory
1741
+ # usage. Launching a new Ruby process for this will produce
1742
+ # more stable result but we need to specify target code as
1743
+ # `String` instead of block for the approach. We choose easy
1744
+ # to write API approach rather than more stable result
1745
+ # approach for this case.
1746
+ #
1747
+ # @example Pass pattern
1748
+ # require "objspace"
1749
+ # size_per_object = ObjectSpace.memsize_of("Hello")
1750
+ # # If memory isn't leaked, physical memory of almost created objects
1751
+ # # (1000 - 10 objects) must be freed.
1752
+ # assert_nothing_leaked_memory(size_per_object * 10) do
1753
+ # 1_000.times do
1754
+ # "Hello".dup
1755
+ # end
1756
+ # end # => pass
1757
+ #
1758
+ # @example Failure pattern
1759
+ # require "objspace"
1760
+ # size_per_object = ObjectSpace.memsize_of("Hello")
1761
+ # strings = []
1762
+ # assert_nothing_leaked_memory(size_per_object * 10) do
1763
+ # 10_000.times do
1764
+ # # Created objects aren't GC-ed because they are referred.
1765
+ # strings << "Hello".dup
1766
+ # end
1767
+ # end # => failure
1768
+ #
1769
+ # @param target [:physical, :virtual] which memory usage is
1770
+ # used for comparing. `:physical` means physical memory usage
1771
+ # also known as Resident Set Size (RSS). `:virtual` means
1772
+ # virtual memory usage.
1773
+ # @yield [] do anything you want to measure memory usage
1774
+ # in the block.
1775
+ # @yieldreturn [void]
1776
+ # @return [void]
1777
+ #
1778
+ # @since 3.4.5
1779
+ def assert_nothing_leaked_memory(max_increasable_size,
1780
+ target=:physical,
1781
+ message=nil)
1782
+ _wrap_assertion do
1783
+ GC.start
1784
+ before = Util::MemoryUsage.new
1785
+ unless before.collected?
1786
+ omit("memory usage collection isn't supported on this platform")
1787
+ end
1788
+ yield
1789
+ GC.start
1790
+ after = Util::MemoryUsage.new
1791
+ before_value = before.__send__(target)
1792
+ after_value = after.__send__(target)
1793
+ actual_increased_size = after_value - before_value
1794
+ template = <<-TEMPLATE
1795
+ <?> was expected to be less than
1796
+ <?>.
1797
+ TEMPLATE
1798
+ full_message = build_message(message,
1799
+ template,
1800
+ actual_increased_size,
1801
+ max_increasable_size)
1802
+ assert_block(full_message) do
1803
+ actual_increased_size < max_increasable_size
1804
+ end
1805
+ end
1806
+ end
1807
+
1732
1808
  ##
1733
1809
  # Builds a failure message. `user_message` is added before the
1734
1810
  # `template` and `arguments` replaces the '?'s positionally in
@@ -1,10 +1,10 @@
1
1
  require "English"
2
+ require "optparse"
2
3
 
3
4
  require "test/unit/color-scheme"
4
5
  require "test/unit/priority"
5
6
  require "test/unit/attribute-matcher"
6
7
  require "test/unit/testcase"
7
- require "optparse"
8
8
 
9
9
  module Test
10
10
  module Unit
@@ -144,6 +144,7 @@ module Test
144
144
  attr_accessor :pattern, :exclude, :base, :workdir
145
145
  attr_accessor :color_scheme, :listeners
146
146
  attr_writer :stop_on_failure
147
+ attr_writer :debug_on_failure
147
148
  attr_writer :runner, :collector
148
149
 
149
150
  def initialize(standalone)
@@ -159,6 +160,7 @@ module Test
159
160
  @workdir = nil
160
161
  @listeners = []
161
162
  @stop_on_failure = false
163
+ @debug_on_failure = false
162
164
  config_file = "test-unit.yml"
163
165
  if File.exist?(config_file)
164
166
  load_config(config_file)
@@ -172,6 +174,10 @@ module Test
172
174
  @stop_on_failure
173
175
  end
174
176
 
177
+ def debug_on_failure?
178
+ @debug_on_failure
179
+ end
180
+
175
181
  def prepare
176
182
  PREPARE_HOOKS.each do |handler|
177
183
  handler.call(self)
@@ -381,6 +387,12 @@ module Test
381
387
  @stop_on_failure = boolean
382
388
  end
383
389
 
390
+ o.on("--[no-]debug-on-failure",
391
+ "Run debugger if available on failure",
392
+ "(#{AssertionFailedError.debug_on_failure?})") do |boolean|
393
+ AssertionFailedError.debug_on_failure = boolean
394
+ end
395
+
384
396
  ADDITIONAL_OPTIONS.each do |option_builder|
385
397
  option_builder.call(self, o)
386
398
  end
@@ -11,6 +11,7 @@ module Test
11
11
  def collect(name=NAME)
12
12
  suite = TestSuite.new(name)
13
13
  add_test_cases(suite, TestCase::DESCENDANTS)
14
+ adjust_ractor_tests(suite)
14
15
  suite
15
16
  end
16
17
  end
@@ -25,9 +25,9 @@ module Test
25
25
  basedir = @base
26
26
  $:.push(basedir) if basedir
27
27
  if(from.empty?)
28
- recursive_collect('.', find_test_cases)
28
+ suite = recursive_collect('.', find_test_cases)
29
29
  elsif(from.size == 1)
30
- recursive_collect(from.first, find_test_cases)
30
+ suite = recursive_collect(from.first, find_test_cases)
31
31
  else
32
32
  suites = []
33
33
  from.each do |f|
@@ -38,6 +38,8 @@ module Test
38
38
  sort(suites).each{|s| suite << s}
39
39
  suite
40
40
  end
41
+ adjust_ractor_tests(suite)
42
+ suite
41
43
  ensure
42
44
  $:.delete_at($:.rindex(basedir)) if basedir
43
45
  end
@@ -60,6 +60,8 @@ module Test
60
60
  test_suite = test_suites.first
61
61
  end
62
62
 
63
+ adjust_ractor_tests(test_suite)
64
+
63
65
  test_suite
64
66
  end
65
67
  end
@@ -26,6 +26,7 @@ module Test
26
26
  end
27
27
  end
28
28
  sort(sub_suites).each{|s| suite << s}
29
+ adjust_ractor_tests(suite)
29
30
  suite
30
31
  end
31
32
  end
@@ -68,6 +68,37 @@ module Test
68
68
  suite << sub_suite
69
69
  end
70
70
  end
71
+
72
+ def adjust_ractor_tests(suite)
73
+ return if suite.nil?
74
+ ractor_suites = extract_ractor_tests(suite)
75
+ ractor_suites.each do |ractor_suite|
76
+ suite << ractor_suite
77
+ end
78
+ end
79
+
80
+ def extract_ractor_tests(suite)
81
+ ractor_suites = []
82
+ ractor_tests = []
83
+ suite.tests.each do |test|
84
+ case test
85
+ when TestSuite
86
+ ractor_suites.concat(extract_ractor_tests(test))
87
+ else
88
+ next unless test[:ractor]
89
+ ractor_tests << test
90
+ end
91
+ end
92
+ unless ractor_tests.empty?
93
+ suite.delete_tests(ractor_tests)
94
+ ractor_suite = TestSuite.new(suite.name, suite.test_case)
95
+ ractor_tests.each do |ractor_test|
96
+ ractor_suite << ractor_test
97
+ end
98
+ ractor_suites << ractor_suite
99
+ end
100
+ ractor_suites
101
+ end
71
102
  end
72
103
  end
73
104
  end
@@ -351,6 +351,36 @@ module Test
351
351
  attribute(:description, value, {}, *targets)
352
352
  end
353
353
 
354
+ # Declares that the following test uses Ractor.
355
+ #
356
+ # Tests that use Ractor are executed at the end. Because multi
357
+ # Ractor mode is enabled in the current process and it's not
358
+ # disabled even when only one Ractor is running after running
359
+ # a test that uses Ractor on Ruby 3.0. It will be solved in
360
+ # Ruby 3.1.
361
+ #
362
+ # This is implemented by setting the `:ractor` attribute of
363
+ # the test to `true`.
364
+ #
365
+ # @param options [Hash] See {Attribute::ClassMethods#attribute}
366
+ # for details.
367
+ #
368
+ # @return [void]
369
+ #
370
+ # @example Declares that test_do_something_with_ractor uses Ractor
371
+ #
372
+ # ractor
373
+ # def test_do_something_with_ractor
374
+ # Ractor.new do
375
+ # # ...
376
+ # end
377
+ # end
378
+ #
379
+ # @since 3.4.6
380
+ def ractor(options={})
381
+ attribute(:ractor, true, options)
382
+ end
383
+
354
384
  # Defines a sub test case.
355
385
  #
356
386
  # This is a syntax sugar. The both of the following codes are
@@ -447,7 +477,7 @@ module Test
447
477
  # @private
448
478
  @@method_locations = {}
449
479
  # @private
450
- @@method_location_mutex = Mutex.new
480
+ @@method_location_mutex = Thread::Mutex.new
451
481
 
452
482
  # @private
453
483
  def method_locations
@@ -821,6 +851,9 @@ module Test
821
851
  notify("<#{signature}> was redefined",
822
852
  :backtrace => redefined_info[:backtrace])
823
853
  end
854
+ if self[:ractor] and not defined?(::Ractor)
855
+ omit("<#{signature}> requires Ractor")
856
+ end
824
857
  if @internal_data.have_test_data?
825
858
  test_method = method(@method_name)
826
859
  arity = test_method.arity
@@ -77,7 +77,7 @@ module Test
77
77
  @tests -= tests
78
78
  end
79
79
 
80
- # Retuns the rolled up number of tests in this suite;
80
+ # Returns the rolled up number of tests in this suite;
81
81
  # i.e. if the suite contains other suites, it counts the
82
82
  # tests within those suites, not the suites themselves.
83
83
  def size
@@ -0,0 +1,47 @@
1
+ module Test
2
+ module Unit
3
+ module Util
4
+ class MemoryUsage
5
+ attr_reader :virtual
6
+ attr_reader :physical
7
+ def initialize
8
+ @virtual = nil
9
+ @physical = nil
10
+ collect_data
11
+ end
12
+
13
+ def collected?
14
+ return false if @virtual.nil?
15
+ return false if @physical.nil?
16
+ true
17
+ end
18
+
19
+ private
20
+ def collect_data
21
+ collect_data_proc
22
+ end
23
+
24
+ def collect_data_proc
25
+ status_file = "/proc/self/status"
26
+ return false unless File.exist?(status_file)
27
+
28
+ data = File.binread(status_file)
29
+ data.each_line do |line|
30
+ case line
31
+ when /\AVm(Size|RSS):\s*(\d+)\s*kB/
32
+ name = $1
33
+ value = Integer($2, 10) * 1024
34
+ case name
35
+ when "Size"
36
+ @virtual = value
37
+ when "RSS"
38
+ @physical = value
39
+ end
40
+ end
41
+ end
42
+ collected?
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -1,5 +1,5 @@
1
1
  module Test
2
2
  module Unit
3
- VERSION = "3.4.4"
3
+ VERSION = "3.4.8"
4
4
  end
5
5
  end