tcp-client 0.7.0 → 0.9.2

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.
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