nio4r 2.3.1 → 2.5.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/workflow.yml +43 -0
  3. data/.gitignore +1 -0
  4. data/.rubocop.yml +37 -11
  5. data/CHANGES.md +40 -0
  6. data/Gemfile +5 -6
  7. data/README.md +53 -7
  8. data/Rakefile +0 -2
  9. data/examples/echo_server.rb +2 -2
  10. data/ext/libev/Changes +35 -0
  11. data/ext/libev/README +2 -1
  12. data/ext/libev/ev.c +213 -151
  13. data/ext/libev/ev.h +95 -88
  14. data/ext/libev/ev_epoll.c +26 -15
  15. data/ext/libev/ev_kqueue.c +11 -5
  16. data/ext/libev/ev_linuxaio.c +642 -0
  17. data/ext/libev/ev_poll.c +13 -8
  18. data/ext/libev/ev_port.c +5 -2
  19. data/ext/libev/ev_vars.h +14 -3
  20. data/ext/libev/ev_wrap.h +16 -0
  21. data/ext/nio4r/extconf.rb +2 -0
  22. data/ext/nio4r/monitor.c +1 -0
  23. data/ext/nio4r/nio4r.h +1 -1
  24. data/ext/nio4r/org/nio4r/Selector.java +5 -1
  25. data/ext/nio4r/selector.c +5 -5
  26. data/lib/nio.rb +3 -3
  27. data/lib/nio/bytebuffer.rb +4 -0
  28. data/lib/nio/monitor.rb +10 -8
  29. data/lib/nio/selector.rb +3 -1
  30. data/lib/nio/version.rb +1 -1
  31. data/nio4r.gemspec +10 -2
  32. data/{tasks → rakelib}/extension.rake +2 -0
  33. data/{tasks → rakelib}/rspec.rake +0 -0
  34. data/{tasks → rakelib}/rubocop.rake +0 -0
  35. data/spec/nio/acceptables_spec.rb +3 -5
  36. data/spec/nio/bytebuffer_spec.rb +2 -4
  37. data/spec/nio/monitor_spec.rb +2 -2
  38. data/spec/nio/selectables/ssl_socket_spec.rb +50 -20
  39. data/spec/nio/selectables/tcp_socket_spec.rb +23 -17
  40. data/spec/nio/selectables/udp_socket_spec.rb +13 -8
  41. data/spec/nio/selector_spec.rb +34 -16
  42. data/spec/spec_helper.rb +4 -16
  43. data/spec/support/selectable_examples.rb +37 -17
  44. metadata +18 -17
  45. data/.travis.yml +0 -36
  46. data/LICENSE.txt +0 -20
  47. data/appveyor.yml +0 -27
  48. data/ext/libev/README.embed +0 -3
  49. data/ext/libev/test_libev_win32.c +0 -123
@@ -4,19 +4,22 @@ require "spec_helper"
4
4
 
5
5
  RSpec.describe TCPSocket do
6
6
  let(:addr) { "127.0.0.1" }
7
- let(:port) { next_available_tcp_port }
8
7
 
9
8
  let :readable_subject do
10
- server = TCPServer.new(addr, port)
11
- sock = TCPSocket.new(addr, port)
9
+ server = TCPServer.new(addr, 0)
10
+ sock = TCPSocket.new(addr, server.local_address.ip_port)
12
11
  peer = server.accept
13
- peer << "data"
12
+
13
+ peer << "Xdata"
14
+ peer.flush
15
+ sock.read(1)
16
+
14
17
  sock
15
18
  end
16
19
 
17
20
  let :unreadable_subject do
18
- TCPServer.new(addr, port)
19
- sock = TCPSocket.new(addr, port)
21
+ server = TCPServer.new(addr, 0)
22
+ sock = TCPSocket.new(addr, server.local_address.ip_port)
20
23
 
21
24
  # Sanity check to make sure we actually produced an unreadable socket
22
25
  pending "Failed to produce an unreadable socket" if select([sock], [], [], 0)
@@ -25,13 +28,13 @@ RSpec.describe TCPSocket do
25
28
  end
26
29
 
27
30
  let :writable_subject do
28
- TCPServer.new(addr, port)
29
- TCPSocket.new(addr, port)
31
+ server = TCPServer.new(addr, 0)
32
+ TCPSocket.new(addr, server.local_address.ip_port)
30
33
  end
31
34
 
32
35
  let :unwritable_subject do
33
- server = TCPServer.new(addr, port)
34
- sock = TCPSocket.new(addr, port)
36
+ server = TCPServer.new(addr, 0)
37
+ sock = TCPSocket.new(addr, server.local_address.ip_port)
35
38
 
36
39
  # TODO: close this socket
37
40
  _peer = server.accept
@@ -61,8 +64,8 @@ RSpec.describe TCPSocket do
61
64
  end
62
65
 
63
66
  let :pair do
64
- server = TCPServer.new(addr, port)
65
- client = TCPSocket.new(addr, port)
67
+ server = TCPServer.new(addr, 0)
68
+ client = TCPSocket.new(addr, server.local_address.ip_port)
66
69
  [client, server.accept]
67
70
  end
68
71
 
@@ -71,19 +74,22 @@ RSpec.describe TCPSocket do
71
74
  it_behaves_like "an NIO bidirectional stream"
72
75
 
73
76
  context :connect do
74
- it "selects writable when connected", retry: 5 do # retry: Flaky on OS X
77
+ include_context NIO::Selector
78
+
79
+ it "selects writable when connected" do
75
80
  begin
76
- server = TCPServer.new(addr, port)
77
- selector = NIO::Selector.new
81
+ server = TCPServer.new(addr, 0)
78
82
 
79
83
  client = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
80
84
  monitor = selector.register(client, :w)
81
85
 
82
86
  expect do
83
- client.connect_nonblock Socket.sockaddr_in(port, addr)
87
+ client.connect_nonblock server.local_address
84
88
  end.to raise_exception Errno::EINPROGRESS
85
89
 
86
- expect(selector.select(0.001)).to include monitor
90
+ ready = selector.select(1)
91
+
92
+ expect(ready).to include monitor
87
93
  result = client.getsockopt(::Socket::SOL_SOCKET, ::Socket::SO_ERROR)
88
94
  expect(result.unpack("i").first).to be_zero
89
95
  ensure
@@ -6,32 +6,37 @@ RSpec.describe UDPSocket, if: !defined?(JRUBY_VERSION) do
6
6
  let(:udp_port) { 23_456 }
7
7
 
8
8
  let :readable_subject do
9
- sock = UDPSocket.new
10
- sock.bind("127.0.0.1", udp_port)
9
+ server = UDPSocket.new
10
+ server.bind("127.0.0.1", 0)
11
11
 
12
12
  peer = UDPSocket.new
13
- peer.send("hi there", 0, "127.0.0.1", udp_port)
13
+ peer.send("hi there", 0, "127.0.0.1", server.local_address.ip_port)
14
14
 
15
- sock
15
+ server
16
16
  end
17
17
 
18
18
  let :unreadable_subject do
19
19
  sock = UDPSocket.new
20
- sock.bind("127.0.0.1", udp_port + 1)
20
+ sock.bind("127.0.0.1", 0)
21
21
  sock
22
22
  end
23
23
 
24
24
  let :writable_subject do
25
+ server = UDPSocket.new
26
+ server.bind("127.0.0.1", 0)
27
+
25
28
  peer = UDPSocket.new
26
- peer.connect "127.0.0.1", udp_port
29
+ peer.connect("127.0.0.1", server.local_address.ip_port)
30
+
27
31
  cntr = 0
28
32
  begin
29
33
  peer.send("X" * 1024, 0)
30
34
  cntr += 1
31
35
  t = select [], [peer], [], 0
32
- rescue Errno::ECONNREFUSED => ex
33
- skip "Couln't make writable UDPSocket subject: #{ex.class}: #{ex}"
36
+ rescue Errno::ECONNREFUSED => e
37
+ skip "Couldn't make writable UDPSocket subject: #{e.class}: #{e}"
34
38
  end while t && t[1].include?(peer) && cntr < 5
39
+
35
40
  peer
36
41
  end
37
42
 
@@ -3,12 +3,6 @@
3
3
  require "spec_helper"
4
4
  require "timeout"
5
5
 
6
- # Timeouts should be at least this precise (in seconds) to pass the tests
7
- # Typical precision should be better than this, but if it's worse it will fail
8
- # the tests
9
- TIMEOUT_PRECISION = 0.1
10
-
11
- # rubocop:disable Metrics/BlockLength
12
6
  RSpec.describe NIO::Selector do
13
7
  let(:pair) { IO.pipe }
14
8
  let(:reader) { pair.first }
@@ -22,10 +16,12 @@ RSpec.describe NIO::Selector do
22
16
  end
23
17
 
24
18
  context "#initialize" do
25
- it "allows explicitly specifying a backend" do
19
+ it "allows explicitly specifying a backend" do |example|
26
20
  backend = described_class.backends.first
27
21
  selector = described_class.new(backend)
28
22
  expect(selector.backend).to eq backend
23
+
24
+ example.reporter.message "Supported backends: #{described_class.backends}"
29
25
  end
30
26
 
31
27
  it "raises ArgumentError if given an invalid backend" do
@@ -38,8 +34,10 @@ RSpec.describe NIO::Selector do
38
34
  end
39
35
 
40
36
  context "backend" do
41
- it "knows its backend" do
37
+ it "knows its backend" do |example|
42
38
  expect(subject.backend).to be_a Symbol
39
+
40
+ example.reporter.message "Current backend: #{subject.backend}"
43
41
  end
44
42
  end
45
43
 
@@ -73,6 +71,15 @@ RSpec.describe NIO::Selector do
73
71
  expect(monitor).to be_closed
74
72
  end
75
73
 
74
+ it "allows deregistering closed IO objects" do
75
+ subject.register(reader, :r)
76
+ reader.close
77
+
78
+ expect do
79
+ subject.deregister(reader)
80
+ end.not_to raise_error
81
+ end
82
+
76
83
  it "reports if it is empty" do
77
84
  expect(subject).to be_empty
78
85
  subject.register(reader, :r)
@@ -96,31 +103,43 @@ RSpec.describe NIO::Selector do
96
103
  end
97
104
 
98
105
  context "timeouts" do
99
- it "waits for a timeout when selecting" do
106
+ let(:select_precision) {0.2}
107
+ let(:timeout) {2.0}
108
+ let(:payload) {"hi there"}
109
+
110
+ it "waits for timeout when selecting from empty selector" do
111
+ started_at = Time.now
112
+ expect(subject.select(timeout)).to be_nil
113
+ expect(Time.now - started_at).to be_within(select_precision).of(timeout)
114
+ end
115
+
116
+ it "waits for a timeout when selecting with reader" do
100
117
  monitor = subject.register(reader, :r)
101
118
 
102
- payload = "hi there"
103
119
  writer << payload
104
120
 
105
- timeout = 0.5
106
121
  started_at = Time.now
107
122
  expect(subject.select(timeout)).to include monitor
108
- expect(Time.now - started_at).to be_within(TIMEOUT_PRECISION).of(0)
123
+ expect(Time.now - started_at).to be_within(select_precision).of(0)
109
124
  reader.read_nonblock(payload.size)
110
125
 
111
126
  started_at = Time.now
112
127
  expect(subject.select(timeout)).to be_nil
113
- expect(Time.now - started_at).to be_within(TIMEOUT_PRECISION).of(timeout)
128
+ expect(Time.now - started_at).to be_within(select_precision).of(timeout)
114
129
  end
115
130
 
116
131
  it "raises ArgumentError if given a negative timeout" do
117
132
  subject.register(reader, :r)
118
133
 
119
- expect { subject.select(-1) }.to raise_exception(ArgumentError)
134
+ expect do
135
+ subject.select(-1)
136
+ end.to raise_exception(ArgumentError)
120
137
  end
121
138
  end
122
139
 
123
140
  context "wakeup" do
141
+ let(:select_precision) {0.2}
142
+
124
143
  it "wakes up if signaled to from another thread" do
125
144
  subject.register(reader, :r)
126
145
 
@@ -134,7 +153,7 @@ RSpec.describe NIO::Selector do
134
153
  sleep timeout
135
154
  subject.wakeup
136
155
 
137
- expect(thread.value).to be_within(TIMEOUT_PRECISION).of(timeout)
156
+ expect(thread.value).to be_within(select_precision).of(timeout)
138
157
  end
139
158
 
140
159
  it "raises IOError if asked to wake up a closed selector" do
@@ -215,4 +234,3 @@ RSpec.describe NIO::Selector do
215
234
  expect(subject).to be_closed
216
235
  end
217
236
  end
218
- # rubocop:enable Metrics/BlockLength
@@ -5,26 +5,14 @@ Coveralls.wear!
5
5
 
6
6
  require "nio"
7
7
  require "support/selectable_examples"
8
- require "rspec/retry"
9
8
 
10
9
  RSpec.configure do |config|
11
10
  config.disable_monkey_patching!
12
- config.verbose_retry = true
13
- config.display_try_failure_messages = true
14
- end
15
-
16
- $current_tcp_port = 10_000
17
-
18
- def next_available_tcp_port
19
- loop do
20
- $current_tcp_port += 1
21
11
 
22
- begin
23
- sock = Timeout.timeout(0.5) { TCPSocket.new("127.0.0.1", $current_tcp_port) }
24
- rescue Errno::ECONNREFUSED, Timeout::Error
25
- break $current_tcp_port
26
- end
12
+ # Enable flags like --only-failures and --next-failure
13
+ config.example_status_persistence_file_path = ".rspec_status"
27
14
 
28
- sock.close
15
+ config.expect_with :rspec do |c|
16
+ c.syntax = :expect
29
17
  end
30
18
  end
@@ -1,11 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ RSpec.shared_context NIO::Selector do
4
+ let(:selector) {@selector = NIO::Selector.new}
5
+
6
+ after(:each) do
7
+ if defined?(@selector)
8
+ @selector.close
9
+ end
10
+ end
11
+ end
12
+
3
13
  RSpec.shared_context "an NIO selectable" do
4
- let(:selector) { NIO::Selector.new }
14
+ include_context NIO::Selector
5
15
 
6
- it "selects readable objects", retry: 5 do # retry: Flaky on OS X
16
+ it "selects readable objects" do
7
17
  monitor = selector.register(readable_subject, :r)
8
- ready = selector.select(0)
18
+ ready = selector.select(1)
9
19
  expect(ready).to be_an Enumerable
10
20
  expect(ready).to include monitor
11
21
  end
@@ -17,25 +27,29 @@ RSpec.shared_context "an NIO selectable" do
17
27
 
18
28
  it "selects writable objects" do
19
29
  monitor = selector.register(writable_subject, :w)
20
- ready = selector.select(0)
30
+ ready = selector.select(1)
21
31
  expect(ready).to be_an Enumerable
22
32
  expect(ready).to include monitor
23
33
  end
24
34
 
25
35
  it "does not select unwritable objects" do
26
36
  selector.register(unwritable_subject, :w)
27
- expect(selector.select(0)).to be_nil
37
+ ready = selector.select(0)
38
+ expect(ready).to be_nil
28
39
  end
29
40
  end
30
41
 
31
- RSpec.shared_context "an NIO selectable stream" do
32
- let(:selector) { NIO::Selector.new }
42
+ RSpec.shared_context "an NIO selectable stream" do |is_tls13|
43
+ include_context NIO::Selector
44
+
33
45
  let(:stream) { pair.first }
34
46
  let(:peer) { pair.last }
35
47
 
36
48
  it "selects readable when the other end closes" do
37
49
  monitor = selector.register(stream, :r)
38
- expect(selector.select(0)).to be_nil
50
+ unless is_tls13
51
+ expect(selector.select(1)).to be_nil
52
+ end
39
53
 
40
54
  peer.close
41
55
  # Wait and give the TCP session time to close
@@ -44,22 +58,28 @@ RSpec.shared_context "an NIO selectable stream" do
44
58
  end
45
59
 
46
60
  RSpec.shared_context "an NIO bidirectional stream" do
47
- let(:selector) { NIO::Selector.new }
48
- let(:stream) { pair.first }
49
- let(:peer) { pair.last }
61
+ include_context NIO::Selector
62
+
63
+ let(:stream) {pair.first}
64
+ let(:peer) {pair.last}
50
65
 
51
- it "selects readable and writable", retry: 5 do # retry: Flaky on OS X
66
+ it "selects readable and writable" do
52
67
  selector.register(readable_subject, :rw)
53
- selector.select(0) do |m|
54
- expect(m.readiness).to eq(:rw)
68
+
69
+ selector.select(1) do |monitor|
70
+ expect(monitor.readiness).to eq(:rw)
55
71
  end
72
+
73
+ readable_subject.close
56
74
  end
75
+
57
76
  it "keeps readiness after the selectable has been closed" do
58
77
  selector.register(readable_subject, :rw)
59
- selector.select(0) do |m|
60
- expect(m.readiness).to eq(:rw)
78
+
79
+ selector.select(1) do |monitor|
80
+ expect(monitor.readiness).to eq(:rw)
61
81
  readable_subject.close
62
- expect(m.readiness).to eq(:rw)
82
+ expect(monitor.readiness).to eq(:rw)
63
83
  end
64
84
  end
65
85
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nio4r
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.1
4
+ version: 2.5.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tony Arcieri
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-05-02 00:00:00.000000000 Z
11
+ date: 2020-09-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -47,33 +47,30 @@ extensions:
47
47
  - ext/nio4r/extconf.rb
48
48
  extra_rdoc_files: []
49
49
  files:
50
+ - ".github/workflows/workflow.yml"
50
51
  - ".gitignore"
51
52
  - ".rspec"
52
53
  - ".rubocop.yml"
53
- - ".travis.yml"
54
54
  - CHANGES.md
55
55
  - Gemfile
56
56
  - Guardfile
57
- - LICENSE.txt
58
57
  - README.md
59
58
  - Rakefile
60
- - appveyor.yml
61
59
  - examples/echo_server.rb
62
60
  - ext/libev/Changes
63
61
  - ext/libev/LICENSE
64
62
  - ext/libev/README
65
- - ext/libev/README.embed
66
63
  - ext/libev/ev.c
67
64
  - ext/libev/ev.h
68
65
  - ext/libev/ev_epoll.c
69
66
  - ext/libev/ev_kqueue.c
67
+ - ext/libev/ev_linuxaio.c
70
68
  - ext/libev/ev_poll.c
71
69
  - ext/libev/ev_port.c
72
70
  - ext/libev/ev_select.c
73
71
  - ext/libev/ev_vars.h
74
72
  - ext/libev/ev_win32.c
75
73
  - ext/libev/ev_wrap.h
76
- - ext/libev/test_libev_win32.c
77
74
  - ext/nio4r/bytebuffer.c
78
75
  - ext/nio4r/extconf.rb
79
76
  - ext/nio4r/libev.h
@@ -92,6 +89,9 @@ files:
92
89
  - lib/nio/version.rb
93
90
  - logo.png
94
91
  - nio4r.gemspec
92
+ - rakelib/extension.rake
93
+ - rakelib/rspec.rake
94
+ - rakelib/rubocop.rake
95
95
  - spec/nio/acceptables_spec.rb
96
96
  - spec/nio/bytebuffer_spec.rb
97
97
  - spec/nio/monitor_spec.rb
@@ -102,14 +102,16 @@ files:
102
102
  - spec/nio/selector_spec.rb
103
103
  - spec/spec_helper.rb
104
104
  - spec/support/selectable_examples.rb
105
- - tasks/extension.rake
106
- - tasks/rspec.rake
107
- - tasks/rubocop.rake
108
105
  homepage: https://github.com/socketry/nio4r
109
106
  licenses:
110
107
  - MIT
111
- metadata: {}
112
- post_install_message:
108
+ metadata:
109
+ bug_tracker_uri: https://github.com/socketry/nio4r/issues
110
+ changelog_uri: https://github.com/socketry/nio4r/blob/master/CHANGES.md
111
+ documentation_uri: https://www.rubydoc.info/gems/nio4r/2.5.3
112
+ source_code_uri: https://github.com/socketry/nio4r/tree/v2.5.3
113
+ wiki_uri: https://github.com/socketry/nio4r/wiki
114
+ post_install_message:
113
115
  rdoc_options: []
114
116
  require_paths:
115
117
  - lib
@@ -117,16 +119,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
117
119
  requirements:
118
120
  - - ">="
119
121
  - !ruby/object:Gem::Version
120
- version: 2.2.2
122
+ version: '2.4'
121
123
  required_rubygems_version: !ruby/object:Gem::Requirement
122
124
  requirements:
123
125
  - - ">="
124
126
  - !ruby/object:Gem::Version
125
127
  version: '0'
126
128
  requirements: []
127
- rubyforge_project:
128
- rubygems_version: 2.7.4
129
- signing_key:
129
+ rubygems_version: 3.1.2
130
+ signing_key:
130
131
  specification_version: 4
131
132
  summary: New IO for Ruby
132
133
  test_files: