eventmachine 0.12.0 → 0.12.2
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.
- data/ext/cmain.cpp +27 -1
- data/ext/ed.cpp +17 -2
- data/ext/ed.h +9 -1
- data/ext/em.cpp +111 -2
- data/ext/em.h +4 -1
- data/ext/eventmachine.h +9 -2
- data/ext/rubymain.cpp +49 -1
- data/lib/eventmachine.rb +139 -15
- data/lib/eventmachine_version.rb +2 -2
- data/lib/jeventmachine.rb +30 -4
- data/lib/protocols/header_and_content.rb +8 -2
- data/lib/protocols/httpclient.rb +14 -3
- data/lib/protocols/linetext2.rb +20 -2
- data/lib/protocols/postgres.rb +261 -0
- data/lib/protocols/stomp.rb +4 -1
- data/tests/test_attach.rb +66 -0
- data/tests/test_basic.rb +38 -2
- data/tests/test_hc.rb +189 -141
- data/tests/test_httpclient.rb +22 -1
- data/tests/test_ltp2.rb +60 -1
- data/tests/test_next_tick.rb +45 -1
- data/tests/test_sasl.rb +2 -1
- data/tests/test_timers.rb +4 -2
- metadata +63 -61
data/lib/protocols/stomp.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# $Id: stomp.rb
|
1
|
+
# $Id: stomp.rb 738 2008-07-06 01:01:04Z francis $
|
2
2
|
#
|
3
3
|
# Author:: Francis Cianfrocca (gmail: blackhedd)
|
4
4
|
# Homepage:: http://rubyeventmachine.com
|
@@ -120,6 +120,9 @@ module EventMachine
|
|
120
120
|
def subscribe dest, ack=false
|
121
121
|
send_frame "SUBSCRIBE", {:destination=>dest, :ack=>(ack ? "client" : "auto")}
|
122
122
|
end
|
123
|
+
def ack msgid
|
124
|
+
send_frame "ACK", { :'message-id'=> msgid }
|
125
|
+
end
|
123
126
|
|
124
127
|
end
|
125
128
|
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# $Id: test_attach.rb 785 2008-09-15 09:46:23Z francis $
|
2
|
+
#
|
3
|
+
#----------------------------------------------------------------------------
|
4
|
+
#
|
5
|
+
# Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
|
6
|
+
# Gmail: blackhedd
|
7
|
+
#
|
8
|
+
# This program is free software; you can redistribute it and/or modify
|
9
|
+
# it under the terms of either: 1) the GNU General Public License
|
10
|
+
# as published by the Free Software Foundation; either version 2 of the
|
11
|
+
# License, or (at your option) any later version; or 2) Ruby's License.
|
12
|
+
#
|
13
|
+
# See the file COPYING for complete licensing information.
|
14
|
+
#
|
15
|
+
#---------------------------------------------------------------------------
|
16
|
+
#
|
17
|
+
|
18
|
+
$:.unshift "../lib"
|
19
|
+
require 'eventmachine'
|
20
|
+
require 'socket'
|
21
|
+
require 'test/unit'
|
22
|
+
|
23
|
+
|
24
|
+
class TestAttach < Test::Unit::TestCase
|
25
|
+
|
26
|
+
Host = "127.0.0.1"
|
27
|
+
Port = 9550
|
28
|
+
|
29
|
+
class EchoServer < EM::Connection
|
30
|
+
def receive_data data
|
31
|
+
send_data data
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class EchoClient < EM::Connection
|
36
|
+
def connection_completed
|
37
|
+
$sock.write("abc\n")
|
38
|
+
end
|
39
|
+
|
40
|
+
def notify_readable
|
41
|
+
$read = $sock.readline
|
42
|
+
$fd = detach
|
43
|
+
end
|
44
|
+
|
45
|
+
def unbind
|
46
|
+
EM.next_tick do
|
47
|
+
$sock.write("def\n")
|
48
|
+
EM.add_timer(0.5){ EM.stop }
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_attach
|
54
|
+
EM.run{
|
55
|
+
EM.start_server Host, Port, EchoServer
|
56
|
+
$sock = TCPSocket.new Host, Port
|
57
|
+
EM.attach $sock, EchoClient
|
58
|
+
}
|
59
|
+
|
60
|
+
assert_equal $read, "abc\n"
|
61
|
+
assert_equal $fd, $sock.fileno
|
62
|
+
assert_equal false, $sock.closed?
|
63
|
+
assert_equal $sock.readline, "def\n"
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
data/tests/test_basic.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# $Id: test_basic.rb
|
1
|
+
# $Id: test_basic.rb 735 2008-07-05 18:18:49Z francis $
|
2
2
|
#
|
3
3
|
# Author:: Francis Cianfrocca (gmail: blackhedd)
|
4
4
|
# Homepage:: http://rubyeventmachine.com
|
@@ -137,6 +137,42 @@ class TestBasic < Test::Unit::TestCase
|
|
137
137
|
}
|
138
138
|
end
|
139
139
|
|
140
|
-
end
|
141
140
|
|
141
|
+
#------------------------------------
|
142
|
+
#
|
143
|
+
# TODO. This is an unfinished bug fix.
|
144
|
+
# This case was originally reported by Dan Aquino. If you throw a Ruby exception
|
145
|
+
# in a post_init handler, it gets rethrown as a confusing reactor exception.
|
146
|
+
# The problem is in eventmachine.rb, which calls post_init within the private
|
147
|
+
# initialize method of the EM::Connection class. This happens in both the EM::connect
|
148
|
+
# method and in the code that responds to connection-accepted events.
|
149
|
+
# What happens is that we instantiate the new connection object, which calls
|
150
|
+
# initialize, and then after initialize returns, we stick the new connection object
|
151
|
+
# into EM's @conns hashtable.
|
152
|
+
# But the problem is that Connection::initialize calls #post_init before it returns,
|
153
|
+
# and this may be user-written code that may throw an uncaught Ruby exception.
|
154
|
+
# If that happens, the reactor will abort, and it will then try to run down open
|
155
|
+
# connections. Because @conns never got a chance to properly reflect the new connection
|
156
|
+
# (because initialize never returned), we throw a ConnectionNotBound error
|
157
|
+
# (eventmachine.rb line 1080).
|
158
|
+
# When the bug is fixed, activate this test case.
|
159
|
+
#
|
160
|
+
|
161
|
+
class PostInitError < EM::Connection
|
162
|
+
def post_init
|
163
|
+
aaa bbb # should produce a Ruby exception
|
164
|
+
end
|
165
|
+
end
|
166
|
+
def test_post_init_error
|
167
|
+
assert_raise( NameError ) {
|
168
|
+
EM.run {
|
169
|
+
EM::Timer.new(1) {EM.stop}
|
170
|
+
EM.start_server TestHost, TestPort
|
171
|
+
EM.connect TestHost, TestPort, PostInitError
|
172
|
+
}
|
173
|
+
}
|
174
|
+
end
|
175
|
+
|
176
|
+
|
177
|
+
end
|
142
178
|
|
data/tests/test_hc.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# $Id: test_hc.rb
|
1
|
+
# $Id: test_hc.rb 721 2008-06-21 00:45:57Z francis $
|
2
2
|
#
|
3
3
|
# Author:: Francis Cianfrocca (gmail: blackhedd)
|
4
4
|
# Homepage:: http://rubyeventmachine.com
|
@@ -33,119 +33,157 @@ require 'test/unit'
|
|
33
33
|
# Part of it is thread race conditions. I added some sleeps to make these
|
34
34
|
# tests work. Native threads do strange things when you do I/O on them.
|
35
35
|
#
|
36
|
+
# And it's even worse in Java, where I/O on native threads doesn't seem
|
37
|
+
# to be reliable at all.
|
38
|
+
#
|
36
39
|
|
37
40
|
|
38
41
|
class TestHeaderAndContentProtocol < Test::Unit::TestCase
|
39
42
|
|
40
|
-
|
41
|
-
|
43
|
+
TestHost = "127.0.0.1"
|
44
|
+
TestPort = 8905
|
42
45
|
|
43
46
|
|
44
|
-
|
47
|
+
#--------------------------------------------------------------------
|
45
48
|
|
46
|
-
|
47
|
-
|
49
|
+
class SimpleTest < EventMachine::Protocols::HeaderAndContentProtocol
|
50
|
+
attr_reader :first_header, :my_headers, :request
|
48
51
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
+
def receive_first_header_line hdr
|
53
|
+
@first_header ||= []
|
54
|
+
@first_header << hdr
|
55
|
+
end
|
56
|
+
def receive_headers hdrs
|
57
|
+
@my_headers ||= []
|
58
|
+
@my_headers << hdrs
|
59
|
+
end
|
60
|
+
def receive_request hdrs, content
|
61
|
+
@request ||= []
|
62
|
+
@request << [hdrs, content]
|
63
|
+
end
|
52
64
|
end
|
53
|
-
|
54
|
-
|
55
|
-
|
65
|
+
|
66
|
+
|
67
|
+
def test_no_content
|
68
|
+
Thread.abort_on_exception = true
|
69
|
+
the_connection = nil
|
70
|
+
EventMachine.run {
|
71
|
+
EventMachine.start_server( TestHost, TestPort, SimpleTest ) do |conn|
|
72
|
+
the_connection = conn
|
73
|
+
end
|
74
|
+
EventMachine.add_timer(4) {raise "test timed out"}
|
75
|
+
|
76
|
+
pr = proc {
|
77
|
+
t = TCPSocket.new TestHost, TestPort
|
78
|
+
t.write [ "aaa\n", "bbb\r\n", "ccc\n", "\n" ].join
|
79
|
+
t.close
|
80
|
+
}
|
81
|
+
|
82
|
+
if RUBY_PLATFORM =~ /java/i
|
83
|
+
pr.call
|
84
|
+
EM.add_timer(0.5) {EM.stop}
|
85
|
+
else
|
86
|
+
EventMachine.defer proc {
|
87
|
+
pr.call
|
88
|
+
if RUBY_VERSION =~ /\A1\.9\./
|
89
|
+
sleep 0.1
|
90
|
+
STDERR.puts "Introducing extraneous sleep for Ruby 1.9"
|
91
|
+
end
|
92
|
+
}, proc {
|
93
|
+
EventMachine.stop
|
94
|
+
}
|
95
|
+
end
|
96
|
+
}
|
97
|
+
assert_equal( ["aaa"], the_connection.first_header )
|
98
|
+
assert_equal( [%w(aaa bbb ccc)], the_connection.my_headers )
|
99
|
+
assert_equal( [[%w(aaa bbb ccc), ""]], the_connection.request )
|
56
100
|
end
|
57
|
-
|
58
|
-
|
59
|
-
|
101
|
+
|
102
|
+
|
103
|
+
|
104
|
+
|
105
|
+
def test_content
|
106
|
+
Thread.abort_on_exception = true
|
107
|
+
the_connection = nil
|
108
|
+
content = "A" * 50
|
109
|
+
headers = ["aaa", "bbb", "Content-length: #{content.length}", "ccc"]
|
110
|
+
EventMachine.run {
|
111
|
+
EventMachine.start_server( TestHost, TestPort, SimpleTest ) do |conn|
|
112
|
+
the_connection = conn
|
113
|
+
end
|
114
|
+
EventMachine.add_timer(4) {raise "test timed out"}
|
115
|
+
|
116
|
+
pr = proc {
|
117
|
+
t = TCPSocket.new TestHost, TestPort
|
118
|
+
headers.each {|h| t.write "#{h}\r\n" }
|
119
|
+
t.write "\n"
|
120
|
+
t.write content
|
121
|
+
t.close
|
122
|
+
}
|
123
|
+
|
124
|
+
if RUBY_PLATFORM =~ /java/i
|
125
|
+
# I/O on threads seems completely unreliable in Java.
|
126
|
+
pr.call
|
127
|
+
EM.add_timer(0.5) {EM.stop}
|
128
|
+
else
|
129
|
+
EventMachine.defer proc {
|
130
|
+
pr.call
|
131
|
+
if RUBY_VERSION =~ /\A1\.9\./
|
132
|
+
sleep 0.1
|
133
|
+
STDERR.puts "Introducing extraneous sleep for Ruby 1.9"
|
134
|
+
end
|
135
|
+
}, proc {
|
136
|
+
EM.stop
|
137
|
+
}
|
138
|
+
end
|
139
|
+
}
|
140
|
+
assert_equal( ["aaa"], the_connection.first_header )
|
141
|
+
assert_equal( [headers], the_connection.my_headers )
|
142
|
+
assert_equal( [[headers, content]], the_connection.request )
|
60
143
|
end
|
61
|
-
end
|
62
144
|
|
63
|
-
def test_no_content
|
64
|
-
Thread.abort_on_exception = true
|
65
|
-
the_connection = nil
|
66
|
-
EventMachine.run {
|
67
|
-
EventMachine.start_server( TestHost, TestPort, SimpleTest ) do |conn|
|
68
|
-
the_connection = conn
|
69
|
-
end
|
70
|
-
EventMachine.add_timer(4) {raise "test timed out"}
|
71
|
-
EventMachine.defer proc {
|
72
|
-
t = TCPSocket.new TestHost, TestPort
|
73
|
-
t.write [
|
74
|
-
"aaa\n", "bbb\r\n", "ccc\n", "\n"
|
75
|
-
].join
|
76
|
-
t.close
|
77
|
-
if RUBY_VERSION =~ /\A1\.9\./
|
78
|
-
sleep 0.1
|
79
|
-
STDERR.puts "Introducing extraneous sleep for Ruby 1.9"
|
80
|
-
end
|
81
|
-
}, proc {
|
82
|
-
EventMachine.stop
|
83
|
-
}
|
84
|
-
}
|
85
|
-
assert_equal( ["aaa"], the_connection.first_header )
|
86
|
-
assert_equal( [%w(aaa bbb ccc)], the_connection.my_headers )
|
87
|
-
assert_equal( [[%w(aaa bbb ccc), ""]], the_connection.request )
|
88
|
-
end
|
89
145
|
|
90
|
-
def test_content
|
91
|
-
Thread.abort_on_exception = true
|
92
|
-
the_connection = nil
|
93
|
-
content = "A" * 50
|
94
|
-
headers = ["aaa", "bbb", "Content-length: #{content.length}", "ccc"]
|
95
|
-
EventMachine.run {
|
96
|
-
EventMachine.start_server( TestHost, TestPort, SimpleTest ) do |conn|
|
97
|
-
the_connection = conn
|
98
|
-
end
|
99
|
-
EventMachine.add_timer(4) {raise "test timed out"}
|
100
|
-
EventMachine.defer proc {
|
101
|
-
t = TCPSocket.new TestHost, TestPort
|
102
|
-
headers.each {|h| t.write "#{h}\r\n" }
|
103
|
-
t.write "\n"
|
104
|
-
t.write content
|
105
|
-
t.close
|
106
|
-
if RUBY_VERSION =~ /\A1\.9\./
|
107
|
-
sleep 0.1
|
108
|
-
STDERR.puts "Introducing extraneous sleep for Ruby 1.9"
|
109
|
-
end
|
110
|
-
}, proc {
|
111
|
-
EM.stop
|
112
|
-
}
|
113
|
-
}
|
114
|
-
assert_equal( ["aaa"], the_connection.first_header )
|
115
|
-
assert_equal( [headers], the_connection.my_headers )
|
116
|
-
assert_equal( [[headers, content]], the_connection.request )
|
117
|
-
end
|
118
146
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
147
|
+
def test_several_requests
|
148
|
+
Thread.abort_on_exception = true
|
149
|
+
the_connection = nil
|
150
|
+
content = "A" * 50
|
151
|
+
headers = ["aaa", "bbb", "Content-length: #{content.length}", "ccc"]
|
152
|
+
EventMachine.run {
|
153
|
+
EventMachine.start_server( TestHost, TestPort, SimpleTest ) do |conn|
|
154
|
+
the_connection = conn
|
155
|
+
end
|
156
|
+
EventMachine.add_timer(4) {raise "test timed out"}
|
157
|
+
|
158
|
+
pr = proc {
|
159
|
+
t = TCPSocket.new TestHost, TestPort
|
160
|
+
5.times {
|
161
|
+
headers.each {|h| t.write "#{h}\r\n" }
|
162
|
+
t.write "\n"
|
163
|
+
t.write content
|
164
|
+
}
|
165
|
+
t.close
|
166
|
+
}
|
167
|
+
|
168
|
+
if RUBY_PLATFORM =~ /java/i
|
169
|
+
pr.call
|
170
|
+
EM.add_timer(1) {EM.stop}
|
171
|
+
else
|
172
|
+
EventMachine.defer proc {
|
173
|
+
pr.call
|
174
|
+
if RUBY_VERSION =~ /\A1\.9\./
|
175
|
+
sleep 0.1
|
176
|
+
STDERR.puts "Introducing extraneous sleep for Ruby 1.9"
|
177
|
+
end
|
178
|
+
}, proc {
|
179
|
+
EventMachine.stop
|
180
|
+
}
|
181
|
+
end
|
135
182
|
}
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
end
|
141
|
-
}, proc {
|
142
|
-
EventMachine.stop
|
143
|
-
}
|
144
|
-
}
|
145
|
-
assert_equal( ["aaa"] * 5, the_connection.first_header )
|
146
|
-
assert_equal( [headers] * 5, the_connection.my_headers )
|
147
|
-
assert_equal( [[headers, content]] * 5, the_connection.request )
|
148
|
-
end
|
183
|
+
assert_equal( ["aaa"] * 5, the_connection.first_header )
|
184
|
+
assert_equal( [headers] * 5, the_connection.my_headers )
|
185
|
+
assert_equal( [[headers, content]] * 5, the_connection.request )
|
186
|
+
end
|
149
187
|
|
150
188
|
|
151
189
|
def x_test_multiple_content_length_headers
|
@@ -171,50 +209,60 @@ class TestHeaderAndContentProtocol < Test::Unit::TestCase
|
|
171
209
|
}
|
172
210
|
end
|
173
211
|
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
EventMachine.run {
|
186
|
-
EventMachine.start_server( TestHost, TestPort, SimpleTest ) do |conn|
|
187
|
-
the_connection = conn
|
188
|
-
end
|
189
|
-
EventMachine.add_timer(4) {raise "test timed out"}
|
190
|
-
EventMachine.defer proc {
|
191
|
-
t = TCPSocket.new TestHost, TestPort
|
192
|
-
headers.each {|h| t.write "#{h}\r\n" }
|
193
|
-
t.write "\n"
|
194
|
-
t.write content
|
195
|
-
t.close
|
196
|
-
if RUBY_VERSION =~ /\A1\.9\./
|
197
|
-
sleep 0.1
|
198
|
-
STDERR.puts "Introducing extraneous sleep for Ruby 1.9"
|
199
|
-
end
|
200
|
-
}, proc {
|
201
|
-
EventMachine.stop
|
202
|
-
}
|
203
|
-
}
|
212
|
+
def test_interpret_headers
|
213
|
+
Thread.abort_on_exception = true
|
214
|
+
the_connection = nil
|
215
|
+
content = "A" * 50
|
216
|
+
headers = [
|
217
|
+
"GET / HTTP/1.0",
|
218
|
+
"Accept: aaa",
|
219
|
+
"User-Agent: bbb",
|
220
|
+
"Host: ccc",
|
221
|
+
"x-tempest-header:ddd"
|
222
|
+
]
|
204
223
|
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
224
|
+
EventMachine.run {
|
225
|
+
EventMachine.start_server( TestHost, TestPort, SimpleTest ) do |conn|
|
226
|
+
the_connection = conn
|
227
|
+
end
|
228
|
+
EventMachine.add_timer(4) {raise "test timed out"}
|
229
|
+
|
230
|
+
pr = proc {
|
231
|
+
t = TCPSocket.new TestHost, TestPort
|
232
|
+
headers.each {|h| t.write "#{h}\r\n" }
|
233
|
+
t.write "\n"
|
234
|
+
t.write content
|
235
|
+
t.close
|
236
|
+
}
|
237
|
+
|
238
|
+
if RUBY_PLATFORM =~ /java/i
|
239
|
+
pr.call
|
240
|
+
EM.add_timer(0.5) {EM.stop}
|
241
|
+
else
|
242
|
+
EventMachine.defer proc {
|
243
|
+
pr.call
|
244
|
+
if RUBY_VERSION =~ /\A1\.9\./
|
245
|
+
sleep 0.1
|
246
|
+
STDERR.puts "Introducing extraneous sleep for Ruby 1.9"
|
247
|
+
end
|
248
|
+
}, proc {
|
249
|
+
EventMachine.stop
|
250
|
+
}
|
251
|
+
end
|
252
|
+
}
|
253
|
+
|
254
|
+
hsh = the_connection.headers_2_hash( the_connection.my_headers.shift )
|
255
|
+
assert_equal(
|
256
|
+
{
|
257
|
+
:accept => "aaa",
|
258
|
+
:user_agent => "bbb",
|
259
|
+
:host => "ccc",
|
260
|
+
:x_tempest_header => "ddd"
|
261
|
+
},
|
262
|
+
hsh
|
263
|
+
)
|
264
|
+
end
|
216
265
|
|
217
|
-
#--------------------------------------------------------------------
|
218
266
|
|
219
267
|
end
|
220
268
|
|