uringmachine 0.29.2 → 0.31.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +18 -4
- data/README.md +46 -38
- data/TODO.md +68 -75
- data/benchmark/bm_io_ssl.rb +128 -0
- data/benchmark/bm_redis_client.rb +76 -0
- data/benchmark/common.rb +1 -0
- data/benchmark/gets.rb +7 -7
- data/benchmark/gets_concurrent.rb +10 -10
- data/benchmark/http_parse.rb +15 -15
- data/benchmark/http_server_accept_queue.rb +11 -7
- data/benchmark/http_server_multi_accept.rb +7 -7
- data/benchmark/http_server_multi_ractor.rb +7 -7
- data/benchmark/http_server_single_thread.rb +7 -7
- data/benchmark/openssl.rb +50 -22
- data/docs/design/buffer_pool.md +1 -1
- data/examples/fiber_concurrency_io.rb +52 -0
- data/examples/fiber_concurrency_naive.rb +26 -0
- data/examples/fiber_concurrency_runqueue.rb +33 -0
- data/examples/io_uring_simple.c +24 -0
- data/examples/pg.rb +2 -2
- data/examples/stream.rb +2 -2
- data/ext/um/um.c +71 -3
- data/ext/um/um.h +34 -22
- data/ext/um/um_buffer_pool.c +11 -11
- data/ext/um/um_class.c +57 -0
- data/ext/um/um_connection.c +775 -0
- data/ext/um/um_connection_class.c +394 -0
- data/ext/um/um_ssl.c +43 -7
- data/ext/um/um_utils.c +1 -1
- data/grant-2025/final-report.md +269 -0
- data/grant-2025/journal.md +1 -1
- data/lib/uringmachine/version.rb +1 -1
- data/lib/uringmachine.rb +47 -6
- data/test/{test_stream.rb → test_connection.rb} +321 -151
- data/test/test_ssl.rb +27 -0
- data/test/test_um.rb +174 -17
- metadata +13 -6
- data/ext/um/um_stream.c +0 -674
- data/ext/um/um_stream_class.c +0 -303
|
@@ -5,24 +5,24 @@ require 'securerandom'
|
|
|
5
5
|
require 'openssl'
|
|
6
6
|
require 'localhost/authority'
|
|
7
7
|
|
|
8
|
-
class
|
|
9
|
-
attr_reader :
|
|
8
|
+
class ConnectionBaseTest < UMBaseTest
|
|
9
|
+
attr_reader :conn
|
|
10
10
|
|
|
11
11
|
def setup
|
|
12
12
|
super
|
|
13
13
|
@rfd, @wfd = UM.pipe
|
|
14
|
-
@
|
|
14
|
+
@conn = UM::Connection.new(@machine, @rfd)
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
def teardown
|
|
18
|
-
@
|
|
18
|
+
@conn = nil
|
|
19
19
|
machine.close(@rfd) rescue nil
|
|
20
20
|
machine.close(@wfd) rescue nil
|
|
21
21
|
super
|
|
22
22
|
end
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
-
class
|
|
25
|
+
class ConnectionTest < ConnectionBaseTest
|
|
26
26
|
def buffer_metrics
|
|
27
27
|
machine.metrics.fetch_values(
|
|
28
28
|
:buffers_allocated,
|
|
@@ -33,19 +33,19 @@ class StreamTest < StreamBaseTest
|
|
|
33
33
|
)
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
-
def
|
|
36
|
+
def test_connection_basic_usage
|
|
37
37
|
assert_equal [0, 0, 0, 0, 0], buffer_metrics
|
|
38
38
|
machine.write(@wfd, "foobar")
|
|
39
39
|
machine.close(@wfd)
|
|
40
40
|
|
|
41
|
-
buf =
|
|
41
|
+
buf = conn.read(3)
|
|
42
42
|
assert_equal 'foo', buf
|
|
43
43
|
|
|
44
|
-
buf =
|
|
44
|
+
buf = conn.read(-6)
|
|
45
45
|
assert_equal 'bar', buf
|
|
46
|
-
assert
|
|
46
|
+
assert conn.eof?
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
conn.clear
|
|
49
49
|
|
|
50
50
|
# initial buffer size: 6BKV, initial buffers commited: 16 (256KB)
|
|
51
51
|
# (plus an additional buffer commited after first usage)
|
|
@@ -53,20 +53,20 @@ class StreamTest < StreamBaseTest
|
|
|
53
53
|
assert_equal 0, machine.metrics[:ops_pending]
|
|
54
54
|
end
|
|
55
55
|
|
|
56
|
-
def
|
|
56
|
+
def test_connection_clear
|
|
57
57
|
rfd, wfd = UM.pipe
|
|
58
|
-
|
|
58
|
+
conn = UM::Connection.new(machine, rfd)
|
|
59
59
|
|
|
60
60
|
assert_equal [0, 0, 0, 0, 0], buffer_metrics
|
|
61
61
|
machine.write(wfd, "foobar")
|
|
62
62
|
|
|
63
|
-
buf =
|
|
63
|
+
buf = conn.read(3)
|
|
64
64
|
assert_equal 'foo', buf
|
|
65
65
|
|
|
66
66
|
assert_equal 1, machine.metrics[:ops_pending]
|
|
67
67
|
assert_equal 255, machine.metrics[:segments_free]
|
|
68
68
|
|
|
69
|
-
|
|
69
|
+
conn.clear
|
|
70
70
|
machine.snooze
|
|
71
71
|
assert_equal 0, machine.metrics[:ops_pending]
|
|
72
72
|
assert_equal 256, machine.metrics[:segments_free]
|
|
@@ -77,9 +77,9 @@ class StreamTest < StreamBaseTest
|
|
|
77
77
|
machine.close(wfd) rescue nil
|
|
78
78
|
end
|
|
79
79
|
|
|
80
|
-
def
|
|
80
|
+
def test_connection_big_read
|
|
81
81
|
s1, s2 = UM.socketpair(UM::AF_UNIX, UM::SOCK_STREAM, 0)
|
|
82
|
-
|
|
82
|
+
conn = UM::Connection.new(machine, s2)
|
|
83
83
|
|
|
84
84
|
msg = '1234567' * 20000
|
|
85
85
|
|
|
@@ -89,16 +89,16 @@ class StreamTest < StreamBaseTest
|
|
|
89
89
|
machine.shutdown(s1, UM::SHUT_WR)
|
|
90
90
|
end
|
|
91
91
|
|
|
92
|
-
buf =
|
|
92
|
+
buf = conn.read(msg.bytesize)
|
|
93
93
|
assert_equal msg, buf
|
|
94
94
|
ensure
|
|
95
95
|
machine.terminate(f)
|
|
96
96
|
machine.join(f)
|
|
97
97
|
end
|
|
98
98
|
|
|
99
|
-
def
|
|
99
|
+
def test_connection_buffer_reuse
|
|
100
100
|
s1, s2 = UM.socketpair(UM::AF_UNIX, UM::SOCK_STREAM, 0)
|
|
101
|
-
|
|
101
|
+
conn = UM::Connection.new(machine, s2)
|
|
102
102
|
|
|
103
103
|
msg = '1234567' * 20000
|
|
104
104
|
|
|
@@ -109,19 +109,19 @@ class StreamTest < StreamBaseTest
|
|
|
109
109
|
machine.shutdown(s1, UM::SHUT_WR)
|
|
110
110
|
end
|
|
111
111
|
|
|
112
|
-
buf =
|
|
112
|
+
buf = conn.read(msg.bytesize)
|
|
113
113
|
assert_equal msg, buf
|
|
114
114
|
|
|
115
|
-
buf =
|
|
115
|
+
buf = conn.read(msg.bytesize)
|
|
116
116
|
assert_equal msg, buf
|
|
117
117
|
|
|
118
|
-
buf =
|
|
118
|
+
buf = conn.read(msg.bytesize)
|
|
119
119
|
assert_equal msg, buf
|
|
120
120
|
|
|
121
|
-
buf =
|
|
121
|
+
buf = conn.read(msg.bytesize)
|
|
122
122
|
assert_equal msg, buf
|
|
123
123
|
|
|
124
|
-
|
|
124
|
+
conn.clear
|
|
125
125
|
# numbers may vary with different kernel versions
|
|
126
126
|
assert_in_range 24..32, machine.metrics[:buffers_allocated]
|
|
127
127
|
assert_in_range 10..18, machine.metrics[:buffers_free]
|
|
@@ -131,23 +131,23 @@ class StreamTest < StreamBaseTest
|
|
|
131
131
|
machine.join(f)
|
|
132
132
|
end
|
|
133
133
|
|
|
134
|
-
def
|
|
134
|
+
def test_connection_read_line
|
|
135
135
|
machine.write(@wfd, "foo\nbar\r\nbaz")
|
|
136
136
|
machine.close(@wfd)
|
|
137
137
|
|
|
138
138
|
assert_equal [0, 0, 0, 0, 0], buffer_metrics
|
|
139
139
|
|
|
140
|
-
assert_equal 'foo',
|
|
140
|
+
assert_equal 'foo', conn.read_line(0)
|
|
141
141
|
|
|
142
142
|
assert_equal [16, 0, 255, 16384 * 16, 16384 * 16 - 12], buffer_metrics
|
|
143
|
-
assert_equal 'bar',
|
|
144
|
-
assert_nil
|
|
145
|
-
assert_equal "baz",
|
|
143
|
+
assert_equal 'bar', conn.read_line(0)
|
|
144
|
+
assert_nil conn.read_line(0)
|
|
145
|
+
assert_equal "baz", conn.read(-6)
|
|
146
146
|
end
|
|
147
147
|
|
|
148
|
-
def
|
|
148
|
+
def test_connection_read_line_segmented
|
|
149
149
|
machine.write(@wfd, "foo\n")
|
|
150
|
-
assert_equal 'foo',
|
|
150
|
+
assert_equal 'foo', conn.read_line(0)
|
|
151
151
|
|
|
152
152
|
machine.write(@wfd, "bar")
|
|
153
153
|
machine.write(@wfd, "\r\n")
|
|
@@ -156,19 +156,19 @@ class StreamTest < StreamBaseTest
|
|
|
156
156
|
|
|
157
157
|
# three segments received
|
|
158
158
|
assert_equal [16, 0, 253, 16384 * 16, 16384 * 16 - 13], buffer_metrics
|
|
159
|
-
assert_equal 'bar',
|
|
159
|
+
assert_equal 'bar', conn.read_line(0)
|
|
160
160
|
assert_equal [16, 0, 255, 16384 * 16, 16384 * 16 - 13], buffer_metrics
|
|
161
|
-
assert_equal 'baz',
|
|
161
|
+
assert_equal 'baz', conn.read_line(0)
|
|
162
162
|
assert_equal [16, 0, 256, 16384 * 16, 16384 * 16 - 13], buffer_metrics
|
|
163
|
-
assert_nil
|
|
163
|
+
assert_nil conn.read_line(0)
|
|
164
164
|
end
|
|
165
165
|
|
|
166
|
-
def
|
|
166
|
+
def test_connection_read_line_maxlen
|
|
167
167
|
machine.write(@wfd, "foobar\r\n")
|
|
168
168
|
|
|
169
|
-
assert_nil
|
|
170
|
-
# verify that
|
|
171
|
-
assert_equal 'foobar',
|
|
169
|
+
assert_nil conn.read_line(3)
|
|
170
|
+
# verify that connecvtion pos has not changed
|
|
171
|
+
assert_equal 'foobar', conn.read_line(0)
|
|
172
172
|
|
|
173
173
|
machine.write(@wfd, "baz")
|
|
174
174
|
machine.write(@wfd, "\n")
|
|
@@ -176,62 +176,83 @@ class StreamTest < StreamBaseTest
|
|
|
176
176
|
machine.write(@wfd, "\n")
|
|
177
177
|
machine.close(@wfd)
|
|
178
178
|
|
|
179
|
-
assert_nil
|
|
180
|
-
assert_nil
|
|
181
|
-
assert_equal 'baz',
|
|
179
|
+
assert_nil conn.read_line(2)
|
|
180
|
+
assert_nil conn.read_line(3)
|
|
181
|
+
assert_equal 'baz', conn.read_line(4)
|
|
182
182
|
|
|
183
|
-
assert_nil
|
|
184
|
-
assert_nil
|
|
185
|
-
assert_equal 'bizz',
|
|
183
|
+
assert_nil conn.read_line(3)
|
|
184
|
+
assert_nil conn.read_line(4)
|
|
185
|
+
assert_equal 'bizz', conn.read_line(5)
|
|
186
186
|
|
|
187
|
-
assert_nil
|
|
187
|
+
assert_nil conn.read_line(8)
|
|
188
188
|
assert_equal [16, 0, 256, 16384 * 16, 16384 * 16 - 17], buffer_metrics
|
|
189
189
|
end
|
|
190
190
|
|
|
191
|
-
def
|
|
191
|
+
def test_connection_read
|
|
192
192
|
machine.write(@wfd, "foobarbazblahzzz")
|
|
193
193
|
machine.close(@wfd)
|
|
194
194
|
|
|
195
|
-
assert_equal 'foobar',
|
|
196
|
-
assert_equal 'baz',
|
|
197
|
-
assert_equal 'blah',
|
|
198
|
-
assert_nil
|
|
195
|
+
assert_equal 'foobar', conn.read(6)
|
|
196
|
+
assert_equal 'baz', conn.read(3)
|
|
197
|
+
assert_equal 'blah', conn.read(4)
|
|
198
|
+
assert_nil conn.read(4)
|
|
199
199
|
end
|
|
200
200
|
|
|
201
|
-
def
|
|
201
|
+
def test_connection_read_zero_len
|
|
202
202
|
machine.write(@wfd, "foobar")
|
|
203
203
|
|
|
204
|
-
assert_equal 'foobar',
|
|
204
|
+
assert_equal 'foobar', conn.read(0)
|
|
205
205
|
|
|
206
206
|
machine.write(@wfd, "bazblah")
|
|
207
207
|
machine.close(@wfd)
|
|
208
|
-
assert_equal 'bazblah',
|
|
209
|
-
assert_nil
|
|
208
|
+
assert_equal 'bazblah', conn.read(0)
|
|
209
|
+
assert_nil conn.read(0)
|
|
210
210
|
end
|
|
211
211
|
|
|
212
|
-
def
|
|
212
|
+
def test_connection_read_negative_len
|
|
213
213
|
machine.write(@wfd, "foobar")
|
|
214
214
|
|
|
215
|
-
assert_equal 'foo',
|
|
216
|
-
assert_equal 'bar',
|
|
215
|
+
assert_equal 'foo', conn.read(-3)
|
|
216
|
+
assert_equal 'bar', conn.read(-6)
|
|
217
217
|
|
|
218
218
|
machine.write(@wfd, "bazblah")
|
|
219
219
|
machine.close(@wfd)
|
|
220
|
-
assert_equal 'bazblah',
|
|
221
|
-
assert_nil
|
|
220
|
+
assert_equal 'bazblah', conn.read(-12)
|
|
221
|
+
assert_nil conn.read(-3)
|
|
222
222
|
end
|
|
223
223
|
|
|
224
|
-
def
|
|
224
|
+
def test_connection_read_to_delim
|
|
225
|
+
machine.write(@wfd, "abc,def,ghi")
|
|
226
|
+
machine.close(@wfd)
|
|
227
|
+
|
|
228
|
+
assert_nil conn.read_to_delim('!', 0) # not there
|
|
229
|
+
assert_nil conn.read_to_delim(',', 2) # too long
|
|
230
|
+
assert_equal 'abc', conn.read_to_delim(',', 0)
|
|
231
|
+
assert_equal 'def', conn.read_to_delim(',', 0)
|
|
232
|
+
assert_nil conn.read_to_delim(',', 0)
|
|
233
|
+
assert_equal 'ghi', conn.read_to_delim(',', -3)
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
def test_connection_read_to_delim_invalid_delim
|
|
237
|
+
machine.write(@wfd, "abc,def,ghi")
|
|
238
|
+
|
|
239
|
+
assert_raises(ArgumentError) { conn.read_to_delim(:foo, 0) }
|
|
240
|
+
assert_raises(UM::Error) { conn.read_to_delim('', 0) }
|
|
241
|
+
assert_raises(UM::Error) { conn.read_to_delim('ab', 0) }
|
|
242
|
+
assert_raises(UM::Error) { conn.read_to_delim('🙂', 0) }
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
def test_connection_skip
|
|
225
246
|
machine.write(@wfd, "foobarbaz")
|
|
226
247
|
|
|
227
|
-
|
|
228
|
-
assert_equal 'obar',
|
|
248
|
+
conn.skip(2)
|
|
249
|
+
assert_equal 'obar', conn.read(4)
|
|
229
250
|
|
|
230
|
-
|
|
231
|
-
assert_equal 'az',
|
|
251
|
+
conn.skip(1)
|
|
252
|
+
assert_equal 'az', conn.read(0)
|
|
232
253
|
end
|
|
233
254
|
|
|
234
|
-
def
|
|
255
|
+
def test_connection_big_data
|
|
235
256
|
data = SecureRandom.random_bytes(300_000)
|
|
236
257
|
fiber = machine.spin {
|
|
237
258
|
machine.writev(@wfd, data)
|
|
@@ -240,7 +261,7 @@ class StreamTest < StreamBaseTest
|
|
|
240
261
|
|
|
241
262
|
received = []
|
|
242
263
|
loop {
|
|
243
|
-
msg =
|
|
264
|
+
msg = conn.read(-60_000)
|
|
244
265
|
break if !msg
|
|
245
266
|
|
|
246
267
|
received << msg
|
|
@@ -251,89 +272,225 @@ class StreamTest < StreamBaseTest
|
|
|
251
272
|
assert_equal 9, received.size
|
|
252
273
|
assert_equal data, received.join
|
|
253
274
|
end
|
|
275
|
+
|
|
276
|
+
def test_connection_read_each
|
|
277
|
+
bufs = []
|
|
278
|
+
f = machine.spin do
|
|
279
|
+
bufs << :ready
|
|
280
|
+
conn.read_each {
|
|
281
|
+
assert_kind_of IO::Buffer, it
|
|
282
|
+
bufs << it.get_string
|
|
283
|
+
}
|
|
284
|
+
bufs << :done
|
|
285
|
+
rescue => e
|
|
286
|
+
p e
|
|
287
|
+
p e.backtrace
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
machine.snooze
|
|
291
|
+
assert_equal [:ready], bufs
|
|
292
|
+
|
|
293
|
+
machine.write(@wfd, 'foo')
|
|
294
|
+
machine.snooze
|
|
295
|
+
assert_equal [:ready, 'foo'], bufs
|
|
296
|
+
|
|
297
|
+
machine.write(@wfd, 'barb')
|
|
298
|
+
machine.snooze
|
|
299
|
+
assert_equal [:ready, 'foo', 'barb'], bufs
|
|
300
|
+
|
|
301
|
+
machine.close(@wfd)
|
|
302
|
+
machine.snooze
|
|
303
|
+
assert_equal [:ready, 'foo', 'barb', :done], bufs
|
|
304
|
+
ensure
|
|
305
|
+
machine.terminate(f)
|
|
306
|
+
machine.join(f)
|
|
307
|
+
end
|
|
254
308
|
end
|
|
255
309
|
|
|
256
|
-
class
|
|
257
|
-
|
|
310
|
+
class ConnectionWriteTest < UMBaseTest
|
|
311
|
+
attr_reader :conn
|
|
312
|
+
|
|
313
|
+
def setup
|
|
314
|
+
super
|
|
315
|
+
@s1, @s2 = UM.socketpair(UM::AF_UNIX, UM::SOCK_STREAM, 0)
|
|
316
|
+
@conn = UM::Connection.new(@machine, @s1)
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
def teardown
|
|
320
|
+
@conn = nil
|
|
321
|
+
machine.close(@s1) rescue nil
|
|
322
|
+
machine.close(@s2) rescue nil
|
|
323
|
+
super
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
def test_connection_write_single_buf
|
|
327
|
+
assert_equal 3, conn.write('foo')
|
|
328
|
+
|
|
329
|
+
buf = +''
|
|
330
|
+
machine.read(@s2, buf, 100)
|
|
331
|
+
assert_equal 'foo', buf
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
def test_connection_write_multi_buf
|
|
335
|
+
assert_equal 6, conn.write('foo', 'bar')
|
|
336
|
+
|
|
337
|
+
buf = +''
|
|
338
|
+
machine.read(@s2, buf, 100)
|
|
339
|
+
assert_equal 'foobar', buf
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
def test_connection_write_socket_mode
|
|
343
|
+
conn = machine.connection(@s2, :socket)
|
|
344
|
+
|
|
345
|
+
assert_equal 6, conn.write('foo', 'bar')
|
|
346
|
+
|
|
347
|
+
buf = +''
|
|
348
|
+
machine.read(@s1, buf, 100)
|
|
349
|
+
assert_equal 'foobar', buf
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
def test_connection_write_ssl_mode
|
|
353
|
+
ssl1 = OpenSSL::SSL::SSLSocket.new(IO.for_fd(@s1), Localhost::Authority.fetch.server_context)
|
|
354
|
+
ssl1.sync_close = true
|
|
355
|
+
ssl2 = OpenSSL::SSL::SSLSocket.new(IO.for_fd(@s2), OpenSSL::SSL::SSLContext.new)
|
|
356
|
+
ssl2.sync_close = true
|
|
357
|
+
|
|
358
|
+
machine.ssl_set_bio(ssl1)
|
|
359
|
+
machine.ssl_set_bio(ssl2)
|
|
360
|
+
|
|
361
|
+
f = machine.spin { ssl1.accept rescue nil }
|
|
362
|
+
|
|
363
|
+
ssl2.connect
|
|
364
|
+
refute_equal 0, @machine.metrics[:total_ops]
|
|
365
|
+
|
|
366
|
+
conn1 = machine.connection(ssl1)
|
|
367
|
+
conn2 = machine.connection(ssl2)
|
|
368
|
+
|
|
369
|
+
assert_equal 10, conn1.write('foobar', "\n", 'baz')
|
|
370
|
+
|
|
371
|
+
assert_equal "foobar\nbaz", conn2.read(10)
|
|
372
|
+
ensure
|
|
373
|
+
ssl1.close rescue nil
|
|
374
|
+
ss2.close rescue nil
|
|
375
|
+
if f
|
|
376
|
+
machine.terminate(f)
|
|
377
|
+
machine.join(f)
|
|
378
|
+
end
|
|
379
|
+
end
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
class ConnectionRespTest < ConnectionBaseTest
|
|
383
|
+
def test_connection_resp_read
|
|
258
384
|
machine.write(@wfd, "+foo bar\r\n")
|
|
259
|
-
assert_equal "foo bar",
|
|
385
|
+
assert_equal "foo bar", conn.resp_read
|
|
260
386
|
|
|
261
387
|
machine.write(@wfd, "+baz\r\n")
|
|
262
|
-
assert_equal "baz",
|
|
388
|
+
assert_equal "baz", conn.resp_read
|
|
263
389
|
|
|
264
390
|
machine.write(@wfd, "-foobar\r\n")
|
|
265
|
-
o =
|
|
266
|
-
assert_kind_of UM::
|
|
391
|
+
o = conn.resp_read
|
|
392
|
+
assert_kind_of UM::Connection::RESPError, o
|
|
267
393
|
assert_equal "foobar", o.message
|
|
268
394
|
|
|
269
395
|
machine.write(@wfd, "!3\r\nbaz\r\n")
|
|
270
|
-
o =
|
|
271
|
-
assert_kind_of UM::
|
|
396
|
+
o = conn.resp_read
|
|
397
|
+
assert_kind_of UM::Connection::RESPError, o
|
|
272
398
|
assert_equal "baz", o.message
|
|
273
399
|
|
|
274
400
|
machine.write(@wfd, ":123\r\n")
|
|
275
|
-
assert_equal 123,
|
|
401
|
+
assert_equal 123, conn.resp_read
|
|
276
402
|
|
|
277
403
|
machine.write(@wfd, ":-123\r\n")
|
|
278
|
-
assert_equal(-123,
|
|
404
|
+
assert_equal(-123, conn.resp_read)
|
|
279
405
|
|
|
280
406
|
machine.write(@wfd, ",123.321\r\n")
|
|
281
|
-
assert_equal 123.321,
|
|
407
|
+
assert_equal 123.321, conn.resp_read
|
|
282
408
|
|
|
283
409
|
machine.write(@wfd, "_\r\n")
|
|
284
|
-
assert_nil
|
|
410
|
+
assert_nil conn.resp_read
|
|
285
411
|
|
|
286
412
|
machine.write(@wfd, "#t\r\n")
|
|
287
|
-
assert_equal true,
|
|
413
|
+
assert_equal true, conn.resp_read
|
|
288
414
|
|
|
289
415
|
machine.write(@wfd, "#f\r\n")
|
|
290
|
-
assert_equal false,
|
|
416
|
+
assert_equal false, conn.resp_read
|
|
291
417
|
|
|
292
418
|
machine.write(@wfd, "$6\r\nfoobar\r\n")
|
|
293
|
-
assert_equal "foobar",
|
|
419
|
+
assert_equal "foobar", conn.resp_read
|
|
294
420
|
|
|
295
421
|
machine.write(@wfd, "$3\r\nbaz\r\n")
|
|
296
|
-
assert_equal "baz",
|
|
422
|
+
assert_equal "baz", conn.resp_read
|
|
297
423
|
|
|
298
424
|
machine.write(@wfd, "=10\r\ntxt:foobar\r\n")
|
|
299
|
-
assert_equal "foobar",
|
|
425
|
+
assert_equal "foobar", conn.resp_read
|
|
300
426
|
|
|
301
427
|
machine.write(@wfd, "*3\r\n+foo\r\n:42\r\n$3\r\nbar\r\n")
|
|
302
|
-
assert_equal ['foo', 42, 'bar'],
|
|
428
|
+
assert_equal ['foo', 42, 'bar'], conn.resp_read
|
|
303
429
|
|
|
304
430
|
machine.write(@wfd, "~3\r\n+foo\r\n:42\r\n$3\r\nbar\r\n")
|
|
305
|
-
assert_equal ['foo', 42, 'bar'],
|
|
431
|
+
assert_equal ['foo', 42, 'bar'], conn.resp_read
|
|
306
432
|
|
|
307
433
|
machine.write(@wfd, ">3\r\n+foo\r\n:42\r\n$3\r\nbar\r\n")
|
|
308
|
-
assert_equal ['foo', 42, 'bar'],
|
|
434
|
+
assert_equal ['foo', 42, 'bar'], conn.resp_read
|
|
309
435
|
|
|
310
436
|
machine.write(@wfd, "%2\r\n+a\r\n:42\r\n+b\r\n:43\r\n")
|
|
311
|
-
assert_equal({ 'a' => 42, 'b' => 43 },
|
|
437
|
+
assert_equal({ 'a' => 42, 'b' => 43 }, conn.resp_read)
|
|
312
438
|
|
|
313
439
|
machine.write(@wfd, "|2\r\n+a\r\n:42\r\n+b\r\n:43\r\n")
|
|
314
|
-
assert_equal({ 'a' => 42, 'b' => 43 },
|
|
440
|
+
assert_equal({ 'a' => 42, 'b' => 43 }, conn.resp_read)
|
|
315
441
|
|
|
316
442
|
machine.write(@wfd, "%2\r\n+a\r\n:42\r\n+b\r\n*3\r\n+foo\r\n+bar\r\n+baz\r\n")
|
|
317
|
-
assert_equal({ 'a' => 42, 'b' => ['foo', 'bar', 'baz'] },
|
|
443
|
+
assert_equal({ 'a' => 42, 'b' => ['foo', 'bar', 'baz'] }, conn.resp_read)
|
|
318
444
|
end
|
|
319
445
|
|
|
320
|
-
def
|
|
446
|
+
def test_connection_resp_read_segmented
|
|
321
447
|
machine.write(@wfd, "\n")
|
|
322
|
-
assert_equal "",
|
|
448
|
+
assert_equal "", conn.read_line(0)
|
|
323
449
|
|
|
324
450
|
machine.write(@wfd, "+foo")
|
|
325
451
|
machine.write(@wfd, " ")
|
|
326
452
|
machine.write(@wfd, "bar\r")
|
|
327
453
|
machine.write(@wfd, "\n")
|
|
328
|
-
assert_equal "foo bar",
|
|
454
|
+
assert_equal "foo bar", conn.resp_read
|
|
329
455
|
machine.write(@wfd, "$6\r")
|
|
330
456
|
machine.write(@wfd, "\nbazbug")
|
|
331
457
|
machine.write(@wfd, "\r\n")
|
|
332
|
-
assert_equal "bazbug",
|
|
458
|
+
assert_equal "bazbug", conn.resp_read
|
|
333
459
|
end
|
|
334
460
|
|
|
335
|
-
def
|
|
336
|
-
|
|
461
|
+
def test_connection_resp_write
|
|
462
|
+
writer = machine.connection(@wfd)
|
|
463
|
+
|
|
464
|
+
writer.resp_write(nil);
|
|
465
|
+
assert_equal "_\r\n", conn.read(-100)
|
|
466
|
+
|
|
467
|
+
writer.resp_write(true);
|
|
468
|
+
assert_equal "#t\r\n", conn.read(-100)
|
|
469
|
+
|
|
470
|
+
writer.resp_write(false);
|
|
471
|
+
assert_equal "#f\r\n", conn.read(-100)
|
|
472
|
+
|
|
473
|
+
writer.resp_write(42);
|
|
474
|
+
assert_equal ":42\r\n", conn.read(-100)
|
|
475
|
+
|
|
476
|
+
writer.resp_write(42.1)
|
|
477
|
+
assert_equal ",42.1\r\n", conn.read(-100)
|
|
478
|
+
|
|
479
|
+
writer.resp_write('foobar')
|
|
480
|
+
assert_equal "$6\r\nfoobar\r\n", conn.read(-100)
|
|
481
|
+
|
|
482
|
+
writer.resp_write('פובאר')
|
|
483
|
+
assert_equal (+"$10\r\nפובאר\r\n").force_encoding('ASCII-8BIT'), conn.read(-100)
|
|
484
|
+
|
|
485
|
+
writer.resp_write(['foo', 'bar'])
|
|
486
|
+
assert_equal "*2\r\n$3\r\nfoo\r\n$3\r\nbar\r\n", conn.read(-100)
|
|
487
|
+
|
|
488
|
+
writer.resp_write({ 'foo' => 'bar', 'baz' => 42 })
|
|
489
|
+
assert_equal "%2\r\n$3\r\nfoo\r\n$3\r\nbar\r\n$3\r\nbaz\r\n:42\r\n", conn.read(-100)
|
|
490
|
+
end
|
|
491
|
+
|
|
492
|
+
def test_connection_resp_encode
|
|
493
|
+
s = UM::Connection
|
|
337
494
|
assert_equal "_\r\n", s.resp_encode(+'', nil)
|
|
338
495
|
assert_equal "#t\r\n", s.resp_encode(+'', true)
|
|
339
496
|
assert_equal "#f\r\n", s.resp_encode(+'', false)
|
|
@@ -350,7 +507,7 @@ class StreamRespTest < StreamBaseTest
|
|
|
350
507
|
end
|
|
351
508
|
end
|
|
352
509
|
|
|
353
|
-
class
|
|
510
|
+
class ConnectionStressTest < UMBaseTest
|
|
354
511
|
def setup
|
|
355
512
|
super
|
|
356
513
|
|
|
@@ -368,8 +525,8 @@ class StreamStressTest < UMBaseTest
|
|
|
368
525
|
|
|
369
526
|
def start_connection_fiber(fd)
|
|
370
527
|
machine.spin do
|
|
371
|
-
|
|
372
|
-
while (msg =
|
|
528
|
+
conn = UM::Connection.new(machine, fd)
|
|
529
|
+
while (msg = conn.read_line(0))
|
|
373
530
|
@received << msg
|
|
374
531
|
end
|
|
375
532
|
machine.sendv(fd, @response_headers, @response_body)
|
|
@@ -380,7 +537,7 @@ class StreamStressTest < UMBaseTest
|
|
|
380
537
|
end
|
|
381
538
|
end
|
|
382
539
|
|
|
383
|
-
def
|
|
540
|
+
def test_connection_server_big_lines
|
|
384
541
|
server_fibers = []
|
|
385
542
|
server_fibers << machine.spin do
|
|
386
543
|
machine.accept_each(@listen_fd) { |fd|
|
|
@@ -423,7 +580,7 @@ class StreamStressTest < UMBaseTest
|
|
|
423
580
|
assert_equal msg * client_count, @received.map { it + "\n" }.join
|
|
424
581
|
end
|
|
425
582
|
|
|
426
|
-
def
|
|
583
|
+
def test_connection_server_http
|
|
427
584
|
server_fibers = []
|
|
428
585
|
server_fibers << machine.spin do
|
|
429
586
|
machine.accept_each(@listen_fd) { |fd|
|
|
@@ -463,50 +620,50 @@ class StreamStressTest < UMBaseTest
|
|
|
463
620
|
end
|
|
464
621
|
end
|
|
465
622
|
|
|
466
|
-
class
|
|
467
|
-
def
|
|
623
|
+
class ConnectionDevRandomTest < UMBaseTest
|
|
624
|
+
def test_connection_dev_random_read_line
|
|
468
625
|
fd = machine.open('/dev/random', UM::O_RDONLY)
|
|
469
|
-
|
|
626
|
+
conn = UM::Connection.new(machine, fd)
|
|
470
627
|
|
|
471
628
|
n = 100000
|
|
472
629
|
lines = []
|
|
473
630
|
n.times {
|
|
474
|
-
lines <<
|
|
631
|
+
lines << conn.read_line(0)
|
|
475
632
|
}
|
|
476
633
|
|
|
477
634
|
assert_equal n, lines.size
|
|
478
635
|
ensure
|
|
479
|
-
|
|
636
|
+
conn.clear rescue nil
|
|
480
637
|
machine.close(fd) rescue nil
|
|
481
638
|
end
|
|
482
639
|
|
|
483
|
-
def
|
|
640
|
+
def read_line_do(n, acc)
|
|
484
641
|
fd = @machine.open('/dev/random', UM::O_RDONLY)
|
|
485
|
-
|
|
486
|
-
n.times { acc <<
|
|
642
|
+
conn = UM::Connection.new(@machine, fd)
|
|
643
|
+
n.times { acc << conn.read_line(0) }
|
|
487
644
|
end
|
|
488
645
|
|
|
489
|
-
def
|
|
646
|
+
def test_connection_dev_random_read_line_concurrent
|
|
490
647
|
acc = []
|
|
491
648
|
c = 1
|
|
492
649
|
n = 100000
|
|
493
650
|
ff = c.times.map {
|
|
494
|
-
machine.spin {
|
|
651
|
+
machine.spin { read_line_do(n, acc) }
|
|
495
652
|
}
|
|
496
653
|
machine.await(ff)
|
|
497
654
|
assert_equal c * n, acc.size
|
|
498
655
|
end
|
|
499
656
|
|
|
500
|
-
def
|
|
657
|
+
def test_connection_dev_random_read
|
|
501
658
|
fd = machine.open('/dev/random', UM::O_RDONLY)
|
|
502
|
-
|
|
659
|
+
conn = UM::Connection.new(machine, fd)
|
|
503
660
|
|
|
504
661
|
n = 256
|
|
505
662
|
size = 65536 * 8
|
|
506
663
|
count = 0
|
|
507
664
|
# lines = []
|
|
508
665
|
n.times {
|
|
509
|
-
l =
|
|
666
|
+
l = conn.read(size)
|
|
510
667
|
refute_nil l
|
|
511
668
|
assert_equal size, l.bytesize
|
|
512
669
|
|
|
@@ -515,49 +672,62 @@ class StreamDevRandomTest < UMBaseTest
|
|
|
515
672
|
|
|
516
673
|
assert_equal n, count
|
|
517
674
|
ensure
|
|
518
|
-
|
|
675
|
+
conn.clear rescue nil
|
|
519
676
|
end
|
|
520
677
|
end
|
|
521
678
|
|
|
522
|
-
class
|
|
523
|
-
def
|
|
679
|
+
class ConnectionModeTest < UMBaseTest
|
|
680
|
+
def test_connection_default_mode
|
|
524
681
|
r, w = UM.pipe
|
|
525
|
-
|
|
526
|
-
assert_equal :
|
|
682
|
+
conn = UM::Connection.new(machine, r)
|
|
683
|
+
assert_equal :fd, conn.mode
|
|
527
684
|
ensure
|
|
528
685
|
machine.close(r) rescue nil
|
|
529
686
|
machine.close(w) rescue nil
|
|
530
687
|
end
|
|
531
688
|
|
|
532
|
-
def
|
|
689
|
+
def test_connection_default_mode_ssl
|
|
690
|
+
authority = Localhost::Authority.fetch
|
|
691
|
+
@server_ctx = authority.server_context
|
|
692
|
+
sock1, sock2 = UNIXSocket.pair
|
|
693
|
+
|
|
694
|
+
s1 = OpenSSL::SSL::SSLSocket.new(sock1, @server_ctx)
|
|
695
|
+
conn = UM::Connection.new(machine, s1)
|
|
696
|
+
assert_equal :ssl, conn.mode
|
|
697
|
+
ensure
|
|
698
|
+
sock1&.close rescue nil
|
|
699
|
+
sock2&.close rescue nil
|
|
700
|
+
end
|
|
701
|
+
|
|
702
|
+
def test_connection_socket_mode_non_socket
|
|
533
703
|
r, w = UM.pipe
|
|
534
704
|
machine.write(w, 'foobar')
|
|
535
705
|
machine.close(w)
|
|
536
706
|
|
|
537
|
-
|
|
538
|
-
assert_equal :
|
|
539
|
-
# assert :
|
|
540
|
-
assert_raises(Errno::ENOTSOCK) {
|
|
707
|
+
conn = UM::Connection.new(machine, r, :socket)
|
|
708
|
+
assert_equal :socket, conn.mode
|
|
709
|
+
# assert :socket, conn.mode
|
|
710
|
+
assert_raises(Errno::ENOTSOCK) { conn.read(0) }
|
|
541
711
|
ensure
|
|
542
712
|
machine.close(r) rescue nil
|
|
543
713
|
machine.close(w) rescue nil
|
|
544
714
|
end
|
|
545
715
|
|
|
546
|
-
def
|
|
716
|
+
def test_connection_socket_mode_socket
|
|
547
717
|
r, w = UM.socketpair(UM::AF_UNIX, UM::SOCK_STREAM, 0)
|
|
548
718
|
machine.write(w, 'foobar')
|
|
549
719
|
machine.close(w)
|
|
550
720
|
|
|
551
|
-
|
|
552
|
-
assert_equal :
|
|
553
|
-
buf =
|
|
721
|
+
conn = UM::Connection.new(machine, r, :socket)
|
|
722
|
+
assert_equal :socket, conn.mode
|
|
723
|
+
buf = conn.read(0)
|
|
554
724
|
assert_equal 'foobar', buf
|
|
555
725
|
ensure
|
|
556
726
|
machine.close(r) rescue nil
|
|
557
727
|
machine.close(w) rescue nil
|
|
558
728
|
end
|
|
559
729
|
|
|
560
|
-
def
|
|
730
|
+
def test_connection_ssl_mode
|
|
561
731
|
authority = Localhost::Authority.fetch
|
|
562
732
|
@server_ctx = authority.server_context
|
|
563
733
|
sock1, sock2 = UNIXSocket.pair
|
|
@@ -581,18 +751,18 @@ class StreamModeTest < UMBaseTest
|
|
|
581
751
|
assert_equal 10, @machine.ssl_write(s1, buf, buf.bytesize)
|
|
582
752
|
buf = +''
|
|
583
753
|
|
|
584
|
-
|
|
585
|
-
assert_equal "foobar",
|
|
754
|
+
conn = UM::Connection.new(machine, s2, :ssl)
|
|
755
|
+
assert_equal "foobar", conn.read_line(0)
|
|
586
756
|
|
|
587
757
|
buf = "buh"
|
|
588
758
|
@machine.ssl_write(s1, buf, buf.bytesize)
|
|
589
759
|
|
|
590
|
-
assert_equal "baz",
|
|
591
|
-
assert_equal "buh",
|
|
760
|
+
assert_equal "baz", conn.read(0)
|
|
761
|
+
assert_equal "buh", conn.read(0)
|
|
592
762
|
|
|
593
763
|
s1.close
|
|
594
764
|
|
|
595
|
-
assert_nil
|
|
765
|
+
assert_nil conn.read(0)
|
|
596
766
|
rescue => e
|
|
597
767
|
p e
|
|
598
768
|
p e.backtrace
|
|
@@ -604,35 +774,35 @@ class StreamModeTest < UMBaseTest
|
|
|
604
774
|
end
|
|
605
775
|
end
|
|
606
776
|
|
|
607
|
-
class
|
|
608
|
-
def
|
|
777
|
+
class ConnectionByteCountsTest < ConnectionBaseTest
|
|
778
|
+
def test_connection_byte_counts
|
|
609
779
|
machine.write(@wfd, "foobar")
|
|
610
780
|
|
|
611
|
-
assert_equal 0,
|
|
612
|
-
assert_equal 0,
|
|
781
|
+
assert_equal 0, conn.consumed
|
|
782
|
+
assert_equal 0, conn.pending
|
|
613
783
|
|
|
614
|
-
buf =
|
|
784
|
+
buf = conn.read(2)
|
|
615
785
|
assert_equal 'fo', buf
|
|
616
|
-
assert_equal 2,
|
|
617
|
-
assert_equal 4,
|
|
786
|
+
assert_equal 2, conn.consumed
|
|
787
|
+
assert_equal 4, conn.pending
|
|
618
788
|
|
|
619
|
-
buf =
|
|
789
|
+
buf = conn.read(3)
|
|
620
790
|
assert_equal 'oba', buf
|
|
621
|
-
assert_equal 5,
|
|
622
|
-
assert_equal 1,
|
|
791
|
+
assert_equal 5, conn.consumed
|
|
792
|
+
assert_equal 1, conn.pending
|
|
623
793
|
|
|
624
794
|
machine.write(@wfd, "abc\ndef")
|
|
625
795
|
machine.snooze
|
|
626
|
-
assert_equal 5,
|
|
627
|
-
assert_equal 1,
|
|
796
|
+
assert_equal 5, conn.consumed
|
|
797
|
+
assert_equal 1, conn.pending
|
|
628
798
|
|
|
629
|
-
buf =
|
|
799
|
+
buf = conn.read_line(0)
|
|
630
800
|
assert_equal 'rabc', buf
|
|
631
|
-
assert_equal 10,
|
|
632
|
-
assert_equal 3,
|
|
801
|
+
assert_equal 10, conn.consumed
|
|
802
|
+
assert_equal 3, conn.pending
|
|
633
803
|
|
|
634
|
-
|
|
635
|
-
assert_equal 10,
|
|
636
|
-
assert_equal 0,
|
|
804
|
+
conn.clear
|
|
805
|
+
assert_equal 10, conn.consumed
|
|
806
|
+
assert_equal 0, conn.pending
|
|
637
807
|
end
|
|
638
808
|
end
|