From d4a8ae5e59b45221c139869c56ad69daaee332d3 Mon Sep 17 00:00:00 2001 From: Shwetha K Acharya Date: Thu, 12 Oct 2023 14:42:03 +0530 Subject: [PATCH] Introduce setup and teardown fixtures With this change, multiple test modules triggered from testcases/mount can be run as individual tests complying to pytest standards. Also any number of new tests can be added efficiently on the mount. Fixes: #30 Signed-off-by: Shwetha K Acharya --- conftest.py | 47 ++++++++++++++++ testcases/mount/test_mount.py | 56 ------------------- .../mount/{mount_dbm.py => test_mount_dbm.py} | 21 ++++++- .../mount/{mount_io.py => test_mount_io.py} | 20 +++++-- testhelper/testhelper.py | 18 +++++- 5 files changed, 99 insertions(+), 63 deletions(-) delete mode 100755 testcases/mount/test_mount.py rename testcases/mount/{mount_dbm.py => test_mount_dbm.py} (84%) mode change 100644 => 100755 rename testcases/mount/{mount_io.py => test_mount_io.py} (85%) mode change 100644 => 100755 diff --git a/conftest.py b/conftest.py index e69de29..c353914 100644 --- a/conftest.py +++ b/conftest.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python3 + +import pytest +import os +import shutil +import testhelper +import typing + +flag_mounted: bool = False +tmp_root: str +test_dir: str + + +@pytest.fixture +def setup_mount(ipaddr: str, share_name: str) -> str: + global flag_mounted, tmp_root, test_dir + try: + mount_params = testhelper.get_mount_parameters( + os.getenv("TEST_INFO_FILE"), share_name + ) + mount_params["host"] = ipaddr + tmp_root = testhelper.get_tmp_root() + mount_point = testhelper.get_tmp_mount_point(tmp_root) + + # mount cifs share + testhelper.cifs_mount(mount_params, mount_point) + flag_mounted = True + test_dir = mount_point + "/mount_test" + os.mkdir(test_dir) + except Exception as e: + raise Exception(f"Setup failed: {str(e)}") + return test_dir + + +@pytest.fixture +def teardown_mount(mount_point: str) -> typing.Generator[None, str, None]: + yield + + global flag_mounted, tmp_root, test_dir + try: + if flag_mounted: + shutil.rmtree(test_dir, ignore_errors=True) + testhelper.cifs_umount(mount_point) + os.rmdir(mount_point) + os.rmdir(tmp_root) + except Exception as e: + raise Exception(f"Teardown failed: {str(e)}") diff --git a/testcases/mount/test_mount.py b/testcases/mount/test_mount.py deleted file mode 100755 index 320ff2a..0000000 --- a/testcases/mount/test_mount.py +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env python3 - -# Test mounts a cifs share, creates a new file on it, writes to it, -# deletes the file and unmounts - -import testhelper -import os -import pytest -import typing -import shutil - -from .mount_io import check_io_consistency -from .mount_dbm import check_dbm_consistency - -test_info = os.getenv("TEST_INFO_FILE") -test_info_dict = testhelper.read_yaml(test_info) - - -def mount_check(ipaddr: str, share_name: str) -> None: - mount_params = testhelper.get_mount_parameters(test_info_dict, share_name) - mount_params["host"] = ipaddr - tmp_root = testhelper.get_tmp_root() - mount_point = testhelper.get_tmp_mount_point(tmp_root) - flag_mounted = False - try: - testhelper.cifs_mount(mount_params, mount_point) - flag_mounted = True - test_dir = mount_point + "/mount_test" - os.mkdir(test_dir) - check_io_consistency(test_dir) - check_dbm_consistency(test_dir) - finally: - if flag_mounted: - shutil.rmtree(test_dir, ignore_errors=True) - testhelper.cifs_umount(mount_point) - os.rmdir(mount_point) - os.rmdir(tmp_root) - - -def generate_mount_check( - test_info_file: dict, -) -> typing.List[typing.Tuple[str, str]]: - if not test_info_file: - return [] - arr = [] - for ipaddr in test_info_file["public_interfaces"]: - for share_name in test_info_file["exported_sharenames"]: - arr.append((ipaddr, share_name)) - return arr - - -@pytest.mark.parametrize( - "ipaddr,share_name", generate_mount_check(test_info_dict) -) -def test_mount(ipaddr: str, share_name: str) -> None: - mount_check(ipaddr, share_name) diff --git a/testcases/mount/mount_dbm.py b/testcases/mount/test_mount_dbm.py old mode 100644 new mode 100755 similarity index 84% rename from testcases/mount/mount_dbm.py rename to testcases/mount/test_mount_dbm.py index eb25ed7..9f2c2c3 --- a/testcases/mount/mount_dbm.py +++ b/testcases/mount/test_mount_dbm.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 # Test various database operations via SMB mount-point. +import pytest import dbm import hashlib import pickle @@ -8,6 +9,8 @@ import shutil import typing import random +import os +import testhelper class Record: @@ -89,8 +92,21 @@ def _check_dbm_consistency(base: pathlib.Path, nrecs: int) -> None: db.destroy() -def check_dbm_consistency(rootdir: str) -> None: - base = pathlib.Path(rootdir) / "dbm-consistency" +test_info_file = os.getenv("TEST_INFO_FILE") + + +@pytest.mark.parametrize( + "ipaddr,share_name", testhelper.generate_mount_check(test_info_file) +) +def test_check_dbm_consistency( + ipaddr: str, + sharename: str, + rootdir: str, + setup_mount: typing.Any, + teardown_mount: typing.Any, +) -> None: + mount_point = setup_mount(ipaddr, sharename) + base = pathlib.Path(mount_point) / "dbm-consistency" base.mkdir(parents=True, exist_ok=True) try: _check_dbm_consistency(base, 10) @@ -98,3 +114,4 @@ def check_dbm_consistency(rootdir: str) -> None: _check_dbm_consistency(base, 10000) finally: shutil.rmtree(base, ignore_errors=True) + teardown_mount(mount_point) diff --git a/testcases/mount/mount_io.py b/testcases/mount/test_mount_io.py old mode 100644 new mode 100755 similarity index 85% rename from testcases/mount/mount_io.py rename to testcases/mount/test_mount_io.py index 8e642dd..8478c6d --- a/testcases/mount/mount_io.py +++ b/testcases/mount/test_mount_io.py @@ -2,12 +2,15 @@ # Test various file-system I/O operations via local SMB mount-point. +import pytest import datetime import pathlib import shutil import typing import testhelper import random +import os +from typing import Any class DataPath: @@ -101,11 +104,11 @@ def _run_checks(dsets: typing.List[DataPath]) -> None: dset.verify_noent() -def _check_io_consistency(rootdir: str) -> None: +def _check_io_consistency(test_dir: str) -> None: base = None try: print("\n") - base = pathlib.Path(rootdir) / "test_io_consistency" + base = pathlib.Path(test_dir) / "test_io_consistency" base.mkdir(parents=True) # Case-1: single 4K file _run_checks(_make_datasets(base, 4096, 1)) @@ -129,6 +132,15 @@ def _reset_random_seed() -> None: random.seed(seed) -def check_io_consistency(rootdir: str) -> None: +@pytest.mark.parametrize( + "ipaddr,share_name", + testhelper.generate_mount_check(os.getenv("TEST_INFO_FILE")), +) +def test_check_io_consistency( + ipaddr: str, share_name: str, setup_mount: Any, teardown_mount: Any +) -> None: + print("%s - %s" % (ipaddr, share_name)) _reset_random_seed() - _check_io_consistency(rootdir) + mount_point = setup_mount(ipaddr, share_name) + _check_io_consistency(mount_point) + teardown_mount(mount_point) diff --git a/testhelper/testhelper.py b/testhelper/testhelper.py index a3d4876..b523bb1 100644 --- a/testhelper/testhelper.py +++ b/testhelper/testhelper.py @@ -2,6 +2,8 @@ import typing import random +test_info: typing.Dict[str, typing.Any] = {} + def read_yaml(test_info): """Returns a dict containing the contents of the yaml file. @@ -72,7 +74,7 @@ def get_total_mount_parameter_combinations(test_info: dict) -> int: def get_mount_parameters( - test_info: dict, share: str, combonum: int = 0 + test_info_file: typing.Optional[str], share: str, combonum: int = 0 ) -> typing.Dict[str, str]: """Get the mount_params dict for a given share and given combination number @@ -137,3 +139,17 @@ def generate_random_bytes(size: int) -> bytes: else: rbytes = rba + rbytes + rba + rbytes return rbytes[:size] + + +def generate_mount_check( + test_info_file: typing.Optional[str], +) -> typing.List[typing.Tuple[str, str]]: + global test_info + if not test_info_file: + return [] + test_info = read_yaml(test_info_file) + arr = [] + for ipaddr in test_info["public_interfaces"]: + for share_name in test_info["exported_sharenames"]: + arr.append((ipaddr, share_name)) + return arr