diff --git a/README.md b/README.md index 370a6eb97..d66ad7fa2 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,12 @@ The preferred way is via `runner/runc.sh`, which builds a container image and ru ./runner/runc.sh ./runner/regression.sh ``` +Run with clock skew on one pool node: + +```sh +./runner/runc.sh -- TIME_DRIFT_POOL=1 TIME_DRIFT_SPEC='+0 x1.008' ./runner/regression.sh +``` + Run a specific test: ```sh @@ -167,6 +173,9 @@ You can fine-tune test runs using these environment variables: | `TX_CENTRIFUGE_REV`| `tx-centrifuge` version (default: `bench/leios-11.0.1`) | | `PYTEST_ARGS` | Extra options passed to pytest. | | `TEST_THREADS` | Number of pytest workers (default: `20`). | +| `TIME_DRIFT_POOL` | Pool (1-3) for libfaketime clock skew; unset = off. | +| `TIME_DRIFT_SPEC` | libfaketime `FAKETIME` string, e.g. `+0 x1.008`. | +| `LIBFAKETIME_PATH` | Override path to `libfaketimeMT.so.1`. | ### 💡 Usage Examples diff --git a/cardano_node_tests/utils/cluster_scripts.py b/cardano_node_tests/utils/cluster_scripts.py index 8ad26f041..214beb8f2 100644 --- a/cardano_node_tests/utils/cluster_scripts.py +++ b/cardano_node_tests/utils/cluster_scripts.py @@ -74,6 +74,48 @@ def get_testnet_variant_scriptdir2(*, testnet_variant: str) -> pl.Path: return scriptdir +_TIME_DRIFT_HOOK = """\ +# TIME_DRIFT: activate clock skew on this pool when TIME_DRIFT_POOL=%%POOL_NUM%% +if [[ -n "${TIME_DRIFT_POOL:-}" && -n "${TIME_DRIFT_SPEC:-}" \\ + && "${TIME_DRIFT_POOL}" == "%%POOL_NUM%%" ]]; then + _ft_so="${LIBFAKETIME_PATH:-/usr/lib/x86_64-linux-gnu/faketime/libfaketimeMT.so.1}" + if [[ ! -f "$_ft_so" ]]; then + _ft_bin="$(command -v faketime 2>/dev/null || true)" + if [[ -n "$_ft_bin" ]]; then + _ft_so="$(dirname "$(dirname "$_ft_bin")")/lib/faketime/libfaketimeMT.so.1" + fi + fi + if [[ ! -f "$_ft_so" ]]; then + echo "[faketime] ERROR: libfaketimeMT.so.1 not found" >&2 + exit 1 + fi + export LD_PRELOAD="${LD_PRELOAD:+${LD_PRELOAD}:}$_ft_so" + export FAKETIME="${TIME_DRIFT_SPEC}" + echo "[faketime] pool%%POOL_NUM%%: LD_PRELOAD=$LD_PRELOAD FAKETIME=$FAKETIME" >&2 +fi +""" + + +def _inject_time_drift_hook(content: str, pool_num: int) -> str: + """Inject a conditional clock-skew bash block into pool wrapper scripts. + + Appends after the pre-run setup placeholder in the cardonnay template, leaving + the placeholder itself intact. Activated only when TIME_DRIFT_POOL= + and TIME_DRIFT_SPEC are set at cluster start time. Default-off: unset env vars + leave behaviour unchanged. + + Raises: + ValueError: When the pre-run setup placeholder is absent from the template. + """ + marker = "# --- Placeholder for any pre-run setup ---" + if marker not in content: + msg = f"TIME_DRIFT hook: pre-run placeholder missing in pool{pool_num} wrapper." + raise ValueError(msg) + + hook = _TIME_DRIFT_HOOK.replace("%%POOL_NUM%%", str(pool_num)) + return content.replace(marker, f"{marker}\n{hook.rstrip(chr(10))}", 1) + + class CustomCardonnayScripts(cardonnay_local.LocalScripts): """Scripts for starting local cluster. @@ -187,6 +229,9 @@ def _reconfigure_local(self, indir: pl.Path, destdir: pl.Path, instance_num: int node_rec=node_rec, instance_num=instance_num, ) + supervisor_script_content = _inject_time_drift_hook( + content=supervisor_script_content, pool_num=node_rec.num + ) supervisor_script.unlink(missing_ok=True) supervisor_script.write_text(f"{supervisor_script_content}\n", encoding="utf-8") supervisor_script.chmod(0o755) diff --git a/flake.nix b/flake.nix index 9c4689785..85b6b4270 100644 --- a/flake.nix +++ b/flake.nix @@ -46,6 +46,7 @@ nodePkgs.bech32 nodePkgs.tx-generator centrifugePkgs.tx-centrifuge + pkgs.libfaketime pkgs.bashInteractive ]; };