cool.io 1.2.3-x86-mingw32 → 1.4.1-x86-mingw32

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.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +3 -0
  3. data/.travis.yml +3 -3
  4. data/CHANGES.md +35 -0
  5. data/README.md +1 -3
  6. data/Rakefile +11 -13
  7. data/cool.io.gemspec +3 -2
  8. data/examples/callbacked_echo_server.rb +24 -0
  9. data/ext/cool.io/extconf.rb +8 -24
  10. data/ext/cool.io/loop.c +1 -1
  11. data/ext/iobuffer/iobuffer.c +2 -0
  12. data/ext/libev/Changes +123 -4
  13. data/ext/libev/LICENSE +2 -1
  14. data/ext/libev/README +8 -8
  15. data/ext/libev/ev.c +313 -144
  16. data/ext/libev/ev.h +18 -10
  17. data/ext/libev/ev_epoll.c +4 -1
  18. data/ext/libev/ev_kqueue.c +1 -1
  19. data/ext/libev/ev_select.c +3 -4
  20. data/ext/libev/ev_vars.h +3 -2
  21. data/ext/libev/ev_win32.c +1 -1
  22. data/ext/libev/win_select.patch +115 -0
  23. data/lib/cool.io.rb +6 -4
  24. data/lib/cool.io/dns_resolver.rb +4 -10
  25. data/lib/cool.io/dsl.rb +6 -2
  26. data/lib/cool.io/io.rb +36 -16
  27. data/lib/cool.io/loop.rb +3 -11
  28. data/lib/cool.io/meta.rb +2 -2
  29. data/lib/cool.io/version.rb +4 -2
  30. data/spec/async_watcher_spec.rb +5 -5
  31. data/spec/dns_spec.rb +11 -7
  32. data/spec/iobuffer_spec.rb +147 -0
  33. data/spec/spec_helper.rb +2 -2
  34. data/spec/stat_watcher_spec.rb +3 -3
  35. data/spec/tcp_server_spec.rb +98 -5
  36. data/spec/tcp_socket_spec.rb +185 -0
  37. data/spec/timer_watcher_spec.rb +23 -19
  38. data/spec/udp_socket_spec.rb +58 -0
  39. data/spec/unix_listener_spec.rb +7 -7
  40. data/spec/unix_server_spec.rb +7 -7
  41. metadata +83 -103
  42. data/examples/httpclient.rb +0 -38
  43. data/ext/http11_client/.gitignore +0 -5
  44. data/ext/http11_client/LICENSE +0 -31
  45. data/ext/http11_client/ext_help.h +0 -14
  46. data/ext/http11_client/extconf.rb +0 -6
  47. data/ext/http11_client/http11_client.c +0 -300
  48. data/ext/http11_client/http11_parser.c +0 -403
  49. data/ext/http11_client/http11_parser.h +0 -48
  50. data/ext/http11_client/http11_parser.rl +0 -173
  51. data/lib/cool.io/eventmachine.rb +0 -234
  52. data/lib/cool.io/http_client.rb +0 -427
@@ -15,17 +15,9 @@ end
15
15
 
16
16
  module Coolio
17
17
  class Loop
18
- # In Ruby 1.9 we want a Coolio::Loop per thread, but Ruby 1.8 is unithreaded
19
- if RUBY_VERSION >= "1.9.0"
20
- # Retrieve the default event loop for the current thread
21
- def self.default
22
- Thread.current._coolio_loop
23
- end
24
- else
25
- # Retrieve the default event loop
26
- def self.default
27
- @@_coolio_loop ||= Coolio::Loop.new
28
- end
18
+ # Retrieve the default event loop for the current thread
19
+ def self.default
20
+ Thread.current._coolio_loop
29
21
  end
30
22
 
31
23
  # Create a new Coolio::Loop
@@ -11,7 +11,7 @@ module Coolio
11
11
  # an event to occur before the current watcher can be used in earnest,
12
12
  # such as making an outgoing TCP connection.
13
13
  def watcher_delegate(proxy_var)
14
- %w{attach detach enable disable}.each do |method|
14
+ %w{attach attached? detach enable disable}.each do |method|
15
15
  module_eval <<-EOD
16
16
  def #{method}(*args)
17
17
  if defined? #{proxy_var} and #{proxy_var}
@@ -39,7 +39,7 @@ module Coolio
39
39
  end
40
40
 
41
41
  if defined? @#{method}_callback and @#{method}_callback
42
- instance_exec(*args, &@#{method}_callback)
42
+ @#{method}_callback.call(*args)
43
43
  end
44
44
  end
45
45
  EOD
@@ -1,5 +1,7 @@
1
1
  module Coolio
2
- VERSION = "1.2.3"
2
+ VERSION = "1.4.1"
3
3
 
4
- def self.version; VERSION; end
4
+ def self.version
5
+ VERSION
6
+ end
5
7
  end
@@ -2,7 +2,7 @@ require File.expand_path('../spec_helper', __FILE__)
2
2
  require 'tempfile'
3
3
  require 'fcntl'
4
4
 
5
- describe Cool.io::AsyncWatcher, :env => :win do
5
+ describe Cool.io::AsyncWatcher, :env => :exclude_win do
6
6
 
7
7
  it "does not signal on spurious wakeups" do
8
8
  aw = Cool.io::AsyncWatcher.new
@@ -30,7 +30,7 @@ describe Cool.io::AsyncWatcher, :env => :win do
30
30
  end
31
31
 
32
32
  # ensure children are ready
33
- nr_fork.times { rd.sysread(1).should == '.' }
33
+ nr_fork.times { expect(rd.sysread(1)).to eq('.') }
34
34
 
35
35
  # send our signals
36
36
  nr_signal.times { aw.signal }
@@ -41,15 +41,15 @@ describe Cool.io::AsyncWatcher, :env => :win do
41
41
  children.each do |pid|
42
42
  Process.kill(:TERM, pid)
43
43
  _, status = Process.waitpid2(pid)
44
- status.exitstatus.should == 0
44
+ expect(status.exitstatus).to eq(0)
45
45
  end
46
46
 
47
47
  # we should've written a line for every signal we sent
48
48
  lines = tmp.readlines
49
- lines.size.should == nr_signal
49
+ expect(lines.size).to eq(nr_signal)
50
50
 
51
51
  # theoretically a bad kernel scheduler could give us fewer...
52
- lines.sort.uniq.size.should == nr_fork
52
+ expect(lines.sort.uniq.size).to eq(nr_fork)
53
53
 
54
54
  tmp.close!
55
55
  end
@@ -22,18 +22,22 @@ describe "DNS" do
22
22
  end
23
23
 
24
24
  it "connects to valid domains" do
25
- ConnectorThingy.connect(VALID_DOMAIN, 80).attach(@loop)
26
-
27
- proc do
28
- @loop.run
29
- end.should raise_error(ItWorked)
25
+ begin
26
+ c = ConnectorThingy.connect(VALID_DOMAIN, 80).attach(@loop)
27
+
28
+ expect do
29
+ @loop.run
30
+ end.to raise_error(ItWorked)
31
+ ensure
32
+ c.close
33
+ end
30
34
  end
31
35
 
32
36
  it "fires on_resolve_failed for invalid domains" do
33
37
  ConnectorThingy.connect(INVALID_DOMAIN, 80).attach(@loop)
34
38
 
35
- proc do
39
+ expect do
36
40
  @loop.run
37
- end.should raise_error(WontResolve)
41
+ end.to raise_error(WontResolve)
38
42
  end
39
43
  end
@@ -0,0 +1,147 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+
3
+
4
+ describe IO::Buffer do
5
+
6
+ let :buffer do
7
+ IO::Buffer.new
8
+ end
9
+
10
+ it "provides a subset of the methods available in Strings" do
11
+ expect(buffer << "foo").to eq "foo"
12
+ expect(buffer << "bar").to eq "bar"
13
+ expect(buffer.to_str).to eq "foobar"
14
+ expect(buffer.to_str).to eq "foobar"
15
+ expect(buffer.size).to eq 6
16
+ end
17
+
18
+ it "provides append and prepend" do
19
+ expect(buffer.append "bar").to eq "bar"
20
+ expect(buffer.prepend "foo").to eq "foo"
21
+ expect(buffer.append "baz").to eq "baz"
22
+ expect(buffer.to_str).to eq "foobarbaz"
23
+ end
24
+
25
+ context "#read" do
26
+ it "can be used to retrieve the contents of a buffer" do
27
+ expect(buffer << "foo").to eq "foo"
28
+ expect(buffer.read 2).to eq "fo"
29
+ expect(buffer << "bar").to eq "bar"
30
+ expect(buffer.read 2).to eq "ob"
31
+ expect(buffer << "baz").to eq "baz"
32
+ expect(buffer.read 3).to eq "arb"
33
+ end
34
+ end
35
+
36
+ describe "provides methods for performing non-blocking I/O" do
37
+ require "tempfile"
38
+
39
+ context "#read_from" do
40
+ context "using local file", :env => :exclude_win do
41
+ let :tmp do
42
+ t = Tempfile.open "read_from"
43
+ t << "foobar"
44
+ t.rewind
45
+ t
46
+ end
47
+
48
+ it "will read as much data as possible" do
49
+ expect(buffer.read_from tmp).to eq 6
50
+ expect(buffer.to_str).to eq "foobar"
51
+ end
52
+ end
53
+
54
+ context "using udp socket" do
55
+ before :each do
56
+ @receiver = UDPSocket.open
57
+ @receiver.bind nil, 0
58
+
59
+ @sender = UDPSocket.open
60
+ @sender.connect "localhost", @receiver.addr[1]
61
+ end
62
+ after :each do
63
+ @receiver.close
64
+ @sender.close
65
+ end
66
+
67
+ it "will read as much data as possible" do
68
+ select [], [@sender]
69
+ @sender.send "foo", 0
70
+ select [@receiver]
71
+ expect(buffer.read_from @receiver).to eq 3
72
+ expect(buffer.to_str).to eq "foo"
73
+
74
+ select [], [@sender]
75
+ @sender.send "barbaz", 0
76
+ select [@receiver]
77
+ expect(buffer.read_from @receiver).to eq 6
78
+ expect(buffer.to_str).to eq "foobarbaz"
79
+ end
80
+ end
81
+ end
82
+
83
+ context "#write_to" do
84
+ context "using local file", :env => :exclude_win do
85
+ let :tmp do
86
+ Tempfile.open "write_to"
87
+ end
88
+ it "writes the contents of the buffer" do
89
+ buffer << "foo"
90
+ expect(buffer.write_to tmp).to eq 3
91
+ tmp.rewind
92
+ expect(tmp.read 3).to eq "foo"
93
+ end
94
+ end
95
+
96
+ context "using udp socket" do
97
+ before :each do
98
+ @receiver = UDPSocket.open
99
+ @receiver.bind nil, 0
100
+
101
+ @sender = UDPSocket.open
102
+ @sender.connect "localhost", @receiver.addr[1]
103
+ end
104
+ after :each do
105
+ @receiver.close
106
+ @sender.close
107
+ end
108
+
109
+ it "will read as much data as possible" do
110
+ buffer << "foo"
111
+ select [], [@sender]
112
+ expect(buffer.write_to @sender).to eq 3
113
+ select [@receiver]
114
+ expect(@receiver.recvfrom_nonblock(3)[0]).to eq "foo"
115
+ end
116
+ end
117
+ end
118
+ end
119
+
120
+ context "#clear" do
121
+ it "clear all data" do
122
+ buffer << "foo"
123
+ expect(buffer.size).to eq 3
124
+ expect(buffer.empty?).to eq false
125
+ buffer.clear
126
+ expect(buffer.size).to eq 0
127
+ expect(buffer.empty?).to eq true
128
+ end
129
+ end
130
+
131
+ context "#read_frame" do
132
+ it "Read up to and including the given frame marker" do
133
+ buffer << "foo\nbarbaz"
134
+ data = ""
135
+ expect(buffer.read_frame data, "\n".ord).to eq true
136
+ expect(buffer.empty?).to eq false
137
+ expect(data).to eq "foo\n"
138
+ expect(buffer.to_str).to eq "barbaz"
139
+
140
+ expect(buffer.read_frame data, "\n".ord).to eq false
141
+ expect(buffer.empty?).to eq true
142
+ expect(data).to eq "foo\nbarbaz"
143
+ expect(buffer.to_str).to eq ""
144
+ end
145
+ end
146
+
147
+ end
@@ -12,8 +12,8 @@ def unused_port
12
12
  end
13
13
 
14
14
  RSpec.configure do |c|
15
- if RUBY_PLATFORM =~ /mingw|win32/
15
+ if RUBY_PLATFORM =~ /mingw|mswin/
16
16
  $stderr.puts "Skip some specs on Windows"
17
- c.filter_run_excluding :env => :win
17
+ c.filter_run_excluding :env => :exclude_win
18
18
  end
19
19
  end
@@ -62,16 +62,16 @@ describe Cool.io::StatWatcher do
62
62
  end
63
63
 
64
64
  it "fire on_change when the file it is watching is modified" do
65
- watcher.accessed.should eql(true)
65
+ expect(watcher.accessed).to eq(true)
66
66
  end
67
67
 
68
68
  it "should pass previous and current file stat info given a stat watcher" do
69
- watcher.previous.ino.should eql(watcher.current.ino)
69
+ expect(watcher.previous.ino).to eq(watcher.current.ino)
70
70
  end
71
71
 
72
72
  it "should raise when the handler does not take 2 parameters" do
73
73
  class MyStatWatcher < Cool.io::StatWatcher; def on_change; end; end
74
- lambda { watcher.accessed }.should raise_error(ArgumentError)
74
+ expect { watcher.accessed }.to raise_error(ArgumentError)
75
75
  end
76
76
 
77
77
  end
@@ -106,14 +106,14 @@ ensure
106
106
  end
107
107
 
108
108
  # This test should work on Windows
109
- describe Coolio::TCPServer, :env => :win do
109
+ describe Coolio::TCPServer do
110
110
 
111
111
  it '#run' do
112
- test_run("hello").should == "hello"
112
+ expect(test_run("hello")).to eq("hello")
113
113
  end
114
114
 
115
115
  it '#run_once' do
116
- test_run_once("hello").should == "hello"
116
+ expect(test_run_once("hello")).to eq("hello")
117
117
  end
118
118
 
119
119
  it '#run_once(timeout)' do
@@ -125,8 +125,101 @@ describe Coolio::TCPServer, :env => :win do
125
125
  end
126
126
 
127
127
  it '#run(timeout)' do
128
- test_run_timeout("hello").should == "hello"
128
+ expect(test_run_timeout("hello")).to eq("hello")
129
129
  end
130
130
 
131
+ describe "functionaltest" do
132
+ let :loop do
133
+ Coolio::Loop.new
134
+ end
135
+
136
+ let :port do
137
+ unused_port
138
+ end
139
+
140
+ context "#on_connect" do
141
+ class ServerOnConnect < Coolio::Socket
142
+ def initialize(io, cb)
143
+ super(io)
144
+ @cb = cb
145
+ end
146
+ def on_connect
147
+ @cb.call
148
+ end
149
+ end
150
+
151
+ it "connected socket called on_connect" do
152
+ begin
153
+ connected = false
154
+ server = Cool.io::TCPServer.new("localhost", port, ServerOnConnect, proc { connected = true })
155
+ loop.attach server
156
+ s = TCPSocket.open("localhost", port)
157
+ loop.run_once
158
+ s.close
159
+ expect(connected).to eq true
160
+ ensure
161
+ server.detach
162
+ end
163
+ end
164
+ end
165
+
166
+ context "#on_close" do
167
+ class ServerOnClose < Coolio::Socket
168
+ def initialize(io, cb)
169
+ super(io)
170
+ @cb = cb
171
+ end
172
+ def on_close
173
+ @cb.call
174
+ end
175
+ end
176
+
177
+ it "closed socket called on_close" do
178
+ begin
179
+ closed = false
180
+ server = Cool.io::TCPServer.new("localhost", port, ServerOnConnect, proc { closed = true })
181
+ loop.attach server
182
+ s = TCPSocket.open("localhost", port)
183
+ loop.run_once
184
+ s.close
185
+ loop.run_once
186
+ expect(closed).to eq true
187
+ ensure
188
+ server.detach
189
+ end
190
+ end
191
+ end
192
+
193
+ context "#on_read" do
194
+ class Echo < Coolio::Socket
195
+ def initialize(io, cb)
196
+ super(io)
197
+ @cb = cb
198
+ end
199
+ def on_read(data)
200
+ @cb.call data
201
+ size = write(data + "fff")
202
+ end
203
+ end
204
+
205
+ it "server socket received data" do
206
+ begin
207
+ data = "aaa"
208
+ server = Cool.io::TCPServer.new("localhost", port, Echo, proc { |d| data = d })
209
+ loop.attach server
210
+ thread = Thread.new { loop.run }
211
+ s = TCPSocket.open("localhost", port)
212
+ s.write "zzz"
213
+ sleep 0.1
214
+ expect(data).to eq "zzz"
215
+ expect(s.read 6).to eq "zzzfff"
216
+ ensure
217
+ s.close
218
+ loop.stop
219
+ server.detach
220
+ thread.join
221
+ end
222
+ end
223
+ end
224
+ end
131
225
  end
132
-
@@ -0,0 +1,185 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+
3
+ describe Coolio::TCPSocket do
4
+ let :loop do
5
+ Coolio::Loop.new
6
+ end
7
+
8
+ before :each do
9
+ @echo = TCPServer.new("127.0.0.1", 0)
10
+ @host = @echo.addr[3]
11
+ @port = @echo.addr[1]
12
+ @running = true
13
+ @echo_thread = Thread.new do
14
+ socks = [@echo]
15
+ begin
16
+ serv socks
17
+ ensure
18
+ socks.each do |s|
19
+ s.close
20
+ end
21
+ end
22
+ Thread.pass
23
+ end
24
+ end
25
+
26
+ def serv(socks)
27
+ while @running
28
+ selected = select(socks, [], [], 0.1)
29
+ next if selected.nil?
30
+ selected[0].each do |s|
31
+ if s == @echo
32
+ socks.push s.accept
33
+ next
34
+ end
35
+ begin
36
+ unless s.eof?
37
+ s.write(s.read_nonblock 1)
38
+ end
39
+ rescue SystemCallError, EOFError, IOError, SocketError
40
+ end
41
+ end
42
+ end
43
+ end
44
+
45
+ def shutdown
46
+ if @running
47
+ @running = false
48
+ @echo_thread.join
49
+ end
50
+ end
51
+
52
+ after :each do
53
+ shutdown
54
+ end
55
+
56
+ context "#close" do
57
+ it "detaches all watchers on #close before loop#run" do
58
+ client = Coolio::TCPSocket.connect(@host, @port)
59
+ loop.attach client
60
+ client.close
61
+ expect(loop.watchers.size).to eq 0
62
+ end
63
+ end
64
+
65
+ context "#on_connect" do
66
+ class OnConnect < Cool.io::TCPSocket
67
+ attr :connected
68
+ def on_connect
69
+ @connected = true
70
+ end
71
+ end
72
+
73
+ it "connected client called on_connect" do
74
+ begin
75
+ c = OnConnect.connect(@host, @port)
76
+ loop.attach c
77
+ loop.run_once
78
+ expect(c.connected).to eq true
79
+ ensure
80
+ c.close
81
+ end
82
+ end
83
+ end
84
+
85
+ context "#on_connect_failed" do
86
+ class OnConnectFailed < Cool.io::TCPSocket
87
+ attr :connect_failed
88
+ def on_connect_failed
89
+ @connect_failed = true
90
+ end
91
+ end
92
+
93
+ it "try to connect dead host" do
94
+ serv = TCPServer.new(0)
95
+ dead_host = serv.addr[3]
96
+ dead_port = serv.addr[1]
97
+ serv.close
98
+
99
+ c = OnConnectFailed.connect(dead_host, dead_port)
100
+ loop.attach c
101
+ loop.run_once # on_connect_failed
102
+ expect(c.connect_failed).to eq true
103
+ end
104
+ end
105
+
106
+ context "#on_close" do
107
+ class Closed < StandardError; end
108
+ class OnClose < Cool.io::TCPSocket
109
+ def on_close
110
+ raise Closed
111
+ end
112
+ end
113
+
114
+ let :client do
115
+ OnClose.connect(@host, @port)
116
+ end
117
+
118
+ before :each do
119
+ loop.attach client
120
+ loop.run_once # on_connect
121
+ client.write "0"
122
+ end
123
+
124
+ it "disconnect from client" do
125
+ expect { client.close }.to raise_error(Closed)
126
+ end
127
+
128
+ it "disconnect from server" do
129
+ shutdown
130
+ expect { loop.run }.to raise_error(Closed)
131
+ end
132
+ end
133
+
134
+ context "#on_read" do
135
+ class Finished < StandardError; end
136
+ class OnRead < Cool.io::TCPSocket
137
+ attr :read_data, :times
138
+ def on_connect
139
+ @read_data = ""
140
+ @times = 0
141
+ end
142
+ def on_read(data)
143
+ @read_data += data
144
+ @times += 1
145
+ if @times < 5
146
+ write "#{@times}"
147
+ else
148
+ close
149
+ raise Finished
150
+ end
151
+ end
152
+ end
153
+
154
+ it "receive 5 times" do
155
+ c = OnRead.connect(@host, @port)
156
+ loop.attach c
157
+ loop.run_once # on_connect
158
+ c.write "0"
159
+ expect { loop.run }.to raise_error(Finished)
160
+
161
+ expect(c.times).to eq 5
162
+ expect(c.read_data).to eq "01234"
163
+ end
164
+ end
165
+
166
+ context "#on_write_complete" do
167
+ class WriteComplete < StandardError; end
168
+ class OnWriteComplete < Cool.io::TCPSocket
169
+ attr :called
170
+ def on_write_complete
171
+ @called = true
172
+ close
173
+ raise WriteComplete
174
+ end
175
+ end
176
+
177
+ it "on_write_complete is called" do
178
+ c = OnWriteComplete.connect(@host, @port)
179
+ loop.attach c
180
+ loop.run_once # on_connect
181
+ c.write "aaa"
182
+ expect { loop.run }.to raise_error(WriteComplete)
183
+ end
184
+ end
185
+ end