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_defer.rb
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require_relative 'em_test_helper'
|
|
2
|
+
|
|
3
|
+
class TestDefer < Test::Unit::TestCase
|
|
4
|
+
|
|
5
|
+
def test_defers
|
|
6
|
+
n = 0
|
|
7
|
+
n_times = 20
|
|
8
|
+
EM.run {
|
|
9
|
+
n_times.times {
|
|
10
|
+
work_proc = proc { n += 1 }
|
|
11
|
+
callback = proc { EM.stop if n == n_times }
|
|
12
|
+
EM.defer work_proc, callback
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
assert_equal( n, n_times )
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def test_errbacks
|
|
19
|
+
iterations = 20
|
|
20
|
+
callback_parameter = rand(100)
|
|
21
|
+
callback_parameters = []
|
|
22
|
+
callback_op = proc { callback_parameter }
|
|
23
|
+
callback = proc { |result| callback_parameters << result }
|
|
24
|
+
errback_parameter = Exception.new
|
|
25
|
+
errback_parameters = []
|
|
26
|
+
errback_op = proc { raise errback_parameter }
|
|
27
|
+
errback = proc { |error| errback_parameters << error }
|
|
28
|
+
EventMachine.run do
|
|
29
|
+
(1..iterations).each { |index| EventMachine.defer(index.even? ? callback_op : errback_op, callback, errback) }
|
|
30
|
+
EventMachine.add_periodic_timer(0.1) { EventMachine.stop if EventMachine.defers_finished? }
|
|
31
|
+
end
|
|
32
|
+
assert_equal(callback_parameters.select { |parameter| parameter == callback_parameter }.length, iterations * 0.5)
|
|
33
|
+
assert_equal(errback_parameters.select{ |parameter| parameter == errback_parameter }.length, iterations * 0.5)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require_relative 'em_test_helper'
|
|
2
|
+
|
|
3
|
+
class TestDeferrable < Test::Unit::TestCase
|
|
4
|
+
class Later
|
|
5
|
+
include EM::Deferrable
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def test_timeout_without_args
|
|
9
|
+
assert_nothing_raised do
|
|
10
|
+
EM.run {
|
|
11
|
+
df = Later.new
|
|
12
|
+
df.timeout(0)
|
|
13
|
+
df.errback { EM.stop }
|
|
14
|
+
EM.add_timer(0.01) { flunk "Deferrable was not timed out." }
|
|
15
|
+
}
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def test_timeout_with_args
|
|
20
|
+
args = nil
|
|
21
|
+
|
|
22
|
+
EM.run {
|
|
23
|
+
df = Later.new
|
|
24
|
+
df.timeout(0, :timeout, :foo)
|
|
25
|
+
df.errback do |type, name|
|
|
26
|
+
args = [type, name]
|
|
27
|
+
EM.stop
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
EM.add_timer(0.01) { flunk "Deferrable was not timed out." }
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
assert_equal [:timeout, :foo], args
|
|
34
|
+
end
|
|
35
|
+
end
|
data/tests/test_epoll.rb
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
require_relative 'em_test_helper'
|
|
2
|
+
|
|
3
|
+
class TestEpoll < Test::Unit::TestCase
|
|
4
|
+
|
|
5
|
+
module TestEchoServer
|
|
6
|
+
def receive_data data
|
|
7
|
+
send_data data
|
|
8
|
+
close_connection_after_writing
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
module TestEchoClient
|
|
13
|
+
def connection_completed
|
|
14
|
+
send_data "ABCDE"
|
|
15
|
+
$max += 1
|
|
16
|
+
end
|
|
17
|
+
def receive_data data
|
|
18
|
+
raise "bad response" unless data == "ABCDE"
|
|
19
|
+
end
|
|
20
|
+
def unbind
|
|
21
|
+
$n -= 1
|
|
22
|
+
EM.stop if $n == 0
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
# We can set the rlimit/nofile of a process but we can only set it
|
|
28
|
+
# higher if we're running as root.
|
|
29
|
+
# On most systems, the default value is 1024.
|
|
30
|
+
def test_rlimit
|
|
31
|
+
omit_if(windows? || jruby?)
|
|
32
|
+
unless EM.set_descriptor_table_size >= 1024
|
|
33
|
+
a = EM.set_descriptor_table_size
|
|
34
|
+
assert( a <= 1024 )
|
|
35
|
+
a = EM.set_descriptor_table_size( 1024 )
|
|
36
|
+
assert( a == 1024 )
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Run a high-volume version of this test by kicking the number of connections
|
|
41
|
+
# up past 512. (Each connection uses two sockets, a client and a server.)
|
|
42
|
+
# (Will require running the test as root)
|
|
43
|
+
# This test exercises TCP clients and servers.
|
|
44
|
+
#
|
|
45
|
+
# XXX this test causes all sort of weird issues on OSX (when run as part of the suite)
|
|
46
|
+
def _test_descriptors
|
|
47
|
+
EM.epoll
|
|
48
|
+
EM.set_descriptor_table_size 60000
|
|
49
|
+
EM.run {
|
|
50
|
+
EM.start_server "127.0.0.1", 9800, TestEchoServer
|
|
51
|
+
$n = 0
|
|
52
|
+
$max = 0
|
|
53
|
+
100.times {
|
|
54
|
+
EM.connect("127.0.0.1", 9800, TestEchoClient) {$n += 1}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
assert_equal(0, $n)
|
|
58
|
+
assert_equal(100, $max)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def setup
|
|
62
|
+
@port = next_port
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
module TestDatagramServer
|
|
66
|
+
def receive_data dgm
|
|
67
|
+
$in = dgm
|
|
68
|
+
send_data "abcdefghij"
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
module TestDatagramClient
|
|
72
|
+
def initialize port
|
|
73
|
+
@port = port
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def post_init
|
|
77
|
+
send_datagram "1234567890", "127.0.0.1", @port
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def receive_data dgm
|
|
81
|
+
$out = dgm
|
|
82
|
+
EM.stop
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def test_datagrams
|
|
87
|
+
$in = $out = ""
|
|
88
|
+
EM.run {
|
|
89
|
+
EM.open_datagram_socket "127.0.0.1", @port, TestDatagramServer
|
|
90
|
+
EM.open_datagram_socket "127.0.0.1", 0, TestDatagramClient, @port
|
|
91
|
+
}
|
|
92
|
+
assert_equal( "1234567890", $in )
|
|
93
|
+
assert_equal( "abcdefghij", $out )
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# XXX this test fails randomly...
|
|
97
|
+
def _test_unix_domain
|
|
98
|
+
fn = "/tmp/xxx.chain"
|
|
99
|
+
EM.epoll
|
|
100
|
+
EM.set_descriptor_table_size 60000
|
|
101
|
+
EM.run {
|
|
102
|
+
# The pure-Ruby version won't let us open the socket if the node already exists.
|
|
103
|
+
# Not sure, that actually may be correct and the compiled version is wrong.
|
|
104
|
+
# Pure Ruby also oddly won't let us make that many connections. This test used
|
|
105
|
+
# to run 100 times. Not sure where that lower connection-limit is coming from in
|
|
106
|
+
# pure Ruby.
|
|
107
|
+
# Let's not sweat the Unix-ness of the filename, since this test can't possibly
|
|
108
|
+
# work on Windows anyway.
|
|
109
|
+
#
|
|
110
|
+
File.unlink(fn) if File.exist?(fn)
|
|
111
|
+
EM.start_unix_domain_server fn, TestEchoServer
|
|
112
|
+
$n = 0
|
|
113
|
+
$max = 0
|
|
114
|
+
50.times {
|
|
115
|
+
EM.connect_unix_domain(fn, TestEchoClient) {$n += 1}
|
|
116
|
+
}
|
|
117
|
+
EM::add_timer(1) { $stderr.puts("test_unix_domain timed out!"); EM::stop }
|
|
118
|
+
}
|
|
119
|
+
assert_equal(0, $n)
|
|
120
|
+
assert_equal(50, $max)
|
|
121
|
+
ensure
|
|
122
|
+
File.unlink(fn) if File.exist?(fn)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def test_attach_detach
|
|
126
|
+
EM.epoll
|
|
127
|
+
EM.run {
|
|
128
|
+
EM.add_timer(0.01) { EM.stop }
|
|
129
|
+
|
|
130
|
+
r, _ = IO.pipe
|
|
131
|
+
|
|
132
|
+
# This tests a regression where detach in the same tick as attach crashes EM
|
|
133
|
+
EM.watch(r) do |connection|
|
|
134
|
+
connection.detach
|
|
135
|
+
end
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
assert true
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
require_relative 'em_test_helper'
|
|
2
|
+
|
|
3
|
+
class TestErrorHandler < Test::Unit::TestCase
|
|
4
|
+
def setup
|
|
5
|
+
@exception = Class.new(StandardError)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def test_error_handler
|
|
9
|
+
error = nil
|
|
10
|
+
|
|
11
|
+
EM.error_handler{ |e|
|
|
12
|
+
error = e
|
|
13
|
+
EM.error_handler(nil)
|
|
14
|
+
EM.stop
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
assert_nothing_raised do
|
|
18
|
+
EM.run{
|
|
19
|
+
EM.add_timer(0){
|
|
20
|
+
raise @exception, 'test'
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
assert_equal error.class, @exception
|
|
26
|
+
assert_equal error.message, 'test'
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def test_without_error_handler
|
|
30
|
+
assert_raise @exception do
|
|
31
|
+
EM.run{
|
|
32
|
+
EM.add_timer(0){
|
|
33
|
+
raise @exception, 'test'
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
data/tests/test_exc.rb
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
require_relative 'em_test_helper'
|
|
2
|
+
|
|
3
|
+
class TestSomeExceptions < Test::Unit::TestCase
|
|
4
|
+
class DoomedConnectionError < StandardError
|
|
5
|
+
end
|
|
6
|
+
class DoomedConnection < EventMachine::Connection
|
|
7
|
+
def unbind
|
|
8
|
+
raise DoomedConnectionError
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Read the commentary in EM#run.
|
|
13
|
+
# This test exercises the ensure block in #run that makes sure
|
|
14
|
+
# EM#release_machine gets called even if an exception is
|
|
15
|
+
# thrown within the user code. Without the ensured call to release_machine,
|
|
16
|
+
# the second call to EM#run will fail with a C++ exception
|
|
17
|
+
# because the machine wasn't cleaned up properly.
|
|
18
|
+
|
|
19
|
+
def test_a
|
|
20
|
+
assert_raises(RuntimeError) {
|
|
21
|
+
EM.run { raise "some exception" }
|
|
22
|
+
}
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def test_b
|
|
26
|
+
assert_raises(RuntimeError) {
|
|
27
|
+
EM.run { raise "some exception" }
|
|
28
|
+
}
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def test_exception_on_unbind
|
|
32
|
+
assert_raises(DoomedConnectionError) {
|
|
33
|
+
EM.run { EM.connect("localhost", 8888, DoomedConnection) }
|
|
34
|
+
}
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
end
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
require_relative 'em_test_helper'
|
|
2
|
+
require 'tempfile'
|
|
3
|
+
|
|
4
|
+
class TestFileWatch < Test::Unit::TestCase
|
|
5
|
+
if windows?
|
|
6
|
+
def test_watch_file_raises_unsupported_error
|
|
7
|
+
pend("\nFIXME: Windows as of 2018-06-23 on 32 bit >= 2.4 (#{RUBY_VERSION} #{RUBY_PLATFORM})") if RUBY_PLATFORM[/i386-mingw/] && RUBY_VERSION >= '2.4'
|
|
8
|
+
assert_raises(EM::Unsupported) do
|
|
9
|
+
EM.run do
|
|
10
|
+
file = Tempfile.new("fake_file")
|
|
11
|
+
EM.watch_file(file.path)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
elsif EM.respond_to? :watch_filename
|
|
16
|
+
module FileWatcher
|
|
17
|
+
def file_modified
|
|
18
|
+
$modified = true
|
|
19
|
+
end
|
|
20
|
+
def file_deleted
|
|
21
|
+
$deleted = true
|
|
22
|
+
end
|
|
23
|
+
def unbind
|
|
24
|
+
$unbind = true
|
|
25
|
+
EM.stop
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def setup
|
|
30
|
+
EM.kqueue = true if EM.kqueue?
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def teardown
|
|
34
|
+
EM.kqueue = false if EM.kqueue?
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def test_events
|
|
38
|
+
omit_if(solaris?)
|
|
39
|
+
EM.run{
|
|
40
|
+
file = Tempfile.new('em-watch')
|
|
41
|
+
$tmp_path = file.path
|
|
42
|
+
|
|
43
|
+
# watch it
|
|
44
|
+
watch = EM.watch_file(file.path, FileWatcher)
|
|
45
|
+
$path = watch.path
|
|
46
|
+
|
|
47
|
+
# modify it
|
|
48
|
+
File.open(file.path, 'w'){ |f| f.puts 'hi' }
|
|
49
|
+
|
|
50
|
+
# delete it
|
|
51
|
+
EM.add_timer(0.01){ file.close; file.delete }
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
assert_equal($path, $tmp_path)
|
|
55
|
+
assert($modified)
|
|
56
|
+
assert($deleted)
|
|
57
|
+
assert($unbind)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Refer: https://github.com/eventmachine/eventmachine/issues/512
|
|
61
|
+
def test_invalid_signature
|
|
62
|
+
# This works fine with kqueue, only fails with linux inotify.
|
|
63
|
+
omit_if(EM.kqueue?)
|
|
64
|
+
|
|
65
|
+
EM.run {
|
|
66
|
+
file = Tempfile.new('foo')
|
|
67
|
+
|
|
68
|
+
w1 = EventMachine.watch_file(file.path)
|
|
69
|
+
w2 = EventMachine.watch_file(file.path)
|
|
70
|
+
|
|
71
|
+
assert_raise EventMachine::InvalidSignature do
|
|
72
|
+
w2.stop_watching
|
|
73
|
+
end
|
|
74
|
+
w1.stop_watching rescue nil
|
|
75
|
+
EM.stop
|
|
76
|
+
}
|
|
77
|
+
end
|
|
78
|
+
else
|
|
79
|
+
warn "EM.watch_file not implemented, skipping tests in #{__FILE__}"
|
|
80
|
+
|
|
81
|
+
# Because some rubies will complain if a TestCase class has no tests
|
|
82
|
+
def test_em_watch_file_unsupported
|
|
83
|
+
assert true
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
data/tests/test_fork.rb
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
require_relative 'em_test_helper'
|
|
2
|
+
|
|
3
|
+
class TestFork < Test::Unit::TestCase
|
|
4
|
+
|
|
5
|
+
def test_fork_safe
|
|
6
|
+
omit_if(jruby?)
|
|
7
|
+
omit_if(windows?)
|
|
8
|
+
|
|
9
|
+
fork_pid = nil
|
|
10
|
+
read, write = IO.pipe
|
|
11
|
+
EM.run do
|
|
12
|
+
fork_pid = fork do
|
|
13
|
+
write.puts "forked"
|
|
14
|
+
EM.run do
|
|
15
|
+
EM.next_tick do
|
|
16
|
+
write.puts "EM ran"
|
|
17
|
+
EM.stop
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
EM.stop
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
sleep 0.1
|
|
25
|
+
begin
|
|
26
|
+
Timeout::timeout 1 do
|
|
27
|
+
assert_equal "forked\n", read.readline
|
|
28
|
+
assert_equal "EM ran\n", read.readline
|
|
29
|
+
end
|
|
30
|
+
rescue Timeout::Error
|
|
31
|
+
Process.kill 'TERM', fork_pid
|
|
32
|
+
flunk "Timeout waiting for next_tick in new fork reactor"
|
|
33
|
+
end
|
|
34
|
+
ensure
|
|
35
|
+
read.close rescue nil
|
|
36
|
+
write.close rescue nil
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def test_fork_reactor
|
|
40
|
+
omit_if(jruby?)
|
|
41
|
+
omit_if(windows?)
|
|
42
|
+
|
|
43
|
+
fork_pid = nil
|
|
44
|
+
read, write = IO.pipe
|
|
45
|
+
EM.run do
|
|
46
|
+
EM.defer do
|
|
47
|
+
write.puts Process.pid
|
|
48
|
+
EM.defer do
|
|
49
|
+
EM.stop
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
fork_pid = EM.fork_reactor do
|
|
53
|
+
EM.defer do
|
|
54
|
+
write.puts Process.pid
|
|
55
|
+
EM.stop
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
sleep 0.1
|
|
61
|
+
begin
|
|
62
|
+
Timeout::timeout 1 do
|
|
63
|
+
assert_equal Process.pid.to_s, read.readline.chomp
|
|
64
|
+
assert_equal fork_pid.to_s, read.readline.chomp
|
|
65
|
+
end
|
|
66
|
+
rescue Timeout::Error
|
|
67
|
+
Process.kill 'TERM', fork_pid
|
|
68
|
+
flunk "Timeout waiting for deferred block in fork_reactor"
|
|
69
|
+
end
|
|
70
|
+
ensure
|
|
71
|
+
read.close rescue nil
|
|
72
|
+
write.close rescue nil
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
end
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
require_relative 'em_test_helper'
|
|
2
|
+
|
|
3
|
+
class TestFutures < Test::Unit::TestCase
|
|
4
|
+
|
|
5
|
+
def setup
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def teardown
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def test_future
|
|
12
|
+
assert_equal(100, EM::Deferrable.future(100) )
|
|
13
|
+
|
|
14
|
+
p1 = proc { 100 + 1 }
|
|
15
|
+
assert_equal(101, EM::Deferrable.future(p1) )
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
class MyFuture
|
|
19
|
+
include EM::Deferrable
|
|
20
|
+
def initialize *args
|
|
21
|
+
super
|
|
22
|
+
set_deferred_status :succeeded, 40
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
class MyErrorFuture
|
|
27
|
+
include EM::Deferrable
|
|
28
|
+
def initialize *args
|
|
29
|
+
super
|
|
30
|
+
set_deferred_status :failed, 41
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def test_future_1
|
|
36
|
+
# Call future with one additional argument and it will be treated as a callback.
|
|
37
|
+
def my_future
|
|
38
|
+
MyFuture.new
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
value = nil
|
|
42
|
+
EM::Deferrable.future my_future, proc {|v| value=v}
|
|
43
|
+
assert_equal( 40, value )
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def test_future_2
|
|
48
|
+
# Call future with two additional arguments and they will be treated as a callback
|
|
49
|
+
# and an errback.
|
|
50
|
+
value = nil
|
|
51
|
+
EM::Deferrable.future MyErrorFuture.new, nil, proc {|v| value=v}
|
|
52
|
+
assert_equal( 41, value )
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def test_future_3
|
|
57
|
+
# Call future with no additional arguments but with a block, and the block will be
|
|
58
|
+
# treated as a callback.
|
|
59
|
+
value = nil
|
|
60
|
+
EM::Deferrable.future MyFuture.new do |v|
|
|
61
|
+
value=v
|
|
62
|
+
end
|
|
63
|
+
assert_equal( 40, value )
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class RecursiveCallback
|
|
68
|
+
include EM::Deferrable
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# A Deferrable callback can call #set_deferred_status to change the values
|
|
72
|
+
# passed to subsequent callbacks.
|
|
73
|
+
#
|
|
74
|
+
def test_recursive_callbacks
|
|
75
|
+
n = 0 # counter assures that all the tests actually run.
|
|
76
|
+
rc = RecursiveCallback.new
|
|
77
|
+
rc.callback {|a|
|
|
78
|
+
assert_equal(100, a)
|
|
79
|
+
n += 1
|
|
80
|
+
rc.set_deferred_status :succeeded, 101, 101
|
|
81
|
+
}
|
|
82
|
+
rc.callback {|a,b|
|
|
83
|
+
assert_equal(101, a)
|
|
84
|
+
assert_equal(101, b)
|
|
85
|
+
n += 1
|
|
86
|
+
rc.set_deferred_status :succeeded, 102, 102, 102
|
|
87
|
+
}
|
|
88
|
+
rc.callback {|a,b,c|
|
|
89
|
+
assert_equal(102, a)
|
|
90
|
+
assert_equal(102, b)
|
|
91
|
+
assert_equal(102, c)
|
|
92
|
+
n += 1
|
|
93
|
+
}
|
|
94
|
+
rc.set_deferred_status :succeeded, 100
|
|
95
|
+
assert_equal(3, n)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def test_syntactic_sugar
|
|
99
|
+
rc = RecursiveCallback.new
|
|
100
|
+
rc.set_deferred_success 100
|
|
101
|
+
rc.set_deferred_failure 200
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# It doesn't raise an error to set deferred status more than once.
|
|
105
|
+
# In fact, this is a desired and useful idiom when it happens INSIDE
|
|
106
|
+
# a callback or errback.
|
|
107
|
+
# However, it's less useful otherwise, and in fact would generally be
|
|
108
|
+
# indicative of a programming error. However, we would like to be resistant
|
|
109
|
+
# to such errors. So whenever we set deferred status, we also clear BOTH
|
|
110
|
+
# stacks of handlers.
|
|
111
|
+
#
|
|
112
|
+
def test_double_calls
|
|
113
|
+
s = 0
|
|
114
|
+
e = 0
|
|
115
|
+
|
|
116
|
+
d = EM::DefaultDeferrable.new
|
|
117
|
+
d.callback {s += 1}
|
|
118
|
+
d.errback {e += 1}
|
|
119
|
+
|
|
120
|
+
d.succeed # We expect the callback to be called, and the errback to be DISCARDED.
|
|
121
|
+
d.fail # Presumably an error. We expect the errback NOT to be called.
|
|
122
|
+
d.succeed # We expect the callback to have been discarded and NOT to be called again.
|
|
123
|
+
|
|
124
|
+
assert_equal(1, s)
|
|
125
|
+
assert_equal(0, e)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# Adding a callback to a Deferrable that is already in a success state executes the callback
|
|
129
|
+
# immediately. The same applies to a an errback added to an already-failed Deferrable.
|
|
130
|
+
# HOWEVER, we expect NOT to be able to add errbacks to succeeded Deferrables, or callbacks
|
|
131
|
+
# to failed ones.
|
|
132
|
+
#
|
|
133
|
+
# We illustrate this with a rather contrived test. The test calls #fail after #succeed,
|
|
134
|
+
# which ordinarily would not happen in a real program.
|
|
135
|
+
#
|
|
136
|
+
# What we're NOT attempting to specify is what happens if a Deferrable is succeeded and then
|
|
137
|
+
# failed (or vice-versa). Should we then be able to add callbacks/errbacks of the appropriate
|
|
138
|
+
# type for immediate execution? For now at least, the official answer is "don't do that."
|
|
139
|
+
#
|
|
140
|
+
def test_delayed_callbacks
|
|
141
|
+
s1 = 0
|
|
142
|
+
s2 = 0
|
|
143
|
+
e = 0
|
|
144
|
+
|
|
145
|
+
d = EM::DefaultDeferrable.new
|
|
146
|
+
d.callback {s1 += 1}
|
|
147
|
+
|
|
148
|
+
d.succeed # Triggers and discards the callback.
|
|
149
|
+
|
|
150
|
+
d.callback {s2 += 1} # This callback is executed immediately and discarded.
|
|
151
|
+
|
|
152
|
+
d.errback {e += 1} # This errback should be DISCARDED and never execute.
|
|
153
|
+
d.fail # To prove it, fail and assert e is 0
|
|
154
|
+
|
|
155
|
+
assert_equal( [1,1], [s1,s2] )
|
|
156
|
+
assert_equal( 0, e )
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def test_timeout
|
|
160
|
+
n = 0
|
|
161
|
+
EM.run {
|
|
162
|
+
d = EM::DefaultDeferrable.new
|
|
163
|
+
d.callback {n = 1; EM.stop}
|
|
164
|
+
d.errback {n = 2; EM.stop}
|
|
165
|
+
d.timeout(0.01)
|
|
166
|
+
}
|
|
167
|
+
assert_equal( 2, n )
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require_relative 'em_test_helper'
|
|
2
|
+
|
|
3
|
+
class TestHandlerCheck < Test::Unit::TestCase
|
|
4
|
+
|
|
5
|
+
class Foo < EM::Connection; end;
|
|
6
|
+
module TestModule; end;
|
|
7
|
+
|
|
8
|
+
def test_with_correct_class
|
|
9
|
+
assert_nothing_raised do
|
|
10
|
+
EM.run {
|
|
11
|
+
EM.connect("127.0.0.1", 80, Foo)
|
|
12
|
+
EM.stop_event_loop
|
|
13
|
+
}
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def test_with_incorrect_class
|
|
18
|
+
assert_raise(ArgumentError) do
|
|
19
|
+
EM.run {
|
|
20
|
+
EM.connect("127.0.0.1", 80, String)
|
|
21
|
+
EM.stop_event_loop
|
|
22
|
+
}
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def test_with_module
|
|
27
|
+
assert_nothing_raised do
|
|
28
|
+
EM.run {
|
|
29
|
+
EM.connect("127.0.0.1", 80, TestModule)
|
|
30
|
+
EM.stop_event_loop
|
|
31
|
+
}
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
end
|