From 90252f1ec3aa50e7533a533152f917cf0b178bf7 Mon Sep 17 00:00:00 2001 From: Kamil Gierszewski Date: Mon, 9 Dec 2024 11:37:20 +0100 Subject: [PATCH 01/10] conftest: add create/destroy temporary directory in conftest Signed-off-by: Kamil Gierszewski --- test/functional/tests/conftest.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/test/functional/tests/conftest.py b/test/functional/tests/conftest.py index ab00408f9..bdd20f62c 100644 --- a/test/functional/tests/conftest.py +++ b/test/functional/tests/conftest.py @@ -29,7 +29,7 @@ from test_tools.disk_utils import PartitionTable, create_partition_table from test_tools.device_mapper import DeviceMapper from test_tools.mdadm import Mdadm -from test_tools.fs_utils import remove +from test_tools.fs_utils import remove, check_if_directory_exists from test_tools import initramfs from log.logger import create_log, Log from test_utils.singleton import Singleton @@ -184,6 +184,10 @@ def base_prepare(item): Udev.settle() RamDisk.remove_all() + + if check_if_directory_exists("/tmp/open_cas_test_data"): + remove("/tmp/open_cas_test_data/*", force=True) + for disk in TestRun.disks.values(): disk_serial = get_disk_serial_number(disk.path) if disk.serial_number and disk.serial_number != disk_serial: @@ -250,6 +254,10 @@ def pytest_runtest_teardown(): DeviceMapper.remove_all() RamDisk.remove_all() + + if check_if_directory_exists("/tmp/open_cas_test_data"): + remove("/tmp/open_cas_test_data/*", force=True) + except Exception as ex: TestRun.LOGGER.warning( f"Exception occurred during platform cleanup.\n" From f0756081c13736349cbbfdf6d99035ac93d516aa Mon Sep 17 00:00:00 2001 From: Kamil Gierszewski Date: Mon, 9 Dec 2024 11:37:53 +0100 Subject: [PATCH 02/10] conftest: add cleanup after drbd test Signed-off-by: Kamil Gierszewski --- test/functional/tests/conftest.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/functional/tests/conftest.py b/test/functional/tests/conftest.py index bdd20f62c..4805c29d4 100644 --- a/test/functional/tests/conftest.py +++ b/test/functional/tests/conftest.py @@ -312,6 +312,9 @@ def __drbd_cleanup(): if installer.check_if_installed(): casadm.stop_all_caches() + remove("/etc/drbd.d/caches.res", force=True, ignore_errors=True) + remove("/etc/drbd.d/cores.res", force=True, ignore_errors=True) + class Opencas(metaclass=Singleton): def __init__(self, repo_dir, working_dir): From 4443ef70a821cf366d5129008745d6122f78e752 Mon Sep 17 00:00:00 2001 From: Kamil Gierszewski Date: Mon, 9 Dec 2024 11:39:28 +0100 Subject: [PATCH 03/10] conftest: add TestRun cache/core list Signed-off-by: Kamil Gierszewski --- test/functional/tests/conftest.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/functional/tests/conftest.py b/test/functional/tests/conftest.py index 4805c29d4..46981335f 100644 --- a/test/functional/tests/conftest.py +++ b/test/functional/tests/conftest.py @@ -133,6 +133,9 @@ def pytest_runtest_setup(item): TestRun.dut.plugin_manager = TestRun.plugin_manager TestRun.dut.executor = TestRun.executor TestRun.duts.append(TestRun.dut) + for _ in TestRun.duts: + TestRun.dut.cache_list = [] + TestRun.dut.core_list = [] base_prepare(item) TestRun.LOGGER.write_to_command_log("Test body") From e0e9740917b117b7eb5c4300a3e9e53a714f81b2 Mon Sep 17 00:00:00 2001 From: Kamil Gierszewski Date: Mon, 9 Dec 2024 11:45:42 +0100 Subject: [PATCH 04/10] test-api: minor refactors Signed-off-by: Kamil Gierszewski --- test/functional/api/cas/cache.py | 4 ++-- test/functional/api/cas/casadm.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/test/functional/api/cas/cache.py b/test/functional/api/cas/cache.py index e752a0f71..2d0ebe1b3 100644 --- a/test/functional/api/cas/cache.py +++ b/test/functional/api/cas/cache.py @@ -195,7 +195,7 @@ def set_params_nhit(self, promotion_params_nhit: PromotionParametersNhit) -> Out return casadm.set_param_promotion_nhit( self.cache_id, threshold=promotion_params_nhit.threshold, - trigger=promotion_params_nhit.trigger + trigger=promotion_params_nhit.trigger, ) def get_cache_config(self) -> CacheConfig: @@ -208,7 +208,7 @@ def get_cache_config(self) -> CacheConfig: def standby_detach(self, shortcut: bool = False) -> Output: return casadm.standby_detach_cache(cache_id=self.cache_id, shortcut=shortcut) - def standby_activate(self, device, shortcut: bool = False) -> Output: + def standby_activate(self, device: Device, shortcut: bool = False) -> Output: return casadm.standby_activate_cache( cache_id=self.cache_id, cache_dev=device, shortcut=shortcut ) diff --git a/test/functional/api/cas/casadm.py b/test/functional/api/cas/casadm.py index 292cdbad3..ad578ae8a 100644 --- a/test/functional/api/cas/casadm.py +++ b/test/functional/api/cas/casadm.py @@ -192,7 +192,7 @@ def set_param_promotion(cache_id: int, policy: PromotionPolicy, shortcut: bool = def set_param_promotion_nhit( - cache_id: int, threshold: int = None, trigger: int = None, shortcut: bool = False + cache_id: int, threshold: int = None, trigger: int = None, shortcut: bool = False ) -> Output: _threshold = str(threshold) if threshold is not None else None _trigger = str(trigger) if trigger is not None else None @@ -267,7 +267,7 @@ def get_param_cleaning_acp( def get_param_promotion( - cache_id: int, output_format: OutputFormat = None, shortcut: bool = False + cache_id: int, output_format: OutputFormat = None, shortcut: bool = False ) -> Output: _output_format = output_format.name if output_format else None output = TestRun.executor.run( @@ -281,7 +281,7 @@ def get_param_promotion( def get_param_promotion_nhit( - cache_id: int, output_format: OutputFormat = None, shortcut: bool = False + cache_id: int, output_format: OutputFormat = None, shortcut: bool = False ) -> Output: _output_format = output_format.name if output_format else None output = TestRun.executor.run( From fa230da9ac7ca908f0baa3ad0de2f3355b7c5c4d Mon Sep 17 00:00:00 2001 From: Kamil Gierszewski Date: Mon, 9 Dec 2024 11:53:23 +0100 Subject: [PATCH 05/10] test-api: Change Cache init to force use of the cache_id instead of cache_device Signed-off-by: Kamil Gierszewski --- test/functional/api/cas/cache.py | 37 +++++++----- test/functional/api/cas/casadm.py | 94 +++++++++++++++++++++++++++++-- 2 files changed, 110 insertions(+), 21 deletions(-) diff --git a/test/functional/api/cas/cache.py b/test/functional/api/cas/cache.py index 2d0ebe1b3..1b2233d8a 100644 --- a/test/functional/api/cas/cache.py +++ b/test/functional/api/cas/cache.py @@ -13,21 +13,28 @@ class Cache: - def __init__(self, device: Device, cache_id: int = None) -> None: - self.cache_device = device - self.cache_id = cache_id if cache_id else self.__get_cache_id() - self.__cache_line_size = None - - def __get_cache_id(self) -> int: - device_path = self.__get_cache_device_path() - + def __init__( + self, cache_id: int, device: Device = None, cache_line_size: CacheLineSize = None + ) -> None: + self.cache_id = cache_id + self.cache_device = device if device else self.__get_cache_device() + self.status = None + self.cache_line_size = cache_line_size + self.write_policy = None + + def __get_cache_device(self) -> Device | None: caches_dict = get_cas_devices_dict()["caches"] + cache = next( + iter([cache for cache in caches_dict.values() if cache["id"] == self.cache_id]) + ) + + if not cache: + return None - for cache in caches_dict.values(): - if cache["device_path"] == device_path: - return int(cache["id"]) + if cache["device_path"] is "-": + return None - raise Exception(f"There is no cache started on {device_path}") + return Device(path=cache["device_path"]) def __get_cache_device_path(self) -> str: return self.cache_device.path if self.cache_device is not None else "-" @@ -36,11 +43,11 @@ def get_core_devices(self) -> list: return get_cores(self.cache_id) def get_cache_line_size(self) -> CacheLineSize: - if self.__cache_line_size is None: + if self.cache_line_size is None: stats = self.get_statistics() stats_line_size = stats.config_stats.cache_line_size - self.__cache_line_size = CacheLineSize(stats_line_size) - return self.__cache_line_size + self.cache_line_size = CacheLineSize(stats_line_size) + return self.cache_line_size def get_cleaning_policy(self) -> CleaningPolicy: stats = self.get_statistics() diff --git a/test/functional/api/cas/casadm.py b/test/functional/api/cas/casadm.py index ad578ae8a..febae1615 100644 --- a/test/functional/api/cas/casadm.py +++ b/test/functional/api/cas/casadm.py @@ -48,6 +48,7 @@ def start_cache( ) _cache_id = str(cache_id) if cache_id is not None else None _cache_mode = cache_mode.name.lower() if cache_mode else None + output = TestRun.executor.run( start_cmd( cache_dev=cache_dev.path, @@ -59,16 +60,43 @@ def start_cache( shortcut=shortcut, ) ) + if output.exit_code != 0: raise CmdException("Failed to start cache.", output) - return Cache(cache_dev) + + if not _cache_id: + from api.cas.casadm_parser import get_caches + + cache_list = get_caches() + # compare ids of old and new caches, returning the only one created now. + # This will be needed in case cache_id not present in cli command + + new_cache = next( + iter([cache for cache in cache_list if cache.cache_device.path == cache_dev.path]) + ) + _cache_id = new_cache.cache_id + + cache = Cache(cache_id=int(_cache_id), device=cache_dev, cache_line_size=_cache_line_size) + TestRun.dut.cache_list.append(cache) + return cache def load_cache(device: Device, shortcut: bool = False) -> Cache: + from api.cas.casadm_parser import get_caches + + caches_before_load = get_caches() output = TestRun.executor.run(load_cmd(cache_dev=device.path, shortcut=shortcut)) + if output.exit_code != 0: raise CmdException("Failed to load cache.", output) - return Cache(device) + + caches_after_load = get_caches() + new_cache = next( + iter([cache for cache in caches_after_load if cache not in caches_before_load]) + ) + cache = Cache(cache_id=new_cache.cache_id, device=new_cache.cache_device) + TestRun.dut.cache_list.append(cache) + return cache def attach_cache(cache_id: int, device: Device, force: bool, shortcut: bool = False) -> Output: @@ -84,8 +112,12 @@ def attach_cache(cache_id: int, device: Device, force: bool, shortcut: bool = Fa def detach_cache(cache_id: int, shortcut: bool = False) -> Output: output = TestRun.executor.run(detach_cache_cmd(cache_id=str(cache_id), shortcut=shortcut)) + if output.exit_code != 0: raise CmdException("Failed to detach cache.", output) + + detached_cache = next(cache for cache in TestRun.dut.cache_list if cache.cache_id == cache_id) + detached_cache.cache_device = None return output @@ -93,8 +125,16 @@ def stop_cache(cache_id: int, no_data_flush: bool = False, shortcut: bool = Fals output = TestRun.executor.run( stop_cmd(cache_id=str(cache_id), no_data_flush=no_data_flush, shortcut=shortcut) ) + if output.exit_code != 0: raise CmdException("Failed to stop cache.", output) + + TestRun.dut.cache_list = [ + cache for cache in TestRun.dut.cache_list if cache.cache_id != cache_id + ] + + TestRun.dut.core_list = [core for core in TestRun.dut.core_list if core.cache_id == cache_id] + return output @@ -325,7 +365,11 @@ def add_core(cache: Cache, core_dev: Device, core_id: int = None, shortcut: bool ) if output.exit_code != 0: raise CmdException("Failed to add core.", output) - return Core(core_dev.path, cache.cache_id) + + core = Core(core_dev.path, cache.cache_id) + TestRun.dut.core_list.append(core) + + return core def remove_core(cache_id: int, core_id: int, force: bool = False, shortcut: bool = False) -> Output: @@ -336,6 +380,17 @@ def remove_core(cache_id: int, core_id: int, force: bool = False, shortcut: bool ) if output.exit_code != 0: raise CmdException("Failed to remove core.", output) + + core_to_remove = next( + iter( + [ + core + for core in TestRun.dut.core_list + if core.cache_id == cache_id and core.core_id == core_id + ] + ) + ) + TestRun.dut.core_list.remove(core_to_remove) return output @@ -485,22 +540,45 @@ def standby_init( shortcut=shortcut, ) ) + if output.exit_code != 0: raise CmdException("Failed to init standby cache.", output) - return Cache(cache_dev) + return Cache(cache_id=cache_id, device=cache_dev) def standby_load(cache_dev: Device, shortcut: bool = False) -> Cache: + from api.cas.casadm_parser import get_caches + + caches_before_load = get_caches() output = TestRun.executor.run(standby_load_cmd(cache_dev=cache_dev.path, shortcut=shortcut)) + if output.exit_code != 0: - raise CmdException("Failed to load standby cache.", output) - return Cache(cache_dev) + raise CmdException("Failed to load cache.", output) + caches_after_load = get_caches() + # compare ids of old and new caches, returning the only one created now + new_cache = next( + iter( + [ + cache + for cache in caches_after_load + if cache.cache_id not in [cache.cache_id for cache in caches_before_load] + ] + ) + ) + cache = Cache(cache_id=new_cache.cache_id, device=new_cache.cache_device) + TestRun.dut.cache_list.append(cache) + + return cache def standby_detach_cache(cache_id: int, shortcut: bool = False) -> Output: output = TestRun.executor.run(standby_detach_cmd(cache_id=str(cache_id), shortcut=shortcut)) if output.exit_code != 0: raise CmdException("Failed to detach standby cache.", output) + + detached_cache = next(cache for cache in TestRun.dut.cache_list if cache.cache_id == cache_id) + detached_cache.cache_device = None + return output @@ -510,6 +588,10 @@ def standby_activate_cache(cache_dev: Device, cache_id: int, shortcut: bool = Fa ) if output.exit_code != 0: raise CmdException("Failed to activate standby cache.", output) + + activated_cache = next(cache for cache in TestRun.dut.cache_list if cache.cache_id == cache_id) + activated_cache.cache_device = cache_dev + return output From e698d150e9d3e83cfd460fe4702365e40ef247e1 Mon Sep 17 00:00:00 2001 From: Kamil Gierszewski Date: Tue, 10 Dec 2024 05:19:05 +0100 Subject: [PATCH 06/10] test-api: refactor to fix circular dependencies Signed-off-by: Kamil Gierszewski --- test/functional/api/cas/cache_config.py | 11 +++++ test/functional/api/cas/casadm_parser.py | 48 ++++----------------- test/functional/api/cas/core.py | 53 ++++++++++++++++-------- 3 files changed, 54 insertions(+), 58 deletions(-) diff --git a/test/functional/api/cas/cache_config.py b/test/functional/api/cas/cache_config.py index 0665bd481..0f3fc154b 100644 --- a/test/functional/api/cas/cache_config.py +++ b/test/functional/api/cas/cache_config.py @@ -125,6 +125,17 @@ class CacheStatus(Enum): incomplete = "incomplete" standby = "standby" standby_detached = "standby detached" + detached = "detached" + + def __str__(self): + return self.value + + +class CoreStatus(Enum): + empty = "empty" + active = "active" + inactive = "inactive" + detached = "detached" def __str__(self): return self.value diff --git a/test/functional/api/cas/casadm_parser.py b/test/functional/api/cas/casadm_parser.py index 1285d9972..f8ffa5df5 100644 --- a/test/functional/api/cas/casadm_parser.py +++ b/test/functional/api/cas/casadm_parser.py @@ -5,7 +5,6 @@ # import csv -import io import json from datetime import timedelta, datetime @@ -45,8 +44,8 @@ def get_caches() -> list: for cache in caches_dict.values(): caches_list.append( Cache( + cache_id=(cache["id"]), device=(Device(cache["device_path"]) if cache["device_path"] != "-" else None), - cache_id=cache["id"], ) ) @@ -59,7 +58,7 @@ def get_cores(cache_id: int) -> list: cores_dict = get_cas_devices_dict()["cores"].values() def is_active(core): - return CoreStatus[core["status"].lower()] == CoreStatus.active + return core["status"] == CoreStatus.active return [ Core(core["device_path"], core["cache_id"]) @@ -74,7 +73,7 @@ def get_inactive_cores(cache_id: int) -> list: cores_dict = get_cas_devices_dict()["cores"].values() def is_inactive(core): - return CoreStatus[core["status"].lower()] == CoreStatus.inactive + return core["status"] == CoreStatus.inactive return [ Core(core["device_path"], core["cache_id"]) @@ -89,7 +88,7 @@ def get_detached_cores(cache_id: int) -> list: cores_dict = get_cas_devices_dict()["cores"].values() def is_detached(core): - return CoreStatus[core["status"].lower()] == CoreStatus.detached + return core["status"] == CoreStatus.detached return [ Core(core["device_path"], core["cache_id"]) @@ -110,15 +109,17 @@ def get_cas_devices_dict() -> dict: params = [ ("id", cache_id), ("device_path", device["disk"]), - ("status", device["status"]), + ("status", CacheStatus(device["status"].lower())), ] devices["caches"][cache_id] = dict([(key, value) for key, value in params]) elif device["type"] == "core": params = [ ("cache_id", cache_id), + ("core_id", (int(device["id"]) if device["id"] != "-" else device["id"])), ("device_path", device["disk"]), - ("status", device["status"]), + ("status", CoreStatus(device["status"].lower())), + ("exp_obj", device["device"]), ] if core_pool: params.append(("core_pool", device)) @@ -201,21 +202,6 @@ def get_flush_parameters_acp(cache_id: int): return flush_parameters -def get_seq_cut_off_parameters(cache_id: int, core_id: int): - casadm_output = casadm.get_param_cutoff( - cache_id, core_id, casadm.OutputFormat.csv - ).stdout.splitlines() - seq_cut_off_params = SeqCutOffParameters() - for line in casadm_output: - if "Sequential cutoff threshold" in line: - seq_cut_off_params.threshold = Size(int(line.split(",")[1]), Unit.KibiByte) - if "Sequential cutoff policy" in line: - seq_cut_off_params.policy = SeqCutOffPolicy.from_name(line.split(",")[1]) - if "Sequential cutoff promotion request count threshold" in line: - seq_cut_off_params.promotion_count = int(line.split(",")[1]) - return seq_cut_off_params - - def get_casadm_version(): casadm_output = casadm.print_version(OutputFormat.csv).stdout.split("\n") version_str = casadm_output[1].split(",")[-1] @@ -231,21 +217,3 @@ def get_io_class_list(cache_id: int) -> list: ioclass = IoClass(int(values[0]), values[1], int(values[2]), values[3]) ret.append(ioclass) return ret - - -def get_core_info_for_cache_by_path(core_disk_path: str, target_cache_id: int) -> dict | None: - output = casadm.list_caches(OutputFormat.csv, by_id_path=True) - reader = csv.DictReader(io.StringIO(output.stdout)) - cache_id = -1 - for row in reader: - if row["type"] == "cache": - cache_id = int(row["id"]) - if row["type"] == "core" and row["disk"] == core_disk_path and target_cache_id == cache_id: - return { - "core_id": row["id"], - "core_device": row["disk"], - "status": row["status"], - "exp_obj": row["device"], - } - - return None diff --git a/test/functional/api/cas/core.py b/test/functional/api/cas/core.py index e85eef977..0ff7f2069 100644 --- a/test/functional/api/cas/core.py +++ b/test/functional/api/cas/core.py @@ -6,12 +6,11 @@ from datetime import timedelta from typing import List -from enum import Enum from api.cas import casadm -from api.cas.cache_config import SeqCutOffParameters, SeqCutOffPolicy +from api.cas.cache_config import SeqCutOffParameters, SeqCutOffPolicy, CoreStatus from api.cas.casadm_params import StatsFilter -from api.cas.casadm_parser import get_seq_cut_off_parameters, get_core_info_for_cache_by_path +from api.cas.casadm_parser import get_cas_devices_dict from api.cas.statistics import CoreStats, CoreIoClassStats from core.test_run_utils import TestRun from storage_devices.device import Device @@ -20,13 +19,6 @@ from test_utils.size import Unit, Size -class CoreStatus(Enum): - empty = 0 - active = 1 - inactive = 2 - detached = 3 - - SEQ_CUTOFF_THRESHOLD_MAX = Size(4194181, Unit.KibiByte) SEQ_CUT_OFF_THRESHOLD_DEFAULT = Size(1, Unit.MebiByte) @@ -42,12 +34,22 @@ def __init__(self, core_device: str, cache_id: int): self.core_id = int(core_info["core_id"]) if core_info["exp_obj"] != "-": Device.__init__(self, core_info["exp_obj"]) + self.status = None self.partitions = [] self.block_size = None - def __get_core_info(self): - return get_core_info_for_cache_by_path(core_disk_path=self.core_device.path, - target_cache_id=self.cache_id) + def __get_core_info(self) -> dict | None: + core_dicts = get_cas_devices_dict()["cores"].values() + return next( + iter( + [ + core + for core in core_dicts + if core["cache_id"] == self.cache_id + and core["device_path"] == self.core_device.path + ] + ) + ) def create_filesystem(self, fs_type: disk_utils.Filesystem, force=True, blocksize=None): super().create_filesystem(fs_type, force, blocksize) @@ -77,17 +79,32 @@ def get_statistics( percentage_val=percentage_val, ) - def get_status(self): - return CoreStatus[self.__get_core_info()["status"].lower()] + def get_status(self) -> CoreStatus: + self.status = self.__get_core_info()["status"] + return self.status + + def __get_seq_cut_off_parameters(self): + casadm_output = casadm.get_param_cutoff( + self.cache_id, self.core_id, casadm.OutputFormat.csv + ).stdout.splitlines() + seq_cut_off_params = SeqCutOffParameters() + for line in casadm_output: + if "Sequential cutoff threshold" in line: + seq_cut_off_params.threshold = Size(int(line.split(",")[1]), Unit.KibiByte) + if "Sequential cutoff policy" in line: + seq_cut_off_params.policy = SeqCutOffPolicy.from_name(line.split(",")[1]) + if "Sequential cutoff promotion request count threshold" in line: + seq_cut_off_params.promotion_count = int(line.split(",")[1]) + return seq_cut_off_params def get_seq_cut_off_parameters(self): - return get_seq_cut_off_parameters(self.cache_id, self.core_id) + return self.__get_seq_cut_off_parameters(self.cache_id, self.core_id) def get_seq_cut_off_policy(self): - return get_seq_cut_off_parameters(self.cache_id, self.core_id).policy + return self.__get_seq_cut_off_parameters(self.cache_id, self.core_id).policy def get_seq_cut_off_threshold(self): - return get_seq_cut_off_parameters(self.cache_id, self.core_id).threshold + return self.__get_seq_cut_off_parameters(self.cache_id, self.core_id).threshold def get_dirty_blocks(self): return self.get_statistics().usage_stats.dirty From d8be90c94b03bd593757e8240acfdc5ef027cd35 Mon Sep 17 00:00:00 2001 From: Kamil Gierszewski Date: Tue, 10 Dec 2024 05:41:56 +0100 Subject: [PATCH 07/10] test-api: add Byte unit Signed-off-by: Kamil Gierszewski --- test/functional/api/cas/statistics.py | 1 + 1 file changed, 1 insertion(+) diff --git a/test/functional/api/cas/statistics.py b/test/functional/api/cas/statistics.py index 1f2a9f4af..789560883 100644 --- a/test/functional/api/cas/statistics.py +++ b/test/functional/api/cas/statistics.py @@ -22,6 +22,7 @@ class UnitType(Enum): kibibyte = "[KiB]" gibibyte = "[GiB]" seconds = "[s]" + byte = "[B]" def __str__(self): return self.value From bbcbe92f00069d345032d1058a7a376ee209b383 Mon Sep 17 00:00:00 2001 From: Kamil Gierszewski Date: Tue, 10 Dec 2024 06:00:17 +0100 Subject: [PATCH 08/10] tests: remove duplicated test Signed-off-by: Kamil Gierszewski --- ...i_help_and_version.py => test_cli_help.py} | 29 ------------------- 1 file changed, 29 deletions(-) rename test/functional/tests/cli/{test_cli_help_and_version.py => test_cli_help.py} (82%) diff --git a/test/functional/tests/cli/test_cli_help_and_version.py b/test/functional/tests/cli/test_cli_help.py similarity index 82% rename from test/functional/tests/cli/test_cli_help_and_version.py rename to test/functional/tests/cli/test_cli_help.py index 24eebe8b3..c3c0911b1 100644 --- a/test/functional/tests/cli/test_cli_help_and_version.py +++ b/test/functional/tests/cli/test_cli_help.py @@ -4,12 +4,9 @@ # SPDX-License-Identifier: BSD-3-Clause # -import re - import pytest from api.cas import casadm -from api.cas.casadm_params import OutputFormat from api.cas.cli_help_messages import * from api.cas.cli_messages import check_stderr_msg, check_stdout_msg from core.test_run import TestRun @@ -99,29 +96,3 @@ def test_cli_help(shortcut): + (" -H" if shortcut else " --help")) check_stderr_msg(output, unrecognized_stderr) check_stdout_msg(output, unrecognized_stdout) - - -@pytest.mark.parametrize("output_format", OutputFormat) -@pytest.mark.parametrize("shortcut", [True, False]) -def test_cli_version(shortcut, output_format): - """ - title: Test for 'version' command. - description: Test if version displays. - pass_criteria: - - Proper OCL's components names displays in table with its versions. - """ - TestRun.LOGGER.info("Check OCL's version.") - output = casadm.print_version(output_format, shortcut).stdout - TestRun.LOGGER.info(output) - if not names_in_output(output) or not versions_in_output(output): - TestRun.fail("'Version' command failed.") - - -def names_in_output(output): - return ("CAS Cache Kernel Module" in output - and "CAS CLI Utility" in output) - - -def versions_in_output(output): - version_pattern = re.compile(r"(\d){2}\.(\d){2}\.(\d)\.(\d){4}.(\S)") - return len(version_pattern.findall(output)) == 2 From 75b89c82e1c7d3b928b1b2c1bf3079c1f54c85c9 Mon Sep 17 00:00:00 2001 From: Kamil Gierszewski Date: Wed, 11 Dec 2024 03:58:59 +0100 Subject: [PATCH 09/10] tests: refactor test_cli_help test Signed-off-by: Kamil Gierszewski --- test/functional/tests/cli/test_cli_help.py | 118 +++++++-------------- 1 file changed, 39 insertions(+), 79 deletions(-) diff --git a/test/functional/tests/cli/test_cli_help.py b/test/functional/tests/cli/test_cli_help.py index c3c0911b1..93f387511 100644 --- a/test/functional/tests/cli/test_cli_help.py +++ b/test/functional/tests/cli/test_cli_help.py @@ -6,93 +6,53 @@ import pytest -from api.cas import casadm from api.cas.cli_help_messages import * from api.cas.cli_messages import check_stderr_msg, check_stdout_msg from core.test_run import TestRun -@pytest.mark.parametrize("shortcut", [True, False]) +@pytest.mark.parametrizex("shortcut", [True, False]) def test_cli_help(shortcut): """ title: Test for 'help' command. - description: Test if help for commands displays. + description: | + Test if help for commands displays. pass_criteria: - Proper help displays for every command. """ - TestRun.LOGGER.info("Run 'help' for every 'casadm' command.") - output = casadm.help(shortcut) - check_stdout_msg(output, casadm_help) - - output = TestRun.executor.run("casadm" + (" -S" if shortcut else " --start-cache") - + (" -H" if shortcut else " --help")) - check_stdout_msg(output, start_cache_help) - - output = TestRun.executor.run("casadm" + (" -T" if shortcut else " --stop-cache") - + (" -H" if shortcut else " --help")) - check_stdout_msg(output, stop_cache_help) - - output = TestRun.executor.run("casadm" + (" -X" if shortcut else " --set-param") - + (" -H" if shortcut else " --help")) - check_stdout_msg(output, set_params_help) - - output = TestRun.executor.run("casadm" + (" -G" if shortcut else " --get-param") - + (" -H" if shortcut else " --help")) - check_stdout_msg(output, get_params_help) - - output = TestRun.executor.run("casadm" + (" -Q" if shortcut else " --set-cache-mode") - + (" -H" if shortcut else " --help")) - check_stdout_msg(output, set_cache_mode_help) - - output = TestRun.executor.run("casadm" + (" -A" if shortcut else " --add-core") - + (" -H" if shortcut else " --help")) - check_stdout_msg(output, add_core_help) - - output = TestRun.executor.run("casadm" + (" -R" if shortcut else " --remove-core") - + (" -H" if shortcut else " --help")) - check_stdout_msg(output, remove_core_help) - - output = TestRun.executor.run("casadm" + " --remove-detached" - + (" -H" if shortcut else " --help")) - check_stdout_msg(output, remove_detached_help) - - output = TestRun.executor.run("casadm" + (" -L" if shortcut else " --list-caches") - + (" -H" if shortcut else " --help")) - check_stdout_msg(output, list_caches_help) - - output = TestRun.executor.run("casadm" + (" -P" if shortcut else " --stats") - + (" -H" if shortcut else " --help")) - check_stdout_msg(output, stats_help) - - output = TestRun.executor.run("casadm" + (" -Z" if shortcut else " --reset-counters") - + (" -H" if shortcut else " --help")) - check_stdout_msg(output, reset_counters_help) - - output = TestRun.executor.run("casadm" + (" -F" if shortcut else " --flush-cache") - + (" -H" if shortcut else " --help")) - check_stdout_msg(output, flush_cache_help) - - output = TestRun.executor.run("casadm" + (" -C" if shortcut else " --io-class") - + (" -H" if shortcut else " --help")) - check_stdout_msg(output, ioclass_help) - - output = TestRun.executor.run("casadm" + (" -V" if shortcut else " --version") - + (" -H" if shortcut else " --help")) - check_stdout_msg(output, version_help) - - output = TestRun.executor.run("casadm" + (" -H" if shortcut else " --help") - + (" -H" if shortcut else " --help")) - check_stdout_msg(output, help_help) - - output = TestRun.executor.run("casadm" + " --standby" - + (" -H" if shortcut else " --help")) - check_stdout_msg(output, standby_help) - - output = TestRun.executor.run("casadm" + " --zero-metadata" - + (" -H" if shortcut else " --help")) - check_stdout_msg(output, zero_metadata_help) - - output = TestRun.executor.run("casadm" + (" -Y" if shortcut else " --yell") - + (" -H" if shortcut else " --help")) - check_stderr_msg(output, unrecognized_stderr) - check_stdout_msg(output, unrecognized_stdout) + check_list_cmd = [ + (" -S", " --start-cache", start_cache_help), + # (None, " --attach-cache", attach_cache_help), + # (None, " --detach-cache", detach_cache_help), + (" -T", " --stop-cache", stop_cache_help), + (" -X", " --set-param", set_params_help), + (" -G", " --get-param", get_params_help), + (" -Q", " --set-cache-mode", set_cache_mode_help), + (" -A", " --add-core", add_core_help), + (" -R", " --remove-core", remove_core_help), + (None, "--remove-inactive", remove_inactive_help), + (None, "--remove-detached", remove_detached_help), + (" -L", " --list-caches", list_caches_help), + (" -P", " --stats", stats_help), + (" -Z", " --reset-counters", reset_counters_help), + (" -F", " --flush-cache", flush_cache_help), + (" -C", " --io-class", ioclass_help), + (" -V", " --version", version_help), + # (None, " --standby", standby_help), + (" -H", " --help", help_help), + (" --zero-metadata", zero_metadata_help), + ] + help = "-H" if shortcut else "--help" + + with TestRun.step("Run 'help' for every 'casadm' command and check output"): + for cmds in check_list_cmd: + cmd = cmds[0] if shortcut else cmds[1] + if cmd: + output = TestRun.executor.run("casadm" + cmd + help) + check_stdout_msg(output, cmds[2]) + + with TestRun.step("Run 'help' for command that doesn`t exist and check output"): + cmd = "-Y" if shortcut else "--yell" + output = TestRun.executor.run("casadm" + cmd + help) + check_stderr_msg(output, unrecognized_stderr) + check_stdout_msg(output, unrecognized_stdout) From 0c81b8a542ee5bc9b9f4d97bea26b7efd691993d Mon Sep 17 00:00:00 2001 From: Kamil Gierszewski Date: Tue, 10 Dec 2024 06:12:18 +0100 Subject: [PATCH 10/10] tests: minor refactor Signed-off-by: Kamil Gierszewski --- .../test_cleaning_policy_operation.py | 2 +- .../tests/cli/test_cli_help_spelling.py | 20 +-- test/functional/tests/cli/test_cli_script.py | 33 ++--- .../tests/cli/test_cli_start_stop.py | 132 ++++++++++-------- 4 files changed, 100 insertions(+), 87 deletions(-) diff --git a/test/functional/tests/cache_ops/test_cleaning_policy_operation.py b/test/functional/tests/cache_ops/test_cleaning_policy_operation.py index be6cf25b4..d9ac91cac 100644 --- a/test/functional/tests/cache_ops/test_cleaning_policy_operation.py +++ b/test/functional/tests/cache_ops/test_cleaning_policy_operation.py @@ -106,7 +106,7 @@ def test_cleaning_policies_in_write_back(cleaning_policy: CleaningPolicy): @pytest.mark.parametrize("cleaning_policy", CleaningPolicy) @pytest.mark.require_disk("cache", DiskTypeSet([DiskType.optane, DiskType.nand])) @pytest.mark.require_disk("core", DiskTypeLowerThan("cache")) -def test_cleaning_policies_in_write_through(cleaning_policy): +def test_cleaning_policies_in_write_through(cleaning_policy: CleaningPolicy): """ title: Test for cleaning policy operation in Write-Through cache mode. description: | diff --git a/test/functional/tests/cli/test_cli_help_spelling.py b/test/functional/tests/cli/test_cli_help_spelling.py index aacdbf84e..c3be5917f 100644 --- a/test/functional/tests/cli/test_cli_help_spelling.py +++ b/test/functional/tests/cli/test_cli_help_spelling.py @@ -1,5 +1,6 @@ # # Copyright(c) 2022 Intel Corporation +# Copyright(c) 2024 Huawei Technologies Co., Ltd. # SPDX-License-Identifier: BSD-3-Clause # @@ -12,23 +13,22 @@ def test_cli_help_spelling(): """ title: Spelling test for 'help' command - description: Validates spelling of 'help' in CLI + description: | + Validates spelling of 'help' in CLI pass criteria: - - no spelling mistakes are found + - no spelling mistakes are found """ cas_dictionary = os.path.join(TestRun.usr.repo_dir, "test", "functional", "resources") with TestRun.step("Run aspell"): - TestRun.executor.rsync_to( - f"{cas_dictionary}/", - f"{TestRun.usr.working_dir}/", - delete=True) + TestRun.executor.rsync_to(f"{cas_dictionary}/", f"{TestRun.usr.working_dir}/", delete=True) cas_dictionary = os.path.join(TestRun.usr.working_dir, "cas_ex.en.pws") output = TestRun.executor.run_expect_success( f"{casadm_bin} -H 2>&1 | aspell list -c --lang=en_US " - f"--add-extra-dicts={cas_dictionary}") + f"--add-extra-dicts={cas_dictionary}" + ) if output.stdout: TestRun.LOGGER.error("Misspelled words found:\n") @@ -37,13 +37,15 @@ def test_cli_help_spelling(): output = TestRun.executor.run_expect_success( f"{casadm_bin} -H" " | awk '/Available commands:/{ cmd=1;next } /For detailed help/ { cmd=0 } " - "cmd { print $0 }' | grep -o '\\-\\-\\S*'") + "cmd { print $0 }' | grep -o '\\-\\-\\S*'" + ) commands = output.stdout.splitlines() for command in commands: output = TestRun.executor.run_expect_success( f"{casadm_bin} {command} -H | aspell list --lang=en_US " - f"--add-extra-dicts={cas_dictionary}") + f"--add-extra-dicts={cas_dictionary}" + ) if output.stdout: TestRun.LOGGER.error(f"Misspelled word found in command :{command}\n") diff --git a/test/functional/tests/cli/test_cli_script.py b/test/functional/tests/cli/test_cli_script.py index 81217013e..2286b4fc6 100644 --- a/test/functional/tests/cli/test_cli_script.py +++ b/test/functional/tests/cli/test_cli_script.py @@ -1,12 +1,12 @@ # # Copyright(c) 2020-2021 Intel Corporation +# Copyright(c) 2024 Huawei Technologies Co., Ltd. # SPDX-License-Identifier: BSD-3-Clause # - import pytest -from api.cas import casadm, casadm_parser +from api.cas import casadm from core.test_run import TestRun from test_utils.os_utils import sync from storage_devices.disk import DiskType, DiskTypeSet, DiskTypeLowerThan @@ -19,13 +19,14 @@ @pytest.mark.parametrize("purge_target", ["cache", "core"]) def test_purge(purge_target): """ - title: Call purge without and with `--script` switch - description: | - Check if purge is called only when `--script` switch is used. - pass_criteria: - - casadm returns an error when `--script` is missing - - cache is wiped when purge command is used properly + title: Call purge without and with `--script` switch + description: | + Check if purge is called only when `--script` switch is used. + pass_criteria: + - casadm returns an error when `--script` is missing + - cache is wiped when purge command is used properly """ + with TestRun.step("Prepare devices"): cache_device = TestRun.disks["cache"] core_device = TestRun.disks["core"] @@ -52,25 +53,19 @@ def test_purge(purge_target): dd.run() sync() - with TestRun.step( - f"Try to call purge-{purge_target} without `--script` switch" - ): + with TestRun.step(f"Try to call purge-{purge_target} without `--script` switch"): original_occupancy = cache.get_statistics().usage_stats.occupancy purge_params = f"--cache-id {cache.cache_id} " if purge_target == "core": purge_params += f"--core-id {core.core_id}" - TestRun.executor.run_expect_fail( - f"casadm --purge-{purge_target} {purge_params}" - ) + TestRun.executor.run_expect_fail(f"casadm --purge-{purge_target} {purge_params}") if cache.get_statistics().usage_stats.occupancy != original_occupancy: TestRun.fail( f"Purge {purge_target} should not be possible to use without `--script` switch!" ) - with TestRun.step( - f"Try to call purge-{purge_target} with `--script` switch" - ): + with TestRun.step(f"Try to call purge-{purge_target} with `--script` switch"): TestRun.executor.run_expect_success( f"casadm --script --purge-{purge_target} {purge_params}" ) @@ -79,7 +74,5 @@ def test_purge(purge_target): TestRun.fail(f"{cache.get_statistics().usage_stats.occupancy.get_value()}") TestRun.fail(f"Purge {purge_target} should invalidate all cache lines!") - with TestRun.step( - f"Stop cache" - ): + with TestRun.step(f"Stop cache"): casadm.stop_all_caches() diff --git a/test/functional/tests/cli/test_cli_start_stop.py b/test/functional/tests/cli/test_cli_start_stop.py index 7f1b503d9..2edc1d979 100644 --- a/test/functional/tests/cli/test_cli_start_stop.py +++ b/test/functional/tests/cli/test_cli_start_stop.py @@ -1,9 +1,11 @@ # # Copyright(c) 2019-2021 Intel Corporation +# Copyright(c) 2024 Huawei Technologies Co., Ltd. # SPDX-License-Identifier: BSD-3-Clause # import pytest + from random import randint from api.cas import casadm, casadm_parser, cli_messages @@ -12,23 +14,22 @@ from storage_devices.disk import DiskType, DiskTypeSet, DiskTypeLowerThan from test_utils.size import Unit, Size -CACHE_ID_RANGE = (1, 16384) -CORE_ID_RANGE = (0, 4095) - @pytest.mark.require_disk("cache", DiskTypeSet([DiskType.nand, DiskType.optane])) @pytest.mark.parametrize("shortcut", [True, False]) def test_cli_start_stop_default_id(shortcut): """ - title: Test for starting a cache with a default ID - short and long command - description: | - Start a new cache with a default ID and then stop this cache. - pass_criteria: - - The cache has successfully started with default ID - - The cache has successfully stopped + title: Test for starting a cache with a default ID - short and long command + description: | + Start a new cache with a default ID and then stop this cache. + pass_criteria: + - The cache has successfully started with default ID + - The cache has successfully stopped """ + CACHE_ID_RANGE = (1, 16384) + with TestRun.step("Prepare the device for the cache."): - cache_device = TestRun.disks['cache'] + cache_device = TestRun.disks["cache"] cache_device.create_partitions([Size(500, Unit.MebiByte)]) cache_device = cache_device.partitions[0] @@ -38,12 +39,16 @@ def test_cli_start_stop_default_id(shortcut): with TestRun.step("Check if the cache has started successfully."): caches = casadm_parser.get_caches() if len(caches) != 1: - TestRun.fail(f"There is a wrong number of caches found in the OS: {len(caches)}. " - f"Should be only 1.") + TestRun.fail( + f"There is a wrong number of caches found in the OS: {len(caches)}. " + f"Should be only 1." + ) if cache.cache_device.path != cache_device.path: - TestRun.fail(f"The cache has started using a wrong device:" - f" {cache.cache_device.path}." - f"\nShould use {cache_device.path}.") + TestRun.fail( + f"The cache has started using a wrong device:" + f" {cache.cache_device.path}." + f"\nShould use {cache_device.path}." + ) with TestRun.step("Stop the cache."): casadm.stop_cache(cache.cache_id, shortcut=shortcut) @@ -51,8 +56,10 @@ def test_cli_start_stop_default_id(shortcut): with TestRun.step("Check if the cache has stopped properly."): caches = casadm_parser.get_caches() if len(caches) != 0: - TestRun.fail(f"There is a wrong number of caches found in the OS: {len(caches)}." - f"\nNo cache should be present after stopping the cache.") + TestRun.fail( + f"There is a wrong number of caches found in the OS: {len(caches)}." + f"\nNo cache should be present after stopping the cache." + ) output = casadm.list_caches(shortcut=shortcut) cli_messages.check_stdout_msg(output, cli_messages.no_caches_running) @@ -61,15 +68,16 @@ def test_cli_start_stop_default_id(shortcut): @pytest.mark.parametrize("shortcut", [True, False]) def test_cli_start_stop_custom_id(shortcut): """ - title: Test for starting a cache with a custom ID - short and long command - description: | - Start a new cache with a random ID (from allowed pool) and then stop this cache. - pass_criteria: - - The cache has successfully started with a custom ID - - The cache has successfully stopped + title: Test for starting a cache with a custom ID - short and long command + description: | + Start a new cache with a random ID (from allowed pool) and then stop this cache. + pass_criteria: + - The cache has successfully started with a custom ID + - The cache has successfully stopped """ + with TestRun.step("Prepare the device for the cache."): - cache_device = TestRun.disks['cache'] + cache_device = TestRun.disks["cache"] cache_device.create_partitions([Size(500, Unit.MebiByte)]) cache_device = cache_device.partitions[0] @@ -81,12 +89,16 @@ def test_cli_start_stop_custom_id(shortcut): with TestRun.step("Check if the cache has started successfully."): caches = casadm_parser.get_caches() if len(caches) != 1: - TestRun.fail(f"There is a wrong number of caches found in the OS: {len(caches)}. " - f"Should be only 1.") + TestRun.fail( + f"There is a wrong number of caches found in the OS: {len(caches)}. " + f"Should be only 1." + ) if cache.cache_device.path != cache_device.path: - TestRun.fail(f"The cache has started using a wrong device:" - f" {cache.cache_device.path}." - f"\nShould use {cache_device.path}.") + TestRun.fail( + f"The cache has started using a wrong device:" + f" {cache.cache_device.path}." + f"\nShould use {cache_device.path}." + ) with TestRun.step("Stop the cache."): casadm.stop_cache(cache.cache_id, shortcut=shortcut) @@ -94,8 +106,10 @@ def test_cli_start_stop_custom_id(shortcut): with TestRun.step("Check if the cache has stopped properly."): caches = casadm_parser.get_caches() if len(caches) != 0: - TestRun.fail(f"There is a wrong number of caches found in the OS: {len(caches)}." - f"\nNo cache should be present after stopping the cache.") + TestRun.fail( + f"There is a wrong number of caches found in the OS: {len(caches)}." + f"\nNo cache should be present after stopping the cache." + ) output = casadm.list_caches(shortcut=shortcut) cli_messages.check_stdout_msg(output, cli_messages.no_caches_running) @@ -105,19 +119,20 @@ def test_cli_start_stop_custom_id(shortcut): @pytest.mark.parametrize("shortcut", [True, False]) def test_cli_add_remove_default_id(shortcut): """ - title: Test for adding and removing a core with a default ID - short and long command - description: | - Start a new cache and add a core to it without passing a core ID as an argument - and then remove this core from the cache. - pass_criteria: - - The core is added to the cache with a default ID - - The core is successfully removed from the cache + title: Test for adding and removing a core with a default ID - short and long command + description: | + Start a new cache and add a core to it without passing a core ID as an argument + and then remove this core from the cache. + pass_criteria: + - The core is added to the cache with a default ID + - The core is successfully removed from the cache """ + with TestRun.step("Prepare the devices."): - cache_disk = TestRun.disks['cache'] + cache_disk = TestRun.disks["cache"] cache_disk.create_partitions([Size(50, Unit.MebiByte)]) cache_device = cache_disk.partitions[0] - core_device = TestRun.disks['core'] + core_device = TestRun.disks["core"] with TestRun.step("Start the cache and add the core."): cache = casadm.start_cache(cache_device, shortcut=shortcut, force=True) @@ -156,19 +171,21 @@ def test_cli_add_remove_default_id(shortcut): @pytest.mark.parametrize("shortcut", [True, False]) def test_cli_add_remove_custom_id(shortcut): """ - title: Test for adding and removing a core with a custom ID - short and long command - description: | - Start a new cache and add a core to it with passing a random core ID - (from allowed pool) as an argument and then remove this core from the cache. - pass_criteria: - - The core is added to the cache with a default ID - - The core is successfully removed from the cache + title: Test for adding and removing a core with a custom ID - short and long command + description: | + Start a new cache and add a core to it with passing a random core ID + (from allowed pool) as an argument and then remove this core from the cache. + pass_criteria: + - The core is added to the cache with a default ID + - The core is successfully removed from the cache """ + CORE_ID_RANGE = (0, 4095) + with TestRun.step("Prepare the devices."): - cache_disk = TestRun.disks['cache'] + cache_disk = TestRun.disks["cache"] cache_disk.create_partitions([Size(50, Unit.MebiByte)]) cache_device = cache_disk.partitions[0] - core_device = TestRun.disks['core'] + core_device = TestRun.disks["core"] with TestRun.step("Start the cache and add the core with a random ID."): core_id = randint(*CORE_ID_RANGE) @@ -208,16 +225,17 @@ def test_cli_add_remove_custom_id(shortcut): @pytest.mark.parametrize("shortcut", [True, False]) def test_cli_load_and_force(shortcut): """ - title: Test if it is possible to use start command with 'load' and 'force' flag at once - description: | - Try to start cache with 'load' and 'force' options at the same time - and check if it is not possible to do - pass_criteria: - - Start cache command with both 'force' and 'load' options should fail - - Proper message should be received + title: Test if it is possible to use start command with 'load' and 'force' flag at once + description: | + Try to start cache with 'load' and 'force' options at the same time + and check if it is not possible to do + pass_criteria: + - Start cache command with both 'force' and 'load' options should fail + - Proper message should be received """ + with TestRun.step("Prepare cache."): - cache_device = TestRun.disks['cache'] + cache_device = TestRun.disks["cache"] cache_device.create_partitions([Size(50, Unit.MebiByte)]) cache_device = cache_device.partitions[0] cache = casadm.start_cache(cache_device)