async-io 1.17.2 → 1.18.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ac60f3c447092c125c2bada2e45757ef028828c3dcfa35aebc69dde2f6cf3a3e
4
- data.tar.gz: 9c40c940f5550265375556c156f925a7a7a05cadfeff2fe819cdae8b09cbac29
3
+ metadata.gz: 123cd8404fb47fe4beed0cac26b5b1f6825eb34b6a7e9952ef571c6103f72fab
4
+ data.tar.gz: c2313c72cd403abddfc5a7235f82c7983639501db2ce664792e46d09cfca7ebe
5
5
  SHA512:
6
- metadata.gz: e1c3cf6b86633efe3812b91300a273738f5e01ed5fa1c5ee2fba691cb04abc39f6e69562cc0e382511510052a4a120a901bdf385a48aabe150fddc1644e7f332
7
- data.tar.gz: 4fd20b81655da735b8f327db0bffa3162d452beebcc8bc9da05c88bd097119206da45da1f9b4aa000acac030fa60a0b70e55d2d7e669f3c1bf21e898dc78b63e
6
+ metadata.gz: 7fa15dba98d1c12d00ddfdfd2410cefa1767ef946d58751c2a1498b4226ee74a10255f38749c618275116f2b49f081a9d07518cfe4eb1f82416618db27d04426
7
+ data.tar.gz: df87e800a13784df609488498dba29c72220aac213745e470628f650d0f031dc321b2463e079502a553e5a32aea7d95b6c690d229aa9d5f6201c3e8e45063575
@@ -1,12 +1,7 @@
1
1
  language: ruby
2
- sudo: false
3
- dist: trusty
2
+ dist: xenial
4
3
  cache: bundler
5
4
 
6
- before_script:
7
- - gem update --system
8
- - gem install bundler
9
-
10
5
  matrix:
11
6
  include:
12
7
  - rvm: 2.3
@@ -17,9 +12,7 @@ matrix:
17
12
  - rvm: jruby-head
18
13
  env: JRUBY_OPTS="--debug -X+O"
19
14
  - rvm: ruby-head
20
- - rvm: rbx-3
21
15
  allow_failures:
22
16
  - rvm: ruby-head
23
17
  - rvm: truffleruby
24
18
  - rvm: jruby-head
25
- - rvm: rbx-3
data/README.md CHANGED
@@ -87,6 +87,40 @@ end
87
87
 
88
88
  Any `yield` operation can cause a timeout to trigger. Non-`async` functions might not timeout because they are outside the scope of `async`.
89
89
 
90
+ #### Wrapper Timeouts
91
+
92
+ Asynchronous operations may block forever. You can assign a per-wrapper operation timeout duration. All asynchronous operations will be bounded by this timeout.
93
+
94
+ ```ruby
95
+ peer.timeout_duration = 1
96
+ peer.read(512) # If this takes more than 1 second, Async::TimeoutError will be raised.
97
+ ```
98
+
99
+ The benefit of this approach is that it applies to all operations. Typically, this would be configured by the user, and set to something pretty high, e.g. 120 seconds.
100
+
101
+ ### Reading Characters
102
+
103
+ This example shows how to read one character at a time as the user presses it on the keyboard, and echos it back out as uppercase:
104
+
105
+ ```ruby
106
+ require 'async'
107
+ require 'async/io/stream'
108
+ require 'io/console'
109
+
110
+ $stdin.raw!
111
+ $stdin.echo = false
112
+
113
+ Async do |task|
114
+ stdin = Async::IO::Stream.new(
115
+ Async::IO::Generic.new($stdin)
116
+ )
117
+
118
+ while character = stdin.read(1)
119
+ $stdout.write character.upcase
120
+ end
121
+ end
122
+ ```
123
+
90
124
  ## Contributing
91
125
 
92
126
  1. Fork it
@@ -1,4 +1,4 @@
1
- # coding: utf-8
1
+
2
2
  require_relative 'lib/async/io/version'
3
3
 
4
4
  Gem::Specification.new do |spec|
@@ -15,12 +15,12 @@ Gem::Specification.new do |spec|
15
15
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
16
16
  spec.require_paths = ["lib"]
17
17
 
18
- spec.add_dependency "async", "~> 1.3"
18
+ spec.add_dependency "async", "~> 1.14"
19
19
  spec.add_development_dependency "async-rspec", "~> 1.10"
20
20
 
21
21
  spec.required_ruby_version = '~> 2.3'
22
22
 
23
- spec.add_development_dependency "bundler", "~> 1.3"
23
+ spec.add_development_dependency "bundler"
24
24
  spec.add_development_dependency "rake", "~> 10.0"
25
25
  spec.add_development_dependency "rspec", "~> 3.0"
26
26
  end
@@ -37,6 +37,14 @@ module Async
37
37
  @options[:hostname]
38
38
  end
39
39
 
40
+ def reuse_port
41
+ @options[:reuse_port]
42
+ end
43
+
44
+ def timeout
45
+ @options[:timeout]
46
+ end
47
+
40
48
  def each
41
49
  return to_enum unless block_given?
42
50
 
@@ -97,7 +97,13 @@ module Async
97
97
  alias syswrite write
98
98
  alias << write
99
99
 
100
- def wait(timeout = nil, mode = :read)
100
+ def dup
101
+ super.tap do |copy|
102
+ copy.timeout = self.timeout
103
+ end
104
+ end
105
+
106
+ def wait(timeout = self.timeout, mode = :read)
101
107
  case mode
102
108
  when :read
103
109
  wait_readable(timeout)
@@ -106,12 +112,17 @@ module Async
106
112
  else
107
113
  wait_any(:rw, timeout)
108
114
  end
115
+ rescue TimeoutError
116
+ return nil
109
117
  end
110
118
 
111
119
  def nonblock
112
120
  true
113
121
  end
114
- alias nonblock= nonblock
122
+
123
+ def nonblock= value
124
+ true
125
+ end
115
126
 
116
127
  def nonblock?
117
128
  true
@@ -121,17 +132,19 @@ module Async
121
132
  !@io.closed?
122
133
  end
123
134
 
135
+ attr_accessor :timeout
136
+
124
137
  protected
125
138
 
126
- def async_send(*args)
139
+ def async_send(*args, timeout: self.timeout)
127
140
  while true
128
141
  result = @io.__send__(*args, exception: false)
129
142
 
130
143
  case result
131
144
  when :wait_readable
132
- wait_readable
145
+ wait_readable(timeout)
133
146
  when :wait_writable
134
- wait_writable
147
+ wait_writable(timeout)
135
148
  else
136
149
  return result
137
150
  end
@@ -49,7 +49,9 @@ module Async
49
49
  self.new(endpoint, [peer])
50
50
  end
51
51
 
52
- def initialize(endpoint, wrappers)
52
+ def initialize(endpoint, wrappers, **options)
53
+ super(**options)
54
+
53
55
  @endpoint = endpoint
54
56
  @wrappers = wrappers
55
57
  end
@@ -87,11 +87,11 @@ module Async
87
87
  end
88
88
 
89
89
  module Server
90
- def accept_each(task: Task.current)
90
+ def accept_each(timeout: nil, task: Task.current)
91
91
  task.annotate "accepting connections #{self.local_address.inspect}"
92
92
 
93
93
  while true
94
- self.accept(task: task) do |io, address|
94
+ self.accept(timeout: timeout, task: task) do |io, address|
95
95
  yield io, address, task: task
96
96
  end
97
97
  end
@@ -115,10 +115,13 @@ module Async
115
115
 
116
116
  alias connect_nonblock connect
117
117
 
118
- def accept(task: Task.current)
119
- peer, address = async_send(:accept_nonblock)
118
+ # @param duration [Numeric] the maximum time to wait for accepting a connection, if specified.
119
+ def accept(timeout: nil, task: Task.current)
120
+ peer, address = async_send(:accept_nonblock, timeout: timeout)
120
121
  wrapper = Socket.new(peer, task.reactor)
121
122
 
123
+ wrapper.timeout = self.timeout
124
+
122
125
  return wrapper, address unless block_given?
123
126
 
124
127
  task.async do |task|
@@ -126,8 +129,6 @@ module Async
126
129
 
127
130
  begin
128
131
  yield wrapper, address
129
- rescue
130
- Async.logger.error(self) {$!}
131
132
  ensure
132
133
  wrapper.close
133
134
  end
@@ -137,12 +138,15 @@ module Async
137
138
  alias accept_nonblock accept
138
139
  alias sysaccept accept
139
140
 
140
- def self.build(*args, task: Task.current)
141
+ def self.build(*args, timeout: nil, task: Task.current)
141
142
  socket = wrapped_klass.new(*args)
142
143
 
143
144
  yield socket
144
145
 
145
- return self.new(socket, task.reactor)
146
+ wrapper = self.new(socket, task.reactor)
147
+ wrapper.timeout = timeout
148
+
149
+ return wrapper
146
150
  rescue Exception
147
151
  socket.close if socket
148
152
 
@@ -168,8 +172,6 @@ module Async
168
172
  if local_address
169
173
  socket.bind(local_address.to_sockaddr)
170
174
  end
171
-
172
- self.new(socket, task.reactor)
173
175
  end
174
176
 
175
177
  begin
@@ -199,7 +201,6 @@ module Async
199
201
  Async.logger.debug(self) {"Binding to #{local_address.inspect}"}
200
202
 
201
203
  wrapper = build(local_address.afamily, local_address.socktype, protocol, **options) do |socket|
202
-
203
204
  if reuse_address
204
205
  socket.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_REUSEADDR, 1)
205
206
  end
@@ -84,6 +84,9 @@ module Async
84
84
  # This ensures that when the internal IO is closed, it also closes the internal socket:
85
85
  io.sync_close = true
86
86
 
87
+ # Copy the timeout:
88
+ @timeout = socket.timeout
89
+
87
90
  super(io, socket.reactor)
88
91
  end
89
92
  end
@@ -102,7 +105,7 @@ module Async
102
105
  self.class.new(@server.dup, @context)
103
106
  end
104
107
 
105
- def_delegators :@server, :local_address, :setsockopt, :getsockopt, :close, :close_on_exec=, :reactor=
108
+ def_delegators :@server, :local_address, :setsockopt, :getsockopt, :close, :close_on_exec=, :reactor=, :timeout, :timeout=
106
109
 
107
110
  attr :server
108
111
  attr :context
@@ -111,8 +114,8 @@ module Async
111
114
  @server.listen(*args)
112
115
  end
113
116
 
114
- def accept(task: Task.current)
115
- peer, address = @server.accept
117
+ def accept(task: Task.current, **options)
118
+ peer, address = @server.accept(**options)
116
119
 
117
120
  wrapper = SSLSocket.new(peer, @context)
118
121
 
@@ -126,8 +129,6 @@ module Async
126
129
  wrapper.accept
127
130
 
128
131
  yield wrapper, address
129
- rescue
130
- Async.logger.error(self) {$!}
131
132
  ensure
132
133
  wrapper.close
133
134
  end
@@ -20,6 +20,8 @@
20
20
 
21
21
  require_relative 'notification'
22
22
 
23
+ require 'thread'
24
+
23
25
  module Async
24
26
  module IO
25
27
  # A cross-reactor/process notification pipe.
@@ -27,12 +29,30 @@ module Async
27
29
  def initialize(name)
28
30
  @name = name
29
31
  @notifications = []
32
+
33
+ @installed = false
34
+ @mutex = Mutex.new
35
+ end
36
+
37
+ # Ignore the trap within the current process. Can be invoked before forking and/or invoking `install!` to assert default behaviour.
38
+ def ignore!
39
+ Signal.trap(@name, "IGNORE")
30
40
  end
31
41
 
42
+ # Install the trap into the current process. Thread safe.
43
+ # @return [Boolean] whether the trap was installed or not. If the trap was already installed, returns nil.
32
44
  def install!
33
- Signal.trap(@name, &self.method(:trigger))
45
+ return if @installed
46
+
47
+ @mutex.synchronize do
48
+ return if @installed
49
+
50
+ Signal.trap(@name, &self.method(:trigger))
51
+
52
+ @installed = true
53
+ end
34
54
 
35
- return self
55
+ return true
36
56
  end
37
57
 
38
58
  # Block the calling task until the signal occurs.
@@ -20,6 +20,6 @@
20
20
 
21
21
  module Async
22
22
  module IO
23
- VERSION = "1.17.2"
23
+ VERSION = "1.18.1"
24
24
  end
25
25
  end
@@ -27,7 +27,7 @@ RSpec.describe "echo client/server" do
27
27
  # sudo sysctl -w net.inet.ip.portrange.hifirst=10000
28
28
  # Probably due to the use of select.
29
29
 
30
- let(:repeats) {RUBY_PLATFORM =~ /darwin/ ? 100 : 10000}
30
+ let(:repeats) {RUBY_PLATFORM =~ /darwin/ ? 200 : 10000}
31
31
  let(:server_address) {Async::IO::Address.tcp('0.0.0.0', 10102)}
32
32
 
33
33
  def echo_server(server_address)
@@ -99,19 +99,7 @@ RSpec.describe "echo client/server" do
99
99
  example.run
100
100
  end
101
101
 
102
- example.reporter.message "Handled #{repeats} connections in #{duration}: #{repeats/duration}req/s"
103
- end
104
-
105
- around(:each) do |example|
106
- previous_level = Async.logger.level
107
- # Supress logging:
108
- Async.logger.level = Logger::WARN
109
-
110
- begin
111
- example.run
112
- ensure
113
- Async.logger.level = previous_level
114
- end
102
+ example.reporter.message "Handled #{repeats} connections in #{duration.round(2)}s: #{(repeats/duration).round(2)}req/s"
115
103
  end
116
104
 
117
105
  it "should send/receive 10,000 messages" do
@@ -28,15 +28,23 @@ RSpec.describe Async::IO::Endpoint do
28
28
  it "should have hostname" do
29
29
  expect(subject.hostname).to be == "lolcathost"
30
30
  end
31
+
32
+ it "shouldn't have a timeout duration" do
33
+ expect(subject.timeout).to be_nil
34
+ end
31
35
  end
32
36
 
33
- describe Async::IO::Endpoint.tcp('0.0.0.0', 5234, reuse_port: true) do
37
+ describe Async::IO::Endpoint.tcp('0.0.0.0', 5234, reuse_port: true, timeout: 10) do
34
38
  it "should be a tcp binding" do
35
39
  subject.bind do |server|
36
40
  expect(server.local_address.socktype).to be == ::Socket::SOCK_STREAM
37
41
  end
38
42
  end
39
43
 
44
+ it "should have a timeout duration" do
45
+ expect(subject.timeout).to be 10
46
+ end
47
+
40
48
  it "should print nicely" do
41
49
  expect(subject.to_s).to include('0.0.0.0', '5234')
42
50
  end
@@ -48,6 +56,25 @@ RSpec.describe Async::IO::Endpoint do
48
56
  it "has hostname" do
49
57
  expect(subject.hostname).to be == '0.0.0.0'
50
58
  end
59
+
60
+ let(:message) {"Hello World!"}
61
+
62
+ it "can connect to bound server" do
63
+ server_task = reactor.async do
64
+ subject.accept do |io|
65
+ expect(io.timeout).to be == 10
66
+ io.write message
67
+ io.close
68
+ end
69
+ end
70
+
71
+ io = subject.connect
72
+ expect(io.timeout).to be == 10
73
+ expect(io.read(message.bytesize)).to be == message
74
+ io.close
75
+
76
+ server_task.stop
77
+ end
51
78
  end
52
79
 
53
80
  describe Async::IO::Endpoint.tcp('0.0.0.0', 0) do
@@ -19,6 +19,7 @@
19
19
  # THE SOFTWARE.
20
20
 
21
21
  require 'async/io'
22
+ require 'async/clock'
22
23
 
23
24
  require_relative 'generic_examples'
24
25
 
@@ -31,25 +32,73 @@ RSpec.describe Async::IO::Generic do
31
32
  :bytes, :chars, :codepoints, :each, :each_byte, :each_char, :each_codepoint, :each_line, :getbyte, :getc, :gets, :lineno, :lineno=, :lines, :print, :printf, :putc, :puts, :readbyte, :readchar, :readline, :readlines, :ungetbyte, :ungetc
32
33
  ] + CONSOLE_METHODS
33
34
 
35
+ let(:message) {"Hello World!"}
36
+
34
37
  let(:pipe) {IO.pipe}
35
38
  let(:input) {Async::IO::Generic.new(pipe.first)}
36
39
  let(:output) {Async::IO::Generic.new(pipe.last)}
37
40
 
38
41
  it "should send and receive data within the same reactor" do
39
- message = nil
42
+ received = nil
40
43
 
41
44
  output_task = reactor.async do
42
- message = input.read(1024)
45
+ received = input.read(1024)
43
46
  end
44
47
 
45
48
  reactor.async do
46
- output.write("Hello World")
49
+ output.write(message)
47
50
  end
48
51
 
49
52
  output_task.wait
50
- expect(message).to be == "Hello World"
53
+ expect(received).to be == message
51
54
 
52
55
  input.close
53
56
  output.close
54
57
  end
58
+
59
+ describe '#wait' do
60
+ let(:wait_duration) {0.1}
61
+
62
+ it "can wait for :read and :write" do
63
+ reader = reactor.async do |task|
64
+ duration = Async::Clock.measure do
65
+ input.wait(1, :read)
66
+ end
67
+
68
+ expect(duration).to be_within(10).percent_of(wait_duration)
69
+ expect(input.read(1024)).to be == message
70
+
71
+ input.close
72
+ end
73
+
74
+ writer = reactor.async do |task|
75
+ duration = Async::Clock.measure do
76
+ output.wait(1, :write)
77
+ end
78
+
79
+ task.sleep(wait_duration)
80
+
81
+ output.write(message)
82
+ output.close
83
+ end
84
+
85
+ [reader, writer].each(&:wait)
86
+ end
87
+
88
+ it "can return nil when timeout is exceeded" do
89
+ reader = reactor.async do |task|
90
+ duration = Async::Clock.measure do
91
+ expect(input.wait(wait_duration, :read)).to be_nil
92
+ end
93
+
94
+ expect(duration).to be_within(10).percent_of(wait_duration)
95
+
96
+ input.close
97
+ end
98
+
99
+ [reader].each(&:wait)
100
+
101
+ output.close
102
+ end
103
+ end
55
104
  end
@@ -38,7 +38,7 @@ RSpec.shared_examples_for Async::IO::SharedEndpoint do |container_class|
38
38
  let!(:bound_endpoint) do
39
39
  Async::Reactor.run do
40
40
  Async::IO::SharedEndpoint.bound(server_endpoint)
41
- end.result
41
+ end.wait
42
42
  end
43
43
 
44
44
  it "can use bound endpoint in container" do
@@ -21,32 +21,45 @@
21
21
  require 'async/io/host_endpoint'
22
22
  require 'async/io/shared_endpoint'
23
23
 
24
+ require 'pry'
25
+
24
26
  RSpec.describe Async::IO::SharedEndpoint do
25
27
  include_context Async::RSpec::Reactor
26
28
 
27
29
  describe '#bound' do
28
- let(:endpoint) {Async::IO::Endpoint.tcp("localhost", 5123)}
30
+ let(:endpoint) {Async::IO::Endpoint.tcp("localhost", 5123, timeout: 10)}
29
31
 
30
32
  it "can bind to shared endpoint" do
31
33
  bound_endpoint = described_class.bound(endpoint)
32
-
33
34
  expect(bound_endpoint.wrappers).to_not be_empty
34
- expect(bound_endpoint.wrappers.first).to be_a Async::IO::Socket
35
+
36
+ wrapper = bound_endpoint.wrappers.first
37
+ expect(wrapper).to be_a Async::IO::Socket
38
+ expect(wrapper.timeout).to be == endpoint.timeout
35
39
 
36
40
  bound_endpoint.close
37
41
  end
38
42
  end
39
43
 
40
44
  describe '#connected' do
41
- let(:endpoint) {Async::IO::Endpoint.tcp("www.google.com", 80)}
45
+ let(:endpoint) {Async::IO::Endpoint.tcp("localhost", 5124, timeout: 10)}
42
46
 
43
47
  it "can connect to shared endpoint" do
44
- connected_endpoint = described_class.connected(endpoint)
48
+ server_task = reactor.async do
49
+ endpoint.accept do |io|
50
+ io.close
51
+ end
52
+ end
45
53
 
54
+ connected_endpoint = described_class.connected(endpoint)
46
55
  expect(connected_endpoint.wrappers).to_not be_empty
47
- expect(connected_endpoint.wrappers.first).to be_a Async::IO::Socket
56
+
57
+ wrapper = connected_endpoint.wrappers.first
58
+ expect(wrapper).to be_a Async::IO::Socket
59
+ expect(wrapper.timeout).to be == endpoint.timeout
48
60
 
49
61
  connected_endpoint.close
62
+ server_task.stop
50
63
  end
51
64
  end
52
65
  end
@@ -37,7 +37,7 @@ RSpec.describe Async::IO::Socket do
37
37
  it "should fail to connect if no listening server" do
38
38
  expect do
39
39
  Async::IO::Socket.connect(address)
40
- end.to raise_error(Errno::ECONNREFUSED)
40
+ end.to raise_exception(Errno::ECONNREFUSED)
41
41
  end
42
42
 
43
43
  it "should close the socket when interrupted by a timeout" do
@@ -47,7 +47,7 @@ RSpec.describe Async::IO::Socket do
47
47
  expect(wrapper).to receive(:close)
48
48
  expect do
49
49
  Async::IO::Socket.connect(address)
50
- end.to raise_error(Async::TimeoutError)
50
+ end.to raise_exception(Async::TimeoutError)
51
51
  end
52
52
  end
53
53
 
@@ -57,7 +57,7 @@ RSpec.describe Async::IO::Socket do
57
57
 
58
58
  expect do
59
59
  Async::IO::Socket.bind(address)
60
- end.to raise_error(Errno::EACCES)
60
+ end.to raise_exception(Errno::EACCES)
61
61
  end
62
62
 
63
63
  it "can bind to port 0" do
@@ -84,6 +84,21 @@ RSpec.describe Async::IO::Socket do
84
84
  end
85
85
  end
86
86
 
87
+ describe '#timeout' do
88
+ subject{described_class.pair(:UNIX, :STREAM, 0)}
89
+
90
+ it "should timeout while waiting to receive data" do
91
+ s1, s2 = *subject
92
+
93
+ s2.timeout = 1
94
+
95
+ expect{s2.recv(32)}.to raise_exception(Async::TimeoutError, "execution expired")
96
+
97
+ s1.close
98
+ s2.close
99
+ end
100
+ end
101
+
87
102
  describe '.pair' do
88
103
  subject{described_class.pair(:UNIX, :STREAM, 0)}
89
104
 
@@ -115,7 +115,7 @@ RSpec.describe Async::IO::SSLServer do
115
115
  expect do
116
116
  invalid_client_endpoint.connect do |client|
117
117
  end
118
- end.to raise_error(OpenSSL::SSL::SSLError, /handshake failure/)
118
+ end.to raise_exception(OpenSSL::SSL::SSLError, /handshake failure/)
119
119
 
120
120
  server_task.stop
121
121
  end
@@ -30,9 +30,9 @@ RSpec.describe Async::IO::SSLSocket do
30
30
  it_should_behave_like Async::IO::Generic
31
31
 
32
32
  # Shared port for localhost network tests.
33
- let(:endpoint) {Async::IO::Endpoint.tcp("127.0.0.1", 6779, reuse_port: true)}
34
- let(:server_endpoint) {Async::IO::SSLEndpoint.new(endpoint, ssl_context: server_context)}
35
- let(:client_endpoint) {Async::IO::SSLEndpoint.new(endpoint, ssl_context: client_context)}
33
+ let(:endpoint) {Async::IO::Endpoint.tcp("127.0.0.1", 6779, reuse_port: true, timeout: 10)}
34
+ let(:server_endpoint) {Async::IO::SSLEndpoint.new(endpoint, ssl_context: server_context, timeout: 20)}
35
+ let(:client_endpoint) {Async::IO::SSLEndpoint.new(endpoint, ssl_context: client_context, timeout: 20)}
36
36
 
37
37
  let(:data) {"The quick brown fox jumped over the lazy dog."}
38
38
 
@@ -44,6 +44,8 @@ RSpec.describe Async::IO::SSLSocket do
44
44
 
45
45
  begin
46
46
  server.accept do |peer, address|
47
+ expect(peer.timeout).to be == 10
48
+
47
49
  data = peer.read(512)
48
50
  peer.write(data)
49
51
  end
@@ -64,6 +66,7 @@ RSpec.describe Async::IO::SSLSocket do
64
66
  reactor.async do
65
67
  client_endpoint.connect do |client|
66
68
  expect(client).to be_connected
69
+ expect(client.timeout).to be == 10
67
70
 
68
71
  client.write(data)
69
72
 
@@ -82,7 +85,7 @@ RSpec.describe Async::IO::SSLSocket do
82
85
  reactor.async do
83
86
  expect do
84
87
  client_endpoint.connect
85
- end.to raise_error(OpenSSL::SSL::SSLError)
88
+ end.to raise_exception(OpenSSL::SSL::SSLError)
86
89
  end
87
90
  end
88
91
  end
@@ -161,7 +161,7 @@ RSpec.describe Async::IO::Stream do
161
161
  it "should terminate stream" do
162
162
  expect do
163
163
  stream.eof!
164
- end.to raise_error(EOFError)
164
+ end.to raise_exception(EOFError)
165
165
 
166
166
  expect(stream).to be_eof
167
167
  end
@@ -178,7 +178,7 @@ RSpec.describe Async::IO::Stream do
178
178
 
179
179
  expect do
180
180
  stream.close
181
- end.to_not raise_error
181
+ end.to_not raise_exception
182
182
  end
183
183
  end
184
184
  end
@@ -25,6 +25,12 @@ RSpec.describe Async::IO::Trap do
25
25
 
26
26
  subject {described_class.new(:USR1)}
27
27
 
28
+ it "can ignore signal" do
29
+ subject.ignore!
30
+
31
+ Process.kill(:USR1, Process.pid)
32
+ end
33
+
28
34
  it "should wait for signal" do
29
35
  trapped = false
30
36
 
@@ -39,7 +39,7 @@ RSpec.describe Async::IO do
39
39
  expect do
40
40
  response = HTTP.get('https://www.google.com', wrappers)
41
41
  response.connection.close
42
- end.to_not raise_error
42
+ end.to_not raise_exception
43
43
  end
44
44
  end
45
45
  end
@@ -62,7 +62,7 @@ RSpec.describe Async::IO::TCPSocket do
62
62
 
63
63
  expect do
64
64
  Net::HTTP.get_response('www.google.com', '/')
65
- end.to_not raise_error
65
+ end.to_not raise_exception
66
66
  end
67
67
  end
68
68
 
@@ -70,7 +70,7 @@ RSpec.describe Async::IO::TCPSocket do
70
70
  it "should fetch page" do
71
71
  expect do
72
72
  Net::HTTP.get_response('www.google.com', '/')
73
- end.to_not raise_error
73
+ end.to_not raise_exception
74
74
  end
75
75
  end
76
76
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: async-io
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.17.2
4
+ version: 1.18.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-12-06 00:00:00.000000000 Z
11
+ date: 2019-01-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: async
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.3'
19
+ version: '1.14'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.3'
26
+ version: '1.14'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: async-rspec
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -42,16 +42,16 @@ dependencies:
42
42
  name: bundler
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: '1.3'
47
+ version: '0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - "~>"
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: '1.3'
54
+ version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rake
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -171,8 +171,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
171
171
  - !ruby/object:Gem::Version
172
172
  version: '0'
173
173
  requirements: []
174
- rubyforge_project:
175
- rubygems_version: 2.7.8
174
+ rubygems_version: 3.0.1
176
175
  signing_key:
177
176
  specification_version: 4
178
177
  summary: Provides support for asynchonous TCP, UDP, UNIX and SSL sockets.