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 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
|
require_relative '../../spec_helper'
ruby_version_is "3.2" do
describe "Fiber.new(storage:)" do
it "creates a Fiber with the given storage" do
storage = {life: 42}
fiber = Fiber.new(storage: storage) { Fiber.current.storage }
fiber.resume.should == storage
end
it "creates a fiber with lazily initialized storage" do
Fiber.new(storage: nil) { Fiber[:x] = 10; Fiber.current.storage }.resume.should == {x: 10}
end
it "creates a fiber by inheriting the storage of the parent fiber" do
fiber = Fiber.new(storage: {life: 42}) do
Fiber.new { Fiber.current.storage }.resume
end
fiber.resume.should == {life: 42}
end
it "cannot create a fiber with non-hash storage" do
-> { Fiber.new(storage: 42) {} }.should raise_error(TypeError)
end
it "cannot create a fiber with a frozen hash as storage" do
-> { Fiber.new(storage: {life: 43}.freeze) {} }.should raise_error(FrozenError)
end
it "cannot create a fiber with a storage hash with non-symbol keys" do
-> { Fiber.new(storage: {life: 43, Object.new => 44}) {} }.should raise_error(TypeError)
end
end
describe "Fiber#storage" do
it "cannot be accessed from a different fiber" do
f = Fiber.new(storage: {life: 42}) { nil }
-> {
f.storage
}.should raise_error(ArgumentError, /Fiber storage can only be accessed from the Fiber it belongs to/)
end
end
describe "Fiber#storage=" do
it "can clear the storage of the fiber" do
fiber = Fiber.new(storage: {life: 42}) do
Fiber.current.storage = nil
Fiber[:x] = 10
Fiber.current.storage
end
fiber.resume.should == {x: 10}
end
it "can set the storage of the fiber" do
fiber = Fiber.new(storage: {life: 42}) do
Fiber.current.storage = {life: 43}
Fiber.current.storage
end
fiber.resume.should == {life: 43}
end
it "can't set the storage of the fiber to non-hash" do
-> { Fiber.current.storage = 42 }.should raise_error(TypeError)
end
it "can't set the storage of the fiber to a frozen hash" do
-> { Fiber.current.storage = {life: 43}.freeze }.should raise_error(FrozenError)
end
it "can't set the storage of the fiber to a hash with non-symbol keys" do
-> { Fiber.current.storage = {life: 43, Object.new => 44} }.should raise_error(TypeError)
end
end
describe "Fiber.[]" do
it "returns the value of the given key in the storage of the current fiber" do
Fiber.new(storage: {life: 42}) { Fiber[:life] }.resume.should == 42
end
it "returns nil if the key is not present in the storage of the current fiber" do
Fiber.new(storage: {life: 42}) { Fiber[:death] }.resume.should be_nil
end
it "returns nil if the current fiber has no storage" do
Fiber.new { Fiber[:life] }.resume.should be_nil
end
ruby_version_is "3.2.3" do
it "can use dynamically defined keys" do
key = :"#{self.class.name}#.#{self.object_id}"
Fiber.new { Fiber[key] = 42; Fiber[key] }.resume.should == 42
end
it "can't use invalid keys" do
invalid_keys = [Object.new, "Foo", 12]
invalid_keys.each do |key|
-> { Fiber[key] }.should raise_error(TypeError)
end
end
end
it "can access the storage of the parent fiber" do
f = Fiber.new(storage: {life: 42}) do
Fiber.new { Fiber[:life] }.resume
end
f.resume.should == 42
end
it "can't access the storage of the fiber with non-symbol keys" do
-> { Fiber[Object.new] }.should raise_error(TypeError)
end
end
describe "Fiber.[]=" do
it "sets the value of the given key in the storage of the current fiber" do
Fiber.new(storage: {life: 42}) { Fiber[:life] = 43; Fiber[:life] }.resume.should == 43
end
it "sets the value of the given key in the storage of the current fiber" do
Fiber.new(storage: {life: 42}) { Fiber[:death] = 43; Fiber[:death] }.resume.should == 43
end
it "sets the value of the given key in the storage of the current fiber" do
Fiber.new { Fiber[:life] = 43; Fiber[:life] }.resume.should == 43
end
it "does not overwrite the storage of the parent fiber" do
f = Fiber.new(storage: {life: 42}) do
Fiber.yield Fiber.new { Fiber[:life] = 43; Fiber[:life] }.resume
Fiber[:life]
end
f.resume.should == 43 # Value of the inner fiber
f.resume.should == 42 # Value of the outer fiber
end
it "can't access the storage of the fiber with non-symbol keys" do
-> { Fiber[Object.new] = 44 }.should raise_error(TypeError)
end
ruby_version_is "3.3" do
it "deletes the fiber storage key when assigning nil" do
Fiber.new(storage: {life: 42}) {
Fiber[:life] = nil
Fiber.current.storage
}.resume.should == {}
end
end
end
describe "Thread.new" do
it "creates a thread with the storage of the current fiber" do
fiber = Fiber.new(storage: {life: 42}) do
Thread.new { Fiber.current.storage }.value
end
fiber.resume.should == {life: 42}
end
end
end
|