tcp-client 0.7.0 → 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
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.7.0
4
+ version: 0.9.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Blumtritt
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-11-06 00:00:00.000000000 Z
11
+ date: 2021-12-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -25,7 +25,7 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: minitest
28
+ name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
@@ -39,7 +39,21 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: rake
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: yard
43
57
  requirement: !ruby/object:Gem::Requirement
44
58
  requirements:
45
59
  - - ">="
@@ -68,6 +82,7 @@ extra_rdoc_files:
68
82
  - LICENSE
69
83
  files:
70
84
  - ".gitignore"
85
+ - ".yardopts"
71
86
  - LICENSE
72
87
  - README.md
73
88
  - gems.rb
@@ -85,20 +100,20 @@ files:
85
100
  - rakefile.rb
86
101
  - sample/google.rb
87
102
  - sample/google_ssl.rb
103
+ - spec/helper.rb
104
+ - spec/tcp-client/address_spec.rb
105
+ - spec/tcp-client/configuration_spec.rb
106
+ - spec/tcp-client/default_configuration_spec.rb
107
+ - spec/tcp-client/version_spec.rb
108
+ - spec/tcp_client_spec.rb
88
109
  - tcp-client.gemspec
89
- - test/helper.rb
90
- - test/tcp-client/address_test.rb
91
- - test/tcp-client/configuration_test.rb
92
- - test/tcp-client/deadline_test.rb
93
- - test/tcp-client/default_configuration_test.rb
94
- - test/tcp-client/version_test.rb
95
- - test/tcp_client_test.rb
96
110
  homepage: https://github.com/mblumtritt/tcp-client
97
111
  licenses:
98
112
  - BSD-3-Clause
99
113
  metadata:
100
114
  source_code_uri: https://github.com/mblumtritt/tcp-client
101
115
  bug_tracker_uri: https://github.com/mblumtritt/tcp-client/issues
116
+ documentation_uri: https://rubydoc.info/github/mblumtritt/tcp-client
102
117
  post_install_message:
103
118
  rdoc_options: []
104
119
  require_paths:
@@ -119,10 +134,9 @@ signing_key:
119
134
  specification_version: 4
120
135
  summary: A TCP client implementation with working timeout support.
121
136
  test_files:
122
- - test/helper.rb
123
- - test/tcp-client/address_test.rb
124
- - test/tcp-client/configuration_test.rb
125
- - test/tcp-client/deadline_test.rb
126
- - test/tcp-client/default_configuration_test.rb
127
- - test/tcp-client/version_test.rb
128
- - test/tcp_client_test.rb
137
+ - spec/helper.rb
138
+ - spec/tcp-client/address_spec.rb
139
+ - spec/tcp-client/configuration_spec.rb
140
+ - spec/tcp-client/default_configuration_spec.rb
141
+ - spec/tcp-client/version_spec.rb
142
+ - spec/tcp_client_spec.rb
data/test/helper.rb DELETED
@@ -1,41 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'minitest/autorun'
4
- require 'minitest/parallel'
5
- require_relative '../lib/tcp-client'
6
-
7
- # this pseudo-server never reads or writes anything
8
- PseudoServer = TCPServer.new('localhost', 0)
9
- Minitest.after_run { PseudoServer.close }
10
-
11
- class Test < MiniTest::Test
12
- parallelize_me!
13
- end
14
-
15
- class Timing
16
- def initialize
17
- @start_time = nil
18
- end
19
-
20
- def started?
21
- @start_time != nil
22
- end
23
-
24
- def start
25
- @start_time = now
26
- end
27
-
28
- def elapsed
29
- now - @start_time
30
- end
31
-
32
- if defined?(Process::CLOCK_MONOTONIC)
33
- def now
34
- Process.clock_gettime(Process::CLOCK_MONOTONIC)
35
- end
36
- else
37
- def now
38
- ::Time.now
39
- end
40
- end
41
- end
@@ -1,65 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../helper'
4
-
5
- class AddressTest < Test
6
- def test_create_from_integer
7
- subject = TCPClient::Address.new(42)
8
- assert_equal('localhost:42', subject.to_s)
9
- assert_equal('localhost', subject.hostname)
10
- assert(subject.addrinfo.ip?)
11
- assert(subject.addrinfo.ipv6?)
12
- assert_same(42, subject.addrinfo.ip_port)
13
- end
14
-
15
- def test_create_from_addrinfo
16
- addrinfo = Addrinfo.tcp('localhost', 42)
17
- subject = TCPClient::Address.new(addrinfo)
18
- assert_equal(addrinfo.getnameinfo[0], subject.hostname)
19
- assert_equal(addrinfo, subject.addrinfo)
20
- end
21
-
22
- def test_create_from_str
23
- subject = TCPClient::Address.new('localhost:42')
24
- assert_equal('localhost:42', subject.to_s)
25
- assert_equal('localhost', subject.hostname)
26
- assert(subject.addrinfo.ip?)
27
- assert(subject.addrinfo.ipv6?)
28
- assert_same(42, subject.addrinfo.ip_port)
29
- end
30
-
31
- def test_create_from_str_short
32
- subject = TCPClient::Address.new(':42')
33
- assert_equal(':42', subject.to_s)
34
- assert_empty(subject.hostname)
35
- assert_same(42, subject.addrinfo.ip_port)
36
- assert(subject.addrinfo.ip?)
37
- assert(subject.addrinfo.ipv4?)
38
- end
39
-
40
- def test_create_from_str_ip6
41
- subject = TCPClient::Address.new('[::1]:42')
42
- assert_equal('[::1]:42', subject.to_s)
43
- assert_equal('::1', subject.hostname)
44
- assert_same(42, subject.addrinfo.ip_port)
45
- assert(subject.addrinfo.ip?)
46
- assert(subject.addrinfo.ipv6?)
47
- end
48
-
49
- def test_create_from_empty_str
50
- subject = TCPClient::Address.new('')
51
- assert_equal('localhost:0', subject.to_s)
52
- assert_equal('localhost', subject.hostname)
53
- assert_same(0, subject.addrinfo.ip_port)
54
- assert(subject.addrinfo.ip?)
55
- assert(subject.addrinfo.ipv6?)
56
- end
57
-
58
- def test_compare
59
- a = TCPClient::Address.new('localhost:42')
60
- b = TCPClient::Address.new('localhost:42')
61
- assert_equal(a, b)
62
- assert(a == b)
63
- assert(a === b)
64
- end
65
- end
@@ -1,141 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../helper'
4
-
5
- class ConfigurationTest < Test
6
- def test_defaults
7
- subject = TCPClient::Configuration.new
8
- assert(subject.buffered)
9
- assert(subject.keep_alive)
10
- assert(subject.reverse_lookup)
11
- refute(subject.ssl?)
12
- assert_nil(subject.connect_timeout)
13
- assert_nil(subject.read_timeout)
14
- assert_nil(subject.write_timeout)
15
- end
16
-
17
- def test_configure
18
- subject =
19
- TCPClient::Configuration.create do |cfg|
20
- cfg.buffered = cfg.keep_alive = cfg.reverse_lookup = false
21
- cfg.timeout = 42
22
- cfg.ssl = true
23
- end
24
- refute(subject.buffered)
25
- refute(subject.keep_alive)
26
- refute(subject.reverse_lookup)
27
- assert_same(42, subject.connect_timeout)
28
- assert_same(42, subject.read_timeout)
29
- assert_same(42, subject.write_timeout)
30
- assert(subject.ssl?)
31
- end
32
-
33
- def test_options
34
- subject =
35
- TCPClient::Configuration.new(
36
- buffered: false,
37
- keep_alive: false,
38
- reverse_lookup: false,
39
- connect_timeout: 1,
40
- read_timeout: 2,
41
- write_timeout: 3,
42
- ssl: true,
43
- connect_timeout_error: IOError
44
- )
45
- refute(subject.buffered)
46
- refute(subject.keep_alive)
47
- refute(subject.reverse_lookup)
48
- assert_same(1, subject.connect_timeout)
49
- assert_same(2, subject.read_timeout)
50
- assert_same(3, subject.write_timeout)
51
- assert(subject.ssl?)
52
- assert_same(IOError, subject.connect_timeout_error)
53
- assert_same(TCPClient::ReadTimeoutError, subject.read_timeout_error)
54
- end
55
-
56
- def test_invalid_option
57
- err =
58
- assert_raises(ArgumentError) do
59
- TCPClient::Configuration.new(unknown_attr: :argument)
60
- end
61
- assert_includes(err.message, 'attribute')
62
- assert_includes(err.message, 'unknown_attr')
63
- end
64
-
65
- def test_ssl_params
66
- subject = TCPClient::Configuration.new
67
- refute(subject.ssl?)
68
- assert_nil(subject.ssl_params)
69
- subject.ssl = true
70
- assert(subject.ssl?)
71
- assert_empty(subject.ssl_params)
72
- subject.ssl_params[:ssl_version] = :TLSv1_2
73
- subject.ssl = false
74
- assert_nil(subject.ssl_params)
75
- end
76
-
77
- def test_timeout_overwrite
78
- subject =
79
- TCPClient::Configuration.create do |cfg|
80
- cfg.connect_timeout = 1
81
- cfg.read_timeout = 2
82
- cfg.write_timeout = 3
83
- end
84
- assert_same(1, subject.connect_timeout)
85
- assert_same(2, subject.read_timeout)
86
- assert_same(3, subject.write_timeout)
87
-
88
- subject.timeout = 42
89
- assert_same(42, subject.connect_timeout)
90
- assert_same(42, subject.read_timeout)
91
- assert_same(42, subject.write_timeout)
92
- end
93
-
94
- def test_timeout_error_overwrite
95
- subject = TCPClient::Configuration.new
96
- assert_same(TCPClient::ConnectTimeoutError, subject.connect_timeout_error)
97
- assert_same(TCPClient::ReadTimeoutError, subject.read_timeout_error)
98
- assert_same(TCPClient::WriteTimeoutError, subject.write_timeout_error)
99
-
100
- subject.timeout_error = IOError
101
- assert_same(IOError, subject.connect_timeout_error)
102
- assert_same(IOError, subject.read_timeout_error)
103
- assert_same(IOError, subject.write_timeout_error)
104
- end
105
-
106
- def test_compare
107
- a = TCPClient::Configuration.new
108
- b = TCPClient::Configuration.new
109
- assert_equal(a, b)
110
- assert(a == b)
111
- assert(a === b)
112
- end
113
-
114
- def test_dup
115
- source =
116
- TCPClient::Configuration.new(
117
- buffered: false,
118
- keep_alive: false,
119
- reverse_lookup: false,
120
- connect_timeout: 1,
121
- read_timeout: 2,
122
- write_timeout: 3,
123
- ssl: {
124
- ssl_version: :TLSv1_2
125
- }
126
- )
127
- shadow = source.dup.freeze
128
-
129
- # some changes
130
- source.buffered = true
131
- source.write_timeout = 5
132
- source.ssl_params[:err] = true
133
- source.timeout_error = IOError
134
-
135
- refute_equal(source.__id__, shadow.__id__)
136
- refute(shadow.buffered)
137
- assert_equal(3, shadow.write_timeout)
138
- assert_equal({ ssl_version: :TLSv1_2 }, shadow.ssl_params)
139
- assert_same(TCPClient::ReadTimeoutError, shadow.read_timeout_error)
140
- end
141
- end
@@ -1,26 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../helper'
4
-
5
- class DeadlineTest < Test
6
- Deadline = TCPClient.const_get(:Deadline)
7
-
8
- def test_validity
9
- assert(Deadline.new(1).valid?)
10
- assert(Deadline.new(0.0001).valid?)
11
-
12
- refute(Deadline.new(0).valid?)
13
- refute(Deadline.new(nil).valid?)
14
- end
15
-
16
- def test_remaining_time
17
- assert(Deadline.new(1).remaining_time > 0)
18
-
19
- assert_nil(Deadline.new(0).remaining_time)
20
- assert_nil(Deadline.new(nil).remaining_time)
21
-
22
- deadline = Deadline.new(0.2)
23
- sleep(0.2)
24
- assert_nil(deadline.remaining_time)
25
- end
26
- end
@@ -1,59 +0,0 @@
1
- require_relative '../helper'
2
-
3
- class DefauktConfigurationTest < MiniTest::Test
4
- def test_default
5
- subject = TCPClient.configure # reset to defaults
6
-
7
- assert_same(
8
- TCPClient.default_configuration,
9
- TCPClient::Configuration.default
10
- )
11
- assert(subject.buffered)
12
- assert(subject.keep_alive)
13
- assert(subject.reverse_lookup)
14
- refute(subject.ssl?)
15
- assert_nil(subject.connect_timeout)
16
- assert_nil(subject.read_timeout)
17
- assert_nil(subject.write_timeout)
18
- end
19
-
20
- def test_configure_options
21
- TCPClient.configure(
22
- buffered: false,
23
- keep_alive: false,
24
- reverse_lookup: false,
25
- ssl: true,
26
- connect_timeout: 1,
27
- read_timeout: 2,
28
- write_timeout: 3
29
- )
30
- subject = TCPClient.default_configuration
31
- refute(subject.buffered)
32
- refute(subject.keep_alive)
33
- refute(subject.reverse_lookup)
34
- assert(subject.ssl?)
35
- assert_same(1, subject.connect_timeout)
36
- assert_same(2, subject.read_timeout)
37
- assert_same(3, subject.write_timeout)
38
- end
39
-
40
- def test_configure_block
41
- TCPClient.configure do |cfg|
42
- cfg.buffered = false
43
- cfg.keep_alive = false
44
- cfg.reverse_lookup = false
45
- cfg.ssl = true
46
- cfg.connect_timeout = 1
47
- cfg.read_timeout = 2
48
- cfg.write_timeout = 3
49
- end
50
- subject = TCPClient.default_configuration
51
- refute(subject.buffered)
52
- refute(subject.keep_alive)
53
- refute(subject.reverse_lookup)
54
- assert(subject.ssl?)
55
- assert_same(1, subject.connect_timeout)
56
- assert_same(2, subject.read_timeout)
57
- assert_same(3, subject.write_timeout)
58
- end
59
- end
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../helper'
4
-
5
- class VersionTest < Test
6
- def test_format
7
- assert_match(/\d+\.\d+\.\d+/, TCPClient::VERSION)
8
- end
9
- end
@@ -1,184 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'helper'
4
-
5
- class TCPClientTest < Test
6
- HUGE_AMOUNT_OF_DATA = Array.new(1024, '?' * 2048).freeze
7
-
8
- attr_reader :config
9
-
10
- def setup
11
- @config = TCPClient::Configuration.create(buffered: false)
12
- end
13
-
14
- def port
15
- PseudoServer.local_address.ip_port
16
- end
17
-
18
- def address
19
- "localhost:#{port}"
20
- end
21
-
22
- def test_defaults
23
- subject = TCPClient.new
24
- assert(subject.closed?)
25
- assert_equal('', subject.to_s)
26
- assert_nil(subject.address)
27
- subject.close
28
- assert_raises(TCPClient::NotConnectedError) do
29
- subject.write('hello world!')
30
- end
31
- assert_raises(TCPClient::NotConnectedError) { subject.read(42) }
32
- end
33
-
34
- def create_nonconnected_client
35
- client = TCPClient.new
36
- client.connect('', config)
37
- :you_should_not_get_this
38
- rescue Errno::EADDRNOTAVAIL
39
- client
40
- end
41
-
42
- def test_failed_state
43
- subject = create_nonconnected_client
44
- assert(subject.closed?)
45
- assert_equal('localhost:0', subject.to_s)
46
- refute_nil(subject.address)
47
- assert_equal('localhost:0', subject.address.to_s)
48
- assert_equal('localhost', subject.address.hostname)
49
- assert_instance_of(Addrinfo, subject.address.addrinfo)
50
- assert_same(0, subject.address.addrinfo.ip_port)
51
- assert_raises(TCPClient::NotConnectedError) do
52
- subject.write('hello world!')
53
- end
54
- assert_raises(TCPClient::NotConnectedError) { subject.read(42) }
55
- end
56
-
57
- def test_connected_state
58
- TCPClient.open(address, config) do |subject|
59
- refute(subject.closed?)
60
- assert_equal(address, subject.to_s)
61
- refute_nil(subject.address)
62
- address_when_opened = subject.address
63
- assert_equal(address, subject.address.to_s)
64
- assert_equal('localhost', subject.address.hostname)
65
- assert_instance_of(Addrinfo, subject.address.addrinfo)
66
- assert_same(port, subject.address.addrinfo.ip_port)
67
-
68
- subject.close
69
- assert(subject.closed?)
70
- assert_same(address_when_opened, subject.address)
71
- end
72
- end
73
-
74
- def check_read_timeout(timeout)
75
- TCPClient.open(address, config) do |subject|
76
- refute(subject.closed?)
77
- timing = Timing.new
78
- assert_raises(TCPClient::ReadTimeoutError) do
79
- timing.start
80
- subject.read(42, timeout: timeout)
81
- end
82
- assert_in_delta(timeout, timing.elapsed, 0.15)
83
- end
84
- end
85
-
86
- def test_read_timeout
87
- check_read_timeout(0.5)
88
- check_read_timeout(1)
89
- check_read_timeout(1.5)
90
- end
91
-
92
- def check_write_timeout(timeout)
93
- TCPClient.open(address, config) do |subject|
94
- refute(subject.closed?)
95
- timing = Timing.new
96
- assert_raises(TCPClient::WriteTimeoutError) do
97
- timing.start
98
- subject.write(*HUGE_AMOUNT_OF_DATA, timeout: timeout)
99
- end
100
- assert_in_delta(timeout, timing.elapsed, 0.15)
101
- end
102
- end
103
-
104
- def test_write_timeout
105
- check_write_timeout(0.01)
106
- check_write_timeout(0.25)
107
- end
108
-
109
- def test_write_deadline
110
- TCPClient.open(address, config) do |subject|
111
- refute(subject.closed?)
112
- assert_raises(TCPClient::WriteTimeoutError) do
113
- subject.with_deadline(0.25) do |*args|
114
- assert_equal([subject], args)
115
- loop { subject.write('some data here') }
116
- end
117
- end
118
- end
119
- end
120
-
121
- def test_read_deadline
122
- TCPClient.open(address, config) do |subject|
123
- refute(subject.closed?)
124
- assert_raises(TCPClient::ReadTimeoutError) do
125
- subject.with_deadline(0.25) do |*args|
126
- assert_equal([subject], args)
127
- loop { subject.read(42) }
128
- end
129
- end
130
- end
131
- end
132
-
133
- def test_read_write_deadline
134
- TCPClient.open(address, config) do |subject|
135
- refute(subject.closed?)
136
- assert_raises(TCPClient::TimeoutError) do
137
- subject.with_deadline(0.25) do |*args|
138
- assert_equal([subject], args)
139
- loop do
140
- subject.write('some data')
141
- subject.read(0)
142
- end
143
- end
144
- end
145
- end
146
- end
147
-
148
- def check_connect_timeout(ssl_config)
149
- timing = Timing.new
150
- assert_raises(TCPClient::ConnectTimeoutError) do
151
- timing.start
152
- TCPClient.new.connect(address, ssl_config)
153
- end
154
- assert_in_delta(ssl_config.connect_timeout, timing.elapsed, 0.25)
155
- end
156
-
157
- def test_connect_ssl_timeout
158
- ssl_config = TCPClient::Configuration.new(ssl: true)
159
-
160
- ssl_config.connect_timeout = 0.5
161
- check_connect_timeout(ssl_config)
162
-
163
- ssl_config.connect_timeout = 1
164
- check_connect_timeout(ssl_config)
165
-
166
- ssl_config.connect_timeout = 1.5
167
- check_connect_timeout(ssl_config)
168
- end
169
-
170
- def test_deadline
171
- assert(TCPClient.with_deadline(0.15, address, config, &:itself).closed?)
172
- end
173
-
174
- def test_deadline_timeout
175
- timing = Timing.new
176
- assert_raises(TCPClient::ReadTimeoutError) do
177
- timing.start
178
- TCPClient.with_deadline(0.15, address, config) do |client|
179
- client.read(42)
180
- end
181
- end
182
- assert_in_delta(0.15, timing.elapsed, 0.15)
183
- end
184
- end