net_tcp_client 2.2.0 → 2.2.1
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/README.md +20 -20
- data/Rakefile +7 -7
- data/lib/net/tcp_client/address.rb +11 -6
- data/lib/net/tcp_client/exceptions.rb +3 -3
- data/lib/net/tcp_client/policy/base.rb +0 -1
- data/lib/net/tcp_client/policy/custom.rb +5 -3
- data/lib/net/tcp_client/policy/ordered.rb +1 -2
- data/lib/net/tcp_client/policy/random.rb +1 -2
- data/lib/net/tcp_client/tcp_client.rb +103 -93
- data/lib/net/tcp_client/version.rb +2 -2
- data/lib/net/tcp_client.rb +10 -10
- data/lib/net_tcp_client.rb +1 -1
- metadata +11 -37
- data/test/address_test.rb +0 -91
- data/test/policy/custom_policy_test.rb +0 -42
- data/test/policy/ordered_policy_test.rb +0 -36
- data/test/policy/random_policy_test.rb +0 -45
- data/test/simple_tcp_server.rb +0 -160
- data/test/ssl_files/ca.key +0 -27
- data/test/ssl_files/ca.pem +0 -19
- data/test/ssl_files/localhost-server-key.pem +0 -27
- data/test/ssl_files/localhost-server.pem +0 -19
- data/test/ssl_files/no-sni-key.pem +0 -27
- data/test/ssl_files/no-sni.pem +0 -20
- data/test/tcp_client_test.rb +0 -257
- data/test/test_helper.rb +0 -18
data/test/tcp_client_test.rb
DELETED
@@ -1,257 +0,0 @@
|
|
1
|
-
require 'socket'
|
2
|
-
require_relative 'test_helper'
|
3
|
-
require_relative 'simple_tcp_server'
|
4
|
-
require 'securerandom'
|
5
|
-
|
6
|
-
# Unit Test for Net::TCPClient
|
7
|
-
class TCPClientTest < Minitest::Test
|
8
|
-
describe Net::TCPClient do
|
9
|
-
[false, true].each do |with_ssl|
|
10
|
-
describe (with_ssl ? 'with ssl' : 'without ssl') do
|
11
|
-
describe '#connect' do
|
12
|
-
it 'raises an exception when cannot reach server after 5 retries' do
|
13
|
-
exception = assert_raises Net::TCPClient::ConnectionFailure do
|
14
|
-
new_net_tcp_client(
|
15
|
-
with_ssl,
|
16
|
-
server: 'localhost:3300',
|
17
|
-
connect_retry_interval: 0.1,
|
18
|
-
connect_retry_count: 5
|
19
|
-
)
|
20
|
-
end
|
21
|
-
assert_match(/Connection failure connecting to/, exception.message)
|
22
|
-
assert_match Errno::ECONNREFUSED.to_s, exception.cause.class.to_s
|
23
|
-
end
|
24
|
-
|
25
|
-
it 'times out on connect' do
|
26
|
-
unless with_ssl
|
27
|
-
skip('When not using SSL it will often connect anyway. Maybe a better way to test non-ssl?')
|
28
|
-
end
|
29
|
-
|
30
|
-
# Create a TCP Server, but do not respond to connections to cause a connect timeout
|
31
|
-
server = TCPServer.open(2094)
|
32
|
-
sleep 1
|
33
|
-
|
34
|
-
exception = assert_raises Net::TCPClient::ConnectionTimeout do
|
35
|
-
new_net_tcp_client(
|
36
|
-
with_ssl,
|
37
|
-
server: 'localhost:2094',
|
38
|
-
connect_timeout: 0.5,
|
39
|
-
connect_retry_count: 3
|
40
|
-
)
|
41
|
-
end
|
42
|
-
assert_match(/Timed out after 0\.5 seconds/, exception.message)
|
43
|
-
server.close
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
describe 'with server' do
|
48
|
-
before do
|
49
|
-
@port = 2000 + SecureRandom.random_number(1000)
|
50
|
-
options = {port: @port}
|
51
|
-
if with_ssl
|
52
|
-
options[:ssl] = {
|
53
|
-
# Purposefully serve a cert that doesn't match 'localhost' to force failures unless SNI works.
|
54
|
-
cert: OpenSSL::X509::Certificate.new(File.open(ssl_file_path('no-sni.pem'))),
|
55
|
-
key: OpenSSL::PKey::RSA.new(File.open(ssl_file_path('no-sni-key.pem'))),
|
56
|
-
ca_file: ssl_file_path('ca.pem')
|
57
|
-
}
|
58
|
-
end
|
59
|
-
count = 0
|
60
|
-
begin
|
61
|
-
@server = SimpleTCPServer.new(options)
|
62
|
-
rescue Errno::EADDRINUSE => exc
|
63
|
-
@server.stop if @server
|
64
|
-
# Give previous test server time to stop
|
65
|
-
count += 1
|
66
|
-
sleep 1
|
67
|
-
retry if count <= 30
|
68
|
-
raise exc
|
69
|
-
end
|
70
|
-
|
71
|
-
@server_name = "localhost:#{@port}"
|
72
|
-
end
|
73
|
-
|
74
|
-
after do
|
75
|
-
@client.close if @client
|
76
|
-
@server.stop if @server
|
77
|
-
end
|
78
|
-
|
79
|
-
describe '#read' do
|
80
|
-
it 'read timeout, followed by successful read' do
|
81
|
-
@read_timeout = 3.0
|
82
|
-
# Need a custom client that does not auto close on error:
|
83
|
-
@client = new_net_tcp_client(
|
84
|
-
with_ssl,
|
85
|
-
server: @server_name,
|
86
|
-
read_timeout: @read_timeout,
|
87
|
-
close_on_error: false
|
88
|
-
)
|
89
|
-
|
90
|
-
request = {'action' => 'sleep', 'duration' => @read_timeout + 0.5}
|
91
|
-
@client.write(request.to_bson)
|
92
|
-
|
93
|
-
exception = assert_raises Net::TCPClient::ReadTimeout do
|
94
|
-
# Read 4 bytes from server
|
95
|
-
@client.read(4)
|
96
|
-
end
|
97
|
-
assert_equal false, @client.close_on_error
|
98
|
-
assert @client.alive?, 'The client connection is not alive after the read timed out with close_on_error: false'
|
99
|
-
assert_equal "Timed out after #{@read_timeout} seconds trying to read from localhost[127.0.0.1]:#{@port}", exception.message
|
100
|
-
reply = read_bson_document(@client)
|
101
|
-
assert_equal 'sleep', reply['result']
|
102
|
-
@client.close
|
103
|
-
end
|
104
|
-
|
105
|
-
it 'infinite timeout' do
|
106
|
-
@client = new_net_tcp_client(
|
107
|
-
with_ssl,
|
108
|
-
server: @server_name,
|
109
|
-
connect_timeout: -1
|
110
|
-
)
|
111
|
-
request = {'action' => 'test1'}
|
112
|
-
@client.write(request.to_bson)
|
113
|
-
reply = read_bson_document(@client)
|
114
|
-
assert_equal 'test1', reply['result']
|
115
|
-
@client.close
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
describe '#connect' do
|
120
|
-
it 'calls on_connect after connection' do
|
121
|
-
@client = new_net_tcp_client(
|
122
|
-
with_ssl,
|
123
|
-
server: @server_name,
|
124
|
-
read_timeout: 3,
|
125
|
-
on_connect: Proc.new do |socket|
|
126
|
-
# Reset user_data on each connection
|
127
|
-
socket.user_data = {sequence: 1}
|
128
|
-
end
|
129
|
-
)
|
130
|
-
assert_equal "localhost[127.0.0.1]:#{@port}", @client.address.to_s
|
131
|
-
assert_equal 1, @client.user_data[:sequence]
|
132
|
-
|
133
|
-
request = {'action' => 'test1'}
|
134
|
-
@client.write(request.to_bson)
|
135
|
-
reply = read_bson_document(@client)
|
136
|
-
assert_equal 'test1', reply['result']
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
describe 'failover' do
|
141
|
-
it 'connects to second server when the first is down' do
|
142
|
-
@client = new_net_tcp_client(
|
143
|
-
with_ssl,
|
144
|
-
servers: ['localhost:1999', @server_name],
|
145
|
-
read_timeout: 3
|
146
|
-
)
|
147
|
-
assert_equal "localhost[127.0.0.1]:#{@port}", @client.address.to_s
|
148
|
-
|
149
|
-
request = {'action' => 'test1'}
|
150
|
-
@client.write(request.to_bson)
|
151
|
-
reply = read_bson_document(@client)
|
152
|
-
assert_equal 'test1', reply['result']
|
153
|
-
end
|
154
|
-
end
|
155
|
-
|
156
|
-
describe 'with client' do
|
157
|
-
before do
|
158
|
-
@read_timeout = 3.0
|
159
|
-
@client = new_net_tcp_client(
|
160
|
-
with_ssl,
|
161
|
-
server: @server_name,
|
162
|
-
read_timeout: @read_timeout
|
163
|
-
)
|
164
|
-
assert @client.alive?, @client.ai
|
165
|
-
assert_equal true, @client.close_on_error
|
166
|
-
end
|
167
|
-
|
168
|
-
describe '#alive?' do
|
169
|
-
it 'returns false once the connection is closed' do
|
170
|
-
skip "TODO: #alive? hangs with the latest SSL changes" if with_ssl
|
171
|
-
assert @client.alive?
|
172
|
-
@client.close
|
173
|
-
refute @client.alive?
|
174
|
-
end
|
175
|
-
end
|
176
|
-
|
177
|
-
describe '#closed?' do
|
178
|
-
it 'returns true once the connection is closed' do
|
179
|
-
refute @client.closed?
|
180
|
-
@client.close
|
181
|
-
assert @client.closed?
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
|
-
describe '#close' do
|
186
|
-
it 'closes the connection, repeatedly without error' do
|
187
|
-
@client.close
|
188
|
-
@client.close
|
189
|
-
end
|
190
|
-
end
|
191
|
-
|
192
|
-
describe '#write' do
|
193
|
-
it 'writes data' do
|
194
|
-
request = {'action' => 'test1'}
|
195
|
-
@client.write(request.to_bson)
|
196
|
-
end
|
197
|
-
end
|
198
|
-
|
199
|
-
describe '#read' do
|
200
|
-
it 'reads a response' do
|
201
|
-
request = {'action' => 'test1'}
|
202
|
-
@client.write(request.to_bson)
|
203
|
-
reply = read_bson_document(@client)
|
204
|
-
assert_equal 'test1', reply['result']
|
205
|
-
end
|
206
|
-
|
207
|
-
it 'times out on receive' do
|
208
|
-
request = {'action' => 'sleep', 'duration' => @read_timeout + 0.5}
|
209
|
-
@client.write(request.to_bson)
|
210
|
-
|
211
|
-
exception = assert_raises Net::TCPClient::ReadTimeout do
|
212
|
-
# Read 4 bytes from server
|
213
|
-
@client.read(4)
|
214
|
-
end
|
215
|
-
# Due to close_on_error: true, a timeout will close the connection
|
216
|
-
# to prevent use of a socket connection in an inconsistent state
|
217
|
-
assert_equal false, @client.alive?
|
218
|
-
assert_equal "Timed out after #{@read_timeout} seconds trying to read from localhost[127.0.0.1]:#{@port}", exception.message
|
219
|
-
end
|
220
|
-
end
|
221
|
-
|
222
|
-
describe '#retry_on_connection_failure' do
|
223
|
-
it 'retries on connection failure' do
|
224
|
-
attempt = 0
|
225
|
-
reply = @client.retry_on_connection_failure do
|
226
|
-
request = {'action' => 'fail', 'attempt' => (attempt += 1)}
|
227
|
-
@client.write(request.to_bson)
|
228
|
-
read_bson_document(@client)
|
229
|
-
end
|
230
|
-
assert_equal 'fail', reply['result']
|
231
|
-
end
|
232
|
-
end
|
233
|
-
end
|
234
|
-
end
|
235
|
-
end
|
236
|
-
|
237
|
-
end
|
238
|
-
|
239
|
-
def ssl_file_path(name)
|
240
|
-
File.join(File.dirname(__FILE__), 'ssl_files', name)
|
241
|
-
end
|
242
|
-
|
243
|
-
def new_net_tcp_client(with_ssl, params)
|
244
|
-
params = params.dup
|
245
|
-
if with_ssl
|
246
|
-
params.merge!(
|
247
|
-
ssl: {
|
248
|
-
ca_file: ssl_file_path('ca.pem'),
|
249
|
-
verify_mode: OpenSSL::SSL::VERIFY_PEER
|
250
|
-
}
|
251
|
-
)
|
252
|
-
end
|
253
|
-
Net::TCPClient.new(params)
|
254
|
-
end
|
255
|
-
|
256
|
-
end
|
257
|
-
end
|
data/test/test_helper.rb
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
# Allow test to be run in-place without requiring a gem install
|
2
|
-
$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
|
3
|
-
|
4
|
-
# Configure Rails Environment
|
5
|
-
ENV['RAILS_ENV'] = 'test'
|
6
|
-
|
7
|
-
require 'minitest/autorun'
|
8
|
-
require 'minitest/reporters'
|
9
|
-
require 'net/tcp_client'
|
10
|
-
|
11
|
-
SemanticLogger.default_level = :trace
|
12
|
-
SemanticLogger.add_appender(file_name: 'test.log', formatter: :color)
|
13
|
-
|
14
|
-
reporters = [
|
15
|
-
Minitest::Reporters::SpecReporter.new,
|
16
|
-
# SemanticLogger::Reporters::Minitest.new
|
17
|
-
]
|
18
|
-
Minitest::Reporters.use!(reporters)
|