From 8c6f9cec492f66158b32c0a266b8bf2f2e1d9333 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mattias=20Walstr=C3=B6m?= Date: Mon, 15 Jun 2026 09:18:02 +0200 Subject: [PATCH] test: operational_all: Poll for stuff to get removed from yangerd --- test/case/misc/operational_all/test.py | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/test/case/misc/operational_all/test.py b/test/case/misc/operational_all/test.py index 3f00e6f5..7029ead2 100755 --- a/test/case/misc/operational_all/test.py +++ b/test/case/misc/operational_all/test.py @@ -69,10 +69,19 @@ def absent(dut, xpath): return True -def verify_absent(name, dut): - for xpath in ABSENT: - assert absent(dut, xpath), \ - f"{name}: unexpected operational data at {xpath}" +def features_absent(name, dut): + """True once every unconfigured feature subtree is gone. + + Like the interface set, these subtrees can momentarily linger: a + preceding test (containers, NTP, a routing protocol) leaves state that + yangerd only prunes once the underlying daemon/config is torn down. + Poll until operational has converged rather than asserting on the + transient overlap. + """ + pending = [xpath for xpath in ABSENT if not absent(dut, xpath)] + if pending: + print(f"{name}: feature data still present {pending}, waiting...") + return False return True @@ -92,7 +101,13 @@ with infamy.Test() as test: parallel(*(lambda n=name, d=dut: check(n, d) for name, dut in duts.items())) with test.step("Verify unconfigured feature subtrees are absent"): - parallel(*(lambda n=name, d=dut: verify_absent(n, d) + def check_absent(name, dut): + # NTP is pruned by a periodic collector with a 60s poll + # interval, so a stale subtree can take a full cycle to clear; + # wait comfortably past one interval rather than racing it. + until(lambda: features_absent(name, dut), attempts=120) + + parallel(*(lambda n=name, d=dut: check_absent(n, d) for name, dut in duts.items())) test.succeed()