From: Tomas Krizek Date: Thu, 15 Nov 2018 11:29:22 +0000 (+0100) Subject: pytests: import test_query_flood_no_recv X-Git-Tag: v3.2.0~18^2~36 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c65070e33c56ca3504806493282a3c5590f6adf3;p=thirdparty%2Fknot-resolver.git pytests: import test_query_flood_no_recv --- diff --git a/tests/pytests/test_conn_mgmt.py b/tests/pytests/test_conn_mgmt.py index ca796cb11..0253187df 100644 --- a/tests/pytests/test_conn_mgmt.py +++ b/tests/pytests/test_conn_mgmt.py @@ -120,24 +120,25 @@ def test_ignore_jumbo_message(kresd_sock): assert answer.id == msgid2 +def flood_buffer(msgcount): + flood_buff = bytes() + msgbuff, _ = utils.get_msgbuff() + noid_msgbuff = msgbuff[2:] + + def gen_msg(msgid): + return struct.pack("!H", len(msgbuff)) + struct.pack("!H", msgid) + noid_msgbuff + + for i in range(msgcount): + flood_buff += gen_msg(i) + return flood_buff + + def test_query_flood_close(make_kresd_sock): """ Test floods resolver with queries and closes the connection. Expected: resolver must not crash """ - def flood_buffer(msgcount): - flood_buff = bytes() - msgbuff, _ = utils.get_msgbuff() - noid_msgbuff = msgbuff[2:] - - def gen_msg(msgid): - return struct.pack("!H", len(msgbuff)) + struct.pack("!H", msgid) + noid_msgbuff - - for i in range(msgcount): - flood_buff += gen_msg(i) - return flood_buff - buff = flood_buffer(10000) sock1 = make_kresd_sock() sock1.sendall(buff) @@ -145,3 +146,26 @@ def test_query_flood_close(make_kresd_sock): sock2 = make_kresd_sock() utils.ping_alive(sock2) + + +def test_query_flood_no_recv(make_kresd_sock): + """Flood resolver with queries but don't read any data.""" + # A use-case for TCP_USER_TIMEOUT socket option? See RFC 793 and RFC 5482 + + # It seems it doesn't works as expected. libuv doesn't return any error + # (neither on uv_write() call, not in the callback) when kresd sends answers, + # so kresd can't recognize that client didn't read any answers. At a certain + # point, kresd stops receiving queries from the client (whilst client keep + # sending) and closes connection due to timeout. + + buff = flood_buffer(10000) + sock1 = make_kresd_sock() + end_time = time.time() + utils.MAX_TIMEOUT + + with utils.expect_kresd_close(rst_ok=True): # connection must be closed + while time.time() < end_time: + sock1.sendall(buff) + time.sleep(0.5) + + sock2 = make_kresd_sock() + utils.ping_alive(sock2) # resolver must stay alive diff --git a/tests/pytests/utils.py b/tests/pytests/utils.py index 97328d454..17e5ffc4f 100644 --- a/tests/pytests/utils.py +++ b/tests/pytests/utils.py @@ -84,9 +84,12 @@ def ping_alive(sock): @contextmanager -def expect_kresd_close(): +def expect_kresd_close(rst_ok=False): with pytest.raises(BrokenPipeError, message="kresd didn't close the connection"): try: yield except ConnectionResetError: - pytest.skip("kresd closed connection with TCP RST") + if rst_ok: + raise BrokenPipeError + else: + pytest.skip("kresd closed connection with TCP RST")