nio4r 2.7.1 → 2.7.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,36 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Released under the MIT License.
4
- # Copyright, 2012-2017, by Tony Arcieri.
5
- # Copyright, 2019-2023, by Samuel Williams.
6
-
7
- require "spec_helper"
8
-
9
- RSpec.describe "NIO acceptables" do
10
- shared_context "an NIO acceptable" do
11
- let(:selector) { NIO::Selector.new }
12
-
13
- it "selects for read readiness" do
14
- waiting_monitor = selector.register(unacceptable_subject, :r)
15
- ready_monitor = selector.register(acceptable_subject, :r)
16
-
17
- ready_monitors = selector.select
18
- expect(ready_monitors).to include ready_monitor
19
- expect(ready_monitors).not_to include waiting_monitor
20
- end
21
- end
22
-
23
- describe TCPServer do
24
- let :acceptable_subject do
25
- server = TCPServer.new("127.0.0.1", 0)
26
- TCPSocket.open("127.0.0.1", server.local_address.ip_port)
27
- server
28
- end
29
-
30
- let :unacceptable_subject do
31
- TCPServer.new("127.0.0.1", 0)
32
- end
33
-
34
- it_behaves_like "an NIO acceptable"
35
- end
36
- end
@@ -1,360 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Released under the MIT License.
4
- # Copyright, 2016, by Upekshe Jayasekera.
5
- # Copyright, 2016-2017, by Tony Arcieri.
6
- # Copyright, 2019-2023, by Samuel Williams.
7
- # Copyright, 2020, by Thomas Dziedzic.
8
-
9
- require "spec_helper"
10
-
11
- RSpec.describe NIO::ByteBuffer do
12
- let(:capacity) { 256 }
13
- let(:example_string) { "Testing 1 2 3..." }
14
- subject(:bytebuffer) { described_class.new(capacity) }
15
-
16
- describe "#initialize" do
17
- it "raises TypeError if given a bogus argument" do
18
- expect { described_class.new(:symbols_are_bogus) }.to raise_error(TypeError)
19
- end
20
- end
21
-
22
- describe "#clear" do
23
- it "clears the buffer" do
24
- bytebuffer << example_string
25
- bytebuffer.clear
26
-
27
- expect(bytebuffer.remaining).to eq capacity
28
- end
29
- end
30
-
31
- describe "#position" do
32
- it "defaults to zero" do
33
- expect(bytebuffer.position).to be_zero
34
- end
35
- end
36
-
37
- describe "#position=" do
38
- let(:example_position) { 42 }
39
-
40
- it "sets the buffer's position to a valid value" do
41
- expect(bytebuffer.position).to be_zero
42
- bytebuffer.position = example_position
43
- expect(bytebuffer.position).to eq example_position
44
- end
45
-
46
- it "raises ArgumentError if the specified position is less than zero" do
47
- expect { bytebuffer.position = -1 }.to raise_error(ArgumentError)
48
- end
49
-
50
- it "raises ArgumentError if the specified position exceeds the limit" do
51
- expect { bytebuffer.position = capacity + 1 }.to raise_error(ArgumentError)
52
- end
53
- end
54
-
55
- describe "#limit" do
56
- it "defaults to the buffer's capacity" do
57
- expect(bytebuffer.limit).to eq capacity
58
- end
59
- end
60
-
61
- describe "#limit=" do
62
- it "sets the buffer's limit to a valid value" do
63
- bytebuffer.flip
64
- expect(bytebuffer.limit).to be_zero
65
-
66
- new_limit = capacity / 2
67
- bytebuffer.limit = new_limit
68
- expect(bytebuffer.limit).to eq new_limit
69
- end
70
-
71
- it "preserves position and mark if they're less than the new limit" do
72
- bytebuffer << "four"
73
- bytebuffer.mark
74
- bytebuffer << "more"
75
-
76
- bytebuffer.limit = capacity / 2
77
- expect(bytebuffer.position).to eq 8
78
- bytebuffer.reset
79
- expect(bytebuffer.position).to eq 4
80
- end
81
-
82
- it "sets position to the new limit if the previous position is beyond the limit" do
83
- bytebuffer << "four"
84
- bytebuffer.limit = 2
85
- expect(bytebuffer.position).to eq 2
86
- end
87
-
88
- it "clears the mark if the new limit is before the current mark" do
89
- bytebuffer << "four"
90
- bytebuffer.mark
91
- bytebuffer.limit = 2
92
- expect { bytebuffer.reset }.to raise_error(NIO::ByteBuffer::MarkUnsetError)
93
- end
94
-
95
- it "raises ArgumentError if specified limit is less than zero" do
96
- expect { bytebuffer.limit = -1 }.to raise_error(ArgumentError)
97
- end
98
-
99
- it "raises ArgumentError if specified limit exceeds capacity" do
100
- expect { bytebuffer.limit = capacity }.not_to raise_error
101
- expect { bytebuffer.limit = capacity + 1 }.to raise_error(ArgumentError)
102
- end
103
- end
104
-
105
- describe "#capacity" do
106
- it "has the requested capacity" do
107
- expect(bytebuffer.capacity).to eq capacity
108
- end
109
- end
110
-
111
- describe "#remaining" do
112
- it "calculates the number of bytes remaining" do
113
- expect(bytebuffer.remaining).to eq capacity
114
- bytebuffer << example_string
115
- expect(bytebuffer.remaining).to eq(capacity - example_string.length)
116
- end
117
- end
118
-
119
- describe "#full?" do
120
- it "returns false when there is space remaining in the buffer" do
121
- expect(bytebuffer).not_to be_full
122
- end
123
-
124
- it "returns true when the buffer is full" do
125
- bytebuffer << "X" * capacity
126
- expect(bytebuffer).to be_full
127
- end
128
- end
129
-
130
- describe "#get" do
131
- it "reads all remaining data if no length is given" do
132
- bytebuffer << example_string
133
- bytebuffer.flip
134
-
135
- expect(bytebuffer.get).to eq example_string
136
- end
137
-
138
- it "reads zeroes from a newly initialized buffer" do
139
- expect(bytebuffer.get(capacity)).to eq("\0" * capacity)
140
- end
141
-
142
- it "advances position as data is read" do
143
- bytebuffer << "First"
144
- bytebuffer << "Second"
145
- bytebuffer << "Third"
146
- bytebuffer.flip
147
-
148
- expect(bytebuffer.position).to be_zero
149
- expect(bytebuffer.get(10)).to eq "FirstSecon"
150
- expect(bytebuffer.position).to eq 10
151
- end
152
-
153
- it "raises NIO::ByteBuffer::UnderflowError if there is not enough data in the buffer" do
154
- bytebuffer << example_string
155
- bytebuffer.flip
156
-
157
- expect { bytebuffer.get(example_string.length + 1) }.to raise_error(NIO::ByteBuffer::UnderflowError)
158
- expect(bytebuffer.get(example_string.length)).to eq example_string
159
- end
160
- end
161
-
162
- describe "#[]" do
163
- it "obtains bytes at a given index without altering position" do
164
- bytebuffer << example_string
165
- expect(bytebuffer[7]).to eq example_string.bytes[7]
166
- expect(bytebuffer.position).to eq example_string.length
167
- end
168
-
169
- it "raises ArgumentError if the index is less than zero" do
170
- expect { bytebuffer[-1] }.to raise_error(ArgumentError)
171
- end
172
-
173
- it "raises ArgumentError if the index exceeds the limit" do
174
- bytebuffer << example_string
175
- bytebuffer.flip
176
- expect(bytebuffer[bytebuffer.limit - 1]).to eq example_string.bytes.last
177
- expect { bytebuffer[bytebuffer.limit] }.to raise_error(ArgumentError)
178
- end
179
- end
180
-
181
- describe "#<<" do
182
- it "adds strings to the buffer" do
183
- bytebuffer << example_string
184
- expect(bytebuffer.position).to eq example_string.length
185
- expect(bytebuffer.limit).to eq capacity
186
- end
187
-
188
- it "raises TypeError if given a non-String type" do
189
- expect { bytebuffer << 42 }.to raise_error(TypeError)
190
- expect { bytebuffer << nil }.to raise_error(TypeError)
191
- end
192
-
193
- it "raises NIO::ByteBuffer::OverflowError if the buffer is full" do
194
- bytebuffer << "X" * (capacity - 1)
195
- expect { bytebuffer << "X" }.not_to raise_error
196
- expect { bytebuffer << "X" }.to raise_error(NIO::ByteBuffer::OverflowError)
197
- end
198
- end
199
-
200
- describe "#flip" do
201
- it "flips the bytebuffer" do
202
- bytebuffer << example_string
203
- expect(bytebuffer.position).to eql example_string.length
204
-
205
- expect(bytebuffer.flip).to eq bytebuffer
206
-
207
- expect(bytebuffer.position).to be_zero
208
- expect(bytebuffer.limit).to eq example_string.length
209
- expect(bytebuffer.get).to eq example_string
210
- end
211
-
212
- it "sets remaining to the previous position" do
213
- bytebuffer << example_string
214
- previous_position = bytebuffer.position
215
- expect(bytebuffer.remaining).to eq(capacity - previous_position)
216
- expect(bytebuffer.flip.remaining).to eq previous_position
217
- end
218
-
219
- it "sets limit to the previous position" do
220
- bytebuffer << example_string
221
- expect(bytebuffer.limit).to eql(capacity)
222
-
223
- previous_position = bytebuffer.position
224
- expect(bytebuffer.flip.limit).to eql previous_position
225
- end
226
- end
227
-
228
- describe "#rewind" do
229
- it "rewinds the buffer leaving the limit intact" do
230
- bytebuffer << example_string
231
- expect(bytebuffer.rewind).to eq bytebuffer
232
-
233
- expect(bytebuffer.position).to be_zero
234
- expect(bytebuffer.limit).to eq capacity
235
- end
236
- end
237
-
238
- describe "#mark" do
239
- it "returns self" do
240
- expect(bytebuffer.mark).to eql bytebuffer
241
- end
242
- end
243
-
244
- describe "#reset" do
245
- it "returns to a previously marked position" do
246
- bytebuffer << "First"
247
- expected_position = bytebuffer.position
248
-
249
- expect(bytebuffer.mark).to eq bytebuffer
250
- bytebuffer << "Second"
251
- expect(bytebuffer.position).not_to eq expected_position
252
- expect(bytebuffer.reset.position).to eq expected_position
253
- end
254
-
255
- it "raises NIO::ByteBuffer::MarkUnsetError unless mark has been set" do
256
- expect { bytebuffer.reset }.to raise_error(NIO::ByteBuffer::MarkUnsetError)
257
- end
258
- end
259
-
260
- describe "#compact" do
261
- let(:first_string) { "CompactMe" }
262
- let(:second_string) { "Leftover" }
263
-
264
- it "copies data from the current position to the beginning of the buffer" do
265
- bytebuffer << first_string << second_string
266
- bytebuffer.position = first_string.length
267
- bytebuffer.limit = first_string.length + second_string.length
268
- bytebuffer.compact
269
-
270
- expect(bytebuffer.position).to eq second_string.length
271
- expect(bytebuffer.limit).to eq capacity
272
- expect(bytebuffer.flip.get).to eq second_string
273
- end
274
- end
275
-
276
- describe "#each" do
277
- it "iterates over data in the buffer" do
278
- bytebuffer << example_string
279
- bytebuffer.flip
280
-
281
- bytes = []
282
- bytebuffer.each { |byte| bytes << byte }
283
- expect(bytes).to eq example_string.bytes
284
- end
285
- end
286
-
287
- describe "#inspect" do
288
- it "inspects the buffer offsets" do
289
- regex = /\A#<NIO::ByteBuffer:.*? @position=0 @limit=#{capacity} @capacity=#{capacity}>\z/
290
- expect(bytebuffer.inspect).to match(regex)
291
- end
292
- end
293
-
294
- context "I/O" do
295
- let(:addr) { "127.0.0.1" }
296
- let(:server) { TCPServer.new(addr, 0) }
297
- let(:port) { server.local_address.ip_port }
298
- let(:client) { TCPSocket.new(addr, port) }
299
- let(:peer) { server_thread.value }
300
-
301
- let(:server_thread) do
302
- server
303
-
304
- thread = Thread.new { server.accept }
305
- Thread.pass while thread.status && thread.status != "sleep"
306
-
307
- thread
308
- end
309
-
310
- before do
311
- server_thread
312
- client
313
- end
314
-
315
- after do
316
- server_thread.kill if server_thread.alive?
317
-
318
- server.close rescue nil
319
- client.close rescue nil
320
- peer.close rescue nil
321
- end
322
-
323
- describe "#read_from" do
324
- it "reads data into the buffer" do
325
- client.write(example_string)
326
- expect(bytebuffer.read_from(peer)).to eq example_string.length
327
- bytebuffer.flip
328
-
329
- expect(bytebuffer.get).to eq example_string
330
- end
331
-
332
- it "raises NIO::ByteBuffer::OverflowError if the buffer is already full" do
333
- client.write(example_string)
334
- bytebuffer << "X" * capacity
335
- expect { bytebuffer.read_from(peer) }.to raise_error(NIO::ByteBuffer::OverflowError)
336
- end
337
-
338
- it "returns 0 if no data is available" do
339
- expect(bytebuffer.read_from(peer)).to eq 0
340
- end
341
- end
342
-
343
- describe "#write_to" do
344
- it "writes data from the buffer" do
345
- bytebuffer << example_string
346
- bytebuffer.flip
347
-
348
- expect(bytebuffer.write_to(client)).to eq example_string.length
349
- client.close
350
-
351
- expect(peer.read(example_string.length)).to eq example_string
352
- end
353
-
354
- it "raises NIO::ByteBuffer::UnderflowError if the buffer is out of data" do
355
- bytebuffer.flip
356
- expect { bytebuffer.write_to(peer) }.to raise_error(NIO::ByteBuffer::UnderflowError)
357
- end
358
- end
359
- end
360
- end
@@ -1,169 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Released under the MIT License.
4
- # Copyright, 2011-2018, by Tony Arcieri.
5
- # Copyright, 2012, by Logan Bowers.
6
- # Copyright, 2015, by Tiago Cardoso.
7
- # Copyright, 2015, by Upekshe Jayasekera.
8
- # Copyright, 2018-2023, by Samuel Williams.
9
-
10
- require "spec_helper"
11
- require "socket"
12
-
13
- RSpec.describe NIO::Monitor do
14
- let(:addr) { "127.0.0.1" }
15
-
16
- let(:reader) { TCPServer.new(addr, 0) }
17
- let(:port) { reader.local_address.ip_port }
18
- let(:writer) { TCPSocket.new(addr, port) }
19
-
20
- let(:selector) { NIO::Selector.new }
21
-
22
- subject(:monitor) { selector.register(writer, :rw) }
23
- subject(:peer) { selector.register(reader, :r) }
24
-
25
- before { reader }
26
- before { writer }
27
- after { reader.close }
28
- after { writer.close }
29
- after { selector.close }
30
-
31
- describe "#interests" do
32
- it "knows its interests" do
33
- expect(peer.interests).to eq(:r)
34
- expect(monitor.interests).to eq(:rw)
35
- end
36
- end
37
-
38
- describe "#interests=" do
39
- it "can set interests to nil" do
40
- expect(monitor.interests).not_to eq(nil)
41
- monitor.interests = nil
42
- expect(monitor.interests).to eq(nil)
43
- end
44
-
45
- it "changes the interest set" do
46
- expect(monitor.interests).not_to eq(:w)
47
- monitor.interests = :w
48
- expect(monitor.interests).to eq(:w)
49
- end
50
-
51
- it "raises EOFError if interests are changed after the monitor is closed" do
52
- monitor.close
53
- expect { monitor.interests = :rw }.to raise_error(EOFError)
54
- end
55
- end
56
-
57
- describe "#add_interest" do
58
- it "sets a new interest if it isn't currently registered" do
59
- monitor.interests = :r
60
- expect(monitor.interests).to eq(:r)
61
-
62
- expect(monitor.add_interest(:w)).to eq(:rw)
63
- expect(monitor.interests).to eq(:rw)
64
- end
65
-
66
- it "acts idempotently" do
67
- monitor.interests = :r
68
- expect(monitor.interests).to eq(:r)
69
-
70
- expect(monitor.add_interest(:r)).to eq(:r)
71
- expect(monitor.interests).to eq(:r)
72
- end
73
-
74
- it "raises ArgumentError if given a bogus option" do
75
- expect { monitor.add_interest(:derp) }.to raise_error(ArgumentError)
76
- end
77
- end
78
-
79
- describe "#remove_interest" do
80
- it "removes an interest from the set" do
81
- expect(monitor.interests).to eq(:rw)
82
-
83
- expect(monitor.remove_interest(:r)).to eq(:w)
84
- expect(monitor.interests).to eq(:w)
85
- end
86
-
87
- it "can clear the last interest" do
88
- monitor.interests = :w
89
- expect(monitor.interests).to eq(:w)
90
-
91
- expect(monitor.remove_interest(:w)).to be_nil
92
- expect(monitor.interests).to be_nil
93
- end
94
-
95
- it "acts idempotently" do
96
- monitor.interests = :w
97
- expect(monitor.interests).to eq(:w)
98
-
99
- expect(monitor.remove_interest(:r)).to eq(:w)
100
- expect(monitor.interests).to eq(:w)
101
- end
102
-
103
- it "raises ArgumentError if given a bogus option" do
104
- expect { monitor.add_interest(:derp) }.to raise_error(ArgumentError)
105
- end
106
- end
107
-
108
- describe "#io" do
109
- it "knows its IO object" do
110
- expect(monitor.io).to eq(writer)
111
- end
112
- end
113
-
114
- describe "#selector" do
115
- it "knows its selector" do
116
- expect(monitor.selector).to eq(selector)
117
- end
118
- end
119
-
120
- describe "#value=" do
121
- it "stores arbitrary values" do
122
- monitor.value = 42
123
- expect(monitor.value).to eq(42)
124
- end
125
- end
126
-
127
- describe "#readiness" do
128
- it "knows what operations IO objects are ready for" do
129
- # For whatever odd reason this breaks unless we eagerly evaluate monitor
130
- reader_peer = peer
131
- writer_peer = monitor
132
-
133
- selected = selector.select(0)
134
- expect(selected).to include(writer_peer)
135
-
136
- expect(writer_peer.readiness).to eq(:w)
137
- expect(writer_peer).not_to be_readable
138
- expect(writer_peer).to be_writable
139
-
140
- writer << "testing 1 2 3"
141
-
142
- selected = selector.select(0)
143
- expect(selected).to include(reader_peer)
144
-
145
- expect(reader_peer.readiness).to eq(:r)
146
- expect(reader_peer).to be_readable
147
- expect(reader_peer).not_to be_writable
148
- end
149
- end
150
-
151
- describe "#close" do
152
- it "closes" do
153
- expect(monitor).not_to be_closed
154
- expect(selector.registered?(writer)).to be_truthy
155
-
156
- monitor.close
157
- expect(monitor).to be_closed
158
- expect(selector.registered?(writer)).to be_falsey
159
- end
160
-
161
- it "closes even if the selector has been shutdown" do
162
- expect(monitor).not_to be_closed
163
- selector.close # forces shutdown
164
- expect(monitor).not_to be_closed
165
- monitor.close
166
- expect(monitor).to be_closed
167
- end
168
- end
169
- end
@@ -1,53 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Released under the MIT License.
4
- # Copyright, 2012-2017, by Tony Arcieri.
5
- # Copyright, 2012, by Logan Bowers.
6
- # Copyright, 2017, by Gregory Longtin.
7
- # Copyright, 2023, by Samuel Williams.
8
-
9
- require "spec_helper"
10
-
11
- RSpec.describe "IO.pipe" do
12
- let(:pair) { IO.pipe }
13
-
14
- let :unreadable_subject do
15
- pair.first
16
- end
17
-
18
- let :readable_subject do
19
- pipe, peer = pair
20
- peer << "data"
21
- pipe
22
- end
23
-
24
- let :writable_subject do
25
- pair.last
26
- end
27
-
28
- let :unwritable_subject do
29
- _reader, pipe = pair
30
-
31
- # HACK: On OS X 10.8, this str must be larger than PIPE_BUF. Otherwise,
32
- # the write is atomic and select() will return writable but write()
33
- # will throw EAGAIN if there is too little space to write the string
34
- # TODO: Use FFI to lookup the platform-specific size of PIPE_BUF
35
- str = "JUNK IN THE TUBES" * 10_000
36
- cntr = 0
37
- begin
38
- pipe.write_nonblock str
39
- cntr += 1
40
- t = select [], [pipe], [], 0
41
- rescue Errno::EPIPE
42
- break
43
- rescue IO::EWOULDBLOCKWaitWritable
44
- skip "windows - can't test due to 'select' not showing correct status"
45
- break
46
- end while t && t[1].include?(pipe) && cntr < 20
47
-
48
- pipe
49
- end
50
-
51
- it_behaves_like "an NIO selectable"
52
- it_behaves_like "an NIO selectable stream"
53
- end