async-io 1.4.0 → 1.5.0

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