sonixlabs-eventmachine-java 1.0.0.rc.4-java
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/.gitignore +22 -0
- data/.yardopts +7 -0
- data/GNU +281 -0
- data/Gemfile +3 -0
- data/LICENSE +60 -0
- data/README.md +109 -0
- data/Rakefile +20 -0
- data/docs/DocumentationGuidesIndex.md +27 -0
- data/docs/GettingStarted.md +521 -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/eventmachine.gemspec +34 -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 +46 -0
- data/ext/cmain.cpp +876 -0
- data/ext/ed.cpp +1973 -0
- data/ext/ed.h +422 -0
- data/ext/em.cpp +2353 -0
- data/ext/em.h +239 -0
- data/ext/eventmachine.h +127 -0
- data/ext/extconf.rb +176 -0
- data/ext/fastfilereader/extconf.rb +103 -0
- data/ext/fastfilereader/mapper.cpp +214 -0
- data/ext/fastfilereader/mapper.h +59 -0
- data/ext/fastfilereader/rubymain.cpp +127 -0
- data/ext/kb.cpp +79 -0
- data/ext/page.cpp +107 -0
- data/ext/page.h +51 -0
- data/ext/pipe.cpp +347 -0
- data/ext/project.h +156 -0
- data/ext/rubymain.cpp +1297 -0
- data/ext/ssl.cpp +468 -0
- data/ext/ssl.h +94 -0
- data/java/.classpath +8 -0
- data/java/.project +17 -0
- data/java/src/com/rubyeventmachine/EmReactor.java +588 -0
- data/java/src/com/rubyeventmachine/EmReactorException.java +40 -0
- data/java/src/com/rubyeventmachine/EventableChannel.java +70 -0
- data/java/src/com/rubyeventmachine/EventableDatagramChannel.java +195 -0
- data/java/src/com/rubyeventmachine/EventableSocketChannel.java +364 -0
- data/lib/em/buftok.rb +110 -0
- data/lib/em/callback.rb +58 -0
- data/lib/em/channel.rb +64 -0
- data/lib/em/completion.rb +304 -0
- data/lib/em/connection.rb +712 -0
- data/lib/em/deferrable.rb +210 -0
- data/lib/em/deferrable/pool.rb +2 -0
- data/lib/em/file_watch.rb +73 -0
- data/lib/em/future.rb +61 -0
- data/lib/em/iterator.rb +270 -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.rb +36 -0
- data/lib/em/protocols/header_and_content.rb +138 -0
- data/lib/em/protocols/httpclient.rb +279 -0
- data/lib/em/protocols/httpclient2.rb +600 -0
- data/lib/em/protocols/line_and_text.rb +125 -0
- data/lib/em/protocols/line_protocol.rb +29 -0
- data/lib/em/protocols/linetext2.rb +161 -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 +365 -0
- data/lib/em/protocols/smtpserver.rb +640 -0
- data/lib/em/protocols/socks4.rb +66 -0
- data/lib/em/protocols/stomp.rb +202 -0
- data/lib/em/protocols/tcptest.rb +54 -0
- data/lib/em/pure_ruby.rb +1017 -0
- data/lib/em/queue.rb +71 -0
- data/lib/em/resolver.rb +192 -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 +1532 -0
- data/lib/jeventmachine.rb +284 -0
- data/lib/sonixlabs-eventmachine-java.rb +1 -0
- data/rakelib/cpp.rake_example +77 -0
- data/rakelib/package.rake +98 -0
- data/rakelib/test.rake +8 -0
- data/tests/client.crt +31 -0
- data/tests/client.key +51 -0
- data/tests/em_test_helper.rb +64 -0
- data/tests/test_attach.rb +126 -0
- data/tests/test_basic.rb +294 -0
- data/tests/test_channel.rb +62 -0
- data/tests/test_completion.rb +177 -0
- data/tests/test_connection_count.rb +33 -0
- data/tests/test_defer.rb +18 -0
- data/tests/test_deferrable.rb +35 -0
- data/tests/test_epoll.rb +130 -0
- data/tests/test_error_handler.rb +38 -0
- data/tests/test_exc.rb +28 -0
- data/tests/test_file_watch.rb +65 -0
- data/tests/test_futures.rb +170 -0
- data/tests/test_get_sock_opt.rb +37 -0
- data/tests/test_handler_check.rb +35 -0
- data/tests/test_hc.rb +155 -0
- data/tests/test_httpclient.rb +190 -0
- data/tests/test_httpclient2.rb +128 -0
- data/tests/test_idle_connection.rb +23 -0
- data/tests/test_inactivity_timeout.rb +54 -0
- data/tests/test_kb.rb +34 -0
- data/tests/test_ltp.rb +138 -0
- data/tests/test_ltp2.rb +288 -0
- data/tests/test_next_tick.rb +104 -0
- data/tests/test_object_protocol.rb +36 -0
- data/tests/test_pause.rb +78 -0
- data/tests/test_pending_connect_timeout.rb +52 -0
- data/tests/test_pool.rb +194 -0
- data/tests/test_process_watch.rb +48 -0
- data/tests/test_processes.rb +128 -0
- data/tests/test_proxy_connection.rb +180 -0
- data/tests/test_pure.rb +88 -0
- data/tests/test_queue.rb +50 -0
- data/tests/test_resolver.rb +55 -0
- data/tests/test_running.rb +14 -0
- data/tests/test_sasl.rb +47 -0
- data/tests/test_send_file.rb +217 -0
- data/tests/test_servers.rb +33 -0
- data/tests/test_set_sock_opt.rb +37 -0
- data/tests/test_shutdown_hooks.rb +23 -0
- data/tests/test_smtpclient.rb +55 -0
- data/tests/test_smtpserver.rb +57 -0
- data/tests/test_spawn.rb +293 -0
- data/tests/test_ssl_args.rb +78 -0
- data/tests/test_ssl_methods.rb +48 -0
- data/tests/test_ssl_verify.rb +82 -0
- data/tests/test_threaded_resource.rb +53 -0
- data/tests/test_tick_loop.rb +59 -0
- data/tests/test_timers.rb +123 -0
- data/tests/test_ud.rb +8 -0
- data/tests/test_unbind_reason.rb +48 -0
- metadata +301 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
require 'em_test_helper'
|
|
2
|
+
|
|
3
|
+
class TestPendingConnectTimeout < Test::Unit::TestCase
|
|
4
|
+
|
|
5
|
+
if EM.respond_to? :get_pending_connect_timeout
|
|
6
|
+
def test_default
|
|
7
|
+
EM.run {
|
|
8
|
+
c = EM.connect("127.0.0.1", 54321)
|
|
9
|
+
assert_equal 20.0, c.pending_connect_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.pending_connect_timeout = 2.5
|
|
18
|
+
assert_equal 2.5, c.pending_connect_timeout
|
|
19
|
+
EM.stop
|
|
20
|
+
}
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def test_for_real
|
|
24
|
+
start, finish = nil
|
|
25
|
+
|
|
26
|
+
timeout_handler = Module.new do
|
|
27
|
+
define_method :unbind do
|
|
28
|
+
finish = Time.now
|
|
29
|
+
EM.stop
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
EM.run {
|
|
34
|
+
setup_timeout
|
|
35
|
+
EM.heartbeat_interval = 0.1
|
|
36
|
+
start = Time.now
|
|
37
|
+
c = EM.connect("1.2.3.4", 54321, timeout_handler)
|
|
38
|
+
c.pending_connect_timeout = 0.2
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
assert_in_delta(0.2, (finish - start), 0.1)
|
|
42
|
+
end
|
|
43
|
+
else
|
|
44
|
+
warn "EM.pending_connect_timeout not implemented, skipping tests in #{__FILE__}"
|
|
45
|
+
|
|
46
|
+
# Because some rubies will complain if a TestCase class has no tests
|
|
47
|
+
def test_em_pending_connect_timeout_not_implemented
|
|
48
|
+
assert true
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
end
|
data/tests/test_pool.rb
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
class TestPool < Test::Unit::TestCase
|
|
2
|
+
def pool
|
|
3
|
+
@pool ||= EM::Pool.new
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def go
|
|
7
|
+
EM.run { yield }
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def stop
|
|
11
|
+
EM.stop
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def deferrable
|
|
15
|
+
@deferrable ||= EM::DefaultDeferrable.new
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def test_supports_more_work_than_resources
|
|
19
|
+
ran = false
|
|
20
|
+
go do
|
|
21
|
+
pool.perform do
|
|
22
|
+
ran = true
|
|
23
|
+
deferrable
|
|
24
|
+
end
|
|
25
|
+
stop
|
|
26
|
+
end
|
|
27
|
+
assert_equal false, ran
|
|
28
|
+
go do
|
|
29
|
+
pool.add :resource
|
|
30
|
+
stop
|
|
31
|
+
end
|
|
32
|
+
assert_equal true, ran
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def test_reques_resources_on_error
|
|
36
|
+
pooled_res, pooled_res2 = nil
|
|
37
|
+
pool.add :res
|
|
38
|
+
go do
|
|
39
|
+
pool.perform do |res|
|
|
40
|
+
pooled_res = res
|
|
41
|
+
deferrable
|
|
42
|
+
end
|
|
43
|
+
stop
|
|
44
|
+
end
|
|
45
|
+
deferrable.fail
|
|
46
|
+
go do
|
|
47
|
+
pool.perform do |res|
|
|
48
|
+
pooled_res2 = res
|
|
49
|
+
deferrable
|
|
50
|
+
end
|
|
51
|
+
stop
|
|
52
|
+
end
|
|
53
|
+
assert_equal :res, pooled_res
|
|
54
|
+
assert_equal pooled_res, pooled_res2
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def test_supports_custom_error_handler
|
|
58
|
+
eres = nil
|
|
59
|
+
pool.on_error do |res|
|
|
60
|
+
eres = res
|
|
61
|
+
end
|
|
62
|
+
performs = []
|
|
63
|
+
pool.add :res
|
|
64
|
+
go do
|
|
65
|
+
pool.perform do |res|
|
|
66
|
+
performs << res
|
|
67
|
+
deferrable
|
|
68
|
+
end
|
|
69
|
+
pool.perform do |res|
|
|
70
|
+
performs << res
|
|
71
|
+
deferrable
|
|
72
|
+
end
|
|
73
|
+
deferrable.fail
|
|
74
|
+
stop
|
|
75
|
+
end
|
|
76
|
+
assert_equal :res, eres
|
|
77
|
+
# manual requeues required when error handler is installed:
|
|
78
|
+
assert_equal 1, performs.size
|
|
79
|
+
assert_equal :res, performs.first
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def test_catches_successful_deferrables
|
|
83
|
+
performs = []
|
|
84
|
+
pool.add :res
|
|
85
|
+
go do
|
|
86
|
+
pool.perform { |res| performs << res; deferrable }
|
|
87
|
+
pool.perform { |res| performs << res; deferrable }
|
|
88
|
+
stop
|
|
89
|
+
end
|
|
90
|
+
assert_equal [:res], performs
|
|
91
|
+
deferrable.succeed
|
|
92
|
+
go { stop }
|
|
93
|
+
assert_equal [:res, :res], performs
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def test_prunes_locked_and_removed_resources
|
|
97
|
+
performs = []
|
|
98
|
+
pool.add :res
|
|
99
|
+
deferrable.succeed
|
|
100
|
+
go do
|
|
101
|
+
pool.perform { |res| performs << res; pool.remove res; deferrable }
|
|
102
|
+
pool.perform { |res| performs << res; pool.remove res; deferrable }
|
|
103
|
+
stop
|
|
104
|
+
end
|
|
105
|
+
assert_equal [:res], performs
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Contents is only to be used for inspection of the pool!
|
|
109
|
+
def test_contents
|
|
110
|
+
pool.add :res
|
|
111
|
+
assert_equal [:res], pool.contents
|
|
112
|
+
# Assert that modifying the contents list does not affect the pools
|
|
113
|
+
# contents.
|
|
114
|
+
pool.contents.delete(:res)
|
|
115
|
+
assert_equal [:res], pool.contents
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def test_contents_when_perform_errors_and_on_error_is_not_set
|
|
119
|
+
pool.add :res
|
|
120
|
+
assert_equal [:res], pool.contents
|
|
121
|
+
|
|
122
|
+
pool.perform do |r|
|
|
123
|
+
d = EM::DefaultDeferrable.new
|
|
124
|
+
d.fail
|
|
125
|
+
d
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
EM.run { EM.next_tick { EM.stop } }
|
|
129
|
+
|
|
130
|
+
assert_equal [:res], pool.contents
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def test_contents_when_perform_errors_and_on_error_is_set
|
|
134
|
+
pool.add :res
|
|
135
|
+
res = nil
|
|
136
|
+
pool.on_error do |r|
|
|
137
|
+
res = r
|
|
138
|
+
end
|
|
139
|
+
assert_equal [:res], pool.contents
|
|
140
|
+
|
|
141
|
+
pool.perform do |r|
|
|
142
|
+
d = EM::DefaultDeferrable.new
|
|
143
|
+
d.fail 'foo'
|
|
144
|
+
d
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
EM.run { EM.next_tick { EM.stop } }
|
|
148
|
+
|
|
149
|
+
assert_equal :res, res
|
|
150
|
+
assert_equal [], pool.contents
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def test_num_waiting
|
|
154
|
+
pool.add :res
|
|
155
|
+
assert_equal 0, pool.num_waiting
|
|
156
|
+
pool.perform { |r| EM::DefaultDeferrable.new }
|
|
157
|
+
assert_equal 0, pool.num_waiting
|
|
158
|
+
10.times { pool.perform { |r| EM::DefaultDeferrable.new } }
|
|
159
|
+
EM.run { EM.next_tick { EM.stop } }
|
|
160
|
+
assert_equal 10, pool.num_waiting
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def test_exceptions_in_the_work_block_bubble_up_raise_and_fail_the_resource
|
|
164
|
+
pool.add :res
|
|
165
|
+
|
|
166
|
+
res = nil
|
|
167
|
+
pool.on_error { |r| res = r }
|
|
168
|
+
pool.perform { raise 'boom' }
|
|
169
|
+
|
|
170
|
+
assert_raises(RuntimeError) do
|
|
171
|
+
EM.run { EM.next_tick { EM.stop } }
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
assert_equal [], pool.contents
|
|
175
|
+
assert_equal :res, res
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def test_removed_list_does_not_leak_on_errors
|
|
179
|
+
pool.add :res
|
|
180
|
+
|
|
181
|
+
pool.on_error do |r|
|
|
182
|
+
# This is actually the wrong thing to do, and not required, but some users
|
|
183
|
+
# might do it. When they do, they would find that @removed would cause a
|
|
184
|
+
# slow leak.
|
|
185
|
+
pool.remove r
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
pool.perform { d = EM::DefaultDeferrable.new; d.fail; d }
|
|
189
|
+
|
|
190
|
+
EM.run { EM.next_tick { EM.stop } }
|
|
191
|
+
assert_equal [], pool.instance_variable_get(:@removed)
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
require 'em_test_helper'
|
|
2
|
+
|
|
3
|
+
if EM.kqueue?
|
|
4
|
+
class TestProcessWatch < Test::Unit::TestCase
|
|
5
|
+
module ParentProcessWatcher
|
|
6
|
+
def process_forked
|
|
7
|
+
$forked = true
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
module ChildProcessWatcher
|
|
12
|
+
def process_exited
|
|
13
|
+
$exited = true
|
|
14
|
+
end
|
|
15
|
+
def unbind
|
|
16
|
+
$unbind = true
|
|
17
|
+
EM.stop
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def setup
|
|
22
|
+
EM.kqueue = true
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def teardown
|
|
26
|
+
EM.kqueue = false
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def test_events
|
|
30
|
+
EM.run{
|
|
31
|
+
# watch ourselves for a fork notification
|
|
32
|
+
EM.watch_process(Process.pid, ParentProcessWatcher)
|
|
33
|
+
$fork_pid = fork{ sleep }
|
|
34
|
+
child = EM.watch_process($fork_pid, ChildProcessWatcher)
|
|
35
|
+
$pid = child.pid
|
|
36
|
+
|
|
37
|
+
EM.add_timer(0.2){
|
|
38
|
+
Process.kill('TERM', $fork_pid)
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
assert_equal($pid, $fork_pid)
|
|
43
|
+
assert($forked)
|
|
44
|
+
assert($exited)
|
|
45
|
+
assert($unbind)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
require 'em_test_helper'
|
|
2
|
+
|
|
3
|
+
class TestProcesses < Test::Unit::TestCase
|
|
4
|
+
|
|
5
|
+
if !windows? && !jruby?
|
|
6
|
+
|
|
7
|
+
# EM::DeferrableChildProcess is a sugaring of a common use-case
|
|
8
|
+
# involving EM::popen.
|
|
9
|
+
# Call the #open method on EM::DeferrableChildProcess, passing
|
|
10
|
+
# a command-string. #open immediately returns an EM::Deferrable
|
|
11
|
+
# object. It also schedules the forking of a child process, which
|
|
12
|
+
# will execute the command passed to #open.
|
|
13
|
+
# When the forked child terminates, the Deferrable will be signalled
|
|
14
|
+
# and execute its callbacks, passing the data that the child process
|
|
15
|
+
# wrote to stdout.
|
|
16
|
+
#
|
|
17
|
+
def test_deferrable_child_process
|
|
18
|
+
ls = ""
|
|
19
|
+
EM.run {
|
|
20
|
+
d = EM::DeferrableChildProcess.open( "ls -ltr" )
|
|
21
|
+
d.callback {|data_from_child|
|
|
22
|
+
ls = data_from_child
|
|
23
|
+
EM.stop
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
assert( ls.length > 0)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def setup
|
|
30
|
+
$out = nil
|
|
31
|
+
$status = nil
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def test_em_system
|
|
35
|
+
EM.run{
|
|
36
|
+
EM.system('ls'){ |out,status| $out, $status = out, status; EM.stop }
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
assert( $out.length > 0 )
|
|
40
|
+
assert_equal($status.exitstatus, 0)
|
|
41
|
+
assert_equal($status.class, Process::Status)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def test_em_system_pid
|
|
45
|
+
$pids = []
|
|
46
|
+
|
|
47
|
+
EM.run{
|
|
48
|
+
$pids << EM.system('echo hi', proc{ |out,status|$pids << status.pid; EM.stop })
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
assert_equal $pids[0], $pids[1]
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def test_em_system_with_proc
|
|
55
|
+
EM.run{
|
|
56
|
+
EM.system('ls', proc{ |out,status| $out, $status = out, status; EM.stop })
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
assert( $out.length > 0 )
|
|
60
|
+
assert_equal($status.exitstatus, 0)
|
|
61
|
+
assert_equal($status.class, Process::Status)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def test_em_system_with_two_procs
|
|
65
|
+
EM.run{
|
|
66
|
+
EM.system('sh', proc{ |process|
|
|
67
|
+
process.send_data("echo hello\n")
|
|
68
|
+
process.send_data("exit\n")
|
|
69
|
+
}, proc{ |out,status|
|
|
70
|
+
$out = out
|
|
71
|
+
$status = status
|
|
72
|
+
EM.stop
|
|
73
|
+
})
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
assert_equal("hello\n", $out)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def test_em_system_cmd_arguments
|
|
80
|
+
EM.run{
|
|
81
|
+
EM.system('echo', '1', '2', 'version', proc{ |process|
|
|
82
|
+
}, proc{ |out,status|
|
|
83
|
+
$out = out
|
|
84
|
+
$status = status
|
|
85
|
+
EM.stop
|
|
86
|
+
})
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
assert_match(/1 2 version/i, $out)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def test_em_system_spaced_arguments
|
|
93
|
+
EM.run{
|
|
94
|
+
EM.system('ruby', '-e', 'puts "hello"', proc{ |out,status|
|
|
95
|
+
$out = out
|
|
96
|
+
EM.stop
|
|
97
|
+
})
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
assert_equal("hello\n", $out)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def test_em_popen_pause_resume
|
|
104
|
+
c_rx = 0
|
|
105
|
+
|
|
106
|
+
test_client = Module.new do
|
|
107
|
+
define_method :receive_data do |data|
|
|
108
|
+
c_rx += 1
|
|
109
|
+
pause
|
|
110
|
+
EM.add_timer(0.5) { EM.stop }
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
EM.run{
|
|
115
|
+
EM.popen('cat /dev/random', test_client)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
assert_equal 1, c_rx
|
|
119
|
+
end
|
|
120
|
+
else
|
|
121
|
+
warn "EM.popen not implemented, skipping tests in #{__FILE__}"
|
|
122
|
+
|
|
123
|
+
# Because some rubies will complain if a TestCase class has no tests
|
|
124
|
+
def test_em_popen_unsupported
|
|
125
|
+
assert true
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
require 'em_test_helper'
|
|
2
|
+
|
|
3
|
+
class TestProxyConnection < Test::Unit::TestCase
|
|
4
|
+
|
|
5
|
+
if EM.respond_to?(:start_proxy)
|
|
6
|
+
module ProxyConnection
|
|
7
|
+
def initialize(client, request)
|
|
8
|
+
@client, @request = client, request
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def post_init
|
|
12
|
+
EM::enable_proxy(self, @client)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def connection_completed
|
|
16
|
+
EM.next_tick {
|
|
17
|
+
send_data @request
|
|
18
|
+
}
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def proxy_target_unbound
|
|
22
|
+
$unbound_early = true
|
|
23
|
+
EM.stop
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def unbind
|
|
27
|
+
$proxied_bytes = self.get_proxied_bytes
|
|
28
|
+
@client.close_connection_after_writing
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
module PartialProxyConnection
|
|
33
|
+
def initialize(client, request, length)
|
|
34
|
+
@client, @request, @length = client, request, length
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def post_init
|
|
38
|
+
EM::enable_proxy(self, @client, 0, @length)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def receive_data(data)
|
|
42
|
+
$unproxied_data = data
|
|
43
|
+
@client.send_data(data)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def connection_completed
|
|
47
|
+
EM.next_tick {
|
|
48
|
+
send_data @request
|
|
49
|
+
}
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def proxy_target_unbound
|
|
53
|
+
$unbound_early = true
|
|
54
|
+
EM.stop
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def proxy_completed
|
|
58
|
+
$proxy_completed = true
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def unbind
|
|
62
|
+
@client.close_connection_after_writing
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
module Client
|
|
67
|
+
def connection_completed
|
|
68
|
+
send_data "EM rocks!"
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def receive_data(data)
|
|
72
|
+
$client_data = data
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def unbind
|
|
76
|
+
EM.stop
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
module Client2
|
|
81
|
+
include Client
|
|
82
|
+
def unbind; end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
module Server
|
|
86
|
+
def receive_data(data)
|
|
87
|
+
send_data "I know!" if data == "EM rocks!"
|
|
88
|
+
close_connection_after_writing
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
module ProxyServer
|
|
93
|
+
def initialize port
|
|
94
|
+
@port = port
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def receive_data(data)
|
|
98
|
+
@proxy = EM.connect("127.0.0.1", @port, ProxyConnection, self, data)
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
module PartialProxyServer
|
|
103
|
+
def initialize port
|
|
104
|
+
@port = port
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def receive_data(data)
|
|
108
|
+
EM.connect("127.0.0.1", @port, PartialProxyConnection, self, data, 1)
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
module EarlyClosingProxy
|
|
113
|
+
def initialize port
|
|
114
|
+
@port = port
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def receive_data(data)
|
|
118
|
+
EM.connect("127.0.0.1", @port, ProxyConnection, self, data)
|
|
119
|
+
close_connection
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def setup
|
|
124
|
+
@port = next_port
|
|
125
|
+
@proxy_port = next_port
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def test_proxy_connection
|
|
129
|
+
EM.run {
|
|
130
|
+
EM.start_server("127.0.0.1", @port, Server)
|
|
131
|
+
EM.start_server("127.0.0.1", @proxy_port, ProxyServer, @port)
|
|
132
|
+
EM.connect("127.0.0.1", @proxy_port, Client)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
assert_equal("I know!", $client_data)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def test_proxied_bytes
|
|
139
|
+
EM.run {
|
|
140
|
+
EM.start_server("127.0.0.1", @port, Server)
|
|
141
|
+
EM.start_server("127.0.0.1", @proxy_port, ProxyServer, @port)
|
|
142
|
+
EM.connect("127.0.0.1", @proxy_port, Client)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
assert_equal("I know!", $client_data)
|
|
146
|
+
assert_equal("I know!".bytesize, $proxied_bytes)
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def test_partial_proxy_connection
|
|
150
|
+
EM.run {
|
|
151
|
+
EM.start_server("127.0.0.1", @port, Server)
|
|
152
|
+
EM.start_server("127.0.0.1", @proxy_port, PartialProxyServer, @port)
|
|
153
|
+
EM.connect("127.0.0.1", @proxy_port, Client)
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
assert_equal("I know!", $client_data)
|
|
157
|
+
assert_equal(" know!", $unproxied_data)
|
|
158
|
+
assert($proxy_completed)
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def test_early_close
|
|
162
|
+
$client_data = nil
|
|
163
|
+
EM.run {
|
|
164
|
+
EM.start_server("127.0.0.1", @port, Server)
|
|
165
|
+
EM.start_server("127.0.0.1", @proxy_port, EarlyClosingProxy, @port)
|
|
166
|
+
EM.connect("127.0.0.1", @proxy_port, Client2)
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
assert($unbound_early)
|
|
170
|
+
end
|
|
171
|
+
else
|
|
172
|
+
warn "EM.start_proxy not implemented, skipping tests in #{__FILE__}"
|
|
173
|
+
|
|
174
|
+
# Because some rubies will complain if a TestCase class has no tests
|
|
175
|
+
def test_em_start_proxy_not_implemented
|
|
176
|
+
assert !EM.respond_to?(:start_proxy)
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
end
|