Skip to content

Commit

Permalink
Fix according review
Browse files Browse the repository at this point in the history
  • Loading branch information
EvgeniiMekhanik committed Feb 12, 2025
1 parent 2e7ff77 commit 6e0ff3d
Show file tree
Hide file tree
Showing 7 changed files with 250 additions and 187 deletions.
64 changes: 25 additions & 39 deletions cache/test_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from helpers import deproxy, error, remote
from helpers.control import Tempesta
from helpers.deproxy import HttpMessage
from http_general.test_headers import AssertTrailersInResponse
from test_suite import checks_for_tests as checks
from test_suite import marks, tester

Expand Down Expand Up @@ -2108,18 +2109,8 @@ def encode_chunked(self, data, chunk_size=256):
result += f"{chunk}\r\n"
return result + "0\r\n\r\n"

def __is_server(self, tr):
if tr.lower() == "server":
return True
return False

def __is_hbp(self, tr):
if tr.lower() == "connection" or tr.lower() == "keep-alive":
return True
return False

def start_and_check_first_response(
self, client_id, method, response, tr1, tr1_val, tr2, tr2_val, expected_status_code
self, client_id, method, response, tr1, tr1_val, tr2, tr2_val
):
self.start_all_services()
self.disable_deproxy_auto_parser()
Expand All @@ -2129,20 +2120,28 @@ def start_and_check_first_response(

client = self.get_client(client_id)
request = client.create_request(method=method, headers=[])
client.send_request(request, expected_status_code)
client.send_request(request, "200")

self.assertEqual(client.last_response.headers.get("Trailer"), tr1 + " " + tr2)

if not isinstance(client, DeproxyClientH2):
if method != "HEAD" and not self.__is_hbp(tr1) and not self.__is_server(tr1):
if (
method != "HEAD"
and not AssertTrailersInResponse.is_hop_byp_hop_header(tr1)
and not AssertTrailersInResponse.is_server(tr1)
):
self.assertEqual(
client.last_response.trailer.get(tr1),
tr1_val,
"Moved trailer header value mismatch the original one",
)
else:
self.assertFalse(client.last_response.trailer.get(tr1))
if method != "HEAD" and not self.__is_hbp(tr2) and not self.__is_server(tr2):
if (
method != "HEAD"
and not AssertTrailersInResponse.is_hop_byp_hop_header(tr2)
and not AssertTrailersInResponse.is_server(tr2)
):
self.assertEqual(
client.last_response.trailer.get(tr2),
tr2_val,
Expand All @@ -2154,24 +2153,24 @@ def start_and_check_first_response(
self.assertEqual(client.last_response.headers.get("Trailer"), tr1 + " " + tr2)
if tr1 == "hdr_and_trailer":
self.assertEqual(client.last_response.headers.get(tr1), "header")
elif not self.__is_server(tr1):
elif not AssertTrailersInResponse.is_server(tr1):
self.assertIsNone(client.last_response.headers.get(tr1))
else:
self.assertEqual(client.last_response.headers.get(tr1), "Tempesta FW/0.8.0")
if tr2 == "hdr_and_trailer":
self.assertEqual(client.last_response.headers.get(tr2), "header")
elif not self.__is_server(tr2):
elif not AssertTrailersInResponse.is_server(tr2):
self.assertIsNone(client.last_response.headers.get(tr2))
else:
self.assertEqual(client.last_response.headers.get(tr1), "Tempesta FW/0.8.0")
else:
if method != "HEAD" and not self.__is_hbp(tr1) and not self.__is_server(tr1):
if method != "HEAD" and not AssertTrailersInResponse.is_hop_byp_hop_header(tr1):
self.assertEqual(
client.last_response.headers.get(tr1),
tr1_val,
"Moved trailer header value mismatch the original one",
)
if method != "HEAD" and not self.__is_hbp(tr2) and not self.__is_server(tr2):
if method != "HEAD" and not AssertTrailersInResponse.is_hop_byp_hop_header(tr2):
self.assertEqual(
client.last_response.headers.get(tr2),
tr2_val,
Expand Down Expand Up @@ -2199,7 +2198,7 @@ def check_second_request(self, client_id, method, tr1, tr1_val, tr2, tr2_val):
self.assertTrue(val == tr1_val or val == "header")
count = count + 1
self.assertEqual(count, 2)
elif not self.__is_hbp(tr1):
elif not AssertTrailersInResponse.is_hop_byp_hop_header(tr1):
self.assertEqual(
client.last_response.headers.get(tr1),
tr1_val,
Expand All @@ -2220,7 +2219,7 @@ def check_second_request(self, client_id, method, tr1, tr1_val, tr2, tr2_val):
self.assertTrue(val == tr2_val or val == "header")
count = count + 1
self.assertEqual(count, 2)
elif not self.__is_hbp(tr2):
elif not AssertTrailersInResponse.is_hop_byp_hop_header(tr2):
self.assertEqual(
client.last_response.headers.get(tr2),
tr2_val,
Expand Down Expand Up @@ -2249,15 +2248,13 @@ class TestCacheResponseWithTrailers(TestCacheResponseWithTrailersBase):

@marks.Parameterize.expand(
[
marks.Param(name="GET_GET", method1="GET", method2="GET", expected_status_code="200"),
marks.Param(name="HEAD_GET", method1="HEAD", method2="GET", expected_status_code="200"),
marks.Param(name="GET_HEAD", method1="GET", method2="HEAD", expected_status_code="200"),
marks.Param(
name="HEAD_HEAD", method1="HEAD", method2="HEAD", expected_status_code="200"
),
marks.Param(name="GET_GET", method1="GET", method2="GET"),
marks.Param(name="HEAD_GET", method1="HEAD", method2="GET"),
marks.Param(name="GET_HEAD", method1="GET", method2="HEAD"),
marks.Param(name="HEAD_HEAD", method1="HEAD", method2="HEAD"),
]
)
def test(self, name, method1, method2, expected_status_code):
def test(self, name, method1, method2):
self.start_and_check_first_response(
client_id="deproxy",
method=method1,
Expand All @@ -2275,7 +2272,6 @@ def test(self, name, method1, method2, expected_status_code):
tr1_val="value1",
tr2="X-Token2",
tr2_val="value2",
expected_status_code=expected_status_code,
)

self.check_second_request(
Expand Down Expand Up @@ -2305,7 +2301,6 @@ def test_empty_body_head_to_get(self):
tr1_val="value1",
tr2="X-Token2",
tr2_val="value2",
expected_status_code="200",
)

self.check_second_request(
Expand Down Expand Up @@ -2336,7 +2331,6 @@ def test_same_hdr_and_trailer_head_to_get(self):
tr1_val="trailer",
tr2="X-Token2",
tr2_val="value2",
expected_status_code="200",
)

self.check_second_request(
Expand Down Expand Up @@ -2366,7 +2360,6 @@ def test_same_trailer_head_to_get(self):
tr1_val="value1",
tr2="trailer_and_trailer",
tr2_val="value2",
expected_status_code="200",
)

self.check_second_request(
Expand Down Expand Up @@ -2401,7 +2394,6 @@ def test_server_in_trailers(self, name, method1, method2):
tr1_val="cloudfare",
tr2="X-Token2",
tr2_val="value2",
expected_status_code="200",
)

self.check_second_request(
Expand All @@ -2422,7 +2414,6 @@ def test_server_in_trailers(self, name, method1, method2):
tr1_val="keep-alive",
tr2="X-Token1",
tr2_val="value1",
expected_status_code="200",
),
marks.Param(
name="hbp_GET",
Expand All @@ -2431,7 +2422,6 @@ def test_server_in_trailers(self, name, method1, method2):
tr1_val="keep-alive",
tr2="Keep-Alive",
tr2_val="timeout=5, max=100",
expected_status_code="200",
),
marks.Param(
name="mix_HEAD",
Expand All @@ -2440,7 +2430,6 @@ def test_server_in_trailers(self, name, method1, method2):
tr1_val="keep-alive",
tr2="X-Token1",
tr2_val="value1",
expected_status_code="200",
),
marks.Param(
name="hbp_HEAD",
Expand All @@ -2449,11 +2438,10 @@ def test_server_in_trailers(self, name, method1, method2):
tr1_val="keep-alive",
tr2="Keep-Alive",
tr2_val="timeout=5, max=100",
expected_status_code="200",
),
]
)
def test_hbp_headers(self, name, method, tr1, tr1_val, tr2, tr2_val, expected_status_code):
def test_hbp_headers(self, name, method, tr1, tr1_val, tr2, tr2_val):
self.start_and_check_first_response(
client_id="deproxy",
method=method,
Expand All @@ -2471,7 +2459,6 @@ def test_hbp_headers(self, name, method, tr1, tr1_val, tr2, tr2_val, expected_st
tr1_val=tr1_val,
tr2=tr2,
tr2_val=tr2_val,
expected_status_code=expected_status_code,
)

self.check_second_request(
Expand Down Expand Up @@ -2551,7 +2538,6 @@ def test(self, name, client_id1, client_id2, method):
tr1_val="value1",
tr2="X-Token2",
tr2_val="value2",
expected_status_code="200",
)
self.check_second_request(
client_id=client_id2,
Expand Down
12 changes: 11 additions & 1 deletion framework/deproxy_auto_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import sys

import run_config
from framework.deproxy_client import BaseDeproxyClient
from framework.deproxy_client import BaseDeproxyClient, DeproxyClient, DeproxyClientH2
from framework.deproxy_manager import DeproxyManager
from helpers.deproxy import (
H2Request,
Expand Down Expand Up @@ -199,10 +199,20 @@ def __prepare_hop_by_hop_headers(self, message: HttpMessage) -> None:
4,
self.__dbg_msg.format("Remove hop-by-hop headers from expected response/request"),
)
connection = message.headers.get("connection")
if connection:
connection = connection.split(" ")
for hdr in connection:
message.trailer.delete_all(hdr.lower())

message.headers.delete_all("connection")
message.headers.delete_all("keep-alive")
message.headers.delete_all("proxy-connection")
message.headers.delete_all("upgrade")
message.trailer.delete_all("connection")
message.trailer.delete_all("keep-alive")
message.trailer.delete_all("proxy-connection")
message.trailer.delete_all("upgrade")

def __prepare_chunked_expected_response(self, expected_response: Response | H2Response) -> None:
"""
Expand Down
8 changes: 5 additions & 3 deletions helpers/deproxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -423,15 +423,15 @@ def read_chunked_body(self, stream):
raise ParseError("Error in chunked body")

"""
if trailer is not present don't pass the last CRLF to parse_trailer,
we must append it to body
If trailer is not present don't pass the last CRLF to parse_trailer.
"""
pos = stream.tell()
end = stream.read(2)
if end and end.rstrip("\r\n") == "":
self.body += end
if 2 != self.body[-3:].count("\n"):
raise IncompleteMessage("Incomplete chunked body.")
self.body = self.body[:-2]
return
elif end == "":
raise IncompleteMessage("Incomplete last CRLF in chunked body.")
Expand Down Expand Up @@ -994,7 +994,9 @@ def bind(self, address: tuple):
return super().bind(address)
# When we cannot bind an address, adding more details
except OSError as os_exc:
os_err_msg = f"Cannot assign an address `{str(address)}` for `{self.__class__.__name__}`"
os_err_msg = (
f"Cannot assign an address `{str(address)}` for `{self.__class__.__name__}`"
)
tf_cfg.dbg(6, os_err_msg)
raise OSError(os_err_msg) from os_exc

Expand Down
63 changes: 49 additions & 14 deletions helpers/networker.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@


class NetWorker:
def _get_ipv6_addr(self, dev):
@staticmethod
def _get_ipv6_addr(dev):
was_found = False
cmd = f"ip -6 addr show dev {dev} | grep inet6"
out = remote.client.run_cmd(cmd)
Expand All @@ -23,32 +24,66 @@ def _get_ipv6_addr(self, dev):
return val.split("/")
return None

def _set_ipv6_addr(self, dev, addr, prefix):
@staticmethod
def _set_ipv6_addr(dev, addr, prefix):
cmd = f"ip -6 addr add {addr}/{prefix} dev {dev}"
out = remote.client.run_cmd(cmd)

def get_dev(self):
@staticmethod
def _get_dev():
dev = sysnet.route_dst_ip(remote.client, tf_cfg.cfg.get("Tempesta", "ip"))
return dev

def get_ipv6_addr(self, dev):
return self._get_ipv6_addr(dev)

def set_ipv6_addr(self, dev, ipv6_addr):
self._set_ipv6_addr(dev, ipv6_addr[0], ipv6_addr[1])

def _get_state(self, dev, what):
@staticmethod
def _get_state(dev, what):
cmd = f"ethtool --show-features {dev} | grep {what}"
out = remote.client.run_cmd(cmd)
return out[0].decode("utf-8").split(" ")[-1].strip("\n")

def _set_state(self, dev, what, on=True):
@staticmethod
def _set_state(dev, what, on=True):
if on:
cmd = f"ethtool -K {dev} {what} on"
else:
cmd = f"ethtool -K {dev} {what} off"
out = remote.client.run_cmd(cmd)

@staticmethod
def __protect_ipv6_addr_on_dev(func, *args, **kwargs):
dev = NetWorker._get_dev()
cmd = f"ip -6 addr show dev {dev} | grep inet6"
ipv6_addr = None
was_found = False

try:
out = remote.client.run_cmd(cmd)
out = out[0].decode("utf-8").split(" ")
for val in out:
if val == "inet6":
was_found = True
# Next value is address
continue
if was_found:
ipv6_addr = val.split("/")
break
return func(*args, **kwargs)
finally:
if ipv6_addr:
cmd = f"ip -6 addr add {ipv6_addr[0]}/{ipv6_addr[1]} dev {dev}"
remote.client.run_cmd(cmd)

@staticmethod
def protect_ipv6_addr_on_dev(func):
"""The decorator protect ipv6 device settings."""

def func_wrapper(*args, **kwargs):
return NetWorker.__protect_ipv6_addr_on_dev(func, *args, **kwargs)

# we need to change name of function to work correctly with parametrize
func_wrapper.__name__ = func.__name__

return func_wrapper

def mtu_ctx(self, node, dev, mtu):
try:
yield
Expand Down Expand Up @@ -102,7 +137,7 @@ def run_test_tso_gro_gso(
# interface, so, regardless where the Tempesta node resides, we can
# change MTU on the local interface only to get the same MTU for
# both the client and server connections.
dev = self.get_dev()
dev = NetWorker._get_dev()
prev_mtu = sysnet.change_mtu(remote.client, dev, mtu)
except Exception as err:
self.fail(err)
Expand All @@ -114,7 +149,7 @@ def run_test_tso_gro_gso(
self.change_gro(dev, gro)
self.change_gso(dev, gso)
if option_name and option_val:
self._get_tcp_option(option_name)
NetWorker._get_tcp_option(option_name)
self._set_tcp_option(option_name, option_val)

test(client, server)
Expand All @@ -137,7 +172,7 @@ def run_test_tso_gro_gso_def(
self, client, server, test, mtu, option_name=None, option_val=None
):
try:
dev = self.get_dev()
dev = self._get_dev()
except Exception as err:
self.fail(err)

Expand Down
Loading

0 comments on commit 6e0ff3d

Please sign in to comment.