tcp-client 0.6.0 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,145 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../helper'
4
+
5
+ RSpec.describe TCPClient::Address do
6
+ describe '.new' do
7
+ context 'when called with an Integer parameter' do
8
+ subject(:address) { TCPClient::Address.new(42) }
9
+
10
+ it 'points to the given port on localhost' do
11
+ expect(address.hostname).to eq 'localhost'
12
+ expect(address.to_s).to eq 'localhost:42'
13
+ expect(address.addrinfo.ip_port).to be 42
14
+ end
15
+
16
+ it 'uses IPv6' do
17
+ expect(address.addrinfo.ip?).to be true
18
+ expect(address.addrinfo.ipv6?).to be true
19
+ expect(address.addrinfo.ipv4?).to be false
20
+ end
21
+ end
22
+
23
+ context 'when called with an Addrinfo' do
24
+ subject(:address) { TCPClient::Address.new(addrinfo) }
25
+ let(:addrinfo) { Addrinfo.tcp('::1', 42) }
26
+
27
+ it 'uses the given Addrinfo' do
28
+ expect(address.addrinfo).to eq addrinfo
29
+ end
30
+
31
+ it 'points to the given host and port' do
32
+ expect(address.hostname).to eq addrinfo.getnameinfo[0]
33
+ expect(address.addrinfo.ip_port).to be 42
34
+ end
35
+
36
+ it 'uses IPv6' do
37
+ expect(address.addrinfo.ip?).to be true
38
+ expect(address.addrinfo.ipv6?).to be true
39
+ expect(address.addrinfo.ipv4?).to be false
40
+ end
41
+ end
42
+
43
+ context 'when called with a String' do
44
+ context 'when a host name and port is provided' do
45
+ subject(:address) { TCPClient::Address.new('localhost:42') }
46
+
47
+ it 'points to the given host and port' do
48
+ expect(address.hostname).to eq 'localhost'
49
+ 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
+ expect(address.addrinfo.ip?).to be true
55
+ expect(address.addrinfo.ipv6?).to be true
56
+ expect(address.addrinfo.ipv4?).to be false
57
+ end
58
+ end
59
+
60
+ context 'when only a port is provided' do
61
+ subject(:address) { TCPClient::Address.new(':21') }
62
+
63
+ it 'points to the given port on localhost' do
64
+ expect(address.hostname).to eq ''
65
+ expect(address.to_s).to eq ':21'
66
+ expect(address.addrinfo.ip_port).to be 21
67
+ end
68
+
69
+ it 'uses IPv4' do
70
+ expect(address.addrinfo.ip?).to be true
71
+ expect(address.addrinfo.ipv6?).to be false
72
+ expect(address.addrinfo.ipv4?).to be true
73
+ end
74
+ end
75
+
76
+ context 'when an IPv6 address is provided' do
77
+ subject(:address) { TCPClient::Address.new('[::1]:42') }
78
+
79
+ it 'points to the given port on localhost' do
80
+ expect(address.hostname).to eq '::1'
81
+ 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
+ expect(address.addrinfo.ip?).to be true
87
+ expect(address.addrinfo.ipv6?).to be true
88
+ expect(address.addrinfo.ipv4?).to be false
89
+ end
90
+ end
91
+ end
92
+ end
93
+
94
+ describe '#to_h' do
95
+ subject(:address) { TCPClient::Address.new('localhost:42') }
96
+
97
+ it 'returns itself as an Hash' do
98
+ expect(address.to_h).to eq(host: 'localhost', port: 42)
99
+ end
100
+ end
101
+
102
+ describe 'comparison' do
103
+ context 'comparing two equal instances' do
104
+ let(:address_a) { TCPClient::Address.new('localhost:42') }
105
+ let(:address_b) { TCPClient::Address.new('localhost:42') }
106
+
107
+ it 'compares to equal' do
108
+ expect(address_a).to eq address_b
109
+ end
110
+
111
+ context 'using the == opperator' do
112
+ it 'compares to equal' do
113
+ expect(address_a == address_b).to be true
114
+ end
115
+ end
116
+
117
+ context 'using the === opperator' do
118
+ it 'compares to equal' do
119
+ expect(address_a === address_b).to be true
120
+ end
121
+ end
122
+ end
123
+
124
+ context 'comparing two non-equal instances' do
125
+ let(:address_a) { TCPClient::Address.new('localhost:42') }
126
+ let(:address_b) { TCPClient::Address.new('localhost:21') }
127
+
128
+ it 'compares not to equal' do
129
+ expect(address_a).not_to eq address_b
130
+ end
131
+
132
+ context 'using the == opperator' do
133
+ it 'compares not to equal' do
134
+ expect(address_a == address_b).to be false
135
+ end
136
+ end
137
+
138
+ context 'using the === opperator' do
139
+ it 'compares not to equal' do
140
+ expect(address_a === address_b).to be false
141
+ end
142
+ end
143
+ end
144
+ end
145
+ end
@@ -0,0 +1,269 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../helper'
4
+
5
+ RSpec.describe TCPClient::Configuration do
6
+ describe '.create' do
7
+ it 'yields a configuration' do
8
+ TCPClient::Configuration.create do |cfg|
9
+ expect(cfg).to be_a TCPClient::Configuration
10
+ end
11
+ end
12
+
13
+ it 'returns the configuration' do
14
+ yielded_cfg = nil
15
+ result = TCPClient::Configuration.create { |cfg| yielded_cfg = cfg }
16
+ expect(result).to be yielded_cfg
17
+ end
18
+ end
19
+
20
+ describe '.new' do
21
+ context 'without any parameter' do
22
+ subject(:configuration) { TCPClient::Configuration.new }
23
+
24
+ it 'allows buffering' do
25
+ expect(configuration.buffered).to be true
26
+ end
27
+
28
+ it 'allows keep alive signals' do
29
+ expect(configuration.keep_alive).to be true
30
+ end
31
+
32
+ it 'allows reverse address lokup' do
33
+ expect(configuration.reverse_lookup).to be true
34
+ end
35
+
36
+ it 'does not allow to normalize network errors' do
37
+ expect(configuration.normalize_network_errors).to be false
38
+ end
39
+
40
+ it 'does not allow SSL connections' do
41
+ expect(configuration.ssl?).to be false
42
+ end
43
+
44
+ it 'configures no timeout values' do
45
+ expect(configuration.connect_timeout).to be_nil
46
+ expect(configuration.read_timeout).to be_nil
47
+ expect(configuration.write_timeout).to be_nil
48
+ end
49
+
50
+ it 'configures default errors' do
51
+ expect(
52
+ configuration.connect_timeout_error
53
+ ).to be TCPClient::ConnectTimeoutError
54
+ expect(
55
+ configuration.read_timeout_error
56
+ ).to be TCPClient::ReadTimeoutError
57
+ expect(
58
+ configuration.write_timeout_error
59
+ ).to be TCPClient::WriteTimeoutError
60
+ end
61
+ end
62
+
63
+ context 'with valid options' do
64
+ subject(:configuration) do
65
+ TCPClient::Configuration.new(
66
+ buffered: false,
67
+ keep_alive: false,
68
+ reverse_lookup: false,
69
+ normalize_network_errors: true,
70
+ ssl: true,
71
+ timeout: 60,
72
+ timeout_error: custom_error
73
+ )
74
+ end
75
+ let(:custom_error) { Class.new(StandardError) }
76
+
77
+ it 'allows to configure buffering' do
78
+ expect(configuration.buffered).to be false
79
+ end
80
+
81
+ it 'allows to configure keep alive signals' do
82
+ expect(configuration.keep_alive).to be false
83
+ end
84
+
85
+ it 'allows to configure reverse address lokup' do
86
+ expect(configuration.reverse_lookup).to be false
87
+ end
88
+
89
+ it 'allows to configure to normalize network errors' do
90
+ expect(configuration.normalize_network_errors).to be true
91
+ end
92
+
93
+ it 'allows to configures SSL connections' do
94
+ expect(configuration.ssl?).to be true
95
+ end
96
+
97
+ it 'allows to configure no timeout values' do
98
+ expect(configuration.connect_timeout).to be 60
99
+ expect(configuration.read_timeout).to be 60
100
+ expect(configuration.write_timeout).to be 60
101
+ end
102
+
103
+ it 'allows to configure timeout errors' do
104
+ expect(configuration.connect_timeout_error).to be custom_error
105
+ expect(configuration.read_timeout_error).to be custom_error
106
+ expect(configuration.write_timeout_error).to be custom_error
107
+ end
108
+
109
+ it 'allows to configure dedicated timeout values' do
110
+ config =
111
+ TCPClient::Configuration.new(
112
+ connect_timeout: 21,
113
+ read_timeout: 42,
114
+ write_timeout: 84
115
+ )
116
+ expect(config.connect_timeout).to be 21
117
+ expect(config.read_timeout).to be 42
118
+ expect(config.write_timeout).to be 84
119
+ end
120
+
121
+ it 'allows to configure dedicated timeout errors' do
122
+ custom_connect = Class.new(StandardError)
123
+ custom_read = Class.new(StandardError)
124
+ custom_write = Class.new(StandardError)
125
+ config =
126
+ TCPClient::Configuration.new(
127
+ connect_timeout_error: custom_connect,
128
+ read_timeout_error: custom_read,
129
+ write_timeout_error: custom_write
130
+ )
131
+ expect(config.connect_timeout_error).to be custom_connect
132
+ expect(config.read_timeout_error).to be custom_read
133
+ expect(config.write_timeout_error).to be custom_write
134
+ end
135
+
136
+ it 'raises when no exception class is used to configure a timeout error' do
137
+ expect do
138
+ TCPClient::Configuration.new(
139
+ connect_timeout_error: double(:something)
140
+ )
141
+ end.to raise_error(TCPClient::NotAnExceptionError)
142
+ expect do
143
+ TCPClient::Configuration.new(read_timeout_error: double(:something))
144
+ end.to raise_error(TCPClient::NotAnExceptionError)
145
+ expect do
146
+ TCPClient::Configuration.new(write_timeout_error: double(:something))
147
+ end.to raise_error(TCPClient::NotAnExceptionError)
148
+ end
149
+ end
150
+
151
+ context 'with invalid attribte' do
152
+ it 'raises an error' do
153
+ expect { TCPClient::Configuration.new(invalid: :value) }.to raise_error(
154
+ TCPClient::UnknownAttributeError
155
+ )
156
+ end
157
+ end
158
+ end
159
+
160
+ describe '#to_h' do
161
+ subject(:configuration) do
162
+ TCPClient::Configuration.new(
163
+ buffered: false,
164
+ connect_timeout: 1,
165
+ read_timeout: 2,
166
+ write_timeout: 3,
167
+ ssl: {
168
+ min_version: :TLS1_2,
169
+ max_version: :TLS1_3
170
+ }
171
+ )
172
+ end
173
+
174
+ it 'returns itself as an Hash' do
175
+ expect(configuration.to_h).to eq(
176
+ buffered: false,
177
+ keep_alive: true,
178
+ reverse_lookup: true,
179
+ connect_timeout: 1,
180
+ connect_timeout_error: TCPClient::ConnectTimeoutError,
181
+ read_timeout: 2,
182
+ read_timeout_error: TCPClient::ReadTimeoutError,
183
+ write_timeout: 3,
184
+ write_timeout_error: TCPClient::WriteTimeoutError,
185
+ ssl_params: {
186
+ min_version: :TLS1_2,
187
+ max_version: :TLS1_3
188
+ }
189
+ )
190
+ end
191
+ end
192
+
193
+ describe '#dup' do
194
+ subject(:duplicate) { configuration.dup }
195
+ let(:configuration) do
196
+ TCPClient::Configuration.new(
197
+ buffered: false,
198
+ connect_timeout: 1,
199
+ read_timeout: 2,
200
+ write_timeout: 3,
201
+ ssl: {
202
+ min_version: :TLS1_2,
203
+ max_version: :TLS1_3
204
+ }
205
+ )
206
+ end
207
+
208
+ it 'returns a new instance' do
209
+ expect(duplicate).to be_a TCPClient::Configuration
210
+ expect(duplicate.__id__).not_to eq configuration.__id__
211
+ end
212
+
213
+ it 'contains same values as the original' do
214
+ expect(duplicate.buffered).to be false
215
+ expect(duplicate.connect_timeout).to be 1
216
+ expect(duplicate.read_timeout).to be 2
217
+ expect(duplicate.write_timeout).to be 3
218
+ expect(duplicate.ssl?).to be true
219
+ expect(duplicate.ssl_params).to eq(
220
+ min_version: :TLS1_2,
221
+ max_version: :TLS1_3
222
+ )
223
+ end
224
+ end
225
+
226
+ describe 'comparison' do
227
+ context 'comparing two equal instances' do
228
+ let(:config_a) { TCPClient::Configuration.new(timeout: 10) }
229
+ let(:config_b) { TCPClient::Configuration.new(timeout: 10) }
230
+
231
+ it 'compares to equal' do
232
+ expect(config_a).to eq config_b
233
+ end
234
+
235
+ context 'using the == opperator' do
236
+ it 'compares to equal' do
237
+ expect(config_a == config_b).to be true
238
+ end
239
+ end
240
+
241
+ context 'using the === opperator' do
242
+ it 'compares to equal' do
243
+ expect(config_a === config_b).to be true
244
+ end
245
+ end
246
+ end
247
+
248
+ context 'comparing two non-equal instances' do
249
+ let(:config_a) { TCPClient::Configuration.new(timeout: 10) }
250
+ let(:config_b) { TCPClient::Configuration.new(timeout: 20) }
251
+
252
+ it 'compares not to equal' do
253
+ expect(config_a).not_to eq config_b
254
+ end
255
+
256
+ context 'using the == opperator' do
257
+ it 'compares not to equal' do
258
+ expect(config_a == config_b).to be false
259
+ end
260
+ end
261
+
262
+ context 'using the === opperator' do
263
+ it 'compares not to equal' do
264
+ expect(config_a === config_b).to be false
265
+ end
266
+ end
267
+ end
268
+ end
269
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../helper'
4
+
5
+ RSpec.describe 'TCPClient.configure' do
6
+ it 'is the default configuration' do
7
+ expect(TCPClient.configure).to be TCPClient::Configuration.default
8
+ end
9
+
10
+ context 'called with parameters' do
11
+ it 'creates a new configuratiion' do
12
+ expect(TCPClient::Configuration).to receive(:create).once.with(a: 1, b: 2)
13
+ TCPClient.configure(a: 1, b: 2)
14
+ end
15
+
16
+ it 'returns the new configuratiion' do
17
+ expect(TCPClient::Configuration).to receive(:create).and_return(:a_result)
18
+ TCPClient.configure(something: :new)
19
+ expect(TCPClient::Configuration.default).to be :a_result
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../helper'
4
+
5
+ RSpec.describe 'TCPClient::VERSION' do
6
+ it 'is a valid version string' do
7
+ expect(TCPClient::VERSION).to match(/\d+\.\d+\.\d+/)
8
+ end
9
+
10
+ it 'is frozen' do
11
+ expect(TCPClient::VERSION.frozen?).to be true
12
+ end
13
+ end