Everyone,
I’d like to write a test that ensures a Server application correctly
handles closed client connections – more specifically: I want to set
up a TCPServer, then a client, then close the client, then attempt to
write on the client Connection from server side – and make sure no
Error gets fired.
To my great surprise, the test doesn’t behave in any predictible way
– sometimes it passes, sometimes it fails.
I’ve written a piece of code that illustrates it:
require ‘socket’
consecutive_puts_to_attempt = 1
ok_counter = 0
error_counter = 0
10000.times do
server = TCPServer.open ‘127.0.0.1’, 4807
client = TCPSocket.open ‘127.0.0.1’, 4807
connection = server.accept
client.close
begin
consecutive_puts_to_attempt.times {connection.puts “Hello!”}
ok_counter += 1
rescue
error_counter += 1
end
server.close
end
puts “(Unexpectedly) passed #{ok_counter} times;”
puts “(correctly) failed #{error_counter} times.”
Statistically, this piece of code unexpectedly passes with no raised
error about 98% of the time. Errors are Errno::EPIPE and
Errno::ECONNRESET
When I fiddle with consecutive_puts_to_attempt value, the number of
expected raised errors changes –
puts attempts chances of raised error
1 2%
2 98%
3 98.5%
4 99%
Here is my environment:
ruby -v
ruby 1.8.6 (2007-03-13 patchlevel 0) [i686-darwin8.10.1]
Any idea of what’s going on?
Any suggestion about how I could make this piece of code predictible?
– Emmanuel.