async-io 1.4.0 → 1.5.0

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.
@@ -20,9 +20,17 @@
20
20
 
21
21
  require 'async/io/socket'
22
22
 
23
+ require_relative 'generic_examples'
24
+
25
+ RSpec.describe Async::IO::BasicSocket do
26
+ it_should_behave_like Async::IO::Generic
27
+ end
28
+
23
29
  RSpec.describe Async::IO::Socket do
24
30
  include_context Async::RSpec::Reactor
25
31
 
32
+ it_should_behave_like Async::IO::Generic
33
+
26
34
  describe '#connect' do
27
35
  let(:address) {Async::IO::Address.tcp('127.0.0.1', 12345)}
28
36
 
@@ -42,4 +50,22 @@ RSpec.describe Async::IO::Socket do
42
50
  end.to raise_error(Errno::EACCES)
43
51
  end
44
52
  end
53
+
54
+ describe '.pair' do
55
+ subject{described_class.pair(:UNIX, :STREAM, 0)}
56
+
57
+ it "should be able to send and recv" do
58
+ s1, s2 = *subject
59
+
60
+ s1.send "Hello World", 0
61
+ s1.close
62
+
63
+ expect(s2.recv(32)).to be == "Hello World"
64
+ s2.close
65
+ end
66
+ end
67
+ end
68
+
69
+ RSpec.describe Async::IO::IPSocket do
70
+ it_should_behave_like Async::IO::Generic, [:inspect]
45
71
  end
@@ -0,0 +1,60 @@
1
+ # Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require 'async/io/ssl_socket'
22
+
23
+ require 'async/rspec/ssl'
24
+ require_relative 'generic_examples'
25
+
26
+ RSpec.describe Async::IO::SSLServer do
27
+ include_context Async::RSpec::Reactor
28
+ include_context Async::RSpec::SSL::VerifiedContexts
29
+ include_context Async::RSpec::SSL::ValidCertificate
30
+
31
+ let(:endpoint) {Async::IO::Endpoint.tcp("127.0.0.1", 6780, reuse_port: true)}
32
+ let(:server_endpoint) {Async::IO::SecureEndpoint.new(endpoint, ssl_context: server_context)}
33
+ let(:client_endpoint) {Async::IO::SecureEndpoint.new(endpoint, ssl_context: client_context)}
34
+
35
+ let(:data) {"What one programmer can do in one month, two programmers can do in two months."}
36
+
37
+ it 'can accept_each connections' do
38
+ # Accept a single incoming connection and then finish.
39
+ server_task = reactor.async do |task|
40
+ server_endpoint.bind do |server|
41
+ server.listen(10)
42
+
43
+ server.accept_each do |peer, address|
44
+ data = peer.read(512)
45
+ peer.write(data)
46
+ end
47
+ end
48
+ end
49
+
50
+ reactor.async do
51
+ client_endpoint.connect do |client|
52
+ client.write(data)
53
+
54
+ expect(client.read(512)).to be == data
55
+ end
56
+
57
+ server_task.stop
58
+ end
59
+ end
60
+ end
@@ -21,11 +21,14 @@
21
21
  require 'async/io/ssl_socket'
22
22
 
23
23
  require 'async/rspec/ssl'
24
+ require_relative 'generic_examples'
24
25
 
25
- RSpec.describe Async::Reactor do
26
- include_context Async::RSpec::Leaks
26
+ RSpec.describe Async::IO::SSLSocket do
27
+ include_context Async::RSpec::Reactor
27
28
  include_context Async::RSpec::SSL::VerifiedContexts
28
29
 
30
+ it_should_behave_like Async::IO::Generic
31
+
29
32
  # Shared port for localhost network tests.
30
33
  let(:endpoint) {Async::IO::Endpoint.tcp("127.0.0.1", 6779, reuse_port: true)}
31
34
  let(:server_endpoint) {Async::IO::SecureEndpoint.new(endpoint, ssl_context: server_context)}
@@ -33,26 +36,22 @@ RSpec.describe Async::Reactor do
33
36
 
34
37
  let(:data) {"The quick brown fox jumped over the lazy dog."}
35
38
 
36
- around(:each) do |example|
39
+ let(:server_task) do
37
40
  # Accept a single incoming connection and then finish.
38
- subject.async do |task|
41
+ reactor.async do |task|
39
42
  server_endpoint.bind do |server|
40
43
  server.listen(10)
41
44
 
42
- server.accept do |peer, address|
43
- data = peer.read(512)
44
- peer.write(data)
45
- end rescue nil
45
+ begin
46
+ server.accept do |peer, address|
47
+ data = peer.read(512)
48
+ peer.write(data)
49
+ end
50
+ rescue OpenSSL::SSL::SSLError
51
+ # ignore.
52
+ end
46
53
  end
47
54
  end
48
-
49
- result = example.run
50
-
51
- if result.is_a? Exception
52
- result
53
- else
54
- subject.run
55
- end
56
55
  end
57
56
 
58
57
  describe "#connect" do
@@ -60,9 +59,12 @@ RSpec.describe Async::Reactor do
60
59
  include_context Async::RSpec::SSL::ValidCertificate
61
60
 
62
61
  it "should start server and send data" do
63
- subject.async do
62
+ server_task
63
+
64
+ reactor.async do
64
65
  client_endpoint.connect do |client|
65
66
  client.write(data)
67
+
66
68
  expect(client.read(512)).to be == data
67
69
  end
68
70
  end
@@ -73,7 +75,9 @@ RSpec.describe Async::Reactor do
73
75
  include_context Async::RSpec::SSL::InvalidCertificate
74
76
 
75
77
  it "should fail to connect" do
76
- subject.async do
78
+ server_task
79
+
80
+ reactor.async do
77
81
  expect do
78
82
  client_endpoint.connect
79
83
  end.to raise_error(OpenSSL::SSL::SSLError)
@@ -0,0 +1,45 @@
1
+ # Copyright, 2017, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require 'async/io/standard'
22
+
23
+ RSpec.describe Async::IO::STDIN do
24
+ include_context Async::RSpec::Reactor
25
+
26
+ it "should be able to read" do
27
+ expect(subject.read(0)).to be == ""
28
+ end
29
+ end
30
+
31
+ RSpec.describe Async::IO::STDOUT do
32
+ include_context Async::RSpec::Reactor
33
+
34
+ it "should be able to read" do
35
+ expect(subject.write("")).to be == 0
36
+ end
37
+ end
38
+
39
+ RSpec.describe Async::IO::STDERR do
40
+ include_context Async::RSpec::Reactor
41
+
42
+ it "should be able to read" do
43
+ expect(subject.write("")).to be == 0
44
+ end
45
+ end
@@ -20,18 +20,25 @@
20
20
 
21
21
  require 'async/io/tcp_socket'
22
22
 
23
+ require_relative 'generic_examples'
24
+
23
25
  RSpec.describe Async::IO::TCPSocket do
24
26
  include_context Async::RSpec::Reactor
25
27
 
28
+ it_should_behave_like Async::IO::Generic
29
+
26
30
  # Shared port for localhost network tests.
27
31
  let(:server_address) {Async::IO::Address.tcp("localhost", 6788)}
28
32
  let(:data) {"The quick brown fox jumped over the lazy dog."}
29
33
 
30
- describe 'basic tcp server' do
34
+ describe Async::IO::TCPServer do
35
+ it_should_behave_like Async::IO::Generic
36
+
31
37
  it "should start server and send data" do
32
38
  # Accept a single incoming connection and then finish.
33
39
  server_task = reactor.async do |task|
34
40
  server = Async::IO::TCPServer.new("localhost", 6788)
41
+
35
42
  peer, address = server.accept
36
43
 
37
44
  data = peer.gets
@@ -20,33 +20,35 @@
20
20
 
21
21
  require 'async/io/udp_socket'
22
22
 
23
+ require_relative 'generic_examples'
24
+
23
25
  RSpec.describe Async::IO::UDPSocket do
24
26
  include_context Async::RSpec::Reactor
25
27
 
28
+ it_should_behave_like Async::IO::Generic
29
+
26
30
  let(:data) {"The quick brown fox jumped over the lazy dog."}
27
31
 
28
- describe 'basic udp server' do
29
- it "should echo data back to peer" do
30
- reactor.async do
31
- server = Async::IO::UDPSocket.new(Socket::AF_INET)
32
- server.bind("127.0.0.1", 6778)
33
-
34
- packet, address = server.recvfrom(512)
35
- server.send(packet, 0, address[3], address[1])
36
-
37
- server.close
38
- end
32
+ it "should echo data back to peer" do
33
+ reactor.async do
34
+ server = Async::IO::UDPSocket.new(Socket::AF_INET)
35
+ server.bind("127.0.0.1", 6778)
36
+
37
+ packet, address = server.recvfrom(512)
38
+ server.send(packet, 0, address[3], address[1])
39
+
40
+ server.close
41
+ end
42
+
43
+ reactor.async do
44
+ client = Async::IO::UDPSocket.new(Socket::AF_INET)
45
+ client.connect("127.0.0.1", 6778)
46
+
47
+ client.send(data, 0)
48
+ response = client.recv(512)
49
+ client.close
39
50
 
40
- reactor.async do
41
- client = Async::IO::UDPSocket.new(Socket::AF_INET)
42
- client.connect("127.0.0.1", 6778)
43
-
44
- client.send(data, 0)
45
- response = client.recv(512)
46
- client.close
47
-
48
- expect(response).to be == data
49
- end
51
+ expect(response).to be == data
50
52
  end
51
53
  end
52
54
  end
@@ -20,8 +20,12 @@
20
20
 
21
21
  require 'async/io/unix_socket'
22
22
 
23
- RSpec.describe Async::Reactor do
24
- include_context Async::RSpec::Leaks
23
+ require_relative 'generic_examples'
24
+
25
+ RSpec.describe Async::IO::UNIXSocket do
26
+ include_context Async::RSpec::Reactor
27
+
28
+ it_should_behave_like Async::IO::Generic
25
29
 
26
30
  let(:path) {File.join(__dir__, "unix-socket")}
27
31
  let(:data) {"The quick brown fox jumped over the lazy dog."}
@@ -34,26 +38,27 @@ RSpec.describe Async::Reactor do
34
38
  FileUtils.rm_f path
35
39
  end
36
40
 
37
- describe 'basic unix socket' do
38
- it "should echo data back to peer" do
39
- subject.async do
40
- Async::IO::UNIXServer.wrap(path) do |server|
41
- server.accept do |peer|
42
- peer.send(peer.recv(512))
43
- end
41
+ it "should echo data back to peer" do
42
+ reactor.async do
43
+ Async::IO::UNIXServer.wrap(path) do |server|
44
+ server.accept do |peer|
45
+ peer.send(peer.recv(512))
44
46
  end
45
47
  end
46
-
47
- subject.async do
48
- Async::IO::UNIXSocket.wrap(path) do |client|
49
- client.send(data)
50
- response = client.recv(512)
48
+ end
49
+
50
+ reactor.async do
51
+ Async::IO::UNIXSocket.wrap(path) do |client|
52
+ client.send(data)
51
53
 
52
- expect(response).to be == data
53
- end
54
+ response = client.recv(512)
55
+
56
+ expect(response).to be == data
54
57
  end
55
-
56
- subject.run
57
58
  end
58
59
  end
59
60
  end
61
+
62
+ RSpec.describe Async::IO::UNIXServer do
63
+ it_should_behave_like Async::IO::Generic
64
+ end
@@ -20,21 +20,57 @@
20
20
 
21
21
  require 'net/http'
22
22
 
23
- require 'async/io/wrap/tcp'
23
+ require 'async/io/tcp_socket'
24
24
 
25
- RSpec.describe Async::IO::Wrap::TCPSocket do
26
- include_context Async::RSpec::Reactor
27
-
28
- before(:all) do
29
- # This injects the asynchronous sockets into Net::HTTP.
30
- Net::HTTP.send(:include, Async::IO::Wrap)
25
+ # There are different ways to achieve this. This is really just a proof of concept.
26
+ module Wrap
27
+ module TCPServer
28
+ def self.new(*args)
29
+ if Async::Task.current?
30
+ Async::IO::TCPServer.new(*args)
31
+ else
32
+ ::TCPServer.new(*args)
33
+ end
34
+ end
31
35
  end
32
-
33
- it "should fetch page" do
34
- expect(Async::IO::Wrap::TCPSocket).to receive(:new).and_call_original
36
+
37
+ module TCPSocket
38
+ def self.new(*args)
39
+ if Async::Task.current?
40
+ Async::IO::TCPSocket.new(*args)
41
+ else
42
+ ::TCPSocket.new(*args)
43
+ end
44
+ end
45
+
46
+ def self.open(*args)
47
+ self.new(*args)
48
+ end
49
+ end
50
+ end
51
+
52
+ RSpec.describe Async::IO::TCPSocket do
53
+ describe "inside reactor" do
54
+ include_context Async::RSpec::Reactor
55
+
56
+ before(:all) do
57
+ Net::HTTP.include(Wrap)
58
+ end
35
59
 
36
- expect do
37
- Net::HTTP.get_response('www.google.com', '/')
38
- end.to_not raise_error
60
+ it "should fetch page" do
61
+ expect(Async::IO::TCPSocket).to receive(:new).and_call_original
62
+
63
+ expect do
64
+ Net::HTTP.get_response('www.google.com', '/')
65
+ end.to_not raise_error
66
+ end
67
+ end
68
+
69
+ describe "outside reactor" do
70
+ it "should fetch page" do
71
+ expect do
72
+ Net::HTTP.get_response('www.google.com', '/')
73
+ end.to_not raise_error
74
+ end
39
75
  end
40
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.4.0
4
+ version: 1.5.0
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-03-17 00:00:00.000000000 Z
11
+ date: 2018-03-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: async
@@ -94,7 +94,9 @@ files:
94
94
  - README.md
95
95
  - Rakefile
96
96
  - async-io.gemspec
97
+ - examples/broken_ssl.rb
97
98
  - lib/async/io.rb
99
+ - lib/async/io/address.rb
98
100
  - lib/async/io/binary_string.rb
99
101
  - lib/async/io/endpoint.rb
100
102
  - lib/async/io/generic.rb
@@ -102,23 +104,26 @@ files:
102
104
  - lib/async/io/protocol/line.rb
103
105
  - lib/async/io/socket.rb
104
106
  - lib/async/io/ssl_socket.rb
107
+ - lib/async/io/standard.rb
105
108
  - lib/async/io/stream.rb
106
109
  - lib/async/io/tcp_socket.rb
107
110
  - lib/async/io/trap.rb
108
111
  - lib/async/io/udp_socket.rb
109
112
  - lib/async/io/unix_socket.rb
110
113
  - lib/async/io/version.rb
111
- - lib/async/io/wrap/tcp.rb
112
114
  - spec/async/io/c10k_spec.rb
113
115
  - spec/async/io/echo_spec.rb
114
116
  - spec/async/io/endpoint_spec.rb
117
+ - spec/async/io/generic_examples.rb
115
118
  - spec/async/io/generic_spec.rb
116
119
  - spec/async/io/notification_spec.rb
117
120
  - spec/async/io/protocol/line_spec.rb
118
121
  - spec/async/io/socket/tcp_spec.rb
119
122
  - spec/async/io/socket/udp_spec.rb
120
123
  - spec/async/io/socket_spec.rb
124
+ - spec/async/io/ssl_server_spec.rb
121
125
  - spec/async/io/ssl_socket_spec.rb
126
+ - spec/async/io/standard_spec.rb
122
127
  - spec/async/io/stream_spec.rb
123
128
  - spec/async/io/tcp_socket_spec.rb
124
129
  - spec/async/io/trap_spec.rb
@@ -153,13 +158,16 @@ test_files:
153
158
  - spec/async/io/c10k_spec.rb
154
159
  - spec/async/io/echo_spec.rb
155
160
  - spec/async/io/endpoint_spec.rb
161
+ - spec/async/io/generic_examples.rb
156
162
  - spec/async/io/generic_spec.rb
157
163
  - spec/async/io/notification_spec.rb
158
164
  - spec/async/io/protocol/line_spec.rb
159
165
  - spec/async/io/socket/tcp_spec.rb
160
166
  - spec/async/io/socket/udp_spec.rb
161
167
  - spec/async/io/socket_spec.rb
168
+ - spec/async/io/ssl_server_spec.rb
162
169
  - spec/async/io/ssl_socket_spec.rb
170
+ - spec/async/io/standard_spec.rb
163
171
  - spec/async/io/stream_spec.rb
164
172
  - spec/async/io/tcp_socket_spec.rb
165
173
  - spec/async/io/trap_spec.rb