|
|
@@ -1811,6 +1811,35 @@ def main():
|
|
|
check("tick exceeded" not in app_log or "Dispatch tick failed" in app_log,
|
|
|
"a hung request never freezes the tick latch")
|
|
|
|
|
|
+
|
|
|
+ print("== R6 F2: refresh must not corrupt parked bookkeeping ==")
|
|
|
+ fake.suspend_after_start = True
|
|
|
+ act(auth, slot_public(auth, "/tasks", "tasks")["create"], {
|
|
|
+ "project_id": "1",
|
|
|
+ "title": "Parked refresh parent",
|
|
|
+ "priority": "2",
|
|
|
+ })
|
|
|
+ parked = int([t["id"] for t in slot_public(auth, "/tasks", "tasks")["tasks"]
|
|
|
+ if t["title"] == "Parked refresh parent"][0])
|
|
|
+ check(wait_for(lambda: task_state(auth, parked).get("status") == "suspended"
|
|
|
+ or False, timeout=60, what="parked parent suspends") is not None,
|
|
|
+ "parent parks before the refresh")
|
|
|
+ fake_card = saddle_card("fake-saddle")
|
|
|
+ act(auth, fake_card["refresh"], {})
|
|
|
+ fake_card = saddle_card("fake-saddle")
|
|
|
+ check(fake_card["status"] == "idle" and int(fake_card["current_task_id"] or 0) == 0,
|
|
|
+ "refresh on a parked (suspended) daemon leaves the saddle idle")
|
|
|
+ # The parked task keeps its open session and resumes normally.
|
|
|
+ conn = db()
|
|
|
+ conn.execute("insert into tasks (project_id, title, status, priority, parent_task_id,"
|
|
|
+ " summary, completed_at, created_at) values (1, 'Parked child', 'done', 5,"
|
|
|
+ " ?, 'child finished', strftime('%s','now','+1 second'),"
|
|
|
+ " strftime('%s','now'))", (parked,))
|
|
|
+ conn.commit()
|
|
|
+ conn.close()
|
|
|
+ check(wait_task_done(auth, parked, timeout=90) is not None,
|
|
|
+ "parked parent still resumes after the refresh")
|
|
|
+
|
|
|
finally:
|
|
|
# Exit-code diagnostic: distinguishes a crashed app (negative
|
|
|
# returncode, e.g. -11 SIGSEGV) from a clean shutdown. When
|