eventmachine 1.0.0.beta.2-x86-mswin32-60 → 1.0.0.beta.3-x86-mswin32-60

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. data/.yardopts +3 -0
  2. data/Gemfile +1 -0
  3. data/eventmachine.gemspec +1 -3
  4. data/ext/cmain.cpp +4 -4
  5. data/ext/ed.cpp +13 -16
  6. data/ext/ed.h +9 -10
  7. data/ext/em.cpp +14 -24
  8. data/ext/eventmachine.h +2 -2
  9. data/ext/extconf.rb +1 -1
  10. data/ext/rubymain.cpp +8 -6
  11. data/lib/em/connection.rb +3 -1
  12. data/lib/em/pure_ruby.rb +17 -17
  13. data/lib/em/resolver.rb +186 -0
  14. data/lib/em/spawnable.rb +3 -7
  15. data/lib/em/version.rb +1 -1
  16. data/lib/eventmachine.rb +6 -4
  17. data/lib/jeventmachine.rb +1 -1
  18. data/tasks/package.rake +4 -1
  19. data/tasks/test.rake +1 -0
  20. data/tests/em_test_helper.rb +55 -0
  21. data/tests/test_attach.rb +46 -56
  22. data/tests/test_basic.rb +74 -96
  23. data/tests/test_channel.rb +2 -4
  24. data/tests/test_connection_count.rb +1 -3
  25. data/tests/test_defer.rb +13 -44
  26. data/tests/test_deferrable.rb +19 -19
  27. data/tests/test_epoll.rb +25 -55
  28. data/tests/test_error_handler.rb +10 -7
  29. data/tests/test_exc.rb +6 -33
  30. data/tests/test_file_watch.rb +51 -35
  31. data/tests/test_futures.rb +9 -37
  32. data/tests/test_get_sock_opt.rb +27 -20
  33. data/tests/test_handler_check.rb +1 -3
  34. data/tests/test_hc.rb +24 -59
  35. data/tests/test_httpclient.rb +27 -64
  36. data/tests/test_httpclient2.rb +1 -29
  37. data/tests/test_inactivity_timeout.rb +44 -40
  38. data/tests/test_kb.rb +26 -52
  39. data/tests/test_ltp.rb +23 -67
  40. data/tests/test_ltp2.rb +1 -30
  41. data/tests/test_next_tick.rb +1 -30
  42. data/tests/test_object_protocol.rb +8 -9
  43. data/tests/test_pause.rb +45 -37
  44. data/tests/test_pending_connect_timeout.rb +42 -38
  45. data/tests/test_process_watch.rb +1 -3
  46. data/tests/test_processes.rb +92 -110
  47. data/tests/test_proxy_connection.rb +128 -104
  48. data/tests/test_pure.rb +29 -75
  49. data/tests/test_queue.rb +2 -4
  50. data/tests/test_resolver.rb +55 -0
  51. data/tests/test_running.rb +1 -29
  52. data/tests/test_sasl.rb +7 -32
  53. data/tests/test_send_file.rb +162 -196
  54. data/tests/test_servers.rb +13 -56
  55. data/tests/test_smtpclient.rb +1 -29
  56. data/tests/test_smtpserver.rb +1 -29
  57. data/tests/test_spawn.rb +2 -31
  58. data/tests/test_ssl_args.rb +9 -10
  59. data/tests/test_ssl_methods.rb +1 -3
  60. data/tests/test_ssl_verify.rb +63 -63
  61. data/tests/test_tick_loop.rb +1 -1
  62. data/tests/test_timers.rb +52 -89
  63. data/tests/test_ud.rb +1 -29
  64. metadata +20 -10
  65. data/setup.rb +0 -1585
  66. data/tests/test_errors.rb +0 -82
  67. data/tests/testem.rb +0 -31
@@ -0,0 +1,186 @@
1
+ module EventMachine
2
+ module DNS
3
+ class Resolver
4
+
5
+ def self.resolve(hostname)
6
+ Request.new(socket, hostname)
7
+ end
8
+
9
+ def self.socket
10
+ if !@socket || (@socket && @socket.error?)
11
+ @socket = Socket.open
12
+
13
+ @hosts = {}
14
+ IO.readlines('/etc/hosts').each do |line|
15
+ next if line =~ /^#/
16
+ addr, host = line.split(/\s+/)
17
+
18
+ if @hosts[host]
19
+ @hosts[host] << addr
20
+ else
21
+ @hosts[host] = [addr]
22
+ end
23
+ end
24
+ end
25
+
26
+ @socket
27
+ end
28
+
29
+ def self.nameservers=(ns)
30
+ @nameservers = ns
31
+ end
32
+
33
+ def self.nameservers
34
+ if !@nameservers
35
+ @nameservers = []
36
+ IO.readlines('/etc/resolv.conf').each do |line|
37
+ if line =~ /^nameserver (.+)$/
38
+ @nameservers << $1.split(/\s+/).first
39
+ end
40
+ end
41
+ end
42
+ @nameservers
43
+ end
44
+
45
+ def self.nameserver
46
+ nameservers.shuffle.first
47
+ end
48
+
49
+ def self.hosts
50
+ @hosts
51
+ end
52
+ end
53
+
54
+ class RequestIdAlreadyUsed < RuntimeError; end
55
+
56
+ class Socket < EventMachine::Connection
57
+ def self.open
58
+ EventMachine::open_datagram_socket('0.0.0.0', 0, self)
59
+ end
60
+
61
+ def post_init
62
+ @requests = {}
63
+ EM.add_periodic_timer(0.1, &method(:tick))
64
+ end
65
+
66
+ def unbind
67
+ end
68
+
69
+ def tick
70
+ @requests.each do |id,req|
71
+ req.tick
72
+ end
73
+ end
74
+
75
+ def register_request(id, req)
76
+ if @requests.has_key?(id)
77
+ raise RequestIdAlreadyUsed
78
+ else
79
+ @requests[id] = req
80
+ end
81
+ end
82
+
83
+ def send_packet(pkt)
84
+ send_datagram(pkt, nameserver, 53)
85
+ end
86
+
87
+ def nameserver=(ns)
88
+ @nameserver = ns
89
+ end
90
+
91
+ def nameserver
92
+ @nameserver || Resolver.nameserver
93
+ end
94
+
95
+ # Decodes the packet, looks for the request and passes the
96
+ # response over to the requester
97
+ def receive_data(data)
98
+ msg = nil
99
+ begin
100
+ msg = Resolv::DNS::Message.decode data
101
+ rescue
102
+ else
103
+ req = @requests[msg.id]
104
+ if req
105
+ @requests.delete(msg.id)
106
+ req.receive_answer(msg)
107
+ end
108
+ end
109
+ end
110
+ end
111
+
112
+ class Request
113
+ include Deferrable
114
+ attr_accessor :retry_interval, :max_tries
115
+
116
+ def initialize(socket, hostname)
117
+ @socket = socket
118
+ @hostname = hostname
119
+ @tries = 0
120
+ @last_send = Time.at(0)
121
+ @retry_interval = 3
122
+ @max_tries = 5
123
+
124
+ if addrs = Resolver.hosts[hostname]
125
+ succeed addrs
126
+ else
127
+ EM.next_tick { tick }
128
+ end
129
+ end
130
+
131
+ def tick
132
+ # Break early if nothing to do
133
+ return if @last_send + @retry_interval > Time.now
134
+ if @tries < @max_tries
135
+ send
136
+ else
137
+ fail 'retries exceeded'
138
+ end
139
+ end
140
+
141
+ def receive_answer(msg)
142
+ addrs = []
143
+ msg.each_answer do |name,ttl,data|
144
+ if data.kind_of?(Resolv::DNS::Resource::IN::A) ||
145
+ data.kind_of?(Resolv::DNS::Resource::IN::AAAA)
146
+ addrs << data.address.to_s
147
+ end
148
+ end
149
+
150
+ if addrs.empty?
151
+ fail "rcode=#{msg.rcode}"
152
+ else
153
+ succeed addrs
154
+ end
155
+ end
156
+
157
+ private
158
+
159
+ def send
160
+ @tries += 1
161
+ @last_send = Time.now
162
+ @socket.send_packet(packet.encode)
163
+ end
164
+
165
+ def id
166
+ begin
167
+ @id = rand(65535)
168
+ @socket.register_request(@id, self)
169
+ rescue RequestIdAlreadyUsed
170
+ retry
171
+ end unless defined?(@id)
172
+
173
+ @id
174
+ end
175
+
176
+ def packet
177
+ msg = Resolv::DNS::Message.new
178
+ msg.id = id
179
+ msg.rd = 1
180
+ msg.add_question @hostname, Resolv::DNS::Resource::IN::A
181
+ msg
182
+ end
183
+
184
+ end
185
+ end
186
+ end
data/lib/em/spawnable.rb CHANGED
@@ -45,15 +45,11 @@ module EventMachine
45
45
  end
46
46
  alias_method :resume, :notify
47
47
  alias_method :run, :notify # for formulations like (EM.spawn {xxx}).run
48
- #attr_accessor :receiver
49
48
 
50
- #--
51
- # I know I'm missing something stupid, but the inside of class << s
52
- # can't see locally-bound values. It can see globals, though.
53
49
  def set_receiver blk
54
- $em______tmpglobal = blk
55
- class << self
56
- define_method :call, $em______tmpglobal.dup
50
+ (class << self ; self ; end).class_eval do
51
+ remove_method :call if method_defined? :call
52
+ define_method :call, blk
57
53
  end
58
54
  end
59
55
 
data/lib/em/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module EventMachine
2
- VERSION = "1.0.0.beta.2"
2
+ VERSION = "1.0.0.beta.3"
3
3
  end
data/lib/eventmachine.rb CHANGED
@@ -12,7 +12,7 @@ else
12
12
  end
13
13
  end
14
14
 
15
- require "em/version"
15
+ require 'em/version'
16
16
  require 'em/deferrable'
17
17
  require 'em/future'
18
18
  require 'em/streamer'
@@ -29,9 +29,11 @@ require 'em/channel'
29
29
  require 'em/file_watch'
30
30
  require 'em/process_watch'
31
31
  require 'em/tick_loop'
32
+ require 'em/resolver'
32
33
 
33
34
  require 'shellwords'
34
35
  require 'thread'
36
+ require 'resolv'
35
37
 
36
38
  # == Introduction
37
39
  # EventMachine provides a fast, lightweight framework for implementing
@@ -122,7 +124,7 @@ require 'thread'
122
124
  # Interesting thought.
123
125
  #
124
126
  module EventMachine
125
- class <<self
127
+ class << self
126
128
  # Exposed to allow joining on the thread, when run in a multithreaded
127
129
  # environment. Performing other actions on the thread has undefined
128
130
  # semantics.
@@ -1373,7 +1375,7 @@ module EventMachine
1373
1375
  @wrapped_exception = $!
1374
1376
  EM.stop
1375
1377
  else
1376
- raise ConnectionNotBound, "recieved ConnectionUnbound for an unknown signature: #{conn_binding}"
1378
+ raise ConnectionNotBound, "received ConnectionUnbound for an unknown signature: #{conn_binding}"
1377
1379
  end
1378
1380
  end
1379
1381
  elsif opcode == ConnectionAccepted
@@ -1545,4 +1547,4 @@ end # module EventMachine
1545
1547
 
1546
1548
  # Save everyone some typing.
1547
1549
  EM = EventMachine
1548
- EM::P = EventMachine::Protocols
1550
+ EM::P = EventMachine::Protocols
data/lib/jeventmachine.rb CHANGED
@@ -187,7 +187,7 @@ module EventMachine
187
187
  end
188
188
  def self.get_peername sig
189
189
  if peer = @em.getPeerName(sig)
190
- Socket.pack_sockaddr_in *peer
190
+ Socket.pack_sockaddr_in(*peer)
191
191
  end
192
192
  end
193
193
  def self.attach_fd fileno, watch_mode
data/tasks/package.rake CHANGED
@@ -24,10 +24,12 @@ else
24
24
 
25
25
  Rake::ExtensionTask.new("rubyeventmachine", GEMSPEC) do |ext|
26
26
  ext.ext_dir = 'ext'
27
+ ext.source_pattern = '*.{h,c,cpp}'
27
28
  setup_cross_compilation(ext)
28
29
  end
29
30
  Rake::ExtensionTask.new("fastfilereaderext", GEMSPEC) do |ext|
30
31
  ext.ext_dir = 'ext/fastfilereader'
32
+ ext.source_pattern = '*.{h,c,cpp}'
31
33
  setup_cross_compilation(ext)
32
34
  end
33
35
  end
@@ -47,7 +49,8 @@ end
47
49
 
48
50
  task :cross_cxx do
49
51
  ENV['CROSS_COMPILING'] = 'yes'
50
- ENV['CXX'] = 'i386-mingw32-g++'
52
+ require 'rake/extensioncompiler'
53
+ ENV['CXX'] = "#{Rake::ExtensionCompiler.mingw_host}-g++"
51
54
  end
52
55
 
53
56
  if Rake::Task.task_defined?(:cross)
data/tasks/test.rake CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'rake/testtask'
2
2
 
3
3
  Rake::TestTask.new(:test) do |t|
4
+ t.libs << "tests"
4
5
  t.pattern = 'tests/**/test_*.rb'
5
6
  t.warning = true
6
7
  end
@@ -0,0 +1,55 @@
1
+ require 'lib/eventmachine'
2
+ require 'test/unit'
3
+ require 'rbconfig'
4
+ require 'socket'
5
+
6
+ Test::Unit::TestCase.class_eval do
7
+ class EMTestTimeout < StandardError ; end
8
+
9
+ def setup_timeout(timeout = TIMEOUT_INTERVAL)
10
+ EM.schedule {
11
+ EM.add_timer(timeout) {
12
+ raise EMTestTimeout, "Test was cancelled after #{timeout} seconds."
13
+ }
14
+ }
15
+ end
16
+
17
+ def port_in_use?(port, host="127.0.0.1")
18
+ s = TCPSocket.new(host, port)
19
+ s.close
20
+ s
21
+ rescue Errno::ECONNREFUSED
22
+ false
23
+ end
24
+
25
+ def next_port
26
+ @@port ||= 9000
27
+ begin
28
+ @@port += 1
29
+ end while port_in_use?(@@port)
30
+
31
+ @@port
32
+ end
33
+
34
+ def exception_class
35
+ jruby? ? NativeException : RuntimeError
36
+ end
37
+
38
+ module PlatformHelper
39
+ # http://blog.emptyway.com/2009/11/03/proper-way-to-detect-windows-platform-in-ruby/
40
+ def windows?
41
+ Config::CONFIG['host_os'] =~ /mswin|mingw/
42
+ end
43
+
44
+ # http://stackoverflow.com/questions/1342535/how-can-i-tell-if-im-running-from-jruby-vs-ruby/1685970#1685970
45
+ def jruby?
46
+ defined? JRUBY_VERSION
47
+ end
48
+ end
49
+
50
+ include PlatformHelper
51
+ extend PlatformHelper
52
+
53
+ # Tests run significantly slower on windows. YMMV
54
+ TIMEOUT_INTERVAL = windows? ? 1 : 0.25
55
+ end
data/tests/test_attach.rb CHANGED
@@ -1,31 +1,7 @@
1
- # $Id$
2
- #
3
- #----------------------------------------------------------------------------
4
- #
5
- # Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
6
- # Gmail: blackhedd
7
- #
8
- # This program is free software; you can redistribute it and/or modify
9
- # it under the terms of either: 1) the GNU General Public License
10
- # as published by the Free Software Foundation; either version 2 of the
11
- # License, or (at your option) any later version; or 2) Ruby's License.
12
- #
13
- # See the file COPYING for complete licensing information.
14
- #
15
- #---------------------------------------------------------------------------
16
- #
17
-
18
- $:.unshift "../lib"
19
- require 'eventmachine'
1
+ require 'em_test_helper'
20
2
  require 'socket'
21
- require 'test/unit'
22
-
23
3
 
24
4
  class TestAttach < Test::Unit::TestCase
25
-
26
- Host = "127.0.0.1"
27
- Port = 9550
28
-
29
5
  class EchoServer < EM::Connection
30
6
  def receive_data data
31
7
  send_data data
@@ -33,47 +9,51 @@ class TestAttach < Test::Unit::TestCase
33
9
  end
34
10
 
35
11
  class EchoClient < EM::Connection
36
- def initialize
12
+ def initialize socket
37
13
  self.notify_readable = true
38
- $sock.write("abc\n")
14
+ @socket = socket
15
+ @socket.write("abc\n")
39
16
  end
40
17
 
41
18
  def notify_readable
42
- $read = $sock.readline
19
+ $read = @socket.readline
43
20
  $fd = detach
44
21
  end
45
22
 
46
23
  def unbind
47
24
  EM.next_tick do
48
- $sock.write("def\n")
49
- EM.add_timer(0.1){ EM.stop }
25
+ @socket.write("def\n")
26
+ EM.add_timer(0.1) { EM.stop }
50
27
  end
51
28
  end
52
29
  end
53
30
 
54
31
  def setup
55
- $read, $write, $sock, $r, $w, $fd, $sock, $before, $after = nil
32
+ @port = next_port
33
+ $read, $r, $w, $fd = nil
56
34
  end
57
35
 
58
36
  def teardown
59
- [$read, $write, $sock, $r, $w, $fd, $sock, $before, $after].each do |io|
37
+ [$r, $w].each do |io|
60
38
  io.close rescue nil
61
39
  end
62
40
  end
63
41
 
64
42
  def test_attach
65
- EM.run{
66
- EM.start_server Host, Port, EchoServer
67
- $sock = TCPSocket.new Host, Port
68
- EM.watch $sock, EchoClient
43
+ socket = nil
44
+
45
+ EM.run {
46
+ EM.start_server "127.0.0.1", @port, EchoServer
47
+ socket = TCPSocket.new "127.0.0.1", @port
48
+ EM.watch socket, EchoClient, socket
69
49
  }
70
50
 
71
51
  assert_equal $read, "abc\n"
72
- unless defined? JRuby # jruby filenos are not real
73
- assert_equal $fd, $sock.fileno
52
+ unless jruby? # jruby filenos are not real
53
+ assert_equal $fd, socket.fileno
74
54
  end
75
- assert_equal false, $sock.closed?
76
- assert_equal $sock.readline, "def\n"
55
+ assert_equal false, socket.closed?
56
+ assert_equal socket.readline, "def\n"
77
57
  end
78
58
 
79
59
  module PipeWatch
@@ -96,6 +76,8 @@ class TestAttach < Test::Unit::TestCase
96
76
  end
97
77
 
98
78
  def test_set_readable
79
+ before, after = nil
80
+
99
81
  EM.run{
100
82
  $r, $w = IO.pipe
101
83
  c = EM.watch $r, PipeWatch do |con|
@@ -103,34 +85,42 @@ class TestAttach < Test::Unit::TestCase
103
85
  end
104
86
 
105
87
  EM.next_tick{
106
- $before = c.notify_readable?
88
+ before = c.notify_readable?
107
89
  c.notify_readable = true
108
- $after = c.notify_readable?
90
+ after = c.notify_readable?
109
91
  }
110
92
 
111
93
  $w.write("jkl\n")
112
94
  }
113
95
 
114
- assert !$before
115
- assert $after
96
+ assert !before
97
+ assert after
116
98
  assert_equal $read, "jkl\n"
117
99
  end
118
100
 
119
- module PipeReader
120
- def receive_data data
121
- $read = data
122
- EM.stop
101
+ def test_read_write_pipe
102
+ result = nil
103
+
104
+ pipe_reader = Module.new do
105
+ define_method :receive_data do |data|
106
+ result = data
107
+ EM.stop
108
+ end
123
109
  end
124
- end
125
110
 
126
- def test_read_write_pipe
127
- EM.run{
128
- $r, $w = IO.pipe
129
- EM.attach $r, PipeReader
130
- writer = EM.attach($w)
111
+ r,w = IO.pipe
112
+
113
+ EM.run {
114
+ EM.attach r, pipe_reader
115
+ writer = EM.attach(w)
131
116
  writer.send_data 'ghi'
117
+
118
+ # XXX: Process will hang in Windows without this line
119
+ writer.close_connection_after_writing
132
120
  }
133
121
 
134
- assert_equal $read, "ghi"
122
+ assert_equal "ghi", result
123
+ ensure
124
+ [r,w].each {|io| io.close rescue nil }
135
125
  end
136
- end
126
+ end