eventmachine-mkroman 1.3.0.dev.1
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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +179 -0
- data/GNU +281 -0
- data/LICENSE +60 -0
- data/README.md +110 -0
- data/docs/DocumentationGuidesIndex.md +27 -0
- data/docs/GettingStarted.md +520 -0
- data/docs/old/ChangeLog +211 -0
- data/docs/old/DEFERRABLES +246 -0
- data/docs/old/EPOLL +141 -0
- data/docs/old/INSTALL +13 -0
- data/docs/old/KEYBOARD +42 -0
- data/docs/old/LEGAL +25 -0
- data/docs/old/LIGHTWEIGHT_CONCURRENCY +130 -0
- data/docs/old/PURE_RUBY +75 -0
- data/docs/old/RELEASE_NOTES +94 -0
- data/docs/old/SMTP +4 -0
- data/docs/old/SPAWNED_PROCESSES +148 -0
- data/docs/old/TODO +8 -0
- data/examples/guides/getting_started/01_eventmachine_echo_server.rb +18 -0
- data/examples/guides/getting_started/02_eventmachine_echo_server_that_recognizes_exit_command.rb +22 -0
- data/examples/guides/getting_started/03_simple_chat_server.rb +149 -0
- data/examples/guides/getting_started/04_simple_chat_server_step_one.rb +27 -0
- data/examples/guides/getting_started/05_simple_chat_server_step_two.rb +43 -0
- data/examples/guides/getting_started/06_simple_chat_server_step_three.rb +98 -0
- data/examples/guides/getting_started/07_simple_chat_server_step_four.rb +121 -0
- data/examples/guides/getting_started/08_simple_chat_server_step_five.rb +141 -0
- data/examples/old/ex_channel.rb +43 -0
- data/examples/old/ex_queue.rb +2 -0
- data/examples/old/ex_tick_loop_array.rb +15 -0
- data/examples/old/ex_tick_loop_counter.rb +32 -0
- data/examples/old/helper.rb +2 -0
- data/ext/binder.cpp +124 -0
- data/ext/binder.h +52 -0
- data/ext/cmain.cpp +1046 -0
- data/ext/ed.cpp +2243 -0
- data/ext/ed.h +463 -0
- data/ext/em.cpp +2378 -0
- data/ext/em.h +266 -0
- data/ext/eventmachine.h +152 -0
- data/ext/extconf.rb +291 -0
- data/ext/fastfilereader/extconf.rb +120 -0
- data/ext/fastfilereader/mapper.cpp +214 -0
- data/ext/fastfilereader/mapper.h +59 -0
- data/ext/fastfilereader/rubymain.cpp +126 -0
- data/ext/kb.cpp +79 -0
- data/ext/page.cpp +107 -0
- data/ext/page.h +51 -0
- data/ext/pipe.cpp +354 -0
- data/ext/project.h +174 -0
- data/ext/rubymain.cpp +1643 -0
- data/ext/ssl.cpp +701 -0
- data/ext/ssl.h +103 -0
- data/ext/wait_for_single_fd.h +36 -0
- data/java/.classpath +8 -0
- data/java/.project +17 -0
- data/java/src/com/rubyeventmachine/EmReactor.java +625 -0
- data/java/src/com/rubyeventmachine/EmReactorException.java +40 -0
- data/java/src/com/rubyeventmachine/EmReactorInterface.java +70 -0
- data/java/src/com/rubyeventmachine/EventableChannel.java +72 -0
- data/java/src/com/rubyeventmachine/EventableDatagramChannel.java +201 -0
- data/java/src/com/rubyeventmachine/EventableSocketChannel.java +415 -0
- data/java/src/com/rubyeventmachine/NullEmReactor.java +157 -0
- data/java/src/com/rubyeventmachine/NullEventableChannel.java +81 -0
- data/lib/em/buftok.rb +59 -0
- data/lib/em/callback.rb +58 -0
- data/lib/em/channel.rb +69 -0
- data/lib/em/completion.rb +307 -0
- data/lib/em/connection.rb +802 -0
- data/lib/em/deferrable/pool.rb +2 -0
- data/lib/em/deferrable.rb +210 -0
- data/lib/em/file_watch.rb +73 -0
- data/lib/em/future.rb +61 -0
- data/lib/em/io_streamer.rb +68 -0
- data/lib/em/iterator.rb +252 -0
- data/lib/em/messages.rb +66 -0
- data/lib/em/pool.rb +151 -0
- data/lib/em/process_watch.rb +45 -0
- data/lib/em/processes.rb +123 -0
- data/lib/em/protocols/header_and_content.rb +138 -0
- data/lib/em/protocols/httpclient.rb +303 -0
- data/lib/em/protocols/httpclient2.rb +602 -0
- data/lib/em/protocols/line_and_text.rb +125 -0
- data/lib/em/protocols/line_protocol.rb +33 -0
- data/lib/em/protocols/linetext2.rb +179 -0
- data/lib/em/protocols/memcache.rb +331 -0
- data/lib/em/protocols/object_protocol.rb +46 -0
- data/lib/em/protocols/postgres3.rb +246 -0
- data/lib/em/protocols/saslauth.rb +175 -0
- data/lib/em/protocols/smtpclient.rb +394 -0
- data/lib/em/protocols/smtpserver.rb +666 -0
- data/lib/em/protocols/socks4.rb +66 -0
- data/lib/em/protocols/stomp.rb +205 -0
- data/lib/em/protocols/tcptest.rb +54 -0
- data/lib/em/protocols.rb +37 -0
- data/lib/em/pure_ruby.rb +1300 -0
- data/lib/em/queue.rb +80 -0
- data/lib/em/resolver.rb +232 -0
- data/lib/em/spawnable.rb +84 -0
- data/lib/em/streamer.rb +118 -0
- data/lib/em/threaded_resource.rb +90 -0
- data/lib/em/tick_loop.rb +85 -0
- data/lib/em/timers.rb +61 -0
- data/lib/em/version.rb +3 -0
- data/lib/eventmachine.rb +1602 -0
- data/lib/jeventmachine.rb +319 -0
- data/rakelib/package.rake +120 -0
- data/rakelib/test.rake +6 -0
- data/rakelib/test_pure.rake +11 -0
- data/tests/client.crt +31 -0
- data/tests/client.key +51 -0
- data/tests/dhparam.pem +13 -0
- data/tests/em_ssl_handlers.rb +165 -0
- data/tests/em_test_helper.rb +198 -0
- data/tests/encoded_client.key +54 -0
- data/tests/jruby/test_jeventmachine.rb +38 -0
- data/tests/test_attach.rb +199 -0
- data/tests/test_basic.rb +321 -0
- data/tests/test_channel.rb +75 -0
- data/tests/test_completion.rb +178 -0
- data/tests/test_connection_count.rb +83 -0
- data/tests/test_connection_write.rb +35 -0
- data/tests/test_defer.rb +35 -0
- data/tests/test_deferrable.rb +35 -0
- data/tests/test_epoll.rb +141 -0
- data/tests/test_error_handler.rb +38 -0
- data/tests/test_exc.rb +37 -0
- data/tests/test_file_watch.rb +86 -0
- data/tests/test_fork.rb +75 -0
- data/tests/test_futures.rb +170 -0
- data/tests/test_handler_check.rb +35 -0
- data/tests/test_hc.rb +155 -0
- data/tests/test_httpclient.rb +238 -0
- data/tests/test_httpclient2.rb +132 -0
- data/tests/test_idle_connection.rb +31 -0
- data/tests/test_inactivity_timeout.rb +102 -0
- data/tests/test_io_streamer.rb +48 -0
- data/tests/test_ipv4.rb +96 -0
- data/tests/test_ipv6.rb +107 -0
- data/tests/test_iterator.rb +122 -0
- data/tests/test_kb.rb +28 -0
- data/tests/test_keepalive.rb +113 -0
- data/tests/test_line_protocol.rb +33 -0
- data/tests/test_ltp.rb +155 -0
- data/tests/test_ltp2.rb +332 -0
- data/tests/test_many_fds.rb +21 -0
- data/tests/test_next_tick.rb +104 -0
- data/tests/test_object_protocol.rb +36 -0
- data/tests/test_pause.rb +109 -0
- data/tests/test_pending_connect_timeout.rb +52 -0
- data/tests/test_pool.rb +196 -0
- data/tests/test_process_watch.rb +50 -0
- data/tests/test_processes.rb +147 -0
- data/tests/test_proxy_connection.rb +180 -0
- data/tests/test_pure.rb +156 -0
- data/tests/test_queue.rb +64 -0
- data/tests/test_resolver.rb +129 -0
- data/tests/test_running.rb +14 -0
- data/tests/test_sasl.rb +46 -0
- data/tests/test_send_file.rb +217 -0
- data/tests/test_servers.rb +32 -0
- data/tests/test_shutdown_hooks.rb +23 -0
- data/tests/test_smtpclient.rb +75 -0
- data/tests/test_smtpserver.rb +90 -0
- data/tests/test_sock_opt.rb +53 -0
- data/tests/test_spawn.rb +290 -0
- data/tests/test_ssl_args.rb +70 -0
- data/tests/test_ssl_dhparam.rb +57 -0
- data/tests/test_ssl_ecdh_curve.rb +57 -0
- data/tests/test_ssl_extensions.rb +24 -0
- data/tests/test_ssl_inline_cert.rb +222 -0
- data/tests/test_ssl_methods.rb +31 -0
- data/tests/test_ssl_protocols.rb +190 -0
- data/tests/test_ssl_verify.rb +108 -0
- data/tests/test_stomp.rb +38 -0
- data/tests/test_system.rb +46 -0
- data/tests/test_threaded_resource.rb +68 -0
- data/tests/test_tick_loop.rb +58 -0
- data/tests/test_timers.rb +150 -0
- data/tests/test_ud.rb +8 -0
- data/tests/test_unbind_reason.rb +40 -0
- metadata +389 -0
data/tests/test_hc.rb
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
require_relative 'em_test_helper'
|
|
2
|
+
|
|
3
|
+
class TestHeaderAndContentProtocol < Test::Unit::TestCase
|
|
4
|
+
|
|
5
|
+
class SimpleTest < EM::P::HeaderAndContentProtocol
|
|
6
|
+
attr_reader :first_header, :my_headers, :request
|
|
7
|
+
|
|
8
|
+
def receive_first_header_line hdr
|
|
9
|
+
@first_header ||= []
|
|
10
|
+
@first_header << hdr
|
|
11
|
+
end
|
|
12
|
+
def receive_headers hdrs
|
|
13
|
+
@my_headers ||= []
|
|
14
|
+
@my_headers << hdrs
|
|
15
|
+
end
|
|
16
|
+
def receive_request hdrs, content
|
|
17
|
+
@request ||= []
|
|
18
|
+
@request << [hdrs, content]
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class StopOnUnbind < EM::Connection
|
|
23
|
+
def unbind
|
|
24
|
+
EM.add_timer(0.01) { EM.stop }
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def setup
|
|
29
|
+
@port = next_port
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def test_no_content
|
|
33
|
+
the_connection = nil
|
|
34
|
+
EM.run {
|
|
35
|
+
EM.start_server( "127.0.0.1", @port, SimpleTest ) do |conn|
|
|
36
|
+
the_connection = conn
|
|
37
|
+
end
|
|
38
|
+
setup_timeout
|
|
39
|
+
|
|
40
|
+
EM.connect "127.0.0.1", @port, StopOnUnbind do |c|
|
|
41
|
+
c.send_data [ "aaa\n", "bbb\r\n", "ccc\n", "\n" ].join
|
|
42
|
+
c.close_connection_after_writing
|
|
43
|
+
end
|
|
44
|
+
}
|
|
45
|
+
assert_equal( ["aaa"], the_connection.first_header )
|
|
46
|
+
assert_equal( [%w(aaa bbb ccc)], the_connection.my_headers )
|
|
47
|
+
assert_equal( [[%w(aaa bbb ccc), ""]], the_connection.request )
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def test_content
|
|
51
|
+
the_connection = nil
|
|
52
|
+
content = "A" * 50
|
|
53
|
+
headers = ["aaa", "bbb", "Content-length: #{content.length}", "ccc"]
|
|
54
|
+
EM.run {
|
|
55
|
+
EM.start_server( "127.0.0.1", @port, SimpleTest ) do |conn|
|
|
56
|
+
the_connection = conn
|
|
57
|
+
end
|
|
58
|
+
setup_timeout
|
|
59
|
+
|
|
60
|
+
EM.connect "127.0.0.1", @port, StopOnUnbind do |c|
|
|
61
|
+
headers.each { |h| c.send_data "#{h}\r\n" }
|
|
62
|
+
c.send_data "\n"
|
|
63
|
+
c.send_data content
|
|
64
|
+
c.close_connection_after_writing
|
|
65
|
+
end
|
|
66
|
+
}
|
|
67
|
+
assert_equal( ["aaa"], the_connection.first_header )
|
|
68
|
+
assert_equal( [headers], the_connection.my_headers )
|
|
69
|
+
assert_equal( [[headers, content]], the_connection.request )
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def test_several_requests
|
|
73
|
+
the_connection = nil
|
|
74
|
+
content = "A" * 50
|
|
75
|
+
headers = ["aaa", "bbb", "Content-length: #{content.length}", "ccc"]
|
|
76
|
+
EM.run {
|
|
77
|
+
EM.start_server( "127.0.0.1", @port, SimpleTest ) do |conn|
|
|
78
|
+
the_connection = conn
|
|
79
|
+
end
|
|
80
|
+
setup_timeout
|
|
81
|
+
|
|
82
|
+
EM.connect( "127.0.0.1", @port, StopOnUnbind ) do |c|
|
|
83
|
+
5.times do
|
|
84
|
+
headers.each { |h| c.send_data "#{h}\r\n" }
|
|
85
|
+
c.send_data "\n"
|
|
86
|
+
c.send_data content
|
|
87
|
+
end
|
|
88
|
+
c.close_connection_after_writing
|
|
89
|
+
end
|
|
90
|
+
}
|
|
91
|
+
assert_equal( ["aaa"] * 5, the_connection.first_header )
|
|
92
|
+
assert_equal( [headers] * 5, the_connection.my_headers )
|
|
93
|
+
assert_equal( [[headers, content]] * 5, the_connection.request )
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
# def x_test_multiple_content_length_headers
|
|
98
|
+
# # This is supposed to throw a RuntimeError but it throws a C++ exception instead.
|
|
99
|
+
# the_connection = nil
|
|
100
|
+
# content = "A" * 50
|
|
101
|
+
# headers = ["aaa", "bbb", ["Content-length: #{content.length}"]*2, "ccc"].flatten
|
|
102
|
+
# EM.run {
|
|
103
|
+
# EM.start_server( "127.0.0.1", @port, SimpleTest ) do |conn|
|
|
104
|
+
# the_connection = conn
|
|
105
|
+
# end
|
|
106
|
+
# EM.add_timer(4) {raise "test timed out"}
|
|
107
|
+
# test_proc = proc {
|
|
108
|
+
# t = TCPSocket.new "127.0.0.1", @port
|
|
109
|
+
# headers.each {|h| t.write "#{h}\r\n" }
|
|
110
|
+
# t.write "\n"
|
|
111
|
+
# t.write content
|
|
112
|
+
# t.close
|
|
113
|
+
# }
|
|
114
|
+
# EM.defer test_proc, proc {
|
|
115
|
+
# EM.stop
|
|
116
|
+
# }
|
|
117
|
+
# }
|
|
118
|
+
# end
|
|
119
|
+
|
|
120
|
+
def test_interpret_headers
|
|
121
|
+
the_connection = nil
|
|
122
|
+
content = "A" * 50
|
|
123
|
+
headers = [
|
|
124
|
+
"GET / HTTP/1.0",
|
|
125
|
+
"Accept: aaa",
|
|
126
|
+
"User-Agent: bbb",
|
|
127
|
+
"Host: ccc",
|
|
128
|
+
"x-tempest-header:ddd"
|
|
129
|
+
]
|
|
130
|
+
|
|
131
|
+
EM.run {
|
|
132
|
+
EM.start_server( "127.0.0.1", @port, SimpleTest ) do |conn|
|
|
133
|
+
the_connection = conn
|
|
134
|
+
end
|
|
135
|
+
setup_timeout
|
|
136
|
+
|
|
137
|
+
EM.connect( "127.0.0.1", @port, StopOnUnbind ) do |c|
|
|
138
|
+
headers.each { |h| c.send_data "#{h}\r\n" }
|
|
139
|
+
c.send_data "\n"
|
|
140
|
+
c.send_data content
|
|
141
|
+
c.close_connection_after_writing
|
|
142
|
+
end
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
hsh = the_connection.headers_2_hash( the_connection.my_headers.shift )
|
|
146
|
+
expect = {
|
|
147
|
+
:accept => "aaa",
|
|
148
|
+
:user_agent => "bbb",
|
|
149
|
+
:host => "ccc",
|
|
150
|
+
:x_tempest_header => "ddd"
|
|
151
|
+
}
|
|
152
|
+
assert_equal(expect, hsh)
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
end
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
require_relative 'em_test_helper'
|
|
2
|
+
|
|
3
|
+
class TestHttpClient < Test::Unit::TestCase
|
|
4
|
+
|
|
5
|
+
def setup
|
|
6
|
+
@port = next_port
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
#-------------------------------------
|
|
10
|
+
|
|
11
|
+
def test_http_client
|
|
12
|
+
ok = false
|
|
13
|
+
EM.run {
|
|
14
|
+
c = silent { EM::P::HttpClient.send :request, :host => "www.google.com", :port => 80 }
|
|
15
|
+
c.callback {
|
|
16
|
+
ok = true
|
|
17
|
+
c.close_connection
|
|
18
|
+
EM.stop
|
|
19
|
+
}
|
|
20
|
+
c.errback {EM.stop} # necessary, otherwise a failure blocks the test suite forever.
|
|
21
|
+
}
|
|
22
|
+
assert ok
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
#-------------------------------------
|
|
26
|
+
|
|
27
|
+
def test_http_client_1
|
|
28
|
+
ok = false
|
|
29
|
+
EM.run {
|
|
30
|
+
c = silent { EM::P::HttpClient.send :request, :host => "www.google.com", :port => 80 }
|
|
31
|
+
c.callback {
|
|
32
|
+
ok = true
|
|
33
|
+
c.close_connection
|
|
34
|
+
EM.stop
|
|
35
|
+
}
|
|
36
|
+
c.errback {EM.stop}
|
|
37
|
+
}
|
|
38
|
+
assert ok
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
#-------------------------------------
|
|
42
|
+
|
|
43
|
+
def test_http_client_2
|
|
44
|
+
ok = false
|
|
45
|
+
EM.run {
|
|
46
|
+
c = silent { EM::P::HttpClient.send :request, :host => "www.google.com", :port => 80 }
|
|
47
|
+
c.callback {
|
|
48
|
+
ok = true
|
|
49
|
+
c.close_connection
|
|
50
|
+
EM.stop
|
|
51
|
+
}
|
|
52
|
+
c.errback {EM.stop}
|
|
53
|
+
}
|
|
54
|
+
assert ok
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
#-----------------------------------------
|
|
59
|
+
|
|
60
|
+
# Test a server that returns a page with a zero content-length.
|
|
61
|
+
# This caused an early version of the HTTP client not to generate a response,
|
|
62
|
+
# causing this test to hang. Observe, there was no problem with responses
|
|
63
|
+
# lacking a content-length, just when the content-length was zero.
|
|
64
|
+
#
|
|
65
|
+
class EmptyContent < EM::Connection
|
|
66
|
+
def initialize *args
|
|
67
|
+
super
|
|
68
|
+
end
|
|
69
|
+
def receive_data data
|
|
70
|
+
send_data "HTTP/1.0 404 ...\r\nContent-length: 0\r\n\r\n"
|
|
71
|
+
close_connection_after_writing
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def test_http_empty_content
|
|
76
|
+
ok = false
|
|
77
|
+
EM.run {
|
|
78
|
+
EM.start_server "127.0.0.1", @port, EmptyContent
|
|
79
|
+
c = silent { EM::P::HttpClient.send :request, :host => "127.0.0.1", :port => @port }
|
|
80
|
+
c.callback {
|
|
81
|
+
ok = true
|
|
82
|
+
c.close_connection
|
|
83
|
+
EM.stop
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
assert ok
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
#---------------------------------------
|
|
91
|
+
|
|
92
|
+
class PostContent < EM::P::LineAndTextProtocol
|
|
93
|
+
def initialize *args
|
|
94
|
+
super
|
|
95
|
+
@lines = []
|
|
96
|
+
end
|
|
97
|
+
def receive_line line
|
|
98
|
+
if line.length > 0
|
|
99
|
+
@lines << line
|
|
100
|
+
else
|
|
101
|
+
process_headers
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
def receive_binary_data data
|
|
105
|
+
@post_content = data
|
|
106
|
+
send_response
|
|
107
|
+
end
|
|
108
|
+
def process_headers
|
|
109
|
+
if @lines.first =~ /\APOST ([^\s]+) HTTP\/1.1\Z/
|
|
110
|
+
@uri = $1.dup
|
|
111
|
+
else
|
|
112
|
+
raise "bad request"
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
@lines.each {|line|
|
|
116
|
+
if line =~ /\AContent-length:\s*(\d+)\Z/i
|
|
117
|
+
@content_length = $1.dup.to_i
|
|
118
|
+
elsif line =~ /\AContent-type:\s*(\d+)\Z/i
|
|
119
|
+
@content_type = $1.dup
|
|
120
|
+
end
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
raise "invalid content length" unless @content_length
|
|
124
|
+
set_binary_mode @content_length
|
|
125
|
+
end
|
|
126
|
+
def send_response
|
|
127
|
+
send_data "HTTP/1.1 200 ...\r\nConnection: close\r\nContent-length: 10\r\nContent-type: text/html\r\n\r\n0123456789"
|
|
128
|
+
close_connection_after_writing
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# TODO, this is WRONG. The handler is asserting an HTTP 1.1 request, but the client
|
|
133
|
+
# is sending a 1.0 request. Gotta fix the client
|
|
134
|
+
def test_post
|
|
135
|
+
response = nil
|
|
136
|
+
EM.run {
|
|
137
|
+
EM.start_server '127.0.0.1', @port, PostContent
|
|
138
|
+
setup_timeout 2
|
|
139
|
+
c = silent { EM::P::HttpClient.request(
|
|
140
|
+
:host => '127.0.0.1',
|
|
141
|
+
:port => @port,
|
|
142
|
+
:method => :post,
|
|
143
|
+
:request => "/aaa",
|
|
144
|
+
:content => "XYZ",
|
|
145
|
+
:content_type => "text/plain"
|
|
146
|
+
)}
|
|
147
|
+
c.callback {|r|
|
|
148
|
+
response = r
|
|
149
|
+
EM.stop
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
assert_equal( 200, response[:status] )
|
|
154
|
+
assert_equal( "0123456789", response[:content] )
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
# TODO, need a more intelligent cookie tester.
|
|
159
|
+
# In fact, this whole test-harness needs a beefier server implementation.
|
|
160
|
+
def test_cookie
|
|
161
|
+
ok = false
|
|
162
|
+
EM.run {
|
|
163
|
+
c = silent { EM::Protocols::HttpClient.send :request, :host => "www.google.com", :port => 80, :cookie=>"aaa=bbb" }
|
|
164
|
+
c.callback {
|
|
165
|
+
ok = true
|
|
166
|
+
c.close_connection
|
|
167
|
+
EM.stop
|
|
168
|
+
}
|
|
169
|
+
c.errback {EM.stop}
|
|
170
|
+
}
|
|
171
|
+
assert ok
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
# We can tell the client to send an HTTP/1.0 request (default is 1.1).
|
|
175
|
+
# This is useful for suppressing chunked responses until those are working.
|
|
176
|
+
def test_version_1_0
|
|
177
|
+
ok = false
|
|
178
|
+
EM.run {
|
|
179
|
+
c = silent { EM::P::HttpClient.request(
|
|
180
|
+
:host => "www.google.com",
|
|
181
|
+
:port => 80,
|
|
182
|
+
:version => "1.0"
|
|
183
|
+
)}
|
|
184
|
+
c.callback {
|
|
185
|
+
ok = true
|
|
186
|
+
c.close_connection
|
|
187
|
+
EM.stop
|
|
188
|
+
}
|
|
189
|
+
c.errback {EM.stop}
|
|
190
|
+
}
|
|
191
|
+
assert ok
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
#-----------------------------------------
|
|
195
|
+
|
|
196
|
+
# Test a server that returns chunked encoding
|
|
197
|
+
#
|
|
198
|
+
class ChunkedEncodingContent < EventMachine::Connection
|
|
199
|
+
def initialize *args
|
|
200
|
+
super
|
|
201
|
+
end
|
|
202
|
+
def receive_data data
|
|
203
|
+
send_data ["HTTP/1.1 200 OK",
|
|
204
|
+
"Server: nginx/0.7.67",
|
|
205
|
+
"Date: Sat, 23 Oct 2010 16:41:32 GMT",
|
|
206
|
+
"Content-Type: application/json",
|
|
207
|
+
"Transfer-Encoding: chunked",
|
|
208
|
+
"Connection: keep-alive",
|
|
209
|
+
"",
|
|
210
|
+
"1800",
|
|
211
|
+
"chunk1" * 1024,
|
|
212
|
+
"5a",
|
|
213
|
+
"chunk2" * 15,
|
|
214
|
+
"0",
|
|
215
|
+
""].join("\r\n")
|
|
216
|
+
close_connection_after_writing
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
def test_http_chunked_encoding_content
|
|
221
|
+
ok = false
|
|
222
|
+
EM.run {
|
|
223
|
+
EM.start_server "127.0.0.1", @port, ChunkedEncodingContent
|
|
224
|
+
c = silent { EM::P::HttpClient.send :request, :host => "127.0.0.1", :port => @port }
|
|
225
|
+
c.callback { |result|
|
|
226
|
+
if result[:content] == "chunk1" * 1024 + "chunk2" * 15
|
|
227
|
+
ok = true
|
|
228
|
+
end
|
|
229
|
+
c.close_connection
|
|
230
|
+
EM.stop
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
assert ok
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
require_relative 'em_test_helper'
|
|
2
|
+
|
|
3
|
+
class TestHttpClient2 < Test::Unit::TestCase
|
|
4
|
+
class TestServer < EM::Connection
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
TIMEOUT = (windows? ? 2.0 : 1)
|
|
8
|
+
# below may be due to an issue with OpenSSL 1.0.2 and earlier with Windows
|
|
9
|
+
CI_WINDOWS_OLD = windows? and RUBY_VERSION < '2.5'
|
|
10
|
+
|
|
11
|
+
def setup
|
|
12
|
+
@port = next_port
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# #connect returns an object which has made a connection to an HTTP server
|
|
16
|
+
# and exposes methods for making HTTP requests on that connection.
|
|
17
|
+
# #connect can take either a pair of parameters (a host and a port),
|
|
18
|
+
# or a single parameter which is a Hash.
|
|
19
|
+
#
|
|
20
|
+
def test_connect
|
|
21
|
+
EM.run {
|
|
22
|
+
setup_timeout
|
|
23
|
+
EM.start_server '127.0.0.1', @port, TestServer
|
|
24
|
+
silent do
|
|
25
|
+
EM::P::HttpClient2.connect '127.0.0.1', @port
|
|
26
|
+
EM::P::HttpClient2.connect( :host=>'127.0.0.1', :port=>@port )
|
|
27
|
+
end
|
|
28
|
+
EM.stop
|
|
29
|
+
}
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def test_bad_port
|
|
33
|
+
EM.run {
|
|
34
|
+
setup_timeout
|
|
35
|
+
EM.start_server '127.0.0.1', @port, TestServer
|
|
36
|
+
assert_raises( ArgumentError ) {
|
|
37
|
+
silent { EM::P::HttpClient2.connect '127.0.0.1', "xxx" }
|
|
38
|
+
}
|
|
39
|
+
EM.stop
|
|
40
|
+
}
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def test_bad_server
|
|
44
|
+
err = nil
|
|
45
|
+
EM.run {
|
|
46
|
+
setup_timeout TIMEOUT
|
|
47
|
+
http = silent { EM::P::HttpClient2.connect '127.0.0.1', 9999 }
|
|
48
|
+
d = http.get "/"
|
|
49
|
+
d.errback { err = true; d.internal_error; EM.stop }
|
|
50
|
+
}
|
|
51
|
+
assert(err)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def test_get
|
|
55
|
+
content = nil
|
|
56
|
+
EM.run {
|
|
57
|
+
setup_timeout(CI_WINDOWS_OLD ? 9 : TIMEOUT)
|
|
58
|
+
http = silent { EM::P::HttpClient2.connect :host => "www.google.com", :port => 80 }
|
|
59
|
+
d = http.get "/"
|
|
60
|
+
d.callback {
|
|
61
|
+
content = d.content
|
|
62
|
+
EM.stop
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
assert(content)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Not a pipelined request because we wait for one response before we request the next.
|
|
69
|
+
# XXX this test is broken because it sends the second request to the first connection
|
|
70
|
+
# XXX right before the connection closes
|
|
71
|
+
def _test_get_multiple
|
|
72
|
+
content = nil
|
|
73
|
+
EM.run {
|
|
74
|
+
setup_timeout
|
|
75
|
+
http = silent { EM::P::HttpClient2.connect "www.google.com" }
|
|
76
|
+
d = http.get "/"
|
|
77
|
+
d.callback {
|
|
78
|
+
e = http.get "/"
|
|
79
|
+
e.callback {
|
|
80
|
+
content = e.content
|
|
81
|
+
EM.stop
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
assert(content)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def test_get_pipeline
|
|
89
|
+
headers, headers2 = nil, nil
|
|
90
|
+
EM.run {
|
|
91
|
+
setup_timeout TIMEOUT
|
|
92
|
+
http = silent { EM::P::HttpClient2.connect "www.google.com", 80 }
|
|
93
|
+
d = http.get("/")
|
|
94
|
+
d.callback {
|
|
95
|
+
headers = d.headers
|
|
96
|
+
}
|
|
97
|
+
e = http.get("/")
|
|
98
|
+
e.callback {
|
|
99
|
+
headers2 = e.headers
|
|
100
|
+
}
|
|
101
|
+
EM.tick_loop { EM.stop if headers && headers2 }
|
|
102
|
+
EM.add_timer(1) { EM.stop }
|
|
103
|
+
}
|
|
104
|
+
assert(headers)
|
|
105
|
+
assert(headers2)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def test_authheader
|
|
109
|
+
EM.run {
|
|
110
|
+
setup_timeout TIMEOUT
|
|
111
|
+
EM.start_server '127.0.0.1', @port, TestServer
|
|
112
|
+
http = silent { EM::P::HttpClient2.connect '127.0.0.1', 18842 }
|
|
113
|
+
d = http.get :url=>"/", :authorization=>"Basic xxx"
|
|
114
|
+
d.callback {EM.stop}
|
|
115
|
+
d.errback {EM.stop}
|
|
116
|
+
}
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def test_https_get
|
|
120
|
+
omit("No SSL") unless EM.ssl?
|
|
121
|
+
d = nil
|
|
122
|
+
EM.run {
|
|
123
|
+
setup_timeout(CI_WINDOWS_OLD ? 9 : TIMEOUT)
|
|
124
|
+
http = silent { EM::P::HttpClient2.connect :host => 'www.google.com', :port => 443, :tls => true }
|
|
125
|
+
d = http.get "/"
|
|
126
|
+
d.callback {EM.stop}
|
|
127
|
+
d.errback {EM.stop}
|
|
128
|
+
}
|
|
129
|
+
assert_equal(200, d.status)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
require_relative 'em_test_helper'
|
|
2
|
+
|
|
3
|
+
class TestIdleConnection < Test::Unit::TestCase
|
|
4
|
+
def setup
|
|
5
|
+
@port = next_port
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def test_idle_time
|
|
9
|
+
omit_if(!EM.respond_to?(:get_idle_time))
|
|
10
|
+
|
|
11
|
+
a, b = nil, nil
|
|
12
|
+
EM.run do
|
|
13
|
+
EM.start_server '127.0.0.1', @port, Module.new
|
|
14
|
+
conn = EM.connect '127.0.0.1', @port
|
|
15
|
+
EM.add_timer(0.3) do
|
|
16
|
+
a = conn.get_idle_time
|
|
17
|
+
conn.send_data 'a'
|
|
18
|
+
EM.next_tick do
|
|
19
|
+
EM.next_tick do
|
|
20
|
+
b = conn.get_idle_time
|
|
21
|
+
conn.close_connection
|
|
22
|
+
EM.stop
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
assert_in_delta 0.3, a, (darwin? ? 0.2 : 0.1)
|
|
29
|
+
assert_in_delta 0, b, 0.1
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
require_relative 'em_test_helper'
|
|
2
|
+
|
|
3
|
+
class TestInactivityTimeout < Test::Unit::TestCase
|
|
4
|
+
|
|
5
|
+
if EM.respond_to? :get_comm_inactivity_timeout
|
|
6
|
+
def test_default
|
|
7
|
+
EM.run {
|
|
8
|
+
c = EM.connect("127.0.0.1", 54321)
|
|
9
|
+
assert_equal 0.0, c.comm_inactivity_timeout
|
|
10
|
+
EM.stop
|
|
11
|
+
}
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def test_set_and_get
|
|
15
|
+
EM.run {
|
|
16
|
+
c = EM.connect("127.0.0.1", 54321)
|
|
17
|
+
c.comm_inactivity_timeout = 2.5
|
|
18
|
+
assert_equal 2.5, c.comm_inactivity_timeout
|
|
19
|
+
EM.stop
|
|
20
|
+
}
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def test_for_real
|
|
24
|
+
start, finish, reason = nil
|
|
25
|
+
|
|
26
|
+
timeout_start = Module.new do
|
|
27
|
+
define_method :post_init do
|
|
28
|
+
start = Time.now
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
timeout_handler = Module.new do
|
|
33
|
+
define_method :unbind do
|
|
34
|
+
finish = Time.now
|
|
35
|
+
EM.stop
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
EM.run {
|
|
40
|
+
setup_timeout 0.4
|
|
41
|
+
EM.heartbeat_interval = 0.01
|
|
42
|
+
EM.start_server("127.0.0.1", 12345, timeout_start)
|
|
43
|
+
EM.add_timer(0.01) {
|
|
44
|
+
c = EM.connect("127.0.0.1", 12345, timeout_handler)
|
|
45
|
+
c.comm_inactivity_timeout = 0.02
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
# Travis can vary from 0.02 to 0.17, Appveyor maybe as low as 0.01
|
|
49
|
+
assert_in_delta 0.09, (finish - start), (darwin? ? 0.10 : 0.08)
|
|
50
|
+
|
|
51
|
+
# simplified reproducer for comm_inactivity_timeout taking twice as long
|
|
52
|
+
# as requested -- https://github.com/eventmachine/eventmachine/issues/554
|
|
53
|
+
timeout_start_tls = Module.new do
|
|
54
|
+
define_method :post_init do
|
|
55
|
+
start = Time.now
|
|
56
|
+
start_tls
|
|
57
|
+
end
|
|
58
|
+
define_method :receive_data do |data|
|
|
59
|
+
send_data ">>>you sent: #{data}"
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
timeout_handler_tls = Module.new do
|
|
64
|
+
define_method :connection_completed do
|
|
65
|
+
start_tls
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
define_method :ssl_handshake_completed do
|
|
69
|
+
@timer = EM::PeriodicTimer.new(0.05) do
|
|
70
|
+
#puts "get_idle_time: #{get_idle_time} inactivity: #{comm_inactivity_timeout}"
|
|
71
|
+
end
|
|
72
|
+
send_data "hello world"
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
define_method :unbind do |r|
|
|
76
|
+
finish = Time.now
|
|
77
|
+
reason = r
|
|
78
|
+
EM.stop
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
EM.run {
|
|
83
|
+
setup_timeout 1.4
|
|
84
|
+
EM.start_server("127.0.0.1", 12345, timeout_start_tls)
|
|
85
|
+
c = EM.connect("127.0.0.1", 12345, timeout_handler_tls)
|
|
86
|
+
c.comm_inactivity_timeout = 0.15
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
# .30 is double the timeout and not acceptable
|
|
90
|
+
assert_in_delta 0.15, (finish - start), (darwin? ? 0.20 : 0.14)
|
|
91
|
+
# make sure it was a timeout and not a TLS error
|
|
92
|
+
assert_equal Errno::ETIMEDOUT, reason
|
|
93
|
+
end
|
|
94
|
+
else
|
|
95
|
+
warn "EM.comm_inactivity_timeout not implemented, skipping tests in #{__FILE__}"
|
|
96
|
+
|
|
97
|
+
# Because some rubies will complain if a TestCase class has no tests
|
|
98
|
+
def test_em_comm_inactivity_timeout_not_implemented
|
|
99
|
+
assert true
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'em_test_helper'
|
|
4
|
+
require 'em/io_streamer'
|
|
5
|
+
require 'stringio'
|
|
6
|
+
|
|
7
|
+
# below to stop 'already initialized constant' warning
|
|
8
|
+
EM::IOStreamer.__send__ :remove_const, :CHUNK_SIZE
|
|
9
|
+
EM::IOStreamer.const_set :CHUNK_SIZE, 2
|
|
10
|
+
|
|
11
|
+
class TestIOStreamer < Test::Unit::TestCase
|
|
12
|
+
|
|
13
|
+
class StreamServer < EM::Connection
|
|
14
|
+
def initialize(sent)
|
|
15
|
+
@sent = sent
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def post_init
|
|
19
|
+
io = StringIO.new @sent
|
|
20
|
+
EM::IOStreamer.new(self, io).callback { close_connection_after_writing }
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
class StreamClient < EM::Connection
|
|
25
|
+
def initialize(received)
|
|
26
|
+
@received = received
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def receive_data data
|
|
30
|
+
@received << data
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def unbind
|
|
34
|
+
EM.stop
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def test_io_stream
|
|
39
|
+
sent = 'this is a test'
|
|
40
|
+
received = ''.dup
|
|
41
|
+
EM.run do
|
|
42
|
+
port = next_port
|
|
43
|
+
EM.start_server '127.0.0.1', port, StreamServer, sent
|
|
44
|
+
EM.connect '127.0.0.1', port, StreamClient, received
|
|
45
|
+
end
|
|
46
|
+
assert_equal sent, received
|
|
47
|
+
end
|
|
48
|
+
end
|