diff options
Diffstat (limited to 'test/epoll_enospc.rb')
-rw-r--r-- | test/epoll_enospc.rb | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/test/epoll_enospc.rb b/test/epoll_enospc.rb new file mode 100644 index 0000000..5c254c0 --- /dev/null +++ b/test/epoll_enospc.rb @@ -0,0 +1,100 @@ +#!/usr/bin/env ruby +# -*- encoding: binary -*- +# Copyright (C) 2012-2013, Eric Wong <normalperson@yhbt.net> +# License: GPLv3 or later (see COPYING for details) +require 'test/test_helper' + +TEST_PROG = 'test/epoll-wrap' +has_epoll = false +if File.exist?(TEST_PROG) && `which lsof 2>/dev/null`.strip.size > 0 + s = `strings test/epoll-wrap`.split(/\n/) + has_epoll = !!s.grep(/epoll_ctl failure injection/)[0] +end + +class TestEpollEnospc < Test::Unit::TestCase + def setup + @tmpdir = Dir.mktmpdir('cmogstored-epoll-enospc-test') + @to_close = [] + @host = TEST_HOST + srv = TCPServer.new(@host, 0) + @port = srv.addr[1] + srv.close + @err = Tempfile.new("stderr") + cmd = [ TEST_PROG, "--docroot=#@tmpdir", "--httplisten=#@host:#@port", + "--maxconns=500" ] + vg = ENV["VALGRIND"] and cmd = vg.split(/\s+/).concat(cmd) + @pid = fork { + $stderr.reopen(@err) + @err.close + exec(*cmd) + } + @client = get_client + end + + def wait_for(sec, reason) + stop = Time.now + sec + begin + return if yield + sleep 0.1 + end while Time.now < stop + assert false, reason + end + + def test_close_file + sparse_file_prepare + @client.write "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n" + buf = @client.readpartial(1000) + assert_match(/\r\n\r\n\z/, buf) + Process.kill(:TTIN, @pid) + + wait_for(5, "ENOSPC injection signal") do + File.readlines(@err.path).grep(/ENOSPC on/)[0] + end + @client.write("GET /dev666/sparse-file.fid HTTP/1.1\r\n" \ + "Host: example.com\r\n\r\n") + sleep 1 + bytes = 0 + buf = "" + begin + bytes += @client.readpartial(666666, buf).bytesize + rescue EOFError + break + end while true + + wait_for(5, "failure injection message") do + File.readlines(@err.path).grep(/epoll_ctl failure injection/)[0] + end + + wait_for(5, "sparse file close") do + `lsof -p #@pid` !~ /sparse-file\.fid/ + end + end + + def teardown + Process.kill(:QUIT, @pid) rescue nil + _, status = Process.waitpid2(@pid) + @to_close.each { |io| io.close unless io.closed? } + FileUtils.rm_rf(@tmpdir) + @err.rewind + #$stderr.write(@err.read) + assert status.success?, status.inspect + end + + def sparse_file_prepare(big = nil) + Dir.mkdir("#@tmpdir/dev666") + if nil == big + big = 1024 * 1024 * 500 # only 500M + big /= 10 if ENV["VALGRIND"] # valgrind slows us down enough :P + end + File.open("#@tmpdir/dev666/sparse-file.fid", "w") do |fp| + begin + fp.seek(big - 1) + rescue Errno::EINVAL, Errno::ENOSPC + big /= 2 + warn "trying large file size: #{big}" + retry + end + fp.write('.') + end + end +end if has_epoll |