Commit 2fb654ef16 for bind
commit 2fb654ef16f94f48b3f30ab891dc02a8951aaccb
Author: Nicki Křížek <nicki@isc.org>
Date: Fri Oct 23 09:36:29 2026 +0000
Ensure zone files rewritten before a reload get a newer mtime
Where file timestamps resolve whole seconds only, these rewrites can
land in the same second as the previous version, and named skips the
reload. Only the time the preceding steps take keeps them apart now.
Assisted-by: Claude:claude-opus-5-5
diff --git a/bin/tests/system/cyclic_glue/tests_cyclic_glue.py b/bin/tests/system/cyclic_glue/tests_cyclic_glue.py
index 3ae1d0bcb3..83d1b54481 100644
--- a/bin/tests/system/cyclic_glue/tests_cyclic_glue.py
+++ b/bin/tests/system/cyclic_glue/tests_cyclic_glue.py
@@ -47,7 +47,7 @@ def test_cyclic_glues(ns1, ns4, templates):
# in total we should have test, foo.test, and bar.test, nothing else:
assert len(dump.grep(Re("test. [0-9]* DELEG"))) == 3
- templates.render("ns1/root.db", {"broken_ns": True})
+ templates.render("ns1/root.db", {"broken_ns": True}, newer=True)
with ns1.watch_log_from_here() as watcher:
ns1.rndc("reload")
watcher.wait_for_all(["running", "zone ./IN: loaded serial"])
diff --git a/bin/tests/system/dnssec/tests_validation.py b/bin/tests/system/dnssec/tests_validation.py
index 9a560ffcf5..16568ffd86 100644
--- a/bin/tests/system/dnssec/tests_validation.py
+++ b/bin/tests/system/dnssec/tests_validation.py
@@ -19,7 +19,7 @@ from dns.edns import EDECode
import pytest
-from isctest.util import param
+from isctest.util import newer_mtime, param
import isctest
import isctest.mark
@@ -925,9 +925,9 @@ def test_validation_recovery(ns2, ns4):
watcher.wait_for_line("10.53.0.100")
# then reload server with properly signed zone
- shutil.copyfile(
- "ns2/peer.peer-ns-spoof.db.next", "ns2/peer.peer-ns-spoof.db.signed"
- )
+ zone_file = "ns2/peer.peer-ns-spoof.db.signed"
+ with newer_mtime(zone_file):
+ shutil.copyfile("ns2/peer.peer-ns-spoof.db.next", zone_file)
with ns2.watch_log_from_here() as watcher:
ns2.rndc("reload peer.peer-ns-spoof")
watcher.wait_for_line("zone peer.peer-ns-spoof/IN: loaded serial 2000042408")
@@ -946,9 +946,9 @@ def test_validation_recovery(ns2, ns4):
isctest.check.rr_count_eq(res.answer, 2)
# then reload server with properly signed zone
- shutil.copyfile(
- "ns2/dnskey-rrsigs-stripped.db.next", "ns2/dnskey-rrsigs-stripped.db.signed"
- )
+ zone_file = "ns2/dnskey-rrsigs-stripped.db.signed"
+ with newer_mtime(zone_file):
+ shutil.copyfile("ns2/dnskey-rrsigs-stripped.db.next", zone_file)
with ns2.watch_log_from_here() as watcher:
ns2.rndc("reload dnskey-rrsigs-stripped")
watcher.wait_for_line(
@@ -970,9 +970,9 @@ def test_validation_recovery(ns2, ns4):
isctest.check.rr_count_eq(res.answer, 1)
# then reload server with properly signed zone
- shutil.copyfile(
- "ns2/ds-rrsigs-stripped.db.next", "ns2/ds-rrsigs-stripped.db.signed"
- )
+ zone_file = "ns2/ds-rrsigs-stripped.db.signed"
+ with newer_mtime(zone_file):
+ shutil.copyfile("ns2/ds-rrsigs-stripped.db.next", zone_file)
with ns2.watch_log_from_here() as watcher:
ns2.rndc("reload ds-rrsigs-stripped")
watcher.wait_for_line("zone ds-rrsigs-stripped/IN: loaded serial 2000042408")
diff --git a/bin/tests/system/kasp/tests_kasp.py b/bin/tests/system/kasp/tests_kasp.py
index 28747b5b8c..a030228d22 100644
--- a/bin/tests/system/kasp/tests_kasp.py
+++ b/bin/tests/system/kasp/tests_kasp.py
@@ -27,7 +27,7 @@ import pytest
from isctest.algorithms import ECDSAP256SHA256, ECDSAP384SHA384, Algorithm
from isctest.kasp import KeyProperties, KeyTimingMetadata, SettimeOptions
-from isctest.util import param
+from isctest.util import newer_mtime, param
import isctest
import isctest.mark
@@ -224,7 +224,8 @@ def cb_ixfr_is_signed(expected_updates, params, ksks=None, zsks=None):
isctest.log.debug(
f"expected updates {expected_updates} policy {policy} ksks {ksks} zsks {zsks}"
)
- shutil.copyfile(f"ns2/{zone}.db.in2", f"ns2/{zone}.db")
+ with newer_mtime(f"ns2/{zone}.db"):
+ shutil.copyfile(f"ns2/{zone}.db.in2", f"ns2/{zone}.db")
servers["ns2"].rndc(f"reload {zone}")
def update_is_signed():
@@ -928,7 +929,8 @@ def test_kasp_default(ns3):
# modify unsigned zone file and check that new record is signed.
isctest.log.info("check that an updated zone signs the new record")
- shutil.copyfile("ns3/template2.db.in", f"ns3/{zone}.db")
+ with newer_mtime(f"ns3/{zone}.db"):
+ shutil.copyfile("ns3/template2.db.in", f"ns3/{zone}.db")
ns3.rndc(f"reload {zone}")
def update_is_signed():
@@ -1727,7 +1729,8 @@ def test_kasp_reload_restart(ns6):
soa1, ttl1 = query_soa(zone)
assert ttl1 == 300
- shutil.copyfile(f"ns6/{zone}2.db.in", f"ns6/{zone}.db")
+ with newer_mtime(f"ns6/{zone}.db"):
+ shutil.copyfile(f"ns6/{zone}2.db.in", f"ns6/{zone}.db")
with ns6.watch_log_from_here() as watcher:
ns6.rndc("reload")
watcher.wait_for_line("all zones loaded")
diff --git a/bin/tests/system/nsec_ixfr/tests_nsec_ixfr.py b/bin/tests/system/nsec_ixfr/tests_nsec_ixfr.py
index 93a25b19be..045b2dec48 100644
--- a/bin/tests/system/nsec_ixfr/tests_nsec_ixfr.py
+++ b/bin/tests/system/nsec_ixfr/tests_nsec_ixfr.py
@@ -23,6 +23,8 @@ import shutil
import dns.name
import dns.rdatatype
+from isctest.util import newer_mtime
+
import isctest
ORIGIN = dns.name.from_text("example.")
@@ -44,7 +46,8 @@ def test_nsec_ixfr_empty_nonterminal(ns1, ns2):
isctest.query.wait_for_serial(ns2.ip, "example", 1)
# Step 2: Replace the zone on ns1 with the signed version and reload.
- shutil.copy("ns1/example.db.signed", "ns1/example.db")
+ with newer_mtime("ns1/example.db"):
+ shutil.copy("ns1/example.db.signed", "ns1/example.db")
ns1.rndc("reload")
# Step 3: Wait for ns2 to get the signed zone via IXFR.
diff --git a/bin/tests/system/xfer/tests_xfer.py b/bin/tests/system/xfer/tests_xfer.py
index 0572d3d544..1be47b8ada 100644
--- a/bin/tests/system/xfer/tests_xfer.py
+++ b/bin/tests/system/xfer/tests_xfer.py
@@ -23,7 +23,7 @@ import dns.tsig
import dns.zone
import pytest
-from isctest.util import param
+from isctest.util import newer_mtime, param
import isctest
@@ -165,7 +165,10 @@ def test_zone_is_dumped_after_transfer(ns1, ns2, ns3, ns6, ns7):
"ns6/primary.db",
"ns7/primary2.db",
]:
- with fileinput.FileInput(zone_file, inplace=True) as file:
+ with (
+ newer_mtime(zone_file),
+ fileinput.FileInput(zone_file, inplace=True) as file,
+ ):
for line in file:
print(
line.replace(" 0.0.0.0", " 0.0.0.1").replace(