From c297d48713553e57cf880f29d67dc97c3a2ebe0e Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Thu, 27 May 2010 19:20:04 +0000 Subject: [PATCH] test for non-blocking, non-pipe descriptor --- test/test_io_splice.rb | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/test/test_io_splice.rb b/test/test_io_splice.rb index e975c06..21b990f 100644 --- a/test/test_io_splice.rb +++ b/test/test_io_splice.rb @@ -1,9 +1,53 @@ # -*- encoding: binary -*- require 'test/unit' require 'tempfile' +require 'socket' +require 'io/nonblock' $-w = true require 'io/splice' +# unused_port provides an unused port on +addr+ usable for TCP that is +# guaranteed to be unused across all unicorn builds on that system. It +# prevents race conditions by using a lock file other unicorn builds +# will see. This is required if you perform several builds in parallel +# with a continuous integration system or run tests in parallel via +# gmake. This is NOT guaranteed to be race-free if you run other +# processes that bind to random ports for testing (but the window +# for a race condition is very small). +def unused_port(addr = '127.0.0.1') + retries = 100 + base = 5000 + port = sock = nil + begin + begin + port = base + rand(32768 - base) + while port == 8080 + port = base + rand(32768 - base) + end + + sock = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0) + sock.bind(Socket.pack_sockaddr_in(port, addr)) + sock.listen(5) + rescue Errno::EADDRINUSE, Errno::EACCES + sock.close rescue nil + retry if (retries -= 1) >= 0 + end + + # since we'll end up closing the random port we just got, there's a race + # condition could allow the random port we just chose to reselect itself + # when running tests in parallel with gmake. Create a lock file while + # we have the port here to ensure that does not happen . + lock_path = "#{Dir::tmpdir}/unicorn_test.#{addr}:#{port}.lock" + lock = File.open(lock_path, File::WRONLY|File::CREAT|File::EXCL, 0600) + at_exit { File.unlink(lock_path) rescue nil } + rescue Errno::EEXIST + sock.close rescue nil + retry + end + sock.close rescue nil + port +end + class Test_IO_Splice < Test::Unit::TestCase def test_splice @@ -109,6 +153,17 @@ class Test_IO_Splice < Test::Unit::TestCase } end + def test_splice_nonblock_socket + port = unused_port + server = TCPServer.new('127.0.0.1', port) + rp, wp = IO.pipe + rs = TCPSocket.new('127.0.0.1', port) + rs.nonblock = true + assert_raises(Errno::EAGAIN) { IO.splice(rs, nil, wp, nil, 1024, 0) } + rs.close + server.close + end + def test_tee str = 'abcde' size = 5 -- 2.11.4.GIT