mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Implement `pytest.mark.requires_random_entropy
` marker for simpler usage.
Signed-off-by: Pedro Algarvio <palgarvio@vmware.com>
This commit is contained in:
parent
daf0db7791
commit
af2964f4dd
4 changed files with 103 additions and 33 deletions
|
@ -261,6 +261,16 @@ def pytest_configure(config):
|
|||
"markers",
|
||||
"async_timeout: Timeout, in seconds, for asynchronous test functions(`async def`)",
|
||||
)
|
||||
config.addinivalue_line(
|
||||
"markers",
|
||||
"requires_random_entropy(minimum={}, timeout={}, skip=True): Mark test as "
|
||||
"requiring a minimum value of random entropy. In the case where the value is lower "
|
||||
"than the provided 'minimum', an attempt will be made to raise that value up until "
|
||||
"the provided 'timeout' minutes have passed, at which time, depending on the value "
|
||||
"of 'skip' the test will skip or fail.".format(
|
||||
EntropyGenerator.minimum_entropy, EntropyGenerator.max_minutes
|
||||
),
|
||||
)
|
||||
# "Flag" the slowTest decorator if we're skipping slow tests or not
|
||||
os.environ["SLOW_TESTS"] = str(config.getoption("--run-slow"))
|
||||
|
||||
|
@ -545,6 +555,55 @@ def pytest_runtest_setup(item):
|
|||
)
|
||||
)
|
||||
|
||||
requires_random_entropy_marker = item.get_closest_marker("requires_random_entropy")
|
||||
if requires_random_entropy_marker is not None:
|
||||
if requires_random_entropy_marker.args:
|
||||
raise pytest.UsageError(
|
||||
"'requires_random_entropy' marker does not accept any arguments "
|
||||
"only keyword arguments."
|
||||
)
|
||||
skip = requires_random_entropy_marker.kwargs.pop("skip", None)
|
||||
if skip and not isinstance(skip, bool):
|
||||
raise pytest.UsageError(
|
||||
"The 'skip' keyword argument to the 'requires_random_entropy' marker "
|
||||
"requires a boolean not '{}'.".format(type(skip))
|
||||
)
|
||||
minimum_entropy = requires_random_entropy_marker.kwargs.pop("minimum", None)
|
||||
if minimum_entropy is not None:
|
||||
if not isinstance(minimum_entropy, int):
|
||||
raise pytest.UsageError(
|
||||
"The 'minimum' keyword argument to the 'requires_random_entropy' marker "
|
||||
"must be an integer not '{}'.".format(type(minimum_entropy))
|
||||
)
|
||||
if minimum_entropy <= 0:
|
||||
raise pytest.UsageError(
|
||||
"The 'minimum' keyword argument to the 'requires_random_entropy' marker "
|
||||
"must be an positive integer not '{}'.".format(minimum_entropy)
|
||||
)
|
||||
max_minutes = requires_random_entropy_marker.kwargs.pop("timeout", None)
|
||||
if max_minutes is not None:
|
||||
if not isinstance(max_minutes, int):
|
||||
raise pytest.UsageError(
|
||||
"The 'timeout' keyword argument to the 'requires_random_entropy' marker "
|
||||
"must be an integer not '{}'.".format(type(max_minutes))
|
||||
)
|
||||
if max_minutes <= 0:
|
||||
raise pytest.UsageError(
|
||||
"The 'timeout' keyword argument to the 'requires_random_entropy' marker "
|
||||
"must be an positive integer not '{}'.".format(max_minutes)
|
||||
)
|
||||
if requires_random_entropy_marker.kwargs:
|
||||
raise pytest.UsageError(
|
||||
"Unsupported keyword arguments passed to the 'requires_random_entropy' "
|
||||
"marker: {}".format(
|
||||
", ".join(list(requires_random_entropy_marker.kwargs))
|
||||
)
|
||||
)
|
||||
entropy_generator = EntropyGenerator(
|
||||
minimum_entropy=minimum_entropy, max_minutes=max_minutes, skip=skip
|
||||
)
|
||||
entropy_generator.generate_entropy()
|
||||
|
||||
if salt.utils.platform.is_windows():
|
||||
unit_tests_paths = (
|
||||
str(TESTS_DIR / "unit"),
|
||||
|
|
|
@ -12,6 +12,7 @@ from pytestshellutils.utils.processes import ProcessResult
|
|||
|
||||
pytestmark = [
|
||||
pytest.mark.skip_if_binaries_missing("gpg"),
|
||||
pytest.mark.requires_random_entropy,
|
||||
]
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
|
|
@ -15,12 +15,12 @@ import pytest
|
|||
import salt.modules.gpg as gpg
|
||||
from salt.exceptions import SaltInvocationError
|
||||
from tests.support.mock import MagicMock, patch
|
||||
from tests.support.pytest.helpers import EntropyGenerator
|
||||
|
||||
pytest.importorskip("gnupg")
|
||||
|
||||
pytestmark = [
|
||||
pytest.mark.skip_unless_on_linux,
|
||||
pytest.mark.requires_random_entropy,
|
||||
]
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
@ -157,12 +157,6 @@ OZV2Hg+93dg3Wi6g/JW4OuTKWKuHRqpRB1J4i4lO
|
|||
"""
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def entropy_generation():
|
||||
with EntropyGenerator():
|
||||
yield
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def gpghome(tmp_path):
|
||||
root = tmp_path / "gpghome"
|
||||
|
|
|
@ -614,9 +614,18 @@ class FakeSaltExtension:
|
|||
|
||||
|
||||
class EntropyGenerator:
|
||||
def __init__(self, max_minutes=5, minimum_entropy=800):
|
||||
self.max_minutes = max_minutes
|
||||
self.minimum_entropy = minimum_entropy
|
||||
max_minutes = 5
|
||||
minimum_entropy = 800
|
||||
|
||||
def __init__(self, max_minutes=None, minimum_entropy=None, skip=None):
|
||||
if max_minutes is not None:
|
||||
self.max_minutes = max_minutes
|
||||
if minimum_entropy is not None:
|
||||
self.minimum_entropy = minimum_entropy
|
||||
if skip is None:
|
||||
skip = True
|
||||
self.skip = skip
|
||||
self.current_entropy = 0
|
||||
|
||||
def generate_entropy(self):
|
||||
max_time = self.max_minutes * 60
|
||||
|
@ -625,9 +634,9 @@ class EntropyGenerator:
|
|||
log.info("The '%s' file is not avilable", kernel_entropy_file)
|
||||
return
|
||||
|
||||
available_entropy = int(kernel_entropy_file.read_text().strip())
|
||||
log.info("Available Entropy: %s", available_entropy)
|
||||
if available_entropy >= self.minimum_entropy:
|
||||
self.current_entropy = int(kernel_entropy_file.read_text().strip())
|
||||
log.info("Available Entropy: %s", self.current_entropy)
|
||||
if self.current_entropy >= self.minimum_entropy:
|
||||
return
|
||||
|
||||
exc_kwargs = {}
|
||||
|
@ -641,29 +650,33 @@ class EntropyGenerator:
|
|||
log.info("Using rngd to generate entropy")
|
||||
while True:
|
||||
if time.time() >= timeout:
|
||||
raise pytest.skip.Exception(
|
||||
message = (
|
||||
"Skipping test as generating entropy took more than {} minutes. "
|
||||
"Current entropy value {}".format(
|
||||
self.max_minutes, available_entropy
|
||||
),
|
||||
**exc_kwargs
|
||||
self.max_minutes, self.current_entropy
|
||||
)
|
||||
)
|
||||
if self.skip:
|
||||
raise pytest.skip.Exception(message, **exc_kwargs)
|
||||
raise pytest.fail(message)
|
||||
subprocess.run([rngd, "-r", "/dev/urandom"], shell=False, check=True)
|
||||
available_entropy = int(kernel_entropy_file.read_text().strip())
|
||||
log.info("Available Entropy: %s", available_entropy)
|
||||
if available_entropy >= self.minimum_entropy:
|
||||
self.current_entropy = int(kernel_entropy_file.read_text().strip())
|
||||
log.info("Available Entropy: %s", self.current_entropy)
|
||||
if self.current_entropy >= self.minimum_entropy:
|
||||
break
|
||||
elif openssl:
|
||||
log.info("Using openssl to generate entropy")
|
||||
while True:
|
||||
if time.time() >= timeout:
|
||||
raise pytest.skip.Exception(
|
||||
message = (
|
||||
"Skipping test as generating entropy took more than {} minutes. "
|
||||
"Current entropy value {}".format(
|
||||
self.max_minutes, available_entropy
|
||||
),
|
||||
**exc_kwargs
|
||||
self.max_minutes, self.current_entropy
|
||||
)
|
||||
)
|
||||
if self.skip:
|
||||
raise pytest.skip.Exception(message, **exc_kwargs)
|
||||
raise pytest.fail(message)
|
||||
|
||||
target_file = tempfile.NamedTemporaryFile(
|
||||
delete=False, suffix="sample.txt"
|
||||
|
@ -671,7 +684,7 @@ class EntropyGenerator:
|
|||
target_file.close()
|
||||
subprocess.run(
|
||||
[
|
||||
"openssl",
|
||||
openssl,
|
||||
"rand",
|
||||
"-out",
|
||||
target_file.name,
|
||||
|
@ -682,17 +695,20 @@ class EntropyGenerator:
|
|||
check=True,
|
||||
)
|
||||
os.unlink(target_file.name)
|
||||
available_entropy = int(kernel_entropy_file.read_text().strip())
|
||||
log.info("Available Entropy: %s", available_entropy)
|
||||
if available_entropy >= self.minimum_entropy:
|
||||
self.current_entropy = int(kernel_entropy_file.read_text().strip())
|
||||
log.info("Available Entropy: %s", self.current_entropy)
|
||||
if self.current_entropy >= self.minimum_entropy:
|
||||
break
|
||||
else:
|
||||
raise pytest.skip.Exception(
|
||||
"Skipping test as there's not enough entropy({}) to continue".format(
|
||||
available_entropy
|
||||
),
|
||||
**exc_kwargs
|
||||
message = (
|
||||
"Skipping test as there's not enough entropy({}) to continue and "
|
||||
"neither 'rgn-tools' nor 'openssl' is available on the system.".format(
|
||||
self.current_entropy
|
||||
)
|
||||
)
|
||||
if self.skip:
|
||||
raise pytest.skip.Exception(message, **exc_kwargs)
|
||||
raise pytest.fail(message)
|
||||
|
||||
def __enter__(self):
|
||||
self.generate_entropy()
|
||||
|
|
Loading…
Add table
Reference in a new issue