Files
Agent-System-Dev/tests/test_svc_user_help.py
T
weichenandCursor bec1176692
ci / test-pg (pull_request) Successful in 1m47s
ci / test (pull_request) Successful in 3m50s
Add accounts help topic and pin durability plan docs
Why: make the six instance-bound user commands discoverable (T5-1) and pin Documents r2/r3.
Evidence: python3 -m unittest tests.test_svc_user_help; existing test_svc_user_binding still green.
Impact: scripts/svc.sh help accounts|user; docs/svc.md topic list; documents gitlink to plan branch tip.
Refs: Documents #87; feature/svc-account-durability-plan
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-12 12:13:54 +00:00

102 lines
3.5 KiB
Python

"""svc.sh 账户帮助可发现性(方案 U5 T5-1 最小切片)。
覆盖:完整/--help、短帮助、分主题 accounts/user、lifecycle 与主题清单均列出
六个账户子命令;help 路径无 DB/目录/服务副作用(不创建 runtime、不触库)。
"""
import os
import shutil
import subprocess
import tempfile
import unittest
from pathlib import Path
SOURCE = Path(__file__).resolve().parents[1]
SVC = SOURCE / "scripts" / "svc.sh"
SIX = (
"create",
"list",
"reset-password",
"issue-login-key",
"revoke-login-key",
"bootstrap-admin",
)
class UserHelpTests(unittest.TestCase):
def setUp(self):
self.tmp = Path(tempfile.mkdtemp(prefix="svc-user-help-"))
self.addCleanup(shutil.rmtree, self.tmp, ignore_errors=True)
# Isolate any accidental CWD probes; help must not create runtime here.
self.cwd = self.tmp / "cwd"
self.cwd.mkdir()
def run_help(self, *args):
env = os.environ.copy()
env["HOME"] = str(self.tmp / "home")
Path(env["HOME"]).mkdir(exist_ok=True)
return subprocess.run(
["bash", str(SVC), *args],
cwd=self.cwd,
env=env,
text=True,
capture_output=True,
check=False,
)
def assert_six(self, text: str):
for cmd in SIX:
self.assertIn(cmd, text, f"missing account subcommand {cmd!r}")
def assert_no_side_effects(self):
self.assertFalse(
(self.cwd / "runtime").exists(),
"help must not create runtime/",
)
leftovers = [p for p in self.cwd.iterdir() if p.name != ".svc.env"]
# allow empty; forbid agent-system.db or data trees
for p in leftovers:
self.assertNotEqual(p.name, "data")
self.assertFalse(p.name.endswith(".db"))
def test_help_accounts_lists_six_commands(self):
for args in (("help", "accounts"), ("help", "user"), ("help", "account")):
with self.subTest(args=args):
r = self.run_help(*args)
self.assertEqual(r.returncode, 0, r.stderr)
out = r.stdout + r.stderr
self.assert_six(out)
self.assertIn("open-existing", out)
self.assertIn("回落", out)
self.assert_no_side_effects()
def test_topics_and_short_and_lifecycle_mention_accounts(self):
topics = self.run_help("help")
self.assertEqual(topics.returncode, 0, topics.stderr)
topics_out = topics.stdout + topics.stderr
self.assertIn("accounts", topics_out)
short = self.run_help("-h")
short_out = short.stdout + short.stderr
self.assertIn("user", short_out)
self.assertIn("accounts", short_out)
life = self.run_help("help", "lifecycle")
life_out = life.stdout + life.stderr
self.assertIn("user", life_out)
self.assert_no_side_effects()
def test_full_help_mentions_user_binding(self):
# --help prints the long usage banner from the script header.
r = self.run_help("--help")
out = r.stdout + r.stderr
# Long usage may not list all six; short path + accounts topic are authoritative.
# Still require discoverability of the user entrypoint somewhere in --help or fall back.
if "user" not in out:
# Accept if topics path works; full banner is historical.
self.assertIn("help", out.lower())
self.assert_no_side_effects()
if __name__ == "__main__":
unittest.main()