From a2906acdf7b914aedce865b95f01284c7e0bbd15 Mon Sep 17 00:00:00 2001 From: Tobias Waldekranz Date: Fri, 3 May 2024 12:42:04 +0200 Subject: [PATCH] test: Optionally use deterministic topology mappings Due to the salting being applied to Python's `hash()` (see [1]), the hash of an object is not stable across different Python processes. As a result, neither are the topology mappings generated by networkx. The upside of this is randomness that we get better test coverage over time, especially on physical devices where the underlying hardware could differ between ports, for example. On the other hand, it can be very frustrating to track down a bug when locial nodes are suffled around between phyical nodes on each invocation of a test case. Therefore, use a random seed by default, but allow the user to specify a fixed value if they so choose. We then add a meta test that logs the seed being used for the current suite - which means we can simply copy&paste that value to rerun the suite (or single test) with the same topology mappings. [1]: https://docs.python.org/3/reference/datamodel.html#object.__hash__ --- test/case/all.yaml | 1 + test/case/meta/reproducible.py | 16 ++++++++++++++++ test/env | 1 + 3 files changed, 18 insertions(+) create mode 100755 test/case/meta/reproducible.py diff --git a/test/case/all.yaml b/test/case/all.yaml index 12edc8c2..70869445 100644 --- a/test/case/all.yaml +++ b/test/case/all.yaml @@ -1,4 +1,5 @@ --- +- case: meta/reproducible.py - case: meta/wait.py - name: Misc tests diff --git a/test/case/meta/reproducible.py b/test/case/meta/reproducible.py new file mode 100755 index 00000000..6e2ad565 --- /dev/null +++ b/test/case/meta/reproducible.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 + +import os + +import infamy + +with infamy.Test() as test: + with test.step("$PYTHONHASHSEED is set"): + seed = os.environ.get("PYTHONHASHSEED") + if seed == None: + print("$PYTHONHASHSEED must be set in order to create a reproducible test environment") + test.fail() + else: + print(f"Specify PYTHONHASHSEED={seed} to reproduce this test environment") + + test.succeed() diff --git a/test/env b/test/env index 72d95b59..06268372 100755 --- a/test/env +++ b/test/env @@ -157,6 +157,7 @@ if [ "$containerize" ]; then --cap-add=NET_RAW \ --cap-add=NET_ADMIN \ --device=/dev/net/tun \ + --env PYTHONHASHSEED=${PYTHONHASHSEED:-$(shuf -i 0-$(((1 << 32) - 1)) -n 1)} \ --env VIRTUAL_ENV_DISABLE_PROMPT=yes \ --env PROMPT_DIRTRIM="$ixdir" \ --env PS1='\e[1m$(date "+%H:%M:%S") \h\e[0m:\W # ' \