Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions conftest.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,32 @@
import logging
import pytest

from os.path import splitext
from tests.utils.gen_utils import GenUtils

logger: logging.Logger = logging.getLogger("conftest")


def pytest_runtest_logreport(report: pytest.TestReport) -> None:
if report.outcome != "rerun": # type: ignore - pytest-rerunfailures sets this outcome
return

message: str

try:
crash_msg = report.longrepr.reprcrash.message # type: ignore
message = str(crash_msg) if crash_msg is not None else "" # type: ignore
except AttributeError:
message = report.longreprtext
except Exception as e:
message = str(e)

if len(message) == 0:
message = "Unknwon"

logger.error(f"EXPECTED FAILURE: {message}")
logger.warning(f"RERUN {report.nodeid}")


def pytest_configure(config: pytest.Config) -> None:
# inject current date/time into the configured log file name
Expand Down
22 changes: 11 additions & 11 deletions tests/test_gen_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,24 @@ class TestGenUtils(BaseTestClass):
#region uuid / wait_for / bool_equals

def test_get_uuid_format_and_uniqueness(self) -> None:
uuid1 = GenUtils.get_uuid()
uuid2 = GenUtils.get_uuid()
uuid1: str = GenUtils.get_uuid()
uuid2: str = GenUtils.get_uuid()
logger.debug(f"get_uuid(): {uuid1}, {uuid2}")
assert _UUID_RE.match(uuid1), f"not a UUID: {uuid1}"
assert _UUID_RE.match(uuid2), f"not a UUID: {uuid2}"
assert uuid1 != uuid2

def test_wait_for_blocks_for_at_least_duration(self) -> None:
start = time.monotonic()
start: float = time.monotonic()
GenUtils.wait_for(50)
elapsed_ms = (time.monotonic() - start) * 1000
elapsed_ms: float = (time.monotonic() - start) * 1000
logger.debug(f"wait_for(50) actually took {elapsed_ms:.1f} ms")
assert elapsed_ms >= 50

def test_wait_for_zero_does_not_block(self) -> None:
start = time.monotonic()
start: float = time.monotonic()
GenUtils.wait_for(0)
elapsed_ms = (time.monotonic() - start) * 1000
elapsed_ms: float = (time.monotonic() - start) * 1000
assert elapsed_ms < 50

def test_wait_for_negative_raises(self) -> None:
Expand Down Expand Up @@ -125,27 +125,27 @@ def test_reconcile_uint64_resolve_max_false_picks_lesser(self) -> None:

#region reconcile values

@pytest.mark.xfail(reason="gen_utils::reconcile()'s resolve_true branch casts the boost::optional wrapper to bool instead of its value, so it always returns val1 (ignoring which operand is actually true)", strict=True)
@pytest.mark.xfail(reason="gen_utils::reconcile()'s bug", strict=True)
def test_reconcile_bool_resolve_true_prefers_the_true_operand(self) -> None:
# val1=False, val2=True, resolve_true=True -> should prefer the
# operand that IS true, i.e. val2
result = GenUtils.reconcile_bool(False, True, resolve_true=True)
result: bool | None = GenUtils.reconcile_bool(False, True, resolve_true=True)
logger.debug(f"reconcile_bool(False, True, resolve_true=True) = {result}")
assert result is True

@pytest.mark.xfail(reason="gen_utils::reconcile()'s resolve_true branch casts the boost::optional wrapper to bool instead of its value, so it always returns val2 for resolve_true=False (ignoring which operand is actually false)", strict=True)
@pytest.mark.xfail(reason="gen_utils::reconcile()'s bug", strict=True)
def test_reconcile_bool_resolve_true_false_prefers_the_false_operand(self) -> None:
# val1=False, val2=True, resolve_true=False -> should prefer the
# operand that IS false, i.e. val1
result = GenUtils.reconcile_bool(False, True, resolve_true=False)
result: bool | None = GenUtils.reconcile_bool(False, True, resolve_true=False)
logger.debug(f"reconcile_bool(False, True, resolve_true=False) = {result}")
assert result is False

@pytest.mark.xfail(reason="same resolve_true bug as reconcile_bool, reproduced with the uint64 overload to show it isn't bool-specific", strict=True)
def test_reconcile_uint64_resolve_true_prefers_the_true_operand(self) -> None:
# val1=0 (falsy), val2=1 (truthy), resolve_true=True -> should prefer
# val2 since it's the operand whose bool cast is True
result = GenUtils.reconcile_uint64(0, 1, resolve_true=True)
result: int | None = GenUtils.reconcile_uint64(0, 1, resolve_true=True)
logger.debug(f"reconcile_uint64(0, 1, resolve_true=True) = {result}")
assert result == 1

Expand Down
19 changes: 5 additions & 14 deletions tests/test_monero_common.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import pytest
import logging

from json import loads

from monero import (
SerializableStruct, SslOptions,
MoneroError, MoneroRpcError
)

from utils import BaseTestClass
from utils import BaseTestClass, AssertUtils

logger: logging.Logger = logging.getLogger("TestMoneroCommon")

Expand Down Expand Up @@ -37,21 +35,14 @@ def test_monero_error(self) -> None:
def test_serializable_struct(self) -> None:
SerializableStruct()

# test ssl options serialization integrity
@pytest.mark.xfail(reason="TODO monero-cpp implement ssl_options::from_property_tree()", strict=True)
def test_ssl_options(self) -> None:
# create ssl_options objects and populate properties
ssl_options: SslOptions = SslOptions()
ssl_options.ssl_allow_any_cert = True
ssl_options.ssl_allowed_fingerprints = ["fingerprint1", "fingerprint2"]
ssl_options.ssl_ca_file = "ca_file"
ssl_options.ssl_certificate_path = "certificate_path"
ssl_options.ssl_private_key_path = "private_key_path"
logger.debug(f"Testing ssl options: {ssl_options.serialize()}")
obj: dict[str, str] = loads(ssl_options.serialize())
assert obj['sslAllowAnyCert'] == ssl_options.ssl_allow_any_cert
assert obj['sslCaFile'] == ssl_options.ssl_ca_file
assert obj['sslCertificatePath'] == ssl_options.ssl_certificate_path
assert obj['sslPrivateKeyPath'] == ssl_options.ssl_private_key_path

allowed_fingerprints: list[str] = obj['sslAllowedFingerprints'] # type: ignore

for i, allowed_fingerprint in enumerate(allowed_fingerprints):
assert allowed_fingerprint == ssl_options.ssl_allowed_fingerprints[i]
AssertUtils.assert_serialization_integrity(ssl_options)
Loading
Loading