diff options
Diffstat (limited to 'test/pwrite_wrap.rb')
-rw-r--r-- | test/pwrite_wrap.rb | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/test/pwrite_wrap.rb b/test/pwrite_wrap.rb new file mode 100644 index 0000000..34d342a --- /dev/null +++ b/test/pwrite_wrap.rb @@ -0,0 +1,136 @@ +#!/usr/bin/env ruby +# -*- encoding: binary -*- +# Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> +# License: GPLv3 or later (see COPYING for details) +require 'test/test_helper' +require 'timeout' + +TEST_PROG = 'test/pwrite-wrap' +class TestPwriteWrap < Test::Unit::TestCase + def setup + @tmpdir = Dir.mktmpdir('cmogstored-pwrite-wrap-test') + @to_close = [] + @host = TEST_HOST + + srv = TCPServer.new(@host, 0) + @port = srv.addr[1] + srv.close + + srv = TCPServer.new(@host, 0) + @mgmt_port = srv.addr[1] + srv.close + + Dir.mkdir("#@tmpdir/dev666") + Dir.mkdir("#@tmpdir/dev333") + File.open("#@tmpdir/dev666/get.fid", "w") { |fp| + fp.seek(1000) + fp.write("\0") + } + + @err = Tempfile.new("stderr") + cmd = [ TEST_PROG, "--docroot=#@tmpdir", "--httplisten=#@host:#@port", + "--mgmtlisten=#@host:#@mgmt_port", "--maxconns=500" ] + + @slow_time = 5000 + if vg = ENV["VALGRIND"] + cmd = vg.split(/\s+/).concat(cmd) + # valgrind slows everything down, so increase the sleep time + @slow_time *= 2 + end + ENV["PWRITE_WRAP_SLOW_MSEC"] ||= (@slow_time * 2).to_s + @pid = fork { + $stderr.reopen(@err.path, "a") + @err.close + exec(*cmd) + } + @client = get_client + @mgmt_client = get_client(300, @mgmt_port) + @mgmt_client.write "server aio_threads = 1\r\n" + @mgmt_client.gets + warning = "fewer aio_threads(1) than devices(2)" + wait_for(30, warning) do + buf = File.read(@err.path) + if buf =~ /aio_threads/ + puts "BUF: #{buf}" + end + buf.include?(warning) + end + end + + def wait_for(sec, reason, res = 0.1) + stop = Time.now + sec + begin + return if yield + sleep res + end while Time.now < stop + assert false, reason + end + + def test_pwrite_slow_chunked + __test_pwrite_slow(true) + end + + def test_pwrite_slow_identity + __test_pwrite_slow(false) + end + + def __test_pwrite_slow(chunked) + Process.kill(:VTALRM, @pid) + t_yield + Process.kill(:TTIN, @pid) + wait_for(5, "enable slow knob") do + File.readlines(@err.path).grep(/knob set: slow/)[0] && + File.readlines(@err.path).grep(/flag set: slow/)[0] + end + + client_2 = get_client + + thr = Thread.new do + begin + size = 1024 * 1024 * 1024 * 10 + if chunked + @client.write("PUT /dev666/foo.fid HTTP/1.1\r\n" \ + "Host: example.com\r\n" \ + "Transfer-Encoding: chunked\r\n\r\n" \ + "#{'%x' % size}\r\n") + else + @client.write("PUT /dev666/foo.fid HTTP/1.0\r\n" \ + "Content-Length: #{size}\r\n\r\n") + end + IO.copy_stream("/dev/zero", @client, size) + rescue => err + end + err + end + + wait_for(5, "temporary file to exist", 0.05) do + Dir["#@tmpdir/dev666/foo.*tmp"][0] + end + t_yield + + # this should cause mog_ioq_contended to return true in http_put.c + a = Time.now + Timeout.timeout(@slow_time * 4) { + client_2.write("GET /dev666/get.fid HTTP/1.0\r\n\r\n") + assert_match(%r{HTTP/1\.1 200 OK}, client_2.gets) + } + diff = Time.now - a + assert_operator diff, :<, (@slow_time * 2), "diff=#{diff}" + @client.shutdown + thr.join + Process.kill(:TTOU, @pid) + wait_for(5, "clear slow flag") do + File.readlines(@err.path).grep(/flag set: slow/)[0] + 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) if $DEBUG + assert status.success?, status.inspect + end +end if File.exist?(TEST_PROG) |