From 34df0f5c7fd618b020bb317a7b7f5ac25333c7e9 Mon Sep 17 00:00:00 2001 From: Roman Date: Mon, 3 Mar 2025 00:33:41 +0000 Subject: [PATCH] test: spam protection random bytes single burst - prevent false positives --- src/libs/common.py | 5 ++- src/steps/da.py | 8 ++-- tests/dos_robustness/dos_robustness.py | 52 +++++++++++++++++++------- 3 files changed, 47 insertions(+), 18 deletions(-) diff --git a/src/libs/common.py b/src/libs/common.py index 60e69ae..4d6184d 100644 --- a/src/libs/common.py +++ b/src/libs/common.py @@ -46,8 +46,9 @@ def random_divide_k(n, k): cuts = sorted(random.sample(range(1, n), k - 1)) parts = [cuts[0]] + [cuts[i] - cuts[i - 1] for i in range(1, len(cuts))] + [n - cuts[-1]] return parts - + def generate_random_bytes(n=31): + if n < 0: + raise ValueError("Input must be an unsigned integer (non-negative)") return os.urandom(n) - diff --git a/src/steps/da.py b/src/steps/da.py index 66fddff..53a04ed 100644 --- a/src/steps/da.py +++ b/src/steps/da.py @@ -96,10 +96,12 @@ class StepsDataAvailability(StepsCommon): except Exception as ex: assert "Bad Request" in str(ex) or "Internal Server Error" in str(ex) - assert response.status_code == 200, "Send dispersal finished with unexpected response code" + assert hasattr(response, "status_code"), "Missing status_code" + assert response.status_code in (200, 429), "Unexpected status code" - disperse() + return response + return disperse() @allure.step def get_data_range(self, node, app_id, start, end, timeout_duration=45): @@ -116,4 +118,4 @@ class StepsDataAvailability(StepsCommon): return response - get_range() + return get_range() diff --git a/tests/dos_robustness/dos_robustness.py b/tests/dos_robustness/dos_robustness.py index 04391db..c3884b7 100644 --- a/tests/dos_robustness/dos_robustness.py +++ b/tests/dos_robustness/dos_robustness.py @@ -1,6 +1,7 @@ +import random import pytest -from src.libs.common import delay, to_app_id, to_index, random_divide_k +from src.libs.common import delay, to_app_id, to_index, random_divide_k, generate_random_bytes from src.libs.custom_logger import get_custom_logger from src.steps.da import StepsDataAvailability from src.test_data import DATA_TO_DISPERSE @@ -17,11 +18,11 @@ class TestDosRobustness(StepsDataAvailability): missing_dispersals = num_samples for i in range(num_samples): try: - self.disperse_data(DATA_TO_DISPERSE[i], to_app_id(1), to_index(0), timeout_duration=0) - missing_dispersals -= 1 + response = self.disperse_data(DATA_TO_DISPERSE[i], to_app_id(1), to_index(0), timeout_duration=0) + if response.status_code == 200: + missing_dispersals -= 1 except Exception as ex: - logger.error(f"Dispersal #{i+1} was not successful with error {ex}") - break + raise Exception(f"Dispersal #{i+1} was not successful with error {ex}") delay(0.1) @@ -34,11 +35,34 @@ class TestDosRobustness(StepsDataAvailability): successful_dispersals = 0 for i in range(spam_per_burst): try: - self.disperse_data(DATA_TO_DISPERSE[0], to_app_id(1), to_index(0), timeout_duration=0) - successful_dispersals = i + response = self.disperse_data(DATA_TO_DISPERSE[0], to_app_id(1), to_index(0), timeout_duration=0) + if response.status_code == 429: + break + else: + successful_dispersals += 1 except Exception as ex: - logger.debug(f"Dispersal #{i+1} was not successful with error {ex}") - break + raise Exception(f"Dispersal #{i+1} was not successful with error {ex}") + + assert successful_dispersals <= rate_limit, "All consecutive dispersals were successful without any constraint" + + @pytest.mark.usefixtures("setup_2_node_cluster") + def test_spam_protection_random_bytes_single_burst(self): + rate_limit = 1000 + spam_per_burst = rate_limit + 10 + + n = random.randint(1, 256) + data_to_disperse = generate_random_bytes(n) + + successful_dispersals = 0 + for i in range(spam_per_burst): + try: + response = self.disperse_data(data_to_disperse, to_app_id(1), to_index(0), timeout_duration=0, utf8=False) + if response.status_code == 429: + break + else: + successful_dispersals += 1 + except Exception as ex: + raise Exception(f"Dispersal #{i+1} was not successful with error {ex}") assert successful_dispersals <= rate_limit, "All consecutive dispersals were successful without any constraint" @@ -57,11 +81,13 @@ class TestDosRobustness(StepsDataAvailability): for b in range(bursts): for i in range(spam_per_burst): try: - self.disperse_data(DATA_TO_DISPERSE[0], to_app_id(1), to_index(0), timeout_duration=0) - successful_dispersals = i + response = self.disperse_data(DATA_TO_DISPERSE[7], to_app_id(1), to_index(0), timeout_duration=0) + if response.status_code == 429: + break + else: + successful_dispersals += 1 except Exception as ex: - logger.debug(f"Dispersal #{i+1} was not successful with error {ex}") - break + raise Exception(f"Dispersal #{i+1} was not successful with error {ex}") delay(waiting_intervals[b])