Initial release: iai-mcp v0.1.0
Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: XNLLLLH <XNLLLLH@users.noreply.github.com>
This commit is contained in:
commit
f6b876fbe7
332 changed files with 97258 additions and 0 deletions
96
tests/test_plist_template_lint.py
Normal file
96
tests/test_plist_template_lint.py
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
"""Plan 07.1-01 Task 2: lint + structural assertions for the LaunchAgent
|
||||
plist template.
|
||||
|
||||
The template ``scripts/com.iai-mcp.daemon.plist.template`` is rendered by
|
||||
``scripts/install.sh`` (Wave 2): ``{PYTHON_PATH}`` and ``{HOME}`` are
|
||||
substituted, then the result is written to
|
||||
``~/Library/LaunchAgents/com.iai-mcp.daemon.plist`` and registered with
|
||||
``launchctl load -w``.
|
||||
|
||||
These tests guard the *template itself*:
|
||||
|
||||
* ``test_template_renders_to_valid_plist`` — substitute the placeholders
|
||||
with realistic values, write to a tmp file, run ``plutil -lint``, and
|
||||
assert exit 0 + ``OK`` in stdout.
|
||||
* ``test_template_has_required_keys`` — string-level presence of every
|
||||
D7.1-01 field (Sockets, RunAtLoad, SockPathMode=384, KeepAlive,
|
||||
IAI_MCP_LAUNCHD_MANAGED).
|
||||
* ``test_template_does_not_have_RunAtLoad_true`` — regression trap: the
|
||||
legacy ``deploy/launchd/com.iai-mcp.daemon.plist`` uses
|
||||
``<key>RunAtLoad</key><true/>`` which defeats socket activation; we
|
||||
must NOT reintroduce that pattern in the new template.
|
||||
|
||||
The whole module skips on non-Darwin hosts (``plutil`` is macOS-only).
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import platform
|
||||
import re
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
pytestmark = pytest.mark.skipif(
|
||||
platform.system() != "Darwin",
|
||||
reason="plutil is macOS-only",
|
||||
)
|
||||
|
||||
REPO = Path(__file__).resolve().parent.parent
|
||||
TEMPLATE = REPO / "scripts" / "com.iai-mcp.daemon.plist.template"
|
||||
|
||||
|
||||
def test_template_renders_to_valid_plist(tmp_path: Path) -> None:
|
||||
"""Rendered plist (post-substitution) passes plutil -lint."""
|
||||
template_text = TEMPLATE.read_text()
|
||||
rendered = template_text.replace(
|
||||
"{PYTHON_PATH}", "/usr/bin/python3"
|
||||
).replace("{HOME}", "/tmp/iai-fake-home")
|
||||
rendered_path = tmp_path / "com.iai-mcp.daemon.plist"
|
||||
rendered_path.write_text(rendered)
|
||||
|
||||
result = subprocess.run(
|
||||
["plutil", "-lint", str(rendered_path)],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=False,
|
||||
)
|
||||
assert result.returncode == 0, (
|
||||
f"plutil -lint FAILED on rendered template:\n"
|
||||
f"--- STDOUT ---\n{result.stdout}\n"
|
||||
f"--- STDERR ---\n{result.stderr}\n"
|
||||
)
|
||||
assert "OK" in result.stdout, result.stdout
|
||||
|
||||
|
||||
def test_template_has_required_keys() -> None:
|
||||
"""All D7.1-01 fields present (string-level, no regex)."""
|
||||
text = TEMPLATE.read_text()
|
||||
required_markers = [
|
||||
"<key>Sockets</key>",
|
||||
"<key>RunAtLoad</key>",
|
||||
"<false/>",
|
||||
"<key>SockPathMode</key>",
|
||||
"<integer>384</integer>",
|
||||
"<key>KeepAlive</key>",
|
||||
"IAI_MCP_LAUNCHD_MANAGED",
|
||||
]
|
||||
missing = [m for m in required_markers if m not in text]
|
||||
assert not missing, f"template missing required markers: {missing}"
|
||||
|
||||
|
||||
def test_template_does_not_have_RunAtLoad_true() -> None:
|
||||
"""Regression trap: legacy deploy/launchd plist's <true/> bug must NOT appear.
|
||||
|
||||
The legacy ``deploy/launchd/com.iai-mcp.daemon.plist`` uses
|
||||
``<key>RunAtLoad</key><true/>`` which defeats socket activation
|
||||
(eager spawn at user login = no listener pre-bind). The Phase 7.1
|
||||
template MUST use ``<false/>`` so launchd defers spawn until the
|
||||
first incoming connection on the pre-bound socket.
|
||||
"""
|
||||
text = TEMPLATE.read_text()
|
||||
match = re.search(r"<key>RunAtLoad</key>\s*<true/>", text)
|
||||
assert match is None, (
|
||||
"REGRESSION: template contains <key>RunAtLoad</key>...<true/> which "
|
||||
"defeats socket activation. Use <false/> instead."
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue