Skip to content

Commit 22d391d

Browse files
authored
Add spec for fiber storage. (#6896)
1 parent 2404303 commit 22d391d

File tree

2 files changed

+118
-0
lines changed

2 files changed

+118
-0
lines changed

cont.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2090,10 +2090,17 @@ fiber_storage_validate_each(VALUE key, VALUE value, VALUE _argument)
20902090
static void
20912091
fiber_storage_validate(VALUE value)
20922092
{
2093+
// nil is an allowed value and will be lazily initialized.
2094+
if (value == Qnil) return;
2095+
20932096
if (!RB_TYPE_P(value, T_HASH)) {
20942097
rb_raise(rb_eTypeError, "storage must be a hash");
20952098
}
20962099

2100+
if (RB_OBJ_FROZEN(value)) {
2101+
rb_raise(rb_eFrozenError, "storage must not be frozen");
2102+
}
2103+
20972104
rb_hash_foreach(value, fiber_storage_validate_each, Qundef);
20982105
}
20992106

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
require_relative '../../spec_helper'
2+
3+
require 'fiber'
4+
5+
describe "Fiber.new(storage:)" do
6+
ruby_version_is "3.2" do
7+
it "creates a Fiber with the given storage" do
8+
storage = {life: 42}
9+
fiber = Fiber.new(storage: storage) { Fiber.current.storage }
10+
fiber.resume.should == storage
11+
end
12+
13+
it "creates a fiber with lazily initialized storage" do
14+
fiber = Fiber.new(storage: nil) {}
15+
fiber.storage.should == {}
16+
end
17+
18+
it "creates a fiber by inheriting the storage of the parent fiber" do
19+
fiber = Fiber.new(storage: {life: 42}) do
20+
Fiber.new { Fiber.current.storage }.resume
21+
end
22+
fiber.resume.should == {life: 42}
23+
end
24+
25+
it "creates a fiber with a reference to the storage of the parent fiber" do
26+
fiber = Fiber.new(storage: {life: 42}) do
27+
Fiber.new(storage: false) { Fiber[:life] = 43 }.resume
28+
Fiber.current.storage
29+
end
30+
fiber.resume.should == {life: 43}
31+
end
32+
33+
it "cannot create a fiber with non-hash storage" do
34+
-> { Fiber.new(storage: 42) {} }.should raise_error(TypeError)
35+
end
36+
end
37+
end
38+
39+
describe "Fiber#storage" do
40+
ruby_version_is "3.2" do
41+
it "can clear the storage of the fiber" do
42+
fiber = Fiber.new(storage: {life: 42}) { Fiber.current.storage }
43+
fiber.storage = nil
44+
fiber.resume.should == {}
45+
end
46+
47+
it "can set the storage of the fiber" do
48+
fiber = Fiber.new(storage: {life: 42}) { Fiber.current.storage }
49+
fiber.storage = {life: 43}
50+
fiber.resume.should == {life: 43}
51+
end
52+
53+
it "can't set the storage of the fiber to non-hash" do
54+
fiber = Fiber.new(storage: {life: 42}) { Fiber.current.storage }
55+
-> { fiber.storage = 42 }.should raise_error(TypeError)
56+
end
57+
58+
it "can't set the storage of the fiber to a frozen hash" do
59+
fiber = Fiber.new(storage: {life: 42}) { Fiber.current.storage }
60+
-> { fiber.storage = {life: 43}.freeze }.should raise_error(FrozenError)
61+
end
62+
63+
it "can't set the storage of the fiber to a hash with non-symbol keys" do
64+
fiber = Fiber.new(storage: {life: 42}) { Fiber.current.storage }
65+
-> { fiber.storage = {life: 43, Object.new => 44} }.should raise_error(TypeError)
66+
end
67+
end
68+
end
69+
70+
describe "Fiber.[]" do
71+
ruby_version_is "3.2" do
72+
it "returns the value of the given key in the storage of the current fiber" do
73+
Fiber.new(storage: {life: 42}) { Fiber[:life] }.resume.should == 42
74+
end
75+
76+
it "returns nil if the key is not present in the storage of the current fiber" do
77+
Fiber.new(storage: {life: 42}) { Fiber[:death] }.resume.should be_nil
78+
end
79+
80+
it "returns nil if the current fiber has no storage" do
81+
Fiber.new { Fiber[:life] }.resume.should be_nil
82+
end
83+
end
84+
end
85+
86+
describe "Fiber.[]=" do
87+
ruby_version_is "3.2" do
88+
it "sets the value of the given key in the storage of the current fiber" do
89+
Fiber.new(storage: {life: 42}) { Fiber[:life] = 43; Fiber[:life] }.resume.should == 43
90+
end
91+
92+
it "sets the value of the given key in the storage of the current fiber" do
93+
Fiber.new(storage: {life: 42}) { Fiber[:death] = 43; Fiber[:death] }.resume.should == 43
94+
end
95+
96+
it "sets the value of the given key in the storage of the current fiber" do
97+
Fiber.new { Fiber[:life] = 43; Fiber[:life] }.resume.should == 43
98+
end
99+
end
100+
end
101+
102+
describe "Thread.new" do
103+
ruby_version_is "3.2" do
104+
it "creates a thread with the storage of the current fiber" do
105+
fiber = Fiber.new(storage: {life: 42}) do
106+
Thread.new { Fiber.current.storage }.value
107+
end
108+
fiber.resume.should == {life: 42}
109+
end
110+
end
111+
end

0 commit comments

Comments
 (0)