diff --git a/tests/acceptance/ld_preload.rb b/tests/acceptance/ld_preload.rb index 6ebf3cc..8ce0a8f 100644 --- a/tests/acceptance/ld_preload.rb +++ b/tests/acceptance/ld_preload.rb @@ -39,4 +39,9 @@ module LdPreload l.split(':').map { |i| i =~ /^\d+$/ ? i.to_i : i } end end + + def assert_func_call(loglines, args, msg) + re = Regexp.new('^' + args.join(':')) + assert(loglines.any? { |l| l.match(re) }, msg) + end end diff --git a/tests/acceptance/ld_preloads/setsockopt_logger.c b/tests/acceptance/ld_preloads/setsockopt_logger.c index 08f3142..9a7bf60 100644 --- a/tests/acceptance/ld_preloads/setsockopt_logger.c +++ b/tests/acceptance/ld_preloads/setsockopt_logger.c @@ -26,7 +26,7 @@ int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t fn = getenv("OUTPUT_setsockopt_logger"); if ( fn != NULL && optval != NULL && optlen == 4) { fd = fopen(fn,"a"); - fprintf(fd,"setsockopt:%d:%d:%i:%d\n", level, optname, *(int *)optval, retval); + fprintf(fd,"setsockopt:%d:%d:%d:%i:%d\n", sockfd, level, optname, *(int *)optval, retval); fclose(fd); } diff --git a/tests/acceptance/proxy_tests.rb b/tests/acceptance/proxy_tests.rb index 65fe38a..ab68f44 100644 --- a/tests/acceptance/proxy_tests.rb +++ b/tests/acceptance/proxy_tests.rb @@ -147,45 +147,58 @@ module ProxyTests def test_write_request_retried_when_upstream_dies_partway maker = make_fake_server - with_proxied_client(4096) do |client| - server, sc1 = maker.value + with_ld_preload('setsockopt_logger') do + with_proxied_client(4096) do |client| + server, sc1 = maker.value - # Send the read request to the proxy - client.write(0, (b * 4096)) + # Send the read request to the proxy + client.write(0, (b * 4096)) - # ensure we're given the read request - req1 = sc1.read_request - assert_equal ::FlexNBD::REQUEST_MAGIC, req1[:magic] - assert_equal ::FlexNBD::REQUEST_WRITE, req1[:type] - assert_equal 0, req1[:from] - assert_equal 4096, req1[:len] - data1 = sc1.read_data(4096) - assert_equal((b * 4096), data1, 'Data not proxied successfully') + # ensure we're given the read request + req1 = sc1.read_request + assert_equal ::FlexNBD::REQUEST_MAGIC, req1[:magic] + assert_equal ::FlexNBD::REQUEST_WRITE, req1[:type] + assert_equal 0, req1[:from] + assert_equal 4096, req1[:len] + data1 = sc1.read_data(4096) + assert_equal((b * 4096), data1, 'Data not proxied successfully') - # Kill the server again, now we're sure the read request has been sent once - sc1.close + # Read the setsockopt logs, so we can check that TCP_NODELAY is re-set + # later + read_ld_preload_log('setsockopt_logger') - # We expect the proxy to reconnect without our client doing anything. - sc2 = server.accept - sc2.write_hello + # Kill the server again, now we're sure the read request has been sent once + sc1.close - # And once reconnected, it should resend an identical request. - req2 = sc2.read_request - assert_equal req1, req2 - data2 = sc2.read_data(4096) - assert_equal data1, data2 + # We expect the proxy to reconnect without our client doing anything. + sc2 = server.accept + sc2.write_hello - # The reply should be proxied back to the client. - sc2.write_reply(req2[:handle]) + # And once reconnected, it should resend an identical request. + req2 = sc2.read_request + assert_equal req1, req2 + data2 = sc2.read_data(4096) + assert_equal data1, data2 - # Check it to make sure it's correct - rsp = Timeout.timeout(15) { client.read_response } - assert_equal ::FlexNBD::REPLY_MAGIC, rsp[:magic] - assert_equal 0, rsp[:error] - assert_equal req1[:handle], rsp[:handle] + # The reply should be proxied back to the client. + sc2.write_reply(req2[:handle]) - sc2.close - server.close + # Check it to make sure it's correct + rsp = Timeout.timeout(15) { client.read_response } + assert_equal ::FlexNBD::REPLY_MAGIC, rsp[:magic] + assert_equal 0, rsp[:error] + assert_equal req1[:handle], rsp[:handle] + + sc2.close + server.close + + # Check TCP_NODELAY was set on the upstream socket + log = read_ld_preload_log('setsockopt_logger') + assert_func_call(log, + ['setsockopt', 3, + Socket::SOL_TCP, Socket::TCP_NODELAY, 1, 0], + 'TCP_NODELAY not set on upstream fd 3') + end end end diff --git a/tests/acceptance/test_proxy_mode.rb b/tests/acceptance/test_proxy_mode.rb index 87d10e2..d2e98c1 100644 --- a/tests/acceptance/test_proxy_mode.rb +++ b/tests/acceptance/test_proxy_mode.rb @@ -1,8 +1,11 @@ require 'test/unit' require 'environment' +require 'ld_preload' require 'proxy_tests' class TestProxyMode < Test::Unit::TestCase + + include LdPreload include ProxyTests def setup diff --git a/tests/acceptance/test_serve_mode.rb b/tests/acceptance/test_serve_mode.rb index cc392d6..6c3e3f6 100644 --- a/tests/acceptance/test_serve_mode.rb +++ b/tests/acceptance/test_serve_mode.rb @@ -188,11 +188,23 @@ class TestServeMode < Test::Unit::TestCase def test_server_sets_tcpkeepalive with_ld_preload('setsockopt_logger') do connect_to_server(&:close) - op = parse_ld_preload_logs('setsockopt_logger') - assert(op.any? { |e| e == ['setsockopt', Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, 1, 0] }, 'TCP Keepalive not successfully set') - assert(op.any? { |e| e == ['setsockopt', Socket::SOL_TCP, Socket::TCP_KEEPIDLE, 30, 0] }, 'TCP Keepalive idle timeout not set to 30s') - assert(op.any? { |e| e == ['setsockopt', Socket::SOL_TCP, Socket::TCP_KEEPINTVL, 10, 0] }, 'TCP keepalive retry time not set to 10s') - assert(op.any? { |e| e == ['setsockopt', Socket::SOL_TCP, Socket::TCP_KEEPCNT, 3, 0] }, 'TCP keepalive count not set to 3') + op = read_ld_preload_log('setsockopt_logger') + assert_func_call(op, + ['setsockopt', '\d+', + Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, 1, 0], + 'TCP Keepalive not successfully set') + assert_func_call(op, + ['setsockopt', '\d+', + Socket::SOL_TCP, Socket::TCP_KEEPIDLE, 30, 0], + 'TCP Keepalive idle timeout not set to 30s') + assert_func_call(op, + ['setsockopt', '\d+', + Socket::SOL_TCP, Socket::TCP_KEEPINTVL, 10, 0], + 'TCP keepalive retry time not set to 10s') + assert_func_call(op, + ['setsockopt', '\d+', + Socket::SOL_TCP, Socket::TCP_KEEPCNT, 3, 0], + 'TCP keepalive count not set to 3') end end end