require 'em_test_helper' require 'socket' class TestBasic < Test::Unit::TestCase def setup @port = next_port end def test_connection_class_cache mod = Module.new a, b = nil, nil EM.run { EM.start_server '127.0.0.1', @port, mod a = EM.connect '127.0.0.1', @port, mod b = EM.connect '127.0.0.1', @port, mod EM.stop } assert_equal a.class, b.class assert_kind_of EM::Connection, a end #------------------------------------- def test_em assert_nothing_raised do EM.run { setup_timeout EM.add_timer 0 do EM.stop end } end end #------------------------------------- def test_timer assert_nothing_raised do EM.run { setup_timeout n = 0 EM.add_periodic_timer(0.1) { n += 1 EM.stop if n == 2 } } end end #------------------------------------- # This test once threw an already-running exception. module Trivial def post_init EM.stop end end def test_server assert_nothing_raised do EM.run { setup_timeout EM.start_server "127.0.0.1", @port, Trivial EM.connect "127.0.0.1", @port } end end #-------------------------------------- # EM#run_block starts the reactor loop, runs the supplied block, and then STOPS # the loop automatically. Contrast with EM#run, which keeps running the reactor # even after the supplied block completes. def test_run_block assert !EM.reactor_running? a = nil EM.run_block { a = "Worked" } assert a assert !EM.reactor_running? end class UnbindError < EM::Connection ERR = Class.new(StandardError) def initialize *args super end def connection_completed close_connection_after_writing end def unbind raise ERR end end def test_unbind_error_during_stop assert_raises( UnbindError::ERR ) { EM.run { EM.start_server "127.0.0.1", @port EM.connect "127.0.0.1", @port, UnbindError do EM.stop end } } end def test_unbind_error EM.run { EM.error_handler do |e| assert(e.is_a?(UnbindError::ERR)) EM.stop end EM.start_server "127.0.0.1", @port EM.connect "127.0.0.1", @port, UnbindError } # Remove the error handler before the next test EM.error_handler(nil) end module BrsTestSrv def receive_data data $received << data end def unbind EM.stop end end module BrsTestCli def post_init send_data $sent close_connection_after_writing end end # From ticket #50 def test_byte_range_send $received = '' $sent = (0..255).to_a.pack('C*') EM::run { EM::start_server "127.0.0.1", @port, BrsTestSrv EM::connect "127.0.0.1", @port, BrsTestCli setup_timeout } assert_equal($sent, $received) end def test_bind_connect pend('FIXME: this test is broken on Windows') if windows? local_ip = UDPSocket.open {|s| s.connect('localhost', 80); s.addr.last } bind_port = next_port port, ip = nil bound_server = Module.new do define_method :post_init do begin port, ip = Socket.unpack_sockaddr_in(get_peername) ensure EM.stop end end end EM.run do setup_timeout EM.start_server "127.0.0.1", @port, bound_server EM.bind_connect local_ip, bind_port, "127.0.0.1", @port end assert_equal bind_port, port assert_equal local_ip, ip end def test_invalid_address_bind_connect_dst e = nil EM.run do begin EM.bind_connect('localhost', nil, 'invalid.invalid', 80) rescue Exception => e # capture the exception ensure EM.stop end end assert_kind_of(EventMachine::ConnectionError, e) assert_match(/unable to resolve address:.*not known/, e.message) end def test_invalid_address_bind_connect_src e = nil EM.run do begin EM.bind_connect('invalid.invalid', nil, 'localhost', 80) rescue Exception => e # capture the exception ensure EM.stop end end assert_kind_of(EventMachine::ConnectionError, e) assert_match(/invalid bind address:.*not known/, e.message) end def test_reactor_thread? assert !EM.reactor_thread? EM.run { assert EM.reactor_thread?; EM.stop } assert !EM.reactor_thread? end def test_schedule_on_reactor_thread x = false EM.run do EM.schedule { x = true } EM.stop end assert x end def test_schedule_from_thread x = false EM.run do Thread.new { EM.schedule { x = true; EM.stop } }.join end assert x end def test_set_heartbeat_interval omit_if(jruby?) interval = 0.5 EM.run { EM.set_heartbeat_interval interval $interval = EM.get_heartbeat_interval EM.stop } assert_equal(interval, $interval) end module PostInitRaiser ERR = Class.new(StandardError) def post_init raise ERR end end def test_bubble_errors_from_post_init assert_raises(PostInitRaiser::ERR) do EM.run do EM.start_server "127.0.0.1", @port EM.connect "127.0.0.1", @port, PostInitRaiser end end end module InitializeRaiser ERR = Class.new(StandardError) def initialize raise ERR end end def test_bubble_errors_from_initialize assert_raises(InitializeRaiser::ERR) do EM.run do EM.start_server "127.0.0.1", @port EM.connect "127.0.0.1", @port, InitializeRaiser end end end def test_schedule_close omit_if(jruby?) localhost, port = '127.0.0.1', 9000 timer_ran = false num_close_scheduled = nil EM.run do assert_equal 0, EM.num_close_scheduled EM.add_timer(1) { timer_ran = true; EM.stop } EM.start_server localhost, port do |s| s.close_connection num_close_scheduled = EM.num_close_scheduled end EM.connect localhost, port do |c| def c.unbind EM.stop end end end assert !timer_ran assert_equal 1, num_close_scheduled end def test_error_handler_idempotent # issue 185 errors = [] ticks = [] EM.error_handler do |e| errors << e end EM.run do EM.next_tick do ticks << :first raise end EM.next_tick do ticks << :second end EM.add_timer(0.001) { EM.stop } end # Remove the error handler before the next test EM.error_handler(nil) assert_equal 1, errors.size assert_equal [:first, :second], ticks end end