tcp-client 0.9.1 → 0.10.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/.yardopts +5 -0
- data/README.md +11 -10
- data/gems.rb +2 -1
- data/lib/tcp-client/address.rb +31 -15
- data/lib/tcp-client/configuration.rb +132 -99
- data/lib/tcp-client/deadline.rb +1 -3
- data/lib/tcp-client/default_configuration.rb +20 -8
- data/lib/tcp-client/errors.rb +34 -14
- data/lib/tcp-client/mixin/io_with_deadline.rb +46 -16
- data/lib/tcp-client/version.rb +2 -4
- data/lib/tcp-client.rb +169 -100
- data/rakefile.rb +6 -1
- data/sample/google_ssl.rb +8 -5
- data/spec/tcp-client/address_spec.rb +15 -28
- data/spec/tcp-client/configuration_spec.rb +7 -6
- data/spec/tcp_client_spec.rb +227 -23
- data/tcp-client.gemspec +9 -11
- metadata +5 -4
@@ -9,8 +9,8 @@ RSpec.describe TCPClient::Address do
|
|
9
9
|
|
10
10
|
it 'points to the given port on localhost' do
|
11
11
|
expect(address.hostname).to eq 'localhost'
|
12
|
+
expect(address.port).to be 42
|
12
13
|
expect(address.to_s).to eq 'localhost:42'
|
13
|
-
expect(address.addrinfo.ip_port).to be 42
|
14
14
|
end
|
15
15
|
|
16
16
|
it 'uses IPv6' do
|
@@ -29,8 +29,9 @@ RSpec.describe TCPClient::Address do
|
|
29
29
|
end
|
30
30
|
|
31
31
|
it 'points to the given host and port' do
|
32
|
-
expect(address.hostname).to eq
|
33
|
-
expect(address.
|
32
|
+
expect(address.hostname).to eq 'localhost'
|
33
|
+
expect(address.port).to be 42
|
34
|
+
expect(address.to_s).to eq 'localhost:42'
|
34
35
|
end
|
35
36
|
|
36
37
|
it 'uses IPv6' do
|
@@ -46,30 +47,21 @@ RSpec.describe TCPClient::Address do
|
|
46
47
|
|
47
48
|
it 'points to the given host and port' do
|
48
49
|
expect(address.hostname).to eq 'localhost'
|
50
|
+
expect(address.port).to be 42
|
49
51
|
expect(address.to_s).to eq 'localhost:42'
|
50
|
-
expect(address.addrinfo.ip_port).to be 42
|
51
|
-
end
|
52
|
-
|
53
|
-
it 'uses IPv6' do
|
54
52
|
expect(address.addrinfo.ip?).to be true
|
55
|
-
expect(address.addrinfo.ipv6?).to be true
|
56
|
-
expect(address.addrinfo.ipv4?).to be false
|
57
53
|
end
|
54
|
+
|
58
55
|
end
|
59
56
|
|
60
57
|
context 'when only a port is provided' do
|
61
|
-
subject(:address) { TCPClient::Address.new(':
|
58
|
+
subject(:address) { TCPClient::Address.new(':42') }
|
62
59
|
|
63
60
|
it 'points to the given port on localhost' do
|
64
|
-
expect(address.hostname).to eq ''
|
65
|
-
expect(address.
|
66
|
-
expect(address.
|
67
|
-
end
|
68
|
-
|
69
|
-
it 'uses IPv4' do
|
61
|
+
expect(address.hostname).to eq 'localhost'
|
62
|
+
expect(address.port).to be 42
|
63
|
+
expect(address.to_s).to eq 'localhost:42'
|
70
64
|
expect(address.addrinfo.ip?).to be true
|
71
|
-
expect(address.addrinfo.ipv6?).to be false
|
72
|
-
expect(address.addrinfo.ipv4?).to be true
|
73
65
|
end
|
74
66
|
end
|
75
67
|
|
@@ -78,14 +70,9 @@ RSpec.describe TCPClient::Address do
|
|
78
70
|
|
79
71
|
it 'points to the given port on localhost' do
|
80
72
|
expect(address.hostname).to eq '::1'
|
73
|
+
expect(address.port).to be 42
|
81
74
|
expect(address.to_s).to eq '[::1]:42'
|
82
|
-
expect(address.addrinfo.ip_port).to be 42
|
83
|
-
end
|
84
|
-
|
85
|
-
it 'uses IPv6' do
|
86
75
|
expect(address.addrinfo.ip?).to be true
|
87
|
-
expect(address.addrinfo.ipv6?).to be true
|
88
|
-
expect(address.addrinfo.ipv4?).to be false
|
89
76
|
end
|
90
77
|
end
|
91
78
|
end
|
@@ -108,13 +95,13 @@ RSpec.describe TCPClient::Address do
|
|
108
95
|
expect(address_a).to eq address_b
|
109
96
|
end
|
110
97
|
|
111
|
-
context 'using the ==
|
98
|
+
context 'using the == operator' do
|
112
99
|
it 'compares to equal' do
|
113
100
|
expect(address_a == address_b).to be true
|
114
101
|
end
|
115
102
|
end
|
116
103
|
|
117
|
-
context 'using the ===
|
104
|
+
context 'using the === operator' do
|
118
105
|
it 'compares to equal' do
|
119
106
|
expect(address_a === address_b).to be true
|
120
107
|
end
|
@@ -129,13 +116,13 @@ RSpec.describe TCPClient::Address do
|
|
129
116
|
expect(address_a).not_to eq address_b
|
130
117
|
end
|
131
118
|
|
132
|
-
context 'using the ==
|
119
|
+
context 'using the == operator' do
|
133
120
|
it 'compares not to equal' do
|
134
121
|
expect(address_a == address_b).to be false
|
135
122
|
end
|
136
123
|
end
|
137
124
|
|
138
|
-
context 'using the ===
|
125
|
+
context 'using the === operator' do
|
139
126
|
it 'compares not to equal' do
|
140
127
|
expect(address_a === address_b).to be false
|
141
128
|
end
|
@@ -82,7 +82,7 @@ RSpec.describe TCPClient::Configuration do
|
|
82
82
|
expect(configuration.keep_alive).to be false
|
83
83
|
end
|
84
84
|
|
85
|
-
it 'allows to configure reverse address
|
85
|
+
it 'allows to configure reverse address lookup' do
|
86
86
|
expect(configuration.reverse_lookup).to be false
|
87
87
|
end
|
88
88
|
|
@@ -148,7 +148,7 @@ RSpec.describe TCPClient::Configuration do
|
|
148
148
|
end
|
149
149
|
end
|
150
150
|
|
151
|
-
context 'with invalid
|
151
|
+
context 'with invalid attribute' do
|
152
152
|
it 'raises an error' do
|
153
153
|
expect { TCPClient::Configuration.new(invalid: :value) }.to raise_error(
|
154
154
|
TCPClient::UnknownAttributeError
|
@@ -182,6 +182,7 @@ RSpec.describe TCPClient::Configuration do
|
|
182
182
|
read_timeout_error: TCPClient::ReadTimeoutError,
|
183
183
|
write_timeout: 3,
|
184
184
|
write_timeout_error: TCPClient::WriteTimeoutError,
|
185
|
+
normalize_network_errors: false,
|
185
186
|
ssl_params: {
|
186
187
|
min_version: :TLS1_2,
|
187
188
|
max_version: :TLS1_3
|
@@ -232,13 +233,13 @@ RSpec.describe TCPClient::Configuration do
|
|
232
233
|
expect(config_a).to eq config_b
|
233
234
|
end
|
234
235
|
|
235
|
-
context 'using the ==
|
236
|
+
context 'using the == operator' do
|
236
237
|
it 'compares to equal' do
|
237
238
|
expect(config_a == config_b).to be true
|
238
239
|
end
|
239
240
|
end
|
240
241
|
|
241
|
-
context 'using the ===
|
242
|
+
context 'using the === operator' do
|
242
243
|
it 'compares to equal' do
|
243
244
|
expect(config_a === config_b).to be true
|
244
245
|
end
|
@@ -253,13 +254,13 @@ RSpec.describe TCPClient::Configuration do
|
|
253
254
|
expect(config_a).not_to eq config_b
|
254
255
|
end
|
255
256
|
|
256
|
-
context 'using the ==
|
257
|
+
context 'using the == operator' do
|
257
258
|
it 'compares not to equal' do
|
258
259
|
expect(config_a == config_b).to be false
|
259
260
|
end
|
260
261
|
end
|
261
262
|
|
262
|
-
context 'using the ===
|
263
|
+
context 'using the === operator' do
|
263
264
|
it 'compares not to equal' do
|
264
265
|
expect(config_a === config_b).to be false
|
265
266
|
end
|
data/spec/tcp_client_spec.rb
CHANGED
@@ -26,7 +26,7 @@ RSpec.describe TCPClient do
|
|
26
26
|
subject(:client) { TCPClient.new }
|
27
27
|
|
28
28
|
it 'is closed' do
|
29
|
-
expect(client
|
29
|
+
expect(client).to be_closed
|
30
30
|
end
|
31
31
|
|
32
32
|
it 'has no address' do
|
@@ -64,7 +64,7 @@ RSpec.describe TCPClient do
|
|
64
64
|
before { allow_any_instance_of(::Socket).to receive(:connect) }
|
65
65
|
|
66
66
|
it 'is not closed' do
|
67
|
-
expect(client
|
67
|
+
expect(client).not_to be_closed
|
68
68
|
end
|
69
69
|
|
70
70
|
it 'has an address' do
|
@@ -115,7 +115,7 @@ RSpec.describe TCPClient do
|
|
115
115
|
end
|
116
116
|
|
117
117
|
it 'is closed' do
|
118
|
-
expect(client
|
118
|
+
expect(client).to be_closed
|
119
119
|
end
|
120
120
|
|
121
121
|
it 'has an address' do
|
@@ -157,6 +157,8 @@ RSpec.describe TCPClient do
|
|
157
157
|
|
158
158
|
context 'when not using SSL' do
|
159
159
|
describe '#connect' do
|
160
|
+
subject(:client) { TCPClient.new }
|
161
|
+
|
160
162
|
it 'configures the socket' do
|
161
163
|
expect_any_instance_of(::Socket).to receive(:sync=).once.with(true)
|
162
164
|
expect_any_instance_of(::Socket).to receive(:setsockopt)
|
@@ -169,7 +171,7 @@ RSpec.describe TCPClient do
|
|
169
171
|
.once
|
170
172
|
.with(false)
|
171
173
|
expect_any_instance_of(::Socket).to receive(:connect)
|
172
|
-
|
174
|
+
client.connect('localhost:1234', configuration)
|
173
175
|
end
|
174
176
|
|
175
177
|
context 'when a timeout is specified' do
|
@@ -177,7 +179,26 @@ RSpec.describe TCPClient do
|
|
177
179
|
expect_any_instance_of(::Socket).to receive(:connect_nonblock)
|
178
180
|
.once
|
179
181
|
.with(kind_of(String), exception: false)
|
180
|
-
|
182
|
+
client.connect('localhost:1234', configuration, timeout: 10)
|
183
|
+
end
|
184
|
+
|
185
|
+
it 'is returns itself' do
|
186
|
+
allow_any_instance_of(::Socket).to receive(:connect_nonblock).with(
|
187
|
+
kind_of(String),
|
188
|
+
exception: false
|
189
|
+
)
|
190
|
+
result = client.connect('localhost:1234', configuration, timeout: 10)
|
191
|
+
|
192
|
+
expect(client).to be client
|
193
|
+
end
|
194
|
+
|
195
|
+
it 'is not closed' do
|
196
|
+
allow_any_instance_of(::Socket).to receive(:connect_nonblock).with(
|
197
|
+
kind_of(String),
|
198
|
+
exception: false
|
199
|
+
)
|
200
|
+
client.connect('localhost:1234', configuration, timeout: 10)
|
201
|
+
expect(client).not_to be_closed
|
181
202
|
end
|
182
203
|
|
183
204
|
context 'when the connection can not be established in time' do
|
@@ -188,25 +209,29 @@ RSpec.describe TCPClient do
|
|
188
209
|
|
189
210
|
it 'raises an exception' do
|
190
211
|
expect do
|
191
|
-
|
192
|
-
'localhost:1234',
|
193
|
-
configuration,
|
194
|
-
timeout: 0.25
|
195
|
-
)
|
212
|
+
client.connect('localhost:1234', configuration, timeout: 0.1)
|
196
213
|
end.to raise_error(TCPClient::ConnectTimeoutError)
|
197
214
|
end
|
198
215
|
|
199
216
|
it 'allows to raise a custom exception' do
|
200
217
|
exception = Class.new(StandardError)
|
201
218
|
expect do
|
202
|
-
|
219
|
+
client.connect(
|
203
220
|
'localhost:1234',
|
204
221
|
configuration,
|
205
|
-
timeout: 0.
|
222
|
+
timeout: 0.1,
|
206
223
|
exception: exception
|
207
224
|
)
|
208
225
|
end.to raise_error(exception)
|
209
226
|
end
|
227
|
+
|
228
|
+
it 'is still closed' do
|
229
|
+
begin
|
230
|
+
client.connect('localhost:1234', configuration, timeout: 0.1)
|
231
|
+
rescue TCPClient::ConnectTimeoutError
|
232
|
+
end
|
233
|
+
expect(client).to be_closed
|
234
|
+
end
|
210
235
|
end
|
211
236
|
end
|
212
237
|
|
@@ -226,7 +251,7 @@ RSpec.describe TCPClient do
|
|
226
251
|
end
|
227
252
|
|
228
253
|
SOCKET_ERRORS.each do |error_class|
|
229
|
-
it "raises
|
254
|
+
it "raises TCPClient::NetworkError when a #{error_class} appeared" do
|
230
255
|
allow_any_instance_of(::Socket).to receive(:connect) {
|
231
256
|
raise error_class
|
232
257
|
}
|
@@ -270,18 +295,61 @@ RSpec.describe TCPClient do
|
|
270
295
|
expect(client.read(timeout: 10)).to be data
|
271
296
|
end
|
272
297
|
|
298
|
+
context 'when socket closed before any data can be read' do
|
299
|
+
it 'returns empty buffer' do
|
300
|
+
expect_any_instance_of(::Socket).to receive(:read_nonblock)
|
301
|
+
.and_return(nil)
|
302
|
+
expect(client.read(timeout: 10)).to be_empty
|
303
|
+
end
|
304
|
+
|
305
|
+
it 'is closed' do
|
306
|
+
expect_any_instance_of(::Socket).to receive(:read_nonblock)
|
307
|
+
.and_return(nil)
|
308
|
+
|
309
|
+
client.read(timeout: 10)
|
310
|
+
expect(client).to be_closed
|
311
|
+
end
|
312
|
+
end
|
313
|
+
|
273
314
|
context 'when data can not be fetched in a single chunk' do
|
274
315
|
it 'reads chunk by chunk' do
|
275
316
|
expect_any_instance_of(::Socket).to receive(:read_nonblock)
|
276
317
|
.once
|
277
|
-
.with(
|
318
|
+
.with(instance_of(Integer), exception: false)
|
278
319
|
.and_return(data)
|
279
320
|
expect_any_instance_of(::Socket).to receive(:read_nonblock)
|
280
321
|
.once
|
281
|
-
.with(
|
322
|
+
.with(instance_of(Integer), exception: false)
|
282
323
|
.and_return(data)
|
283
324
|
expect(client.read(data_size * 2, timeout: 10)).to eq data * 2
|
284
325
|
end
|
326
|
+
|
327
|
+
context 'when socket closed before enough data is avail' do
|
328
|
+
it 'returns available data only' do
|
329
|
+
expect_any_instance_of(::Socket).to receive(:read_nonblock)
|
330
|
+
.once
|
331
|
+
.with(instance_of(Integer), exception: false)
|
332
|
+
.and_return(data)
|
333
|
+
expect_any_instance_of(::Socket).to receive(:read_nonblock)
|
334
|
+
.once
|
335
|
+
.with(instance_of(Integer), exception: false)
|
336
|
+
.and_return(nil)
|
337
|
+
expect(client.read(data_size * 2, timeout: 10)).to eq data
|
338
|
+
end
|
339
|
+
|
340
|
+
it 'is closed' do
|
341
|
+
expect_any_instance_of(::Socket).to receive(:read_nonblock)
|
342
|
+
.once
|
343
|
+
.with(instance_of(Integer), exception: false)
|
344
|
+
.and_return(data)
|
345
|
+
expect_any_instance_of(::Socket).to receive(:read_nonblock)
|
346
|
+
.once
|
347
|
+
.with(instance_of(Integer), exception: false)
|
348
|
+
.and_return(nil)
|
349
|
+
client.read(data_size * 2, timeout: 10)
|
350
|
+
expect(client).to be_closed
|
351
|
+
end
|
352
|
+
end
|
285
353
|
end
|
286
354
|
|
287
355
|
context 'when the data can not be read in time' do
|
@@ -329,6 +397,146 @@ RSpec.describe TCPClient do
|
|
329
397
|
end
|
330
398
|
end
|
331
399
|
|
400
|
+
describe '#readline' do
|
401
|
+
before { allow_any_instance_of(::Socket).to receive(:connect) }
|
402
|
+
|
403
|
+
it 'reads from socket' do
|
404
|
+
expect_any_instance_of(::Socket).to receive(:readline)
|
405
|
+
.once
|
406
|
+
.with($/, chomp: false)
|
407
|
+
.and_return("Hello World\n")
|
408
|
+
expect(client.readline).to eq "Hello World\n"
|
409
|
+
end
|
410
|
+
|
411
|
+
context 'when a separator is specified' do
|
412
|
+
it 'forwards the separator' do
|
413
|
+
expect_any_instance_of(::Socket).to receive(:readline)
|
414
|
+
.once
|
415
|
+
.with('/', chomp: false)
|
416
|
+
.and_return('Hello/')
|
417
|
+
expect(client.readline('/')).to eq 'Hello/'
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
421
|
+
context 'when chomp is true' do
|
422
|
+
it 'forwards the flag' do
|
423
|
+
expect_any_instance_of(::Socket).to receive(:readline)
|
424
|
+
.once
|
425
|
+
.with($/, chomp: true)
|
426
|
+
.and_return('Hello World')
|
427
|
+
expect(client.readline(chomp: true)).to eq 'Hello World'
|
428
|
+
end
|
429
|
+
end
|
430
|
+
|
431
|
+
context 'when a timeout is specified' do
|
432
|
+
it 'checks the time' do
|
433
|
+
expect_any_instance_of(::Socket).to receive(:read_nonblock)
|
434
|
+
.and_return("Hello World\nHello World\n")
|
435
|
+
expect(client.readline(timeout: 10)).to eq "Hello World\n"
|
436
|
+
end
|
437
|
+
|
438
|
+
it 'optional chomps the line' do
|
439
|
+
expect_any_instance_of(::Socket).to receive(:read_nonblock)
|
440
|
+
.and_return("Hello World\nHello World\n")
|
441
|
+
expect(client.readline(chomp: true, timeout: 10)).to eq 'Hello World'
|
442
|
+
end
|
443
|
+
|
444
|
+
it 'uses the given separator' do
|
445
|
+
expect_any_instance_of(::Socket).to receive(:read_nonblock)
|
446
|
+
.and_return("Hello/World\n")
|
447
|
+
expect(client.readline('/', timeout: 10)).to eq 'Hello/'
|
448
|
+
end
|
449
|
+
|
450
|
+
context 'when data can not be fetched in a single chunk' do
|
451
|
+
it 'reads chunk by chunk' do
|
452
|
+
expect_any_instance_of(::Socket).to receive(:read_nonblock)
|
453
|
+
.once
|
454
|
+
.with(instance_of(Integer), exception: false)
|
455
|
+
.and_return('Hello ')
|
456
|
+
expect_any_instance_of(::Socket).to receive(:read_nonblock)
|
457
|
+
.once
|
458
|
+
.with(instance_of(Integer), exception: false)
|
459
|
+
.and_return('World')
|
460
|
+
expect_any_instance_of(::Socket).to receive(:read_nonblock)
|
461
|
+
.once
|
462
|
+
.with(instance_of(Integer), exception: false)
|
463
|
+
.and_return("\nAnd so...")
|
464
|
+
expect(client.readline(timeout: 10)).to eq "Hello World\n"
|
465
|
+
end
|
466
|
+
|
467
|
+
context 'when socket closed before enough data is avail' do
|
468
|
+
it 'returns available data only' do
|
469
|
+
expect_any_instance_of(::Socket).to receive(:read_nonblock)
|
470
|
+
.once
|
471
|
+
.with(instance_of(Integer), exception: false)
|
472
|
+
.and_return('Hello ')
|
473
|
+
expect_any_instance_of(::Socket).to receive(:read_nonblock)
|
474
|
+
.once
|
475
|
+
.with(instance_of(Integer), exception: false)
|
476
|
+
.and_return(nil)
|
477
|
+
expect(client.readline(timeout: 10)).to eq "Hello "
|
478
|
+
end
|
479
|
+
|
480
|
+
it 'is closed' do
|
481
|
+
expect_any_instance_of(::Socket).to receive(:read_nonblock)
|
482
|
+
.once
|
483
|
+
.with(instance_of(Integer), exception: false)
|
484
|
+
.and_return('Hello ')
|
485
|
+
expect_any_instance_of(::Socket).to receive(:read_nonblock)
|
486
|
+
.once
|
487
|
+
.with(instance_of(Integer), exception: false)
|
488
|
+
.and_return(nil)
|
489
|
+
client.readline(timeout: 10)
|
490
|
+
expect(client).to be_closed
|
491
|
+
end
|
492
|
+
end
|
493
|
+
end
|
494
|
+
|
495
|
+
context 'when the data can not be read in time' do
|
496
|
+
before do
|
497
|
+
allow_any_instance_of(::Socket).to receive(:read_nonblock)
|
498
|
+
.and_return(:wait_readable)
|
499
|
+
end
|
500
|
+
it 'raises an exception' do
|
501
|
+
expect { client.readline(timeout: 0.25) }.to raise_error(
|
502
|
+
TCPClient::ReadTimeoutError
|
503
|
+
)
|
504
|
+
end
|
505
|
+
|
506
|
+
it 'allows to raise a custom exception' do
|
507
|
+
exception = Class.new(StandardError)
|
508
|
+
expect do
|
509
|
+
client.read(timeout: 0.25, exception: exception)
|
510
|
+
end.to raise_error(exception)
|
511
|
+
end
|
512
|
+
end
|
513
|
+
end
|
514
|
+
|
515
|
+
context 'when a SocketError appears' do
|
516
|
+
it 'does not handle it' do
|
517
|
+
allow_any_instance_of(::Socket).to receive(:read) {
|
518
|
+
raise SocketError
|
519
|
+
}
|
520
|
+
expect { client.read(10) }.to raise_error(SocketError)
|
521
|
+
end
|
522
|
+
|
523
|
+
context 'when normalize_network_errors is configured' do
|
524
|
+
let(:configuration) do
|
525
|
+
TCPClient::Configuration.create(normalize_network_errors: true)
|
526
|
+
end
|
527
|
+
|
528
|
+
SOCKET_ERRORS.each do |error_class|
|
529
|
+
it "raises a TCPClient::NetworkError when a #{error_class} appeared" do
|
530
|
+
allow_any_instance_of(::Socket).to receive(:read) {
|
531
|
+
raise error_class
|
532
|
+
}
|
533
|
+
expect { client.read(12) }.to raise_error(TCPClient::NetworkError)
|
534
|
+
end
|
535
|
+
end
|
536
|
+
end
|
537
|
+
end
|
538
|
+
end
|
539
|
+
|
332
540
|
describe '#write' do
|
333
541
|
let(:data) { 'some bytes' }
|
334
542
|
let(:data_size) { data.bytesize }
|
@@ -463,20 +671,16 @@ RSpec.describe TCPClient do
|
|
463
671
|
.with(kind_of(String), exception: false)
|
464
672
|
expect_any_instance_of(::Socket).to receive(:read_nonblock)
|
465
673
|
.once
|
466
|
-
.with(
|
467
|
-
.and_return('
|
674
|
+
.with(instance_of(Integer), exception: false)
|
675
|
+
.and_return('123456789012abcdefgAB')
|
468
676
|
expect_any_instance_of(::Socket).to receive(:write_nonblock)
|
469
677
|
.once
|
470
678
|
.with('123456', exception: false)
|
471
679
|
.and_return(6)
|
472
680
|
expect_any_instance_of(::Socket).to receive(:read_nonblock)
|
473
681
|
.once
|
474
|
-
.with(
|
475
|
-
.and_return('
|
476
|
-
expect_any_instance_of(::Socket).to receive(:read_nonblock)
|
477
|
-
.once
|
478
|
-
.with(7, exception: false)
|
479
|
-
.and_return('ABCDEFG')
|
682
|
+
.with(instance_of(Integer), exception: false)
|
683
|
+
.and_return('CDEFG')
|
480
684
|
expect_any_instance_of(::Socket).to receive(:write_nonblock)
|
481
685
|
.once
|
482
686
|
.with('abc', exception: false)
|
data/tcp-client.gemspec
CHANGED
@@ -5,12 +5,11 @@ require_relative './lib/tcp-client/version'
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
6
|
spec.name = 'tcp-client'
|
7
7
|
spec.version = TCPClient::VERSION
|
8
|
-
spec.author = 'Mike Blumtritt'
|
9
|
-
|
10
8
|
spec.required_ruby_version = '>= 2.7.0'
|
11
9
|
|
10
|
+
spec.author = 'Mike Blumtritt'
|
12
11
|
spec.summary = 'A TCP client implementation with working timeout support.'
|
13
|
-
spec.description = <<~
|
12
|
+
spec.description = <<~description
|
14
13
|
This Gem implements a TCP client with (optional) SSL support.
|
15
14
|
It is an easy to use, versatile configurable client that can correctly
|
16
15
|
handle time limits.
|
@@ -18,15 +17,15 @@ Gem::Specification.new do |spec|
|
|
18
17
|
predefined/configurable time limits for each method
|
19
18
|
(`connect`, `read`, `write`). Deadlines for a sequence of read/write
|
20
19
|
actions can also be monitored.
|
21
|
-
|
20
|
+
description
|
21
|
+
|
22
22
|
spec.homepage = 'https://github.com/mblumtritt/tcp-client'
|
23
23
|
spec.license = 'BSD-3-Clause'
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
'https://rubydoc.info/github/mblumtritt/tcp-client'
|
28
|
-
|
29
|
-
'https://github.com/mblumtritt/tcp-client/issues'
|
24
|
+
spec.metadata.merge!(
|
25
|
+
'source_code_uri' => 'https://github.com/mblumtritt/tcp-client',
|
26
|
+
'bug_tracker_uri' => 'https://github.com/mblumtritt/tcp-client/issues',
|
27
|
+
'documentation_uri' => 'https://rubydoc.info/github/mblumtritt/tcp-client'
|
28
|
+
)
|
30
29
|
|
31
30
|
spec.add_development_dependency 'bundler'
|
32
31
|
spec.add_development_dependency 'rake'
|
@@ -36,6 +35,5 @@ Gem::Specification.new do |spec|
|
|
36
35
|
all_files = Dir.chdir(__dir__) { `git ls-files -z`.split(0.chr) }
|
37
36
|
spec.test_files = all_files.grep(%r{^spec/})
|
38
37
|
spec.files = all_files - spec.test_files
|
39
|
-
|
40
38
|
spec.extra_rdoc_files = %w[README.md LICENSE]
|
41
39
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tcp-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Blumtritt
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-01-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -82,6 +82,7 @@ extra_rdoc_files:
|
|
82
82
|
- LICENSE
|
83
83
|
files:
|
84
84
|
- ".gitignore"
|
85
|
+
- ".yardopts"
|
85
86
|
- LICENSE
|
86
87
|
- README.md
|
87
88
|
- gems.rb
|
@@ -111,8 +112,8 @@ licenses:
|
|
111
112
|
- BSD-3-Clause
|
112
113
|
metadata:
|
113
114
|
source_code_uri: https://github.com/mblumtritt/tcp-client
|
114
|
-
documentation_uri: https://rubydoc.info/github/mblumtritt/tcp-client
|
115
115
|
bug_tracker_uri: https://github.com/mblumtritt/tcp-client/issues
|
116
|
+
documentation_uri: https://rubydoc.info/github/mblumtritt/tcp-client
|
116
117
|
post_install_message:
|
117
118
|
rdoc_options: []
|
118
119
|
require_paths:
|
@@ -128,7 +129,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
128
129
|
- !ruby/object:Gem::Version
|
129
130
|
version: '0'
|
130
131
|
requirements: []
|
131
|
-
rubygems_version: 3.
|
132
|
+
rubygems_version: 3.3.3
|
132
133
|
signing_key:
|
133
134
|
specification_version: 4
|
134
135
|
summary: A TCP client implementation with working timeout support.
|