Ticket #34: test_lotsa_sockets.rb

File test_lotsa_sockets.rb, 4.5 kB (added by rogerdpack, 5 months ago)
Line 
1 # $Id: test_running.rb 493 2007-08-13 20:10:46Z blackhedd $
2
3 # Author:: Francis Cianfrocca (gmail: blackhedd)
4 # Homepage::  http://rubyeventmachine.com
5 # Date:: 8 April 2006
6 #
7 # See EventMachine and EventMachine::Connection for documentation and
8 # usage examples.
9 #
10 #----------------------------------------------------------------------------
11 #
12 # Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
13 # Gmail: blackhedd
14 #
15 # This program is free software; you can redistribute it and/or modify
16 # it under the terms of either: 1) the GNU General Public License
17 # as published by the Free Software Foundation; either version 2 of the
18 # License, or (at your option) any later version; or 2) Ruby's License.
19 #
20 # See the file COPYING for complete licensing information.
21 #
22 #---------------------------------------------------------------------------
23 #
24 #
25 #
26
27 $:.unshift "../lib"
28 require 'eventmachine'
29
30 class Echoer < EM::Connection
31   def receive_data m
32         send_data m
33   end
34  
35 end
36
37 class SenderCheckerAndCaller < EM::Connection
38         def send_and_receive_cycle string_to_send, proc_to_call_if_successfully_returns
39          @received_send_request = true
40          @string_sent = string_to_send
41          @return_proc = proc_to_call_if_successfully_returns
42          send_data string_to_send
43         end
44
45         def receive_data received
46          if received != @string_sent
47                 print 'arr! echoed wrong string!'
48                 raise
49          else
50            @return_proc.call
51          end
52         end
53
54         def setup_early_unbind proc_to_call_on_early_unbind
55                 @proc_to_call_on_early_unbind = proc_to_call_on_early_unbind
56         end
57
58         def unbind
59                 if !@proc_to_call_on_early_unbind
60                         print "arr no unbind proc!!!"
61                         dbg
62                 end
63                 @proc_to_call_on_early_unbind.call unless @received_send_request
64         end
65 end
66
67 require 'test/unit'
68
69 class TestSocketCounts < Test::Unit::TestCase
70         def setup # TODO right now these have to be run one at a time -- we need a suite
71         end
72        
73         def teardown
74                 EM.stop if EM::reactor_running?
75                 sleep 0.1 while EM::reactor_running?
76         end
77
78        def many_descriptors
79                 100.downto(1) do |n|
80                         if EventMachine.set_descriptor_table_size(n*1000) == n*1000
81                                 print n*1000, 'descriptors given! run sudo for possibly more!'
82                                 break
83                         end
84                 end
85         end
86
87         def test_select # needs to be run first or by itself, or it will have lots of descriptors possibly
88                 create_many_sockets
89         end
90
91         def test_epoll
92                 many_descriptors
93                 EM.epoll # todo could do epoll without lots of descriptors
94                 create_many_sockets
95         end
96
97         def test_select_lots_of_descriptors
98                 many_descriptors
99                 create_many_sockets
100         end
101
102         def test_kqueue
103                 many_descriptors
104                 EM.kqueue
105                 create_many_sockets
106         end
107        
108         def create_many_sockets
109                 # for this one, let's fire up all the sockets we can, then send something to each of them--the count should go up
110                 # todo throw some file descriptors in there, too, and some popen process, why not?
111                 # another test would be to have two processes, so you could test 'just server' and 'just client-side'
112                 # todo do this with some udp too (kinder lower priority, as UDP isn't as commonly used)
113                 all_connections = []
114                 server_port = 2051 + rand(1000)
115                 Thread.new {
116                         EM.run {
117                                 EM::start_server '0.0.0.0', server_port, Echoer
118                         }
119                 }
120                 sleep 0
121                 count_unbound_early = 0
122                 has_hit_error = false
123                 block_size = 10 # TODO if you move this up to 100 it seems to always fail.  Is this the sign of a bug, as well?
124                 while(!has_hit_error && count_unbound_early == 0) # not sure here
125                         starting_size = all_connections.length
126                         EM::next_tick {
127                                 begin
128                                         block_size.times {
129                                                 EM::connect( '127.0.0.1', server_port, SenderCheckerAndCaller ) { |conn|
130                                                         all_connections << conn
131                                                         conn.setup_early_unbind proc { count_unbound_early += 1}
132                                                 }
133                                         }
134                                 rescue RuntimeError
135                                         print "ok stopping their creation!\n"
136                                         has_hit_error = true # assume out of descriptors or slots for select or something
137                                 end
138                         }
139                         while all_connections.length < (starting_size + block_size) and (has_hit_error==false) # let next tick finish
140                                 sleep 0
141                                 print "length #{all_connections.length}, has #{has_hit_error}, unbound #{count_unbound_early}\n"
142                         end
143                 end
144                 sleep 0
145                 counter = 0
146                 for connection in all_connections
147                         connection.send_and_receive_cycle rand(1000000).to_s, proc {counter += 1}
148                 end
149                 sleep 1
150                 within = block_size == 1 ? 1 : block_size * 2
151                 flunk "got #{counter} responses when expected #{all_connections.length} (within #{within})" unless (all_connections.length - count_unbound_early) - counter <= within
152                 for conn in all_connections
153                         conn.close_connection
154                 end
155         end
156 end
157