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
|