Test: Make retry decorator more available and use on ctrl-dynsec

This test sometimes fails if the getDefaultACL check connects before the previous kick has occurred and before it has sent its CONNECT.
This commit is contained in:
Roger A. Light 2026-05-02 01:38:10 +01:00 committed by Roger Light
parent 037be837d9
commit b1a2be20c3
4 changed files with 31 additions and 31 deletions

View file

@ -18,6 +18,8 @@ def write_config(filename, ports):
f.write(f"certfile {Path(ssl_dir, 'server.crt')}\n")
f.write(f"keyfile {Path(ssl_dir, 'server.key')}\n")
@mosq_test.retry()
def ctrl_dynsec_cmd(args, ports, response=None, input=None):
opts = ["-u", "admin",
"-P", "newadmin",]
@ -43,6 +45,7 @@ def ctrl_dynsec_cmd(args, ports, response=None, input=None):
if proc.returncode != 0:
raise ValueError(args)
def ctrl_dynsec_file_cmd(args, ports, response=None):
opts = ["-f", Path(str(ports[0]), "dynamic-security.json")]

View file

@ -8,27 +8,6 @@ import time
from typing import Any, Optional
from types import ModuleType
import time
from functools import wraps
def retry(retries=5, delay=1):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
last_exception = None
for attempt in range(retries):
try:
return func(*args, **kwargs)
except Exception as e:
print(f"Retrying {func.__name__} {attempt}/{retries}")
last_exception = e
if attempt < retries - 1:
time.sleep(delay)
raise last_exception
return wrapper
return decorator
def connect_client(
port: int,
client_id: str,

View file

@ -4,7 +4,6 @@ from pathlib import Path
import sqlite3
import mosq_paths
import mosq_test
from persist_module_helper import retry
mosq_test.require_features(["WITH_PLUGINS", "WITH_PLUGIN_PERSIST_SQLITE"])
@ -131,7 +130,7 @@ def cleanup(port):
return rc
@retry()
@mosq_test.retry()
def check_version_infos(port, database_schema_version):
with get_connection(port) as con:
row = con.execute(
@ -147,7 +146,7 @@ def check_version_infos(port, database_schema_version):
)
@retry()
@mosq_test.retry()
def check_counts(
port,
clients=0,
@ -196,7 +195,7 @@ def check_counts(
raise ValueError("Found %d wills, expected %d" % (row[0], wills))
@retry()
@mosq_test.retry()
def check_client(
port,
client_id,
@ -286,7 +285,7 @@ def modify_client(port: int, client_id: str, sub_expiry_time: int):
return num_modified_rows
@retry()
@mosq_test.retry()
def check_subscription(
port, client_id, topic, subscription_options, subscription_identifier, connection=None
):
@ -318,7 +317,7 @@ def check_subscription(
)
@retry()
@mosq_test.retry()
def check_client_msg(
port, client_id, cmsg_id, store_id, dup, direction, mid, qos, retain, state, connection=None
):
@ -381,7 +380,7 @@ def check_client_msg(
)
@retry()
@mosq_test.retry()
def check_base_msg(
port,
expiry_time,
@ -461,7 +460,7 @@ def modify_base_msgs(
return num_modified_rows
@retry()
@mosq_test.retry()
def check_retain(port, topic, store_id):
with sqlite3.connect(Path(str(port), "mosquitto.sqlite3")) as con:
row = con.execute("SELECT store_id FROM retains WHERE topic=?", (topic,)).fetchone()
@ -470,7 +469,7 @@ def check_retain(port, topic, store_id):
raise ValueError("Invalid store_id %d / %d" % (row[0], store_id))
@retry()
@mosq_test.retry()
def check_will(
port,
client_id: str,

View file

@ -13,8 +13,8 @@ import sys
import tempfile
import time
import uuid
import traceback
from functools import wraps
import mqtt5_props
@ -31,6 +31,25 @@ class TestError(Exception):
def __init__(self, message="Mismatched packets"):
self.message = message
def retry(retries=5, delay=1):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
last_exception = None
for attempt in range(retries):
try:
return func(*args, **kwargs)
except Exception as e:
print(f"Retrying {func.__name__} {attempt+1}/{retries}")
last_exception = e
if attempt < retries - 1:
time.sleep(delay)
raise last_exception
return wrapper
return decorator
def get_build_root():
result = os.getenv("BUILD_ROOT")
if result is None: