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

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 (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