Commit 62ff12e796 for frr

commit 62ff12e79618a2a8a11ce2d48e56d6afbec05681
Author: Rafael Zalamena <rzalamena@opensourcerouting.org>
Date:   Thu Oct 15 18:52:54 2026 -0300

    tests: frr-reload deletes after rejected context

    Run a deletion file where vtysh rejects the line that enters a context.
    `vtysh` then leaves the file at that context's "exit", so check that the
    deletes after it are still applied.

    Signed-off-by: Rafael Zalamena <rzalamena@opensourcerouting.org>

diff --git a/tests/topotests/frr_reload_no_form/test_frr_reload_no_form.py b/tests/topotests/frr_reload_no_form/test_frr_reload_no_form.py
index 1274e4513d..7d0e3d7217 100644
--- a/tests/topotests/frr_reload_no_form/test_frr_reload_no_form.py
+++ b/tests/topotests/frr_reload_no_form/test_frr_reload_no_form.py
@@ -40,6 +40,9 @@ is accepted.
    its transaction, such as the descriptions, so frr-reload.py must retry
    those too and report the failure instead of leaving the old settings
    behind.
+6. Run a deletion file where vtysh rejects a context line. vtysh then leaves
+   the file at that context's "exit", so the deletes after it must still be
+   applied.
 """

 import difflib
@@ -281,6 +284,60 @@ exit
     assert "affinity-map blue" in r1.vtysh_cmd("show running-config")


+def test_delete_file_failed_context():
+    """
+    A rejected context line must not stop the rest of the deletion file.
+
+    When vtysh rejects the line that enters a context, it stays at the
+    config node, so the "exit" closing that context leaves the config file
+    ("early exit from config file") and vtysh stops reading it. Only the
+    entry with the rejected lines is retried, so every delete after it must
+    still be applied.
+    """
+    tgen = get_topogen()
+    if tgen.routers_have_failure():
+        pytest.skip(tgen.errors)
+
+    r1 = tgen.gears["r1"]
+    frrdir = tgen.config.get(tgen.CONFIG_SECTION, "frrdir")
+    prefix_lists = (
+        "ip prefix-list PL-BEFORE seq 5 permit 10.0.0.0/8",
+        "ip prefix-list PL-AFTER seq 5 permit 172.16.0.0/12",
+    )
+    r1.vtysh_multicmd("configure\n" + "\n".join(prefix_lists) + "\n")
+    running = r1.vtysh_cmd("show running-config")
+    for prefix_list in prefix_lists:
+        assert prefix_list in running
+
+    # "router unknown" stands for any context line vtysh rejects.
+    entries = [
+        ((prefix_lists[0],), None),
+        (("router unknown",), "foo bar"),
+        ((prefix_lists[1],), None),
+    ]
+    rc, out, err = r1.net.cmd_status(
+        f"""python3 - <<'EOF'
+import importlib.util
+
+spec = importlib.util.spec_from_file_location(
+    "frr_reload", "{frrdir}/frr-reload.py"
+)
+reload = importlib.util.module_from_spec(spec)
+spec.loader.exec_module(reload)
+ok = reload.exec_delete_lines(reload.Vtysh(), "/var/run/frr", {entries!r})
+print("exec_delete_lines returned", ok)
+EOF""",
+        warn=False,
+    )
+    assert rc == 0, f"running exec_delete_lines failed:\n{out}\n{err}"
+    # The "router unknown" entry cannot be deleted.
+    assert "exec_delete_lines returned False" in out, out
+
+    running = r1.vtysh_cmd("show running-config")
+    for prefix_list in prefix_lists:
+        assert prefix_list not in running, f"{prefix_list!r} was not deleted"
+
+
 def test_memory_leak():
     "Run the memory leak test and report results."
     tgen = get_topogen()