Check that TCP_NODELAY is set on upstream sockets on reconnection
Also rationalize the test to see if a function has been called. Still not great, but getting there :)
This commit is contained in:
@@ -39,4 +39,9 @@ module LdPreload
|
|||||||
l.split(':').map { |i| i =~ /^\d+$/ ? i.to_i : i }
|
l.split(':').map { |i| i =~ /^\d+$/ ? i.to_i : i }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def assert_func_call(loglines, args, msg)
|
||||||
|
re = Regexp.new('^' + args.join(':'))
|
||||||
|
assert(loglines.any? { |l| l.match(re) }, msg)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@@ -26,7 +26,7 @@ int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t
|
|||||||
fn = getenv("OUTPUT_setsockopt_logger");
|
fn = getenv("OUTPUT_setsockopt_logger");
|
||||||
if ( fn != NULL && optval != NULL && optlen == 4) {
|
if ( fn != NULL && optval != NULL && optlen == 4) {
|
||||||
fd = fopen(fn,"a");
|
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);
|
fclose(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -147,45 +147,58 @@ module ProxyTests
|
|||||||
def test_write_request_retried_when_upstream_dies_partway
|
def test_write_request_retried_when_upstream_dies_partway
|
||||||
maker = make_fake_server
|
maker = make_fake_server
|
||||||
|
|
||||||
with_proxied_client(4096) do |client|
|
with_ld_preload('setsockopt_logger') do
|
||||||
server, sc1 = maker.value
|
with_proxied_client(4096) do |client|
|
||||||
|
server, sc1 = maker.value
|
||||||
|
|
||||||
# Send the read request to the proxy
|
# Send the read request to the proxy
|
||||||
client.write(0, (b * 4096))
|
client.write(0, (b * 4096))
|
||||||
|
|
||||||
# ensure we're given the read request
|
# ensure we're given the read request
|
||||||
req1 = sc1.read_request
|
req1 = sc1.read_request
|
||||||
assert_equal ::FlexNBD::REQUEST_MAGIC, req1[:magic]
|
assert_equal ::FlexNBD::REQUEST_MAGIC, req1[:magic]
|
||||||
assert_equal ::FlexNBD::REQUEST_WRITE, req1[:type]
|
assert_equal ::FlexNBD::REQUEST_WRITE, req1[:type]
|
||||||
assert_equal 0, req1[:from]
|
assert_equal 0, req1[:from]
|
||||||
assert_equal 4096, req1[:len]
|
assert_equal 4096, req1[:len]
|
||||||
data1 = sc1.read_data(4096)
|
data1 = sc1.read_data(4096)
|
||||||
assert_equal((b * 4096), data1, 'Data not proxied successfully')
|
assert_equal((b * 4096), data1, 'Data not proxied successfully')
|
||||||
|
|
||||||
# Kill the server again, now we're sure the read request has been sent once
|
# Read the setsockopt logs, so we can check that TCP_NODELAY is re-set
|
||||||
sc1.close
|
# later
|
||||||
|
read_ld_preload_log('setsockopt_logger')
|
||||||
|
|
||||||
# We expect the proxy to reconnect without our client doing anything.
|
# Kill the server again, now we're sure the read request has been sent once
|
||||||
sc2 = server.accept
|
sc1.close
|
||||||
sc2.write_hello
|
|
||||||
|
|
||||||
# And once reconnected, it should resend an identical request.
|
# We expect the proxy to reconnect without our client doing anything.
|
||||||
req2 = sc2.read_request
|
sc2 = server.accept
|
||||||
assert_equal req1, req2
|
sc2.write_hello
|
||||||
data2 = sc2.read_data(4096)
|
|
||||||
assert_equal data1, data2
|
|
||||||
|
|
||||||
# The reply should be proxied back to the client.
|
# And once reconnected, it should resend an identical request.
|
||||||
sc2.write_reply(req2[:handle])
|
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
|
# The reply should be proxied back to the client.
|
||||||
rsp = Timeout.timeout(15) { client.read_response }
|
sc2.write_reply(req2[:handle])
|
||||||
assert_equal ::FlexNBD::REPLY_MAGIC, rsp[:magic]
|
|
||||||
assert_equal 0, rsp[:error]
|
|
||||||
assert_equal req1[:handle], rsp[:handle]
|
|
||||||
|
|
||||||
sc2.close
|
# Check it to make sure it's correct
|
||||||
server.close
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@@ -1,8 +1,11 @@
|
|||||||
require 'test/unit'
|
require 'test/unit'
|
||||||
require 'environment'
|
require 'environment'
|
||||||
|
require 'ld_preload'
|
||||||
require 'proxy_tests'
|
require 'proxy_tests'
|
||||||
|
|
||||||
class TestProxyMode < Test::Unit::TestCase
|
class TestProxyMode < Test::Unit::TestCase
|
||||||
|
|
||||||
|
include LdPreload
|
||||||
include ProxyTests
|
include ProxyTests
|
||||||
|
|
||||||
def setup
|
def setup
|
||||||
|
@@ -188,11 +188,23 @@ class TestServeMode < Test::Unit::TestCase
|
|||||||
def test_server_sets_tcpkeepalive
|
def test_server_sets_tcpkeepalive
|
||||||
with_ld_preload('setsockopt_logger') do
|
with_ld_preload('setsockopt_logger') do
|
||||||
connect_to_server(&:close)
|
connect_to_server(&:close)
|
||||||
op = parse_ld_preload_logs('setsockopt_logger')
|
op = read_ld_preload_log('setsockopt_logger')
|
||||||
assert(op.any? { |e| e == ['setsockopt', Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, 1, 0] }, 'TCP Keepalive not successfully set')
|
assert_func_call(op,
|
||||||
assert(op.any? { |e| e == ['setsockopt', Socket::SOL_TCP, Socket::TCP_KEEPIDLE, 30, 0] }, 'TCP Keepalive idle timeout not set to 30s')
|
['setsockopt', '\d+',
|
||||||
assert(op.any? { |e| e == ['setsockopt', Socket::SOL_TCP, Socket::TCP_KEEPINTVL, 10, 0] }, 'TCP keepalive retry time not set to 10s')
|
Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, 1, 0],
|
||||||
assert(op.any? { |e| e == ['setsockopt', Socket::SOL_TCP, Socket::TCP_KEEPCNT, 3, 0] }, 'TCP keepalive count not set to 3')
|
'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
|
end
|
||||||
end
|
end
|
||||||
|
Reference in New Issue
Block a user