File: ractor_extra_test.rb

package info (click to toggle)
ruby-backports 3.25.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 4,912 kB
  • sloc: ruby: 11,757; makefile: 6
file content (113 lines) | stat: -rw-r--r-- 3,331 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
require './test/test_helper'
require 'backports/3.0.0/ractor.rb'

def thread_eval
  r = nil
  Thread.new { r = yield }.join
  r
end

def storage_change(to, key: :foo)
  current = Ractor.current[key]
  Ractor.current[key] = to
  {current => Ractor.current[key]}
end

class ExtraRactorTest < Test::Unit::TestCase
  def assert_shareable(*objects)
    check_shareability(objects, true)
  end

  def assert_not_shareable(*objects, &block)
    check_shareability(objects, false)
  end

  def check_shareability(objects, shareable)
    objects.each do |obj|
      assert_equal shareable, obj.object_id == Ractor.new(obj, &:object_id).take
      assert_equal shareable, obj.object_id == Ractor.new([obj]) { |x, | x.object_id }.take
      assert_equal obj.frozen?, Ractor.new(obj, &:frozen?).take
      assert_equal obj.frozen?, Ractor.new([obj]) { |x, | x.frozen? } .take
      assert_equal shareable, Ractor.shareable?(obj)
    end
  end

  def test_copy_only_copies_when_needed
    r = Ractor.new {}
    assert_shareable(r, 42, 4.2, 2..4, false, true, nil, 'abc'.freeze)

    assert_not_shareable('abc'.dup, [], {})

    a = []; b = [a].freeze; c = [a].freeze; a << c
    assert_not_shareable(a, b, c)

    a.freeze
    assert_shareable(a, b, c)

    h = {a: 1, b: 2}
    assert_not_shareable(h)
    assert_shareable(h.freeze)

    h = {a: [1, 2, 3], b: 2}
    assert_not_shareable(h)
    assert_not_shareable(h.freeze)
    h[:a].freeze
    assert_shareable(h)
  end

  def make_shareable_fail
    o = Object.new
    def o.freeze; self; end
    assert_raise(Ractor::Error) { Ractor.make_shareable(o) }
  end

  def test_main
    assert_same(Ractor.current, Ractor.main)
    assert_same(Ractor.current, thread_eval { Ractor.main })
    assert_same(thread_eval{ Ractor.current }, Ractor.main)

    r = Ractor.new do
      [ Ractor.main, thread_eval{ Ractor.main },
        Ractor.current, thread_eval{ Ractor.current }]
    end
    main, main2, current, current2 = r.take
    assert_same(r, current)
    assert_same(r, current2)
    assert_same(main, Ractor.main)
    assert_same(main2, Ractor.main)
  end

  def assert_storage(to, from: nil, key: :foo)
    assert_equal from, Ractor.current[key]
    Ractor.current[key] = to
    assert_equal to, Ractor.current[key]
  end

  def test_local_storage
    assert_equal({nil => :first}, storage_change(:first))
    ractor = Ractor.new {
      [storage_change(:in_ractor), thread_eval { storage_change(:in_ractor_thread) }]
    }
    a, b = ractor.take
    assert_equal({nil => :in_ractor}, a)
    assert_equal({in_ractor: :in_ractor_thread}, b)

    assert_equal({first: :in_thread}, thread_eval { storage_change(:in_thread) })
    assert_equal({nil => :different}, storage_change(:different, key: :other))
    assert_equal(:in_thread, Ractor.current[:foo])
    assert_equal(:in_thread, ractor[:foo])
  end

  def test_name
    #<Ractor:#2 (irb):1 blocking>
    assert_match(/#<Ractor:#\d+ #{__FILE__}:#{__LINE__} (blocking|running)>/, ::Ractor.new{ sleep(0.01) }.inspect)
    assert_equal('Ractor', ::Ractor.name)
  end

  def test_namespaced_include
    cmd = "#{RbConfig.ruby} -rbackports/ractor/ractor -e 'p [defined?(Ractor), Backports::Ractor.new { 42 }.take]'"
    puts cmd
    r = `#{cmd}`.chomp
    assert_equal '[nil, 42]', r
  end if RUBY_VERSION < '3' && RUBY_VERSION >= '2.3'
end