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
|
describe :sizedqueue_enq, shared: true do
it "blocks if queued elements exceed size" do
q = @object.call(1)
q.size.should == 0
q.send(@method, :first_element)
q.size.should == 1
blocked_thread = Thread.new { q.send(@method, :second_element) }
sleep 0.01 until blocked_thread.stop?
q.size.should == 1
q.pop.should == :first_element
blocked_thread.join
q.size.should == 1
q.pop.should == :second_element
q.size.should == 0
end
it "raises a ThreadError if queued elements exceed size when not blocking" do
q = @object.call(2)
non_blocking = true
add_to_queue = -> { q.send(@method, Object.new, non_blocking) }
q.size.should == 0
add_to_queue.call
q.size.should == 1
add_to_queue.call
q.size.should == 2
add_to_queue.should raise_error(ThreadError)
end
it "interrupts enqueuing threads with ClosedQueueError when the queue is closed" do
q = @object.call(1)
q << 1
t = Thread.new {
-> { q.send(@method, 2) }.should raise_error(ClosedQueueError, "queue closed")
}
Thread.pass until q.num_waiting == 1
q.close
t.join
q.pop.should == 1
end
describe "with a timeout" do
ruby_version_is "3.2" do
it "returns self if the item was pushed in time" do
q = @object.call(1)
q << 1
t = Thread.new {
q.send(@method, 2, timeout: 1).should == q
}
Thread.pass until t.status == "sleep" && q.num_waiting == 1
q.pop
t.join
end
it "does nothing if the timeout is nil" do
q = @object.call(1)
q << 1
t = Thread.new {
q.send(@method, 2, timeout: nil).should == q
}
t.join(0.2).should == nil
q.pop
t.join
end
it "returns nil if no space is avialable and timeout is 0" do
q = @object.call(1)
q.send(@method, 1, timeout: 0).should == q
q.send(@method, 2, timeout: 0).should == nil
end
it "returns nil if no space is available in time" do
q = @object.call(1)
q << 1
t = Thread.new {
q.send(@method, 2, timeout: 0.1).should == nil
}
t.join
end
it "raise TypeError if timeout is not a valid numeric" do
q = @object.call(1)
-> { q.send(@method, 2, timeout: "1") }.should raise_error(
TypeError,
"no implicit conversion to float from string",
)
-> { q.send(@method, 2, timeout: false) }.should raise_error(
TypeError,
"no implicit conversion to float from false",
)
end
it "raise ArgumentError if non_block = true is passed too" do
q = @object.call(1)
-> { q.send(@method, 2, true, timeout: 1) }.should raise_error(
ArgumentError,
"can't set a timeout if non_block is enabled",
)
end
it "raise ClosedQueueError when closed before enqueued" do
q = @object.call(1)
q.close
-> { q.send(@method, 2, timeout: 1) }.should raise_error(ClosedQueueError, "queue closed")
end
it "interrupts enqueuing threads with ClosedQueueError when the queue is closed" do
q = @object.call(1)
q << 1
t = Thread.new {
-> { q.send(@method, 1, timeout: 0.1) }.should raise_error(ClosedQueueError, "queue closed")
}
Thread.pass until q.num_waiting == 1
q.close
t.join
q.pop.should == 1
end
end
end
end
|