eventmachine-le 1.1.0.beta.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.
Files changed (129) hide show
  1. data/.gitignore +21 -0
  2. data/.yardopts +7 -0
  3. data/GNU +281 -0
  4. data/LICENSE +60 -0
  5. data/README.md +80 -0
  6. data/Rakefile +19 -0
  7. data/eventmachine-le.gemspec +42 -0
  8. data/ext/binder.cpp +124 -0
  9. data/ext/binder.h +46 -0
  10. data/ext/cmain.cpp +841 -0
  11. data/ext/ed.cpp +1995 -0
  12. data/ext/ed.h +424 -0
  13. data/ext/em.cpp +2377 -0
  14. data/ext/em.h +243 -0
  15. data/ext/eventmachine.h +126 -0
  16. data/ext/extconf.rb +166 -0
  17. data/ext/fastfilereader/extconf.rb +94 -0
  18. data/ext/fastfilereader/mapper.cpp +214 -0
  19. data/ext/fastfilereader/mapper.h +59 -0
  20. data/ext/fastfilereader/rubymain.cpp +127 -0
  21. data/ext/kb.cpp +79 -0
  22. data/ext/page.cpp +107 -0
  23. data/ext/page.h +51 -0
  24. data/ext/pipe.cpp +347 -0
  25. data/ext/project.h +155 -0
  26. data/ext/rubymain.cpp +1269 -0
  27. data/ext/ssl.cpp +468 -0
  28. data/ext/ssl.h +94 -0
  29. data/lib/em/buftok.rb +110 -0
  30. data/lib/em/callback.rb +58 -0
  31. data/lib/em/channel.rb +64 -0
  32. data/lib/em/completion.rb +304 -0
  33. data/lib/em/connection.rb +728 -0
  34. data/lib/em/deferrable.rb +210 -0
  35. data/lib/em/deferrable/pool.rb +2 -0
  36. data/lib/em/file_watch.rb +73 -0
  37. data/lib/em/future.rb +61 -0
  38. data/lib/em/iterator.rb +313 -0
  39. data/lib/em/messages.rb +66 -0
  40. data/lib/em/pool.rb +151 -0
  41. data/lib/em/process_watch.rb +45 -0
  42. data/lib/em/processes.rb +123 -0
  43. data/lib/em/protocols.rb +37 -0
  44. data/lib/em/protocols/header_and_content.rb +138 -0
  45. data/lib/em/protocols/httpclient.rb +279 -0
  46. data/lib/em/protocols/httpclient2.rb +600 -0
  47. data/lib/em/protocols/line_and_text.rb +125 -0
  48. data/lib/em/protocols/line_protocol.rb +29 -0
  49. data/lib/em/protocols/linetext2.rb +161 -0
  50. data/lib/em/protocols/memcache.rb +331 -0
  51. data/lib/em/protocols/object_protocol.rb +46 -0
  52. data/lib/em/protocols/postgres3.rb +246 -0
  53. data/lib/em/protocols/saslauth.rb +175 -0
  54. data/lib/em/protocols/smtpclient.rb +365 -0
  55. data/lib/em/protocols/smtpserver.rb +663 -0
  56. data/lib/em/protocols/socks4.rb +66 -0
  57. data/lib/em/protocols/stomp.rb +202 -0
  58. data/lib/em/protocols/tcptest.rb +54 -0
  59. data/lib/em/queue.rb +71 -0
  60. data/lib/em/resolver.rb +195 -0
  61. data/lib/em/spawnable.rb +84 -0
  62. data/lib/em/streamer.rb +118 -0
  63. data/lib/em/threaded_resource.rb +90 -0
  64. data/lib/em/tick_loop.rb +85 -0
  65. data/lib/em/timers.rb +106 -0
  66. data/lib/em/version.rb +3 -0
  67. data/lib/eventmachine-le.rb +10 -0
  68. data/lib/eventmachine.rb +1548 -0
  69. data/rakelib/cpp.rake_example +77 -0
  70. data/rakelib/package.rake +98 -0
  71. data/rakelib/test.rake +8 -0
  72. data/tests/client.crt +31 -0
  73. data/tests/client.key +51 -0
  74. data/tests/em_test_helper.rb +143 -0
  75. data/tests/test_attach.rb +148 -0
  76. data/tests/test_basic.rb +294 -0
  77. data/tests/test_channel.rb +62 -0
  78. data/tests/test_completion.rb +177 -0
  79. data/tests/test_connection_count.rb +33 -0
  80. data/tests/test_defer.rb +18 -0
  81. data/tests/test_deferrable.rb +35 -0
  82. data/tests/test_epoll.rb +134 -0
  83. data/tests/test_error_handler.rb +38 -0
  84. data/tests/test_exc.rb +28 -0
  85. data/tests/test_file_watch.rb +65 -0
  86. data/tests/test_futures.rb +170 -0
  87. data/tests/test_get_sock_opt.rb +37 -0
  88. data/tests/test_handler_check.rb +35 -0
  89. data/tests/test_hc.rb +155 -0
  90. data/tests/test_httpclient.rb +190 -0
  91. data/tests/test_httpclient2.rb +128 -0
  92. data/tests/test_inactivity_timeout.rb +54 -0
  93. data/tests/test_ipv4.rb +125 -0
  94. data/tests/test_ipv6.rb +131 -0
  95. data/tests/test_iterator.rb +110 -0
  96. data/tests/test_kb.rb +34 -0
  97. data/tests/test_line_protocol.rb +33 -0
  98. data/tests/test_ltp.rb +138 -0
  99. data/tests/test_ltp2.rb +288 -0
  100. data/tests/test_next_tick.rb +104 -0
  101. data/tests/test_object_protocol.rb +36 -0
  102. data/tests/test_pause.rb +78 -0
  103. data/tests/test_pending_connect_timeout.rb +52 -0
  104. data/tests/test_pool.rb +196 -0
  105. data/tests/test_process_watch.rb +48 -0
  106. data/tests/test_processes.rb +133 -0
  107. data/tests/test_proxy_connection.rb +168 -0
  108. data/tests/test_pure.rb +88 -0
  109. data/tests/test_queue.rb +50 -0
  110. data/tests/test_resolver.rb +55 -0
  111. data/tests/test_running.rb +14 -0
  112. data/tests/test_sasl.rb +47 -0
  113. data/tests/test_send_file.rb +217 -0
  114. data/tests/test_servers.rb +33 -0
  115. data/tests/test_set_sock_opt.rb +41 -0
  116. data/tests/test_shutdown_hooks.rb +23 -0
  117. data/tests/test_smtpclient.rb +55 -0
  118. data/tests/test_smtpserver.rb +120 -0
  119. data/tests/test_spawn.rb +293 -0
  120. data/tests/test_ssl_args.rb +78 -0
  121. data/tests/test_ssl_methods.rb +48 -0
  122. data/tests/test_ssl_verify.rb +82 -0
  123. data/tests/test_threaded_resource.rb +55 -0
  124. data/tests/test_tick_loop.rb +59 -0
  125. data/tests/test_timers.rb +180 -0
  126. data/tests/test_ud.rb +8 -0
  127. data/tests/test_udp46.rb +53 -0
  128. data/tests/test_unbind_reason.rb +48 -0
  129. metadata +390 -0
@@ -0,0 +1,120 @@
1
+ require 'net/smtp'
2
+ require "net/telnet"
3
+ require 'em_test_helper'
4
+
5
+ class TestSmtpServer < Test::Unit::TestCase
6
+
7
+ # Don't test on port 25. It requires superuser and there's probably
8
+ # a mail server already running there anyway.
9
+ Localhost = "127.0.0.1"
10
+ Localport = 25001
11
+
12
+ # This class is an example of what you need to write in order
13
+ # to implement a mail server. You override the methods you are
14
+ # interested in. Some, but not all, of these are illustrated here.
15
+ #
16
+ class Mailserver < EM::Protocols::SmtpServer
17
+
18
+ attr_reader :my_msg_body, :my_sender, :my_recipients, :messages_count
19
+
20
+
21
+ def initialize *args
22
+ super
23
+ end
24
+
25
+ def receive_sender sender
26
+ @my_sender = sender
27
+ #p sender
28
+ true
29
+ end
30
+
31
+ def receive_recipient rcpt
32
+ @my_recipients ||= []
33
+ @my_recipients << rcpt
34
+ true
35
+ end
36
+
37
+ def receive_data_chunk c
38
+ @my_msg_body = c.last
39
+ end
40
+
41
+ def receive_message
42
+ @messages_count ||= 0
43
+ @messages_count += 1
44
+ true
45
+ end
46
+
47
+ def connection_ended
48
+ EM.stop
49
+ end
50
+ end
51
+
52
+ def run_server
53
+ c = nil
54
+ EM.run {
55
+ EM.start_server( Localhost, Localport, Mailserver ) {|conn| c = conn}
56
+ EM::Timer.new(2) {EM.stop} # prevent hanging the test suite in case of error
57
+ yield if block_given?
58
+ }
59
+ c
60
+ end
61
+
62
+ def test_mail
63
+ c = run_server do
64
+ EM::Protocols::SmtpClient.send :host=>Localhost,
65
+ :port=>Localport,
66
+ :domain=>"bogus",
67
+ :from=>"me@example.com",
68
+ :to=>"you@example.com",
69
+ :header=> {"Subject"=>"Email subject line", "Reply-to"=>"me@example.com"},
70
+ :body=>"Not much of interest here."
71
+ end
72
+ assert_equal( "Not much of interest here.", c.my_msg_body )
73
+ assert_equal( "<me@example.com>", c.my_sender )
74
+ assert_equal( ["<you@example.com>"], c.my_recipients )
75
+ end
76
+
77
+
78
+
79
+ def test_multiple_messages_per_connection
80
+ c = run_server do
81
+ Thread.new do
82
+ Net::SMTP.start( Localhost, Localport, Localhost ) do |smtp|
83
+ 2.times do
84
+ smtp.send_message "This is a test e-mail message.", 'me@fromdomain.com', 'test@todomain.com'
85
+ end
86
+ end
87
+ end
88
+ end
89
+
90
+ assert_equal( 2, c.messages_count )
91
+ end
92
+
93
+ def test_login_authentication
94
+ Mailserver.parms = {:auth => :required}
95
+ connection = run_server do
96
+ Thread.new do
97
+ pop = Net::Telnet::new("Host" => Localhost,
98
+ "Port" =>Localport,
99
+ "Telnetmode" => false,
100
+ "Prompt" => /^\d{3}\s+/n
101
+ )
102
+ pop.cmd(<<-CMD)
103
+ auth login
104
+ #{["aaa"].pack('m').chomp}
105
+ #{["bbb"].pack('m').chomp}
106
+ mail from:a@b.com
107
+ rcpt to:c@d.com
108
+ data
109
+ hello
110
+ .
111
+ quit
112
+ CMD
113
+ end
114
+ end
115
+
116
+ assert_equal( 1, connection.messages_count )
117
+ ensure
118
+ Mailserver.parms = {:auth => nil}
119
+ end
120
+ end
@@ -0,0 +1,293 @@
1
+
2
+ require 'em_test_helper'
3
+
4
+
5
+
6
+ class TestSpawn < Test::Unit::TestCase
7
+
8
+ # Spawn a process that simply stops the reactor.
9
+ # Assert that the notification runs after the block that calls it.
10
+ #
11
+ def test_stop
12
+ x = nil
13
+ EM.run {
14
+ s = EM.spawn {EM.stop}
15
+ s.notify
16
+ x = true
17
+ }
18
+ assert x
19
+ end
20
+
21
+
22
+ # Pass a parameter to a spawned process.
23
+ #
24
+ def test_parms
25
+ val = 5
26
+ EM.run {
27
+ s = EM.spawn {|v| val *= v; EM.stop}
28
+ s.notify 3
29
+ }
30
+ assert_equal( 15, val )
31
+ end
32
+
33
+ # Pass multiple parameters to a spawned process.
34
+ #
35
+ def test_multiparms
36
+ val = 5
37
+ EM.run {
38
+ s = EM.spawn {|v1,v2| val *= (v1 + v2); EM.stop}
39
+ s.notify 3,4
40
+ }
41
+ assert_equal( 35, val )
42
+ end
43
+
44
+
45
+ # This test demonstrates that a notification does not happen immediately,
46
+ # but rather is scheduled sometime after the current code path completes.
47
+ #
48
+ def test_race
49
+ x = 0
50
+ EM.run {
51
+ s = EM.spawn {x *= 2; EM.stop}
52
+ s.notify
53
+ x = 2
54
+ }
55
+ assert_equal( 4, x)
56
+ end
57
+
58
+
59
+ # Spawn a process and notify it 25 times to run fibonacci
60
+ # on a pair of global variables.
61
+ #
62
+ def test_fibonacci
63
+ x = 1
64
+ y = 1
65
+ EM.run {
66
+ s = EM.spawn {x,y = y,x+y}
67
+ 25.times {s.notify}
68
+
69
+ t = EM.spawn {EM.stop}
70
+ t.notify
71
+ }
72
+ assert_equal( 121393, x)
73
+ assert_equal( 196418, y)
74
+ end
75
+
76
+ # This one spawns 25 distinct processes, and notifies each one once,
77
+ # rather than notifying a single process 25 times.
78
+ #
79
+ def test_another_fibonacci
80
+ x = 1
81
+ y = 1
82
+ EM.run {
83
+ 25.times {
84
+ s = EM.spawn {x,y = y,x+y}
85
+ s.notify
86
+ }
87
+
88
+ t = EM.spawn {EM.stop}
89
+ t.notify
90
+ }
91
+ assert_equal( 121393, x)
92
+ assert_equal( 196418, y)
93
+ end
94
+
95
+
96
+ # Make a chain of processes that notify each other in turn
97
+ # with intermediate fibonacci results. The final process in
98
+ # the chain stops the loop and returns the result.
99
+ #
100
+ def test_fibonacci_chain
101
+ a,b = nil
102
+
103
+ EM.run {
104
+ nextpid = EM.spawn {|x,y|
105
+ a,b = x,y
106
+ EM.stop
107
+ }
108
+
109
+ 25.times {
110
+ n = nextpid
111
+ nextpid = EM.spawn {|x,y| n.notify( y, x+y )}
112
+ }
113
+
114
+ nextpid.notify( 1, 1 )
115
+ }
116
+
117
+ assert_equal( 121393, a)
118
+ assert_equal( 196418, b)
119
+ end
120
+
121
+
122
+ # EM#yield gives a spawed process to yield control to other processes
123
+ # (in other words, to stop running), and to specify a different code block
124
+ # that will run on its next notification.
125
+ #
126
+ def test_yield
127
+ a = 0
128
+ EM.run {
129
+ n = EM.spawn {
130
+ a += 10
131
+ EM.yield {
132
+ a += 20
133
+ EM.yield {
134
+ a += 30
135
+ EM.stop
136
+ }
137
+ }
138
+ }
139
+ n.notify
140
+ n.notify
141
+ n.notify
142
+ }
143
+ assert_equal( 60, a )
144
+ end
145
+
146
+ # EM#yield_and_notify behaves like EM#yield, except that it also notifies the
147
+ # yielding process. This may sound trivial, since the yield block will run very
148
+ # shortly after with no action by the program, but this actually can be very useful,
149
+ # because it causes the reactor core to execute once before the yielding process
150
+ # gets control back. So it can be used to allow heavily-used network connections
151
+ # to clear buffers, or allow other processes to process their notifications.
152
+ #
153
+ # Notice in this test code that only a simple notify is needed at the bottom
154
+ # of the initial block. Even so, all of the yielded blocks will execute.
155
+ #
156
+ def test_yield_and_notify
157
+ a = 0
158
+ EM.run {
159
+ n = EM.spawn {
160
+ a += 10
161
+ EM.yield_and_notify {
162
+ a += 20
163
+ EM.yield_and_notify {
164
+ a += 30
165
+ EM.stop
166
+ }
167
+ }
168
+ }
169
+ n.notify
170
+ }
171
+ assert_equal( 60, a )
172
+ end
173
+
174
+ # resume is an alias for notify.
175
+ #
176
+ def test_resume
177
+ EM.run {
178
+ n = EM.spawn {EM.stop}
179
+ n.resume
180
+ }
181
+ assert true
182
+ end
183
+
184
+ # run is an idiomatic alias for notify.
185
+ #
186
+ def test_run
187
+ EM.run {
188
+ (EM.spawn {EM.stop}).run
189
+ }
190
+ assert true
191
+ end
192
+
193
+
194
+ # Clones the ping-pong example from the Erlang tutorial, in much less code.
195
+ # Illustrates that a spawned block executes in the context of a SpawnableObject.
196
+ # (Meaning, we can pass self as a parameter to another process that can then
197
+ # notify us.)
198
+ #
199
+ def test_ping_pong
200
+ n_pongs = 0
201
+ EM.run {
202
+ pong = EM.spawn {|x, ping|
203
+ n_pongs += 1
204
+ ping.notify( x-1 )
205
+ }
206
+ ping = EM.spawn {|x|
207
+ if x > 0
208
+ pong.notify x, self
209
+ else
210
+ EM.stop
211
+ end
212
+ }
213
+ ping.notify 3
214
+ }
215
+ assert_equal( 3, n_pongs )
216
+ end
217
+
218
+ # Illustrates that you can call notify inside a notification, and it will cause
219
+ # the currently-executing process to be re-notified. Of course, the new notification
220
+ # won't run until sometime after the current one completes.
221
+ #
222
+ def test_self_notify
223
+ n = 0
224
+ EM.run {
225
+ pid = EM.spawn {|x|
226
+ if x > 0
227
+ n += x
228
+ notify( x-1 )
229
+ else
230
+ EM.stop
231
+ end
232
+ }
233
+ pid.notify 3
234
+ }
235
+ assert_equal( 6, n )
236
+ end
237
+
238
+
239
+ # Illustrates that the block passed to #spawn executes in the context of a
240
+ # SpawnedProcess object, NOT in the local context. This can often be deceptive.
241
+ #
242
+ class BlockScopeTest
243
+ attr_reader :var
244
+ def run
245
+ # The following line correctly raises a NameError.
246
+ # The problem is that the programmer expected the spawned block to
247
+ # execute in the local context, but it doesn't.
248
+ #
249
+ # (EM.spawn { do_something }).notify ### NO! BAD!
250
+
251
+
252
+
253
+ # The following line correctly passes self as a parameter to the
254
+ # notified process.
255
+ #
256
+ (EM.spawn {|obj| obj.do_something }).notify(self)
257
+
258
+
259
+
260
+ # Here's another way to do it. This works because "myself" is bound
261
+ # in the local scope, unlike "self," so the spawned block sees it.
262
+ #
263
+ myself = self
264
+ (EM.spawn { myself.do_something }).notify
265
+
266
+
267
+
268
+ # And we end the loop.
269
+ # This is a tangential point, but observe that #notify never blocks.
270
+ # It merely appends a message to the internal queue of a spawned process
271
+ # and returns. As it turns out, the reactor processes notifications for ALL
272
+ # spawned processes in the order that #notify is called. So there is a
273
+ # reasonable expectation that the process which stops the reactor will
274
+ # execute after the previous ones in this method. HOWEVER, this is NOT
275
+ # a documented behavior and is subject to change.
276
+ #
277
+ (EM.spawn {EM.stop}).notify
278
+ end
279
+ def do_something
280
+ @var ||= 0
281
+ @var += 100
282
+ end
283
+ end
284
+
285
+ def test_block_scope
286
+ bs = BlockScopeTest.new
287
+ EM.run {
288
+ bs.run
289
+ }
290
+ assert_equal( 200, bs.var )
291
+ end
292
+
293
+ end
@@ -0,0 +1,78 @@
1
+ require "test/unit"
2
+ require 'tempfile'
3
+
4
+ require 'em_test_helper'
5
+
6
+ module EM
7
+ def self._set_mocks
8
+ class <<self
9
+ alias set_tls_parms_old set_tls_parms
10
+ alias start_tls_old start_tls
11
+ begin
12
+ old, $VERBOSE = $VERBOSE, nil
13
+ def set_tls_parms *args; end
14
+ def start_tls *args; end
15
+ ensure
16
+ $VERBOSE = old
17
+ end
18
+ end
19
+ end
20
+
21
+ def self._clear_mocks
22
+ class <<self
23
+ begin
24
+ old, $VERBOSE = $VERBOSE, nil
25
+ alias set_tls_parms set_tls_parms_old
26
+ alias start_tls start_tls_old
27
+ ensure
28
+ $VERBOSE = old
29
+ end
30
+ end
31
+ end
32
+ end
33
+
34
+
35
+
36
+ class TestSslArgs < Test::Unit::TestCase
37
+ def setup
38
+ EM._set_mocks
39
+ end
40
+
41
+ def teardown
42
+ EM._clear_mocks
43
+ end
44
+
45
+ def test_tls_params_file_doesnt_exist
46
+ priv_file, cert_file = 'foo_priv_key', 'bar_cert_file'
47
+ [priv_file, cert_file].all? do |f|
48
+ assert(!File.exists?(f), "Cert file #{f} seems to exist, and should not for the tests")
49
+ end
50
+
51
+ # associate_callback_target is a pain! (build!)
52
+ conn = EM::Connection.new('foo')
53
+
54
+ assert_raises(EM::FileNotFoundException) do
55
+ conn.start_tls(:private_key_file => priv_file)
56
+ end
57
+ assert_raises(EM::FileNotFoundException) do
58
+ conn.start_tls(:cert_chain_file => cert_file)
59
+ end
60
+ assert_raises(EM::FileNotFoundException) do
61
+ conn.start_tls(:private_key_file => priv_file, :cert_chain_file => cert_file)
62
+ end
63
+ end
64
+
65
+ def test_tls_params_file_does_exist
66
+ priv_file = Tempfile.new('em_test')
67
+ cert_file = Tempfile.new('em_test')
68
+ priv_file_path = priv_file.path
69
+ cert_file_path = cert_file.path
70
+ conn = EM::Connection.new('foo')
71
+ params = {:private_key_file => priv_file_path, :cert_chain_file => cert_file_path}
72
+ begin
73
+ conn.start_tls params
74
+ rescue Object
75
+ assert(false, 'should not have raised an exception')
76
+ end
77
+ end
78
+ end if EM.ssl?