async-io 1.17.2 → 1.18.1

Sign up to get free protection for your applications and to get access to all the features.
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.