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

openSUSE Build Service is sponsored by