This commit is contained in:
Andrey Berezin 2024-01-12 15:24:59 +03:00
parent a3bda0b34f
commit ee1f3ab0c1
2 changed files with 131 additions and 2 deletions

View file

@ -3,11 +3,28 @@ import os
from dataclasses import dataclass, field, fields, is_dataclass
from enum import Enum
from types import MappingProxyType
from typing import Any, Optional, get_args
from typing import Any, Callable, Optional, get_args
from frostfs_testlib.utils.converting_utils import calc_unit
def convert_time_to_seconds(time: int | str) -> int:
if time is None:
return None
if str(time).isdigit():
seconds = int(time)
else:
days, hours, minutes = 0, 0, 0
if "d" in time:
days, time = time.split("d")
if "h" in time:
hours, time = time.split("h")
if "min" in time:
minutes = time.replace("min", "")
seconds = int(days) * 86400 + int(hours) * 3600 + int(minutes) * 60
return seconds
class LoadType(Enum):
gRPC = "grpc"
S3 = "s3"
@ -76,6 +93,7 @@ def metadata_field(
scenario_variable: Optional[str] = None,
string_repr: Optional[bool] = True,
distributed: Optional[bool] = False,
formatter: Optional[Callable] = None,
):
return field(
default=None,
@ -85,6 +103,7 @@ def metadata_field(
"env_variable": scenario_variable,
"string_repr": string_repr,
"distributed": distributed,
"formatter": formatter,
},
)
@ -200,7 +219,9 @@ class LoadParams:
# ------- COMMON SCENARIO PARAMS -------
# Load time is the maximum duration for k6 to give load. Default is the BACKGROUND_LOAD_DEFAULT_TIME value.
load_time: Optional[int] = metadata_field(all_load_scenarios, None, "DURATION", False)
load_time: Optional[int] = metadata_field(
all_load_scenarios, None, "DURATION", False, formatter=convert_time_to_seconds
)
# Object size in KB for load and preset.
object_size: Optional[int] = metadata_field(all_load_scenarios, "size", "WRITE_OBJ_SIZE", False)
# For read operations, controls from which set get objects to read
@ -384,6 +405,25 @@ class LoadParams:
return fields_with_data or []
def _get_field_formatter(self, field_name: str) -> Callable | None:
data_fields = fields(self)
formatters = [
field.metadata["formatter"]
for field in data_fields
if field.name == field_name and "formatter" in field.metadata and field.metadata["formatter"] != None
]
if formatters:
return formatters[0]
return None
def __setattr__(self, field_name, value):
formatter = self._get_field_formatter(field_name)
if formatter:
value = formatter(value)
super().__setattr__(field_name, value)
def __str__(self) -> str:
load_type_str = self.scenario.value if self.scenario else self.load_type.value
# TODO: migrate load_params defaults to testlib

View file

@ -141,6 +141,8 @@ class TestLoadConfig:
"--workers '7'",
"--containers '16'",
"--policy 'container_placement_policy'",
"--ignore-errors",
"--sleep '19'",
]
expected_env_vars = {
"DURATION": 9,
@ -151,6 +153,7 @@ class TestLoadConfig:
"WRITERS": 7,
"READERS": 7,
"DELETERS": 8,
"READ_AGE": 8,
"PREGEN_JSON": "pregen_json",
"PREPARE_LOCALLY": True,
}
@ -167,6 +170,8 @@ class TestLoadConfig:
"--workers '7'",
"--containers '16'",
"--policy 'container_placement_policy'",
"--ignore-errors",
"--sleep '19'",
]
expected_env_vars = {
"DURATION": 9,
@ -184,6 +189,7 @@ class TestLoadConfig:
"TIME_UNIT": "time_unit",
"WRITE_RATE": 10,
"READ_RATE": 9,
"READ_AGE": 8,
"DELETE_RATE": 11,
"PREPARE_LOCALLY": True,
}
@ -201,6 +207,8 @@ class TestLoadConfig:
"--workers '7'",
"--buckets '13'",
"--location 's3_location'",
"--ignore-errors",
"--sleep '19'",
]
expected_env_vars = {
"DURATION": 9,
@ -211,6 +219,7 @@ class TestLoadConfig:
"WRITERS": 7,
"READERS": 7,
"DELETERS": 8,
"READ_AGE": 8,
"NO_VERIFY_SSL": True,
"PREGEN_JSON": "pregen_json",
}
@ -218,6 +227,44 @@ class TestLoadConfig:
self._check_preset_params(load_params, expected_preset_args)
self._check_env_vars(load_params, expected_env_vars)
@pytest.mark.parametrize("load_params", [LoadScenario.S3_CAR], indirect=True)
def test_argument_parsing_for_s3_car_scenario_with_stringed_time(self, load_params: LoadParams):
load_params.load_time = "2d3h5min"
expected_preset_args = [
"--size '11'",
"--preload_obj '13'",
"--no-verify-ssl",
"--out 'pregen_json'",
"--workers '7'",
"--buckets '13'",
"--location 's3_location'",
"--ignore-errors",
"--sleep '19'",
]
expected_env_vars = {
"DURATION": 183900,
"WRITE_OBJ_SIZE": 11,
"REGISTRY_FILE": "registry_file",
"K6_MIN_ITERATION_DURATION": "min_iteration_duration",
"K6_SETUP_TIMEOUT": "setup_timeout",
"NO_VERIFY_SSL": True,
"MAX_WRITERS": 11,
"MAX_READERS": 11,
"MAX_DELETERS": 12,
"PRE_ALLOC_DELETERS": 21,
"PRE_ALLOC_READERS": 20,
"PRE_ALLOC_WRITERS": 20,
"PREGEN_JSON": "pregen_json",
"TIME_UNIT": "time_unit",
"WRITE_RATE": 10,
"READ_RATE": 9,
"READ_AGE": 8,
"DELETE_RATE": 11,
}
self._check_preset_params(load_params, expected_preset_args)
self._check_env_vars(load_params, expected_env_vars)
@pytest.mark.parametrize("load_params", [LoadScenario.S3_CAR], indirect=True)
def test_argument_parsing_for_s3_car_scenario(self, load_params: LoadParams):
expected_preset_args = [
@ -228,6 +275,8 @@ class TestLoadConfig:
"--workers '7'",
"--buckets '13'",
"--location 's3_location'",
"--ignore-errors",
"--sleep '19'",
]
expected_env_vars = {
"DURATION": 9,
@ -246,6 +295,7 @@ class TestLoadConfig:
"TIME_UNIT": "time_unit",
"WRITE_RATE": 10,
"READ_RATE": 9,
"READ_AGE": 8,
"DELETE_RATE": 11,
}
@ -262,6 +312,8 @@ class TestLoadConfig:
"--workers '7'",
"--containers '16'",
"--policy 'container_placement_policy'",
"--ignore-errors",
"--sleep '19'",
]
expected_env_vars = {
"DURATION": 9,
@ -273,6 +325,7 @@ class TestLoadConfig:
"WRITERS": 7,
"READERS": 7,
"DELETERS": 8,
"READ_AGE": 8,
"PREGEN_JSON": "pregen_json",
}
@ -288,6 +341,8 @@ class TestLoadConfig:
"--workers '7'",
"--containers '16'",
"--policy 'container_placement_policy'",
"--ignore-errors",
"--sleep '19'",
]
expected_env_vars = {
"CONFIG_FILE": "config_file",
@ -299,6 +354,7 @@ class TestLoadConfig:
"WRITERS": 7,
"READERS": 7,
"DELETERS": 8,
"READ_AGE": 8,
"PREGEN_JSON": "pregen_json",
}
@ -338,6 +394,7 @@ class TestLoadConfig:
"--workers '0'",
"--containers '0'",
"--policy ''",
"--sleep '0'",
]
expected_env_vars = {
"DURATION": 0,
@ -348,6 +405,7 @@ class TestLoadConfig:
"WRITERS": 0,
"READERS": 0,
"DELETERS": 0,
"READ_AGE": 0,
"PREGEN_JSON": "",
"PREPARE_LOCALLY": False,
}
@ -364,6 +422,7 @@ class TestLoadConfig:
"--workers '0'",
"--containers '0'",
"--policy ''",
"--sleep '0'",
]
expected_env_vars = {
"DURATION": 0,
@ -382,6 +441,7 @@ class TestLoadConfig:
"WRITE_RATE": 0,
"READ_RATE": 0,
"DELETE_RATE": 0,
"READ_AGE": 0,
"PREPARE_LOCALLY": False,
}
@ -397,6 +457,7 @@ class TestLoadConfig:
"--workers '0'",
"--buckets '0'",
"--location ''",
"--sleep '0'",
]
expected_env_vars = {
"DURATION": 0,
@ -407,6 +468,7 @@ class TestLoadConfig:
"WRITERS": 0,
"READERS": 0,
"DELETERS": 0,
"READ_AGE": 0,
"NO_VERIFY_SSL": False,
"PREGEN_JSON": "",
}
@ -423,6 +485,7 @@ class TestLoadConfig:
"--workers '0'",
"--buckets '0'",
"--location ''",
"--sleep '0'",
]
expected_env_vars = {
"DURATION": 0,
@ -442,6 +505,7 @@ class TestLoadConfig:
"WRITE_RATE": 0,
"READ_RATE": 0,
"DELETE_RATE": 0,
"READ_AGE": 0,
}
self._check_preset_params(load_params, expected_preset_args)
@ -456,6 +520,7 @@ class TestLoadConfig:
"--workers '0'",
"--containers '0'",
"--policy ''",
"--sleep '0'",
]
expected_env_vars = {
"DURATION": 0,
@ -467,6 +532,7 @@ class TestLoadConfig:
"WRITERS": 0,
"READERS": 0,
"DELETERS": 0,
"READ_AGE": 0,
"PREGEN_JSON": "",
}
@ -482,6 +548,7 @@ class TestLoadConfig:
"--workers '0'",
"--containers '0'",
"--policy ''",
"--sleep '0'",
]
expected_env_vars = {
"CONFIG_FILE": "",
@ -493,6 +560,7 @@ class TestLoadConfig:
"WRITERS": 0,
"READERS": 0,
"DELETERS": 0,
"READ_AGE": 0,
"PREGEN_JSON": "",
}
@ -531,6 +599,27 @@ class TestLoadConfig:
self._check_env_vars(load_params, expected_env_vars)
@pytest.mark.parametrize(
"load_params, load_type",
[(LoadScenario.gRPC, LoadType.gRPC)],
indirect=True,
)
@pytest.mark.parametrize(
"load_time, expected_seconds",
[
(300, 300),
("2d3h45min", 186300),
("1d6h", 108000),
("1d", 86400),
("1d1min", 86460),
("2h", 7200),
("2h2min", 7320),
],
)
def test_convert_time_to_seconds(self, load_params: LoadParams, load_time: str | int, expected_seconds: int):
load_params.load_time = load_time
assert load_params.load_time == expected_seconds
def _check_preset_params(self, load_params: LoadParams, expected_preset_args: list[str]):
preset_parameters = load_params.get_preset_arguments()
assert sorted(preset_parameters) == sorted(expected_preset_args)