File several-fixes-for-tests-to-avoid-errors-and-failures.patch of Package salt
From 57da53c94b9c31003e896d54a585a75155c6c4e6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
Date: Mon, 27 May 2024 12:01:53 +0100
Subject: [PATCH] Several fixes for tests to avoid errors and failures
in some OSes
* test_pip_state: skip tests which requires virtualenv CLI
* test_syndic_eauth: skip when using an incompatible Docker version
* test_pip: skip tests which requires virtualenv CLI
* Some more extra fixes for tests
* Enhance paths to look for 'sftp-server'
* Do trigger errors on newer docker-py version
* Make test_search_not_found to not fail on transactional systems
* Add `@pytest.mark.flaky_jail` to `tests/pytests/integration/ssh/test_ssh_setup.py::test_setup`
Signed-off-by: Pedro Algarvio <palgarvio@vmware.com>
* Prevent crashing if mountpoint does not exist anymore
* Skip failing tests on transactional systems
* test_consul.py: do not produce error if consul is not available
* Redefine max retries for some flaky tests
* test_virt.py: skip as CI containers are not compatible with Salt 3006
* test_schema.py: Adjust expectations to newer jsonschema versions
* Apply suggestions from code review
Co-authored-by: Pedro Algarvio <pedro@algarvio.me>
---------
Signed-off-by: Pedro Algarvio <palgarvio@vmware.com>
Co-authored-by: Pedro Algarvio <palgarvio@vmware.com>
Co-authored-by: Pedro Algarvio <pedro@algarvio.me>
---
salt/modules/status.py | 11 +++---
tests/conftest.py | 2 +
tests/pytests/functional/cache/test_consul.py | 4 ++
tests/pytests/functional/modules/test_pip.py | 4 ++
.../functional/states/test_pip_state.py | 11 ++++++
tests/pytests/functional/states/test_pkg.py | 4 ++
.../integration/cli/test_syndic_eauth.py | 2 +-
.../integration/daemons/test_memory_leak.py | 2 +-
.../integration/modules/test_cmdmod.py | 1 +
.../integration/ssh/test_pre_flight.py | 4 ++
tests/pytests/scenarios/setup/test_man.py | 6 +++
tests/unit/utils/test_schema.py | 37 +++++++++++++++----
12 files changed, 73 insertions(+), 15 deletions(-)
diff --git a/salt/modules/status.py b/salt/modules/status.py
index 71fa6f49cc..1b21dfb4d6 100644
--- a/salt/modules/status.py
+++ b/salt/modules/status.py
@@ -1050,11 +1050,12 @@ def diskusage(*args):
# query the filesystems disk usage
ret = {}
for path in selected:
- fsstats = os.statvfs(path)
- blksz = fsstats.f_bsize
- available = fsstats.f_bavail * blksz
- total = fsstats.f_blocks * blksz
- ret[path] = {"available": available, "total": total}
+ if os.path.exists(path):
+ fsstats = os.statvfs(path)
+ blksz = fsstats.f_bsize
+ available = fsstats.f_bavail * blksz
+ total = fsstats.f_blocks * blksz
+ ret[path] = {"available": available, "total": total}
return ret
diff --git a/tests/conftest.py b/tests/conftest.py
index 1d283a8bbc..cc27415da2 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -1389,6 +1389,8 @@ def sshd_server(salt_factories, sshd_config_dir, salt_master, grains):
"/usr/lib/ssh/sftp-server",
# Photon OS 5
"/usr/libexec/sftp-server",
+ # openSUSE Tumbleweed and SL Micro 6.0
+ "/usr/libexec/ssh/sftp-server",
]
sftp_server_path = None
for path in sftp_server_paths:
diff --git a/tests/pytests/functional/cache/test_consul.py b/tests/pytests/functional/cache/test_consul.py
index 460928d850..c1e7f0c225 100644
--- a/tests/pytests/functional/cache/test_consul.py
+++ b/tests/pytests/functional/cache/test_consul.py
@@ -11,6 +11,10 @@ import salt.loader
from salt.utils.versions import Version
from tests.pytests.functional.cache.helpers import run_common_cache_tests
+pytest.importorskip(
+ "consul",
+ reason="Please install python-consul package to use consul data cache driver",
+)
docker = pytest.importorskip("docker")
log = logging.getLogger(__name__)
diff --git a/tests/pytests/functional/modules/test_pip.py b/tests/pytests/functional/modules/test_pip.py
index fa2b1a6573..e3656a34da 100644
--- a/tests/pytests/functional/modules/test_pip.py
+++ b/tests/pytests/functional/modules/test_pip.py
@@ -78,6 +78,10 @@ def _pip_successful_install(
"pip>=21.0",
),
)
+
+@pytest.mark.requires_network
+@pytest.mark.slow_test
+@pytest.mark.skip_if_binaries_missing("virtualenv", reason="Needs virtualenv binary")
def test_list_available_packages(pip, pip_version, tmp_path):
with VirtualEnv(venv_dir=tmp_path, pip_requirement=pip_version) as virtualenv:
virtualenv.install("-U", pip_version)
diff --git a/tests/pytests/functional/states/test_pip_state.py b/tests/pytests/functional/states/test_pip_state.py
index e23b1f15f6..84bca06924 100644
--- a/tests/pytests/functional/states/test_pip_state.py
+++ b/tests/pytests/functional/states/test_pip_state.py
@@ -117,6 +117,7 @@ def test_pip_installed_removed(states, pkg_name):
@pytest.mark.slow_test
+@pytest.mark.skip_if_binaries_missing("virtualenv", reason="Needs virtualenv binary")
def test_pip_installed_removed_venv(states, venv, pkg_name):
ret = states.pip.installed(name=pkg_name, bin_env=str(venv.venv_dir))
assert ret.result is True
@@ -125,6 +126,7 @@ def test_pip_installed_removed_venv(states, venv, pkg_name):
@pytest.mark.slow_test
+@pytest.mark.skip_if_binaries_missing("virtualenv", reason="Needs virtualenv binary")
def test_pip_installed_errors(tmp_path, modules, state_tree):
venv_dir = tmp_path / "pip-installed-errors"
# Since we don't have the virtualenv created, pip.installed will
@@ -156,6 +158,7 @@ def test_pip_installed_errors(tmp_path, modules, state_tree):
assert state_return.result is True
+@pytest.mark.skip_if_binaries_missing("virtualenv", reason="Needs virtualenv binary")
def test_pip_installed_name_test_mode(states, venv, pkg_name):
"""
Test pip.installed state while test=true
@@ -164,6 +167,7 @@ def test_pip_installed_name_test_mode(states, venv, pkg_name):
assert pkg_name in ret.comment
+@pytest.mark.skip_if_binaries_missing("virtualenv", reason="Needs virtualenv binary")
def test_pip_installed_pkgs_test_mode(states, venv):
"""
Test pip.installed state while test=true
@@ -177,6 +181,7 @@ def test_pip_installed_pkgs_test_mode(states, venv):
@pytest.mark.slow_test
+@pytest.mark.skip_if_binaries_missing("virtualenv", reason="Needs virtualenv binary")
def test_issue_2028_pip_installed_state(
tmp_path, modules, state_tree, get_python_executable
):
@@ -234,6 +239,7 @@ def test_issue_2028_pip_installed_state(
@pytest.mark.slow_test
+@pytest.mark.skip_if_binaries_missing("virtualenv", reason="Needs virtualenv binary")
def test_issue_2087_missing_pip(modules, venv, pkg_name, state_tree):
sls_name = "issue-2087-missing-pip"
sls_contents = f"""
@@ -276,6 +282,7 @@ def test_issue_2087_missing_pip(modules, venv, pkg_name, state_tree):
@pytest.mark.destructive_test
@pytest.mark.slow_test
@pytest.mark.skip_if_not_root
+@pytest.mark.skip_if_binaries_missing("virtualenv", reason="Needs virtualenv binary")
def test_issue_6912_wrong_owner(tmp_path, create_virtualenv, states, account):
# Setup virtual environment directory to be used throughout the test
venv_dir = tmp_path / "6912-wrong-owner"
@@ -333,6 +340,7 @@ def test_issue_6912_wrong_owner(tmp_path, create_virtualenv, states, account):
@pytest.mark.skip_on_darwin(reason="Test is flaky on macosx")
@pytest.mark.slow_test
@pytest.mark.skip_if_not_root
+@pytest.mark.skip_if_binaries_missing("virtualenv", reason="Needs virtualenv binary")
def test_issue_6912_wrong_owner_requirements_file(
tmp_path, create_virtualenv, state_tree, states, account
):
@@ -394,6 +402,7 @@ def test_issue_6912_wrong_owner_requirements_file(
@pytest.mark.destructive_test
@pytest.mark.slow_test
+@pytest.mark.skip_if_binaries_missing("virtualenv", reason="Needs virtualenv binary")
def test_issue_6833_pip_upgrade_pip(tmp_path, create_virtualenv, modules, states):
# Create the testing virtualenv
if sys.platform == "win32":
@@ -450,6 +459,7 @@ def test_issue_6833_pip_upgrade_pip(tmp_path, create_virtualenv, modules, states
@pytest.mark.slow_test
+@pytest.mark.skip_if_binaries_missing("virtualenv", reason="Needs virtualenv binary")
def test_pip_installed_specific_env(state_tree_prod, states, venv):
contents = "pep8\n"
@@ -492,6 +502,7 @@ def test_pip_installed_specific_env(state_tree_prod, states, venv):
@pytest.mark.slow_test
+@pytest.mark.skip_if_binaries_missing("virtualenv", reason="Needs virtualenv binary")
def test_22359_pip_installed_unless_does_not_trigger_warnings(states, venv):
# This test case should be moved to a format_call unit test specific to
# the state internal keywords
diff --git a/tests/pytests/functional/states/test_pkg.py b/tests/pytests/functional/states/test_pkg.py
index 68b2cb843d..c6667c2144 100644
--- a/tests/pytests/functional/states/test_pkg.py
+++ b/tests/pytests/functional/states/test_pkg.py
@@ -21,6 +21,10 @@ pytestmark = [
pytest.mark.skip_if_not_root,
pytest.mark.destructive_test,
pytest.mark.timeout_unless_on_windows(650),
+ pytest.mark.skipif(
+ bool(salt.utils.path.which("transactional-update")),
+ reason="Skipping on transactional systems",
+ ),
]
diff --git a/tests/pytests/integration/cli/test_syndic_eauth.py b/tests/pytests/integration/cli/test_syndic_eauth.py
index 868f596b11..d59014c491 100644
--- a/tests/pytests/integration/cli/test_syndic_eauth.py
+++ b/tests/pytests/integration/cli/test_syndic_eauth.py
@@ -9,7 +9,7 @@ import pytest
from tests.conftest import CODE_DIR
-docker = pytest.importorskip("docker")
+docker = pytest.importorskip("docker", minversion="4.0.0")
log = logging.getLogger(__name__)
diff --git a/tests/pytests/integration/daemons/test_memory_leak.py b/tests/pytests/integration/daemons/test_memory_leak.py
index 92984acbe8..f5af28029c 100644
--- a/tests/pytests/integration/daemons/test_memory_leak.py
+++ b/tests/pytests/integration/daemons/test_memory_leak.py
@@ -56,7 +56,7 @@ def file_add_delete_sls(tmp_path, salt_master):
@pytest.mark.skip(reason="Flawed test")
@pytest.mark.skip_on_darwin(reason="MacOS is a spawning platform, won't work")
@pytest.mark.skipif(GITHUB_ACTIONS, reason="Test is failing in GitHub Actions")
-@pytest.mark.flaky(max_runs=4)
+@pytest.mark.flaky(max_runs=10)
def test_memory_leak(salt_cli, salt_minion, file_add_delete_sls):
max_usg = None
diff --git a/tests/pytests/integration/modules/test_cmdmod.py b/tests/pytests/integration/modules/test_cmdmod.py
index d9c326c3f0..d0b993ddbc 100644
--- a/tests/pytests/integration/modules/test_cmdmod.py
+++ b/tests/pytests/integration/modules/test_cmdmod.py
@@ -63,6 +63,7 @@ def test_avoid_injecting_shell_code_as_root(
@pytest.mark.slow_test
+@pytest.mark.flaky(max_runs=4)
def test_blacklist_glob(salt_call_cli):
"""
cmd_blacklist_glob
diff --git a/tests/pytests/integration/ssh/test_pre_flight.py b/tests/pytests/integration/ssh/test_pre_flight.py
index 7dc56f3753..7bc43edd57 100644
--- a/tests/pytests/integration/ssh/test_pre_flight.py
+++ b/tests/pytests/integration/ssh/test_pre_flight.py
@@ -230,6 +230,10 @@ def demote(user_uid, user_gid):
@pytest.mark.slow_test
+@pytest.mark.skipif(
+ bool(salt.utils.path.which("transactional-update")),
+ reason="Skipping on transactional systems",
+)
def test_ssh_pre_flight_perms(salt_ssh_cli, caplog, _create_roster, account):
"""
Test to ensure standard user cannot run pre flight script
diff --git a/tests/pytests/scenarios/setup/test_man.py b/tests/pytests/scenarios/setup/test_man.py
index 92b91e8e6d..ad748d2758 100644
--- a/tests/pytests/scenarios/setup/test_man.py
+++ b/tests/pytests/scenarios/setup/test_man.py
@@ -9,6 +9,9 @@ import pytest
import salt.utils.platform
from salt.modules.virtualenv_mod import KNOWN_BINARY_NAMES
+from tests.conftest import CODE_DIR
+
+MISSING_SETUP_PY_FILE = not CODE_DIR.joinpath("setup.py").exists()
pytestmark = [
pytest.mark.core_test,
@@ -16,6 +19,9 @@ pytestmark = [
pytest.mark.skip_on_aix,
pytest.mark.skip_initial_onedir_failure,
pytest.mark.skip_if_binaries_missing(*KNOWN_BINARY_NAMES, check_all=False),
+ pytest.mark.skipif(
+ MISSING_SETUP_PY_FILE, reason="This test only work if setup.py is available"
+ ),
]
diff --git a/tests/unit/utils/test_schema.py b/tests/unit/utils/test_schema.py
index ebe3698978..5343726e12 100644
--- a/tests/unit/utils/test_schema.py
+++ b/tests/unit/utils/test_schema.py
@@ -531,7 +531,9 @@ class ConfigTestCase(TestCase):
jsonschema.validate(
{"personal_access_token": "foo"}, Requirements.serialize()
)
- if JSONSCHEMA_VERSION >= Version("3.0.0"):
+ if JSONSCHEMA_VERSION >= Version("3.0.0") and JSONSCHEMA_VERSION < Version(
+ "4.8.0"
+ ):
self.assertIn(
"'ssh_key_file' is a required property", excinfo.exception.message
)
@@ -899,13 +901,20 @@ class ConfigTestCase(TestCase):
except jsonschema.exceptions.ValidationError as exc:
self.fail(f"ValidationError raised: {exc}")
- with self.assertRaises(jsonschema.exceptions.ValidationError) as excinfo:
+ if JSONSCHEMA_VERSION < Version("4.0.0"):
+ with self.assertRaises(jsonschema.exceptions.ValidationError) as excinfo:
+ jsonschema.validate(
+ {"item": "3"},
+ TestConf.serialize(),
+ format_checker=jsonschema.FormatChecker(),
+ )
+ self.assertIn("is not a", excinfo.exception.message)
+ else:
jsonschema.validate(
{"item": "3"},
TestConf.serialize(),
format_checker=jsonschema.FormatChecker(),
)
- self.assertIn("is not a", excinfo.exception.message)
def test_datetime_config(self):
item = schema.DateTimeItem(title="Foo", description="Foo Item")
@@ -1878,7 +1887,9 @@ class ConfigTestCase(TestCase):
jsonschema.validate(
{"item": {"sides": "4", "color": "blue"}}, TestConf.serialize()
)
- if JSONSCHEMA_VERSION >= Version("3.0.0"):
+ if JSONSCHEMA_VERSION >= Version("3.0.0") and JSONSCHEMA_VERSION < Version(
+ "4.8.0"
+ ):
self.assertIn("'4'", excinfo.exception.message)
self.assertIn("is not of type", excinfo.exception.message)
self.assertIn("'boolean'", excinfo.exception.message)
@@ -2003,7 +2014,9 @@ class ConfigTestCase(TestCase):
with self.assertRaises(jsonschema.exceptions.ValidationError) as excinfo:
jsonschema.validate({"item": ["maybe"]}, TestConf.serialize())
- if JSONSCHEMA_VERSION >= Version("3.0.0"):
+ if JSONSCHEMA_VERSION >= Version("3.0.0") and JSONSCHEMA_VERSION < Version(
+ "4.8.0"
+ ):
self.assertIn("'maybe'", excinfo.exception.message)
self.assertIn("is not one of", excinfo.exception.message)
self.assertIn("'yes'", excinfo.exception.message)
@@ -2067,7 +2080,9 @@ class ConfigTestCase(TestCase):
with self.assertRaises(jsonschema.exceptions.ValidationError) as excinfo:
jsonschema.validate({"item": ["maybe"]}, TestConf.serialize())
- if JSONSCHEMA_VERSION >= Version("3.0.0"):
+ if JSONSCHEMA_VERSION >= Version("3.0.0") and JSONSCHEMA_VERSION < Version(
+ "4.8.0"
+ ):
self.assertIn("'maybe'", excinfo.exception.message)
self.assertIn("is not one of", excinfo.exception.message)
self.assertIn("'yes'", excinfo.exception.message)
@@ -2154,11 +2169,17 @@ class ConfigTestCase(TestCase):
with self.assertRaises(jsonschema.exceptions.ValidationError) as excinfo:
jsonschema.validate({"item": [True]}, TestConf.serialize())
- self.assertIn("is not allowed for", excinfo.exception.message)
+ if JSONSCHEMA_VERSION >= Version("4.0.0"):
+ self.assertIn("should not be valid under", excinfo.exception.message)
+ else:
+ self.assertIn("is not allowed for", excinfo.exception.message)
with self.assertRaises(jsonschema.exceptions.ValidationError) as excinfo:
jsonschema.validate({"item": [False]}, TestConf.serialize())
- self.assertIn("is not allowed for", excinfo.exception.message)
+ if JSONSCHEMA_VERSION >= Version("4.0.0"):
+ self.assertIn("should not be valid under", excinfo.exception.message)
+ else:
+ self.assertIn("is not allowed for", excinfo.exception.message)
def test_item_name_override_class_attrname(self):
class TestConf(schema.Schema):
--
2.47.0