cool.io 1.3.0 → 1.3.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
  SHA1:
3
- metadata.gz: 94010c895806ae23b7ac77b906979c31937463f3
4
- data.tar.gz: a73e0f356ee9764a3dd8a3a56c29a187a8ab0693
3
+ metadata.gz: 69788383b1d7d04b499aed3a4c7430bde6af09cb
4
+ data.tar.gz: a5bd943271281ef7e72c886cf07b33ea98a7ca0a
5
5
  SHA512:
6
- metadata.gz: e48dd879dd3a8c76408cbf8569e7fefbf329360cc5b7e95a8f1aeaab2ac647cc9e89d4840fa6b8c86c9eb3cad372f57169303911592914751de1cc94e258569e
7
- data.tar.gz: 1408f73b5abfcf72c6ca5c153aa9f1b72ac7bc1ed549235435c839883c0c8aa00ea375495a7e450f0803a8f75dc8b3212bfa9973509cc3003b27ddbe46d59451
6
+ metadata.gz: 02ff98d0fa4b9b90ed484e5db28c88adcbf4dde3e27ee436282b5a2aab3ea0afe2cfe88d79b10cb643c717e1af0e93736b914112b42061ac640f4ae07a001e84
7
+ data.tar.gz: ec26d9e2759c5b999f82dbf8dcfac2f407aa571bf941df4b0a6761c00787b793d0574429b0be6887316cbe861c7eef661300c50d7a662f69f87618f7be2717e9
data/.gitignore CHANGED
@@ -24,3 +24,6 @@ tmp
24
24
 
25
25
  ## PROJECT::SPECIFIC
26
26
  conftest.dSYM
27
+
28
+ *.lock
29
+ .ruby-version
data/CHANGES.md CHANGED
@@ -1,3 +1,10 @@
1
+ 1.3.1
2
+ -----
3
+
4
+ * Fix several bugs for JRuby support enhancement
5
+ * Fix deadlock bug on Windows environment
6
+ * Use RSpec3
7
+
1
8
  1.3.0
2
9
  -----
3
10
 
@@ -4,25 +4,11 @@ libs = []
4
4
 
5
5
  $defs << "-DRUBY_VERSION_CODE=#{RUBY_VERSION.gsub(/\D/, '')}"
6
6
 
7
- if have_func('rb_thread_blocking_region')
8
- $defs << '-DHAVE_RB_THREAD_BLOCKING_REGION'
9
- end
10
-
11
- if have_func('rb_thread_call_without_gvl')
12
- $defs << '-DHAVE_RB_THEREAD_CALL_WITHOUT_GVL'
13
- end
14
-
15
- if have_func('rb_thread_alone')
16
- $defs << '-DHAVE_RB_THREAD_ALONE'
17
- end
18
-
19
- if have_func('rb_str_set_len')
20
- $defs << '-DHAVE_RB_STR_SET_LEN'
21
- end
22
-
23
- if have_library('rt', 'clock_gettime')
24
- libs << "-lrt"
25
- end
7
+ have_func('rb_thread_blocking_region')
8
+ have_func('rb_thread_call_without_gvl')
9
+ have_func('rb_thread_alone')
10
+ have_func('rb_str_set_len')
11
+ have_library('rt', 'clock_gettime')
26
12
 
27
13
  if have_header('sys/select.h')
28
14
  $defs << '-DEV_USE_SELECT'
@@ -44,9 +30,7 @@ if have_header('port.h')
44
30
  $defs << '-DEV_USE_PORT'
45
31
  end
46
32
 
47
- if have_header('sys/resource.h')
48
- $defs << '-DHAVE_SYS_RESOURCE_H'
49
- end
33
+ have_header('sys/resource.h')
50
34
 
51
35
  # ncpu detection specifics
52
36
  case RUBY_PLATFORM
@@ -64,14 +48,14 @@ dir_config('cool.io_ext')
64
48
  create_makefile('cool.io_ext')
65
49
 
66
50
  # win32 needs to link in "just the right order" for some reason or ioctlsocket will be mapped to an [inverted] ruby specific version. See libev mailing list for (not so helpful discussion--true cause I'm not sure, but this overcomes the symptom)
67
- if RUBY_PLATFORM =~ /mingw|win32/
51
+ if RUBY_PLATFORM =~ /mingw|mswin/
68
52
  makefile_contents = File.read 'Makefile'
69
53
 
70
54
  # "Init_cool could not be found" when loading cool.io.so.
71
55
  # I'm not sure why this is needed. But this line causes "1114 A dynamic link library (DLL) initialization routine failed." So I commented out this line.
72
56
  #makefile_contents.gsub! 'DLDFLAGS = ', 'DLDFLAGS = -export-all '
73
57
 
74
- makefile_contents.gsub! 'LIBS = $(LIBRUBYARG_SHARED)', 'LIBS = -lws2_32 $(LIBRUBYARG_SHARED)'
58
+ makefile_contents.gsub! /LIBS = (.*) (\S*ws2_32\S*)/i, 'LIBS = \\2 \\1'
75
59
  File.open('Makefile', 'w') { |f| f.write makefile_contents }
76
60
  end
77
61
 
data/ext/cool.io/loop.c CHANGED
@@ -81,7 +81,7 @@ static void Coolio_Loop_free(struct Coolio_Loop *loop)
81
81
 
82
82
  static VALUE Coolio_Loop_initialize(VALUE self)
83
83
  {
84
- Coolio_Loop_ev_loop_new(self, INT2NUM(0));
84
+ return Coolio_Loop_ev_loop_new(self, INT2NUM(0));
85
85
  }
86
86
 
87
87
  /* Wrapper for populating a Coolio_Loop struct with a new event loop */
@@ -11,7 +11,9 @@
11
11
 
12
12
  #include <string.h>
13
13
  #include <time.h>
14
+ #ifndef _MSC_VER
14
15
  #include <unistd.h>
16
+ #endif
15
17
  #include <errno.h>
16
18
 
17
19
  /* 1 GiB maximum buffer size */
data/ext/libev/ev.c CHANGED
@@ -1153,8 +1153,8 @@ ecb_inline ecb_bool ecb_little_endian (void) { return ecb_byteorder_helper () ==
1153
1153
  int m = x & 0x3ff;
1154
1154
  float r;
1155
1155
 
1156
- if (!e ) r = ldexpf (m , -24);
1157
- else if (e != 31) r = ldexpf (m + 0x400, e - 25);
1156
+ if (!e ) r = ldexpf ((float)m , -24);
1157
+ else if (e != 31) r = ldexpf ((float)m + 0x400, e - 25);
1158
1158
  else if (m ) r = ECB_NAN;
1159
1159
  else r = ECB_INFINITY;
1160
1160
 
@@ -2263,7 +2263,7 @@ evpipe_write (EV_P_ EV_ATOMIC_T *flag)
2263
2263
  #ifdef _WIN32
2264
2264
  WSABUF buf;
2265
2265
  DWORD sent;
2266
- buf.buf = &buf;
2266
+ buf.buf = (CHAR*)&buf;
2267
2267
  buf.len = 1;
2268
2268
  WSASend (EV_FD_TO_WIN32_HANDLE (evpipe [1]), &buf, 1, &sent, 0, 0, 0);
2269
2269
  #else
@@ -3343,6 +3343,7 @@ VALUE ev_backend_poll(void **args)
3343
3343
  struct ev_loop *loop = (struct ev_loop *)args[0];
3344
3344
  ev_tstamp waittime = *(ev_tstamp *)args[1];
3345
3345
  backend_poll (EV_A_ waittime);
3346
+ return Qnil;
3346
3347
  }
3347
3348
  #endif
3348
3349
  /* ######################################## */
@@ -106,6 +106,7 @@ if (__i == ((fd_set *)(set))->fd_count) {\
106
106
  } while(0)
107
107
  #define EV_WIN_FD_ZERO(set) (((fd_set *)(set))->fd_count=0)
108
108
  #define EV_WIN_FD_ISSET(fd, set) __WSAFDIsSet((SOCKET)(fd), (fd_set *)(set))
109
+ #define EV_WIN_FD_COUNT(set) (((fd_set *)(set))->fd_count)
109
110
  /* ######################################## */
110
111
  #else
111
112
  #define EV_WIN_FD_CLR FD_CLR
@@ -192,6 +193,23 @@ select_poll (EV_P_ ev_tstamp timeout)
192
193
  int res;
193
194
  int fd_setsize;
194
195
 
196
+ #ifdef _WIN32
197
+ /* POSIX defines the case when the readfds, writefds, and errorfds arguments
198
+ * are all null pointers.
199
+ * http://pubs.opengroup.org/onlinepubs/9699919799/functions/select.html
200
+ *
201
+ * But Windows doesn't define such case; simply say don't so that
202
+ * https://msdn.microsoft.com/en-us/library/windows/desktop/ms740141(v=vs.85).aspx
203
+ * "Any two of the parameters, readfds, writefds, or exceptfds, can be given
204
+ * as null. At least one must be non-null, and any non-null descriptor set
205
+ * must contain at least one handle to a socket."
206
+ * At least on Windows Server 2012 R2 Datacenter with Visual Studio 2013
207
+ * (Visual C++ 12), it cause WaitForMultipleObjects stuck.
208
+ */
209
+ if (EV_WIN_FD_COUNT(vec_ri) == 0 && EV_WIN_FD_COUNT(vec_wi) == 0)
210
+ return;
211
+ #endif
212
+
195
213
  EV_RELEASE_CB;
196
214
  EV_TV_SET (tv, timeout);
197
215
 
@@ -246,7 +264,7 @@ select_poll (EV_P_ ev_tstamp timeout)
246
264
  {
247
265
  if (timeout)
248
266
  {
249
- unsigned long ms = timeout * 1e3;
267
+ unsigned long ms = (unsigned long)(timeout * 1e3);
250
268
  Sleep (ms ? ms : 1);
251
269
  }
252
270
 
@@ -106,9 +106,8 @@ module Coolio
106
106
  def send_request
107
107
  nameserver = @nameservers.shift
108
108
  @nameservers << nameserver # rotate them
109
- @socket.connect @nameservers.first, DNS_PORT
110
109
  begin
111
- @socket.send request_message, 0
110
+ @socket.send request_message, 0, @nameservers.first, DNS_PORT
112
111
  rescue Errno::EHOSTUNREACH # TODO figure out why it has to be wrapper here, when the other wrapper should be wrapping this one!
113
112
  end
114
113
  end
data/lib/cool.io/io.rb CHANGED
@@ -102,7 +102,7 @@ module Coolio
102
102
  def close
103
103
  detach if attached?
104
104
  detach_write_watcher
105
- @_io.close unless @_io.closed?
105
+ @_io.close unless closed?
106
106
 
107
107
  on_close
108
108
  nil
@@ -1,5 +1,5 @@
1
1
  module Coolio
2
- VERSION = "1.3.0"
2
+ VERSION = "1.3.1"
3
3
 
4
4
  def self.version
5
5
  VERSION
@@ -30,7 +30,7 @@ describe Cool.io::AsyncWatcher, :env => :exclude_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 => :exclude_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
data/spec/dns_spec.rb CHANGED
@@ -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
data/spec/spec_helper.rb CHANGED
@@ -12,7 +12,7 @@ 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
17
  c.filter_run_excluding :env => :exclude_win
18
18
  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
@@ -109,11 +109,11 @@ end
109
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 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
-
@@ -1,27 +1,185 @@
1
1
  require File.expand_path('../spec_helper', __FILE__)
2
2
 
3
3
  describe Coolio::TCPSocket do
4
-
4
+ let :loop do
5
+ Coolio::Loop.new
6
+ end
7
+
5
8
  before :each do
6
- @server = TCPServer.new('127.0.0.1', 0)
7
- @host = @server.addr[3]
8
- @port = @server.addr[1]
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
9
24
  end
10
-
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
+
11
52
  after :each do
12
- @server.close
53
+ shutdown
13
54
  end
14
55
 
15
- describe '#close' do
16
-
17
- it 'detaches all watchers on #close before loop#run' do
18
- reactor = Coolio::Loop.new
56
+ context "#close" do
57
+ it "detaches all watchers on #close before loop#run" do
19
58
  client = Coolio::TCPSocket.connect(@host, @port)
20
- reactor.attach(client)
59
+ loop.attach client
21
60
  client.close
22
- reactor.watchers.size.should == 0
61
+ expect(loop.watchers.size).to eq 0
23
62
  end
24
63
  end
25
64
 
26
- end
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
27
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
@@ -4,15 +4,19 @@ describe Cool.io::TimerWatcher do
4
4
 
5
5
  interval = 0.010
6
6
 
7
+ let :loop do
8
+ Cool.io::Loop.new
9
+ end
10
+
7
11
  it "can have the on_timer callback defined after creation" do
8
12
  @watcher = Cool.io::TimerWatcher.new(interval, true)
9
13
  nr = '0'
10
- @watcher.on_timer { nr.succ! }.should == nil
11
- @watcher.attach(Cool.io::Loop.default).should == @watcher
12
- nr.should == '0'
14
+ expect(@watcher.on_timer { nr.succ! }).to be_nil
15
+ expect(@watcher.attach(loop)).to eq(@watcher)
16
+ expect(nr).to eq('0')
13
17
  sleep interval
14
- Cool.io::Loop.default.run_once
15
- nr.should == '1'
18
+ loop.run_once
19
+ expect(nr).to eq('1')
16
20
  end
17
21
 
18
22
  it "can be subclassed" do
@@ -24,29 +28,29 @@ describe Cool.io::TimerWatcher do
24
28
  end
25
29
  end
26
30
  @watcher = MyTimerWatcher.new(interval, true)
27
- @watcher.attach(Cool.io::Loop.default).should == @watcher
28
- MyTimerWatcher::TMP.should == '0'
31
+ expect(@watcher.attach(loop)).to eq(@watcher)
32
+ expect(MyTimerWatcher::TMP).to eq('0')
29
33
  sleep interval
30
- Cool.io::Loop.default.run_once
31
- MyTimerWatcher::TMP.should == '1'
34
+ loop.run_once
35
+ expect(MyTimerWatcher::TMP).to eq('1')
32
36
  end
33
37
 
34
38
  it "can have the on_timer callback redefined between runs" do
35
39
  @watcher = Cool.io::TimerWatcher.new(interval, true)
36
40
  nr = '0'
37
- @watcher.on_timer { nr.succ! }.should == nil
38
- @watcher.attach(Cool.io::Loop.default).should == @watcher
39
- nr.should == '0'
41
+ expect(@watcher.on_timer { nr.succ! }).to be_nil
42
+ expect(@watcher.attach(loop)).to eq(@watcher)
43
+ expect(nr).to eq('0')
40
44
  sleep interval
41
- Cool.io::Loop.default.run_once
42
- nr.should == '1'
45
+ loop.run_once
46
+ expect(nr).to eq('1')
43
47
  @watcher.detach
44
- @watcher.on_timer { nr = :foo }.should == nil
45
- @watcher.attach(Cool.io::Loop.default).should == @watcher
46
- nr.should == '1'
48
+ expect(@watcher.on_timer { nr = :foo }).to be_nil
49
+ expect(@watcher.attach(loop)).to eq(@watcher)
50
+ expect(nr).to eq('1')
47
51
  sleep interval
48
- Cool.io::Loop.default.run_once
49
- nr.should == :foo
52
+ loop.run_once
53
+ expect(nr).to eq(:foo)
50
54
  end
51
55
 
52
56
  after :each do
@@ -0,0 +1,58 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+
3
+ describe "Coolio::UDPSocket" do
4
+ let :loop do
5
+ Coolio::Loop.new
6
+ end
7
+
8
+ before :each do
9
+ @echo = UDPSocket.open
10
+ @echo.bind nil, 0
11
+ @port = @echo.addr[1]
12
+
13
+ @running = true
14
+ @echo_thread = Thread.new do
15
+ while @running
16
+ begin
17
+ msg, sender = @echo.recvfrom_nonblock(3)
18
+ @echo.send(msg + "bbb", 0, sender[3], sender[1])
19
+ rescue IO::WaitReadable
20
+ end
21
+ Thread.pass
22
+ end
23
+ end
24
+ end
25
+
26
+ after :each do
27
+ @running = false
28
+ @echo_thread.join
29
+ @echo.close
30
+ end
31
+
32
+ class Readable < Cool.io::IOWatcher
33
+ attr :socket, :received
34
+ def initialize
35
+ @socket = UDPSocket.new
36
+ super(@socket)
37
+ end
38
+
39
+ def on_readable
40
+ @received = @socket.recvfrom_nonblock(6).first
41
+ end
42
+ end
43
+
44
+ it "receive message #on_readable 5 times" do
45
+ 5.times do
46
+ begin
47
+ r = Readable.new
48
+ r.socket.send "aaa", 0, "localhost", @port
49
+
50
+ loop.attach r
51
+ loop.run_once
52
+ expect(r.received).to eq "aaabbb"
53
+ ensure
54
+ r.detach
55
+ end
56
+ end
57
+ end
58
+ end
@@ -5,21 +5,21 @@ describe Cool.io::UNIXListener, :env => :exclude_win do
5
5
 
6
6
  before :each do
7
7
  @tmp = Tempfile.new('coolio_unix_listener_spec')
8
- File.unlink(@tmp.path).should == 1
9
- File.exist?(@tmp.path).should == false
8
+ expect(File.unlink(@tmp.path)).to eq(1)
9
+ expect(File.exist?(@tmp.path)).to eq(false)
10
10
  end
11
11
 
12
12
  it "creates a new UNIXListener" do
13
13
  listener = Cool.io::UNIXListener.new(@tmp.path)
14
- File.socket?(@tmp.path).should == true
14
+ expect(File.socket?(@tmp.path)).to eq(true)
15
15
  end
16
16
 
17
17
  it "builds off an existing UNIXServer" do
18
18
  unix_server = UNIXServer.new(@tmp.path)
19
- File.socket?(@tmp.path).should == true
19
+ expect(File.socket?(@tmp.path)).to eq(true)
20
20
  listener = Cool.io::UNIXListener.new(unix_server)
21
- File.socket?(@tmp.path).should == true
22
- listener.fileno.should == unix_server.fileno
21
+ expect(File.socket?(@tmp.path)).to eq(true)
22
+ expect(listener.fileno).to eq(unix_server.fileno)
23
23
  end
24
24
 
25
25
  end
@@ -5,23 +5,23 @@ describe Cool.io::UNIXServer, :env => :exclude_win do
5
5
 
6
6
  before :each do
7
7
  @tmp = Tempfile.new('coolio_unix_server_spec')
8
- File.unlink(@tmp.path).should == 1
9
- File.exist?(@tmp.path).should == false
8
+ expect(File.unlink(@tmp.path)).to eq(1)
9
+ expect(File.exist?(@tmp.path)).to eq(false)
10
10
  end
11
11
 
12
12
  it "creates a new Cool.io::UNIXServer" do
13
13
  listener = Cool.io::UNIXListener.new(@tmp.path)
14
14
  listener.listen(24)
15
- File.socket?(@tmp.path).should == true
15
+ expect(File.socket?(@tmp.path)).to eq(true)
16
16
  end
17
17
 
18
18
  it "builds off an existing ::UNIXServer" do
19
19
  unix_server = ::UNIXServer.new(@tmp.path)
20
- File.socket?(@tmp.path).should == true
20
+ expect(File.socket?(@tmp.path)).to eq(true)
21
21
  listener = Cool.io::UNIXServer.new(unix_server, Coolio::UNIXSocket)
22
22
  listener.listen(24)
23
- File.socket?(@tmp.path).should == true
24
- listener.fileno.should == unix_server.fileno
23
+ expect(File.socket?(@tmp.path)).to eq(true)
24
+ expect(listener.fileno).to eq(unix_server.fileno)
25
25
  end
26
26
 
27
27
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cool.io
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tony Arcieri
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-01-21 00:00:00.000000000 Z
12
+ date: 2015-05-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake-compiler
@@ -129,11 +129,13 @@ files:
129
129
  - lib/coolio.rb
130
130
  - spec/async_watcher_spec.rb
131
131
  - spec/dns_spec.rb
132
+ - spec/iobuffer_spec.rb
132
133
  - spec/spec_helper.rb
133
134
  - spec/stat_watcher_spec.rb
134
135
  - spec/tcp_server_spec.rb
135
136
  - spec/tcp_socket_spec.rb
136
137
  - spec/timer_watcher_spec.rb
138
+ - spec/udp_socket_spec.rb
137
139
  - spec/unix_listener_spec.rb
138
140
  - spec/unix_server_spec.rb
139
141
  homepage: http://coolio.github.com
@@ -155,17 +157,19 @@ required_rubygems_version: !ruby/object:Gem::Requirement
155
157
  version: '0'
156
158
  requirements: []
157
159
  rubyforge_project:
158
- rubygems_version: 2.4.5
160
+ rubygems_version: 2.2.2
159
161
  signing_key:
160
162
  specification_version: 4
161
163
  summary: A cool framework for doing high performance I/O in Ruby
162
164
  test_files:
163
165
  - spec/async_watcher_spec.rb
164
166
  - spec/dns_spec.rb
167
+ - spec/iobuffer_spec.rb
165
168
  - spec/spec_helper.rb
166
169
  - spec/stat_watcher_spec.rb
167
170
  - spec/tcp_server_spec.rb
168
171
  - spec/tcp_socket_spec.rb
169
172
  - spec/timer_watcher_spec.rb
173
+ - spec/udp_socket_spec.rb
170
174
  - spec/unix_listener_spec.rb
171
175
  - spec/unix_server_spec.rb