diff options
Diffstat (limited to '.ai/scripts/tests/test_inbox_send.py')
| -rw-r--r-- | .ai/scripts/tests/test_inbox_send.py | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/.ai/scripts/tests/test_inbox_send.py b/.ai/scripts/tests/test_inbox_send.py index a0094dc..f75d7a1 100644 --- a/.ai/scripts/tests/test_inbox_send.py +++ b/.ai/scripts/tests/test_inbox_send.py @@ -97,6 +97,52 @@ class TestInboxSendDiscovery: result = run_script(["--list"], roots=[tmp_path / "does-not-exist"]) assert result.returncode == 0 + def test_inbox_send_list_displays_dot_stripped_name(self, project_root, run_script, tmp_path): + """Dotted project basenames display dot-stripped (.emacs.d → emacsd).""" + project_root(".emacs.d") + result = run_script(["--list"], roots=[tmp_path / "projects"]) + assert "emacsd" in result.stdout + + +class TestInboxSendDotAlias: + """A dotted project basename resolves both verbatim and dot-stripped.""" + + def test_resolves_by_dot_stripped_alias(self, project_root, run_script, tmp_path): + """'emacsd' delivers to the .emacs.d project.""" + project_root(".emacs.d") + cwd = project_root("source") + run_script( + ["emacsd", "--text", "hi"], + cwd=cwd, roots=[tmp_path / "projects"], + ) + files = list((tmp_path / "projects" / ".emacs.d" / "inbox").iterdir()) + assert len(files) == 1 + + def test_resolves_by_exact_dotted_name_still(self, project_root, run_script, tmp_path): + """Backward-compat: the verbatim '.emacs.d' target still resolves.""" + project_root(".emacs.d") + cwd = project_root("source") + run_script( + [".emacs.d", "--text", "hi"], + cwd=cwd, roots=[tmp_path / "projects"], + ) + files = list((tmp_path / "projects" / ".emacs.d" / "inbox").iterdir()) + assert len(files) == 1 + + def test_exact_match_wins_over_alias(self, project_root, run_script, tmp_path): + """An exact basename match is preferred over a dot-stripped collision.""" + project_root("emacsd") # exact + project_root(".emacs.d") # would also normalize to 'emacsd' + cwd = project_root("source") + run_script( + ["emacsd", "--text", "hi"], + cwd=cwd, roots=[tmp_path / "projects"], + ) + exact = list((tmp_path / "projects" / "emacsd" / "inbox").iterdir()) + dotted = list((tmp_path / "projects" / ".emacs.d" / "inbox").iterdir()) + assert len(exact) == 1 + assert dotted == [] + # ---------------------------------------------------------------------- # Slug derivation from text and from filenames @@ -355,3 +401,78 @@ class TestInboxSendErrors: assert result.returncode != 0 files = list((tmp_path / "projects" / "target" / "inbox").iterdir()) assert files == [] + + +# ---------------------------------------------------------------------- +# Filename collisions (two sends deriving the same name must not overwrite) +# ---------------------------------------------------------------------- + +def _load_module(): + import importlib.util + spec = importlib.util.spec_from_file_location("inbox_send", SCRIPT) + mod = importlib.util.module_from_spec(spec) + spec.loader.exec_module(mod) + return mod + + +class TestFilenameCollisions: + """Two sends in the same minute with the same leading phrase derived + identical filenames and the second silently overwrote the first + (a message was lost this way, 2026-07-02).""" + + def test_send_text_same_minute_same_phrase_keeps_both(self, tmp_path): + from datetime import datetime + mod = _load_module() + inbox = tmp_path / "inbox" + inbox.mkdir() + now = datetime(2026, 7, 2, 5, 42, 0) + prefix = "identical leading phrase long enough to fill the whole slug budget entirely" + first = mod.send_text(inbox, prefix + " tail one", "archsetup", None, now) + second = mod.send_text(inbox, prefix + " tail two", "archsetup", None, now) + assert first != second + assert first.exists() and second.exists() + assert first.name != second.name + assert "tail one" in first.read_text() + assert "tail two" in second.read_text() + + def test_send_text_collision_suffix_increments(self, tmp_path): + from datetime import datetime + mod = _load_module() + inbox = tmp_path / "inbox" + inbox.mkdir() + now = datetime(2026, 7, 2, 5, 42, 0) + paths = [mod.send_text(inbox, "same lead phrase differs later A", "src", "fixed-slug", now) + for _ in range(3)] + names = [p.name for p in paths] + assert names[0].endswith("fixed-slug.org") + assert names[1].endswith("fixed-slug-2.org") + assert names[2].endswith("fixed-slug-3.org") + + def test_send_file_collision_preserves_extension(self, tmp_path): + from datetime import datetime + mod = _load_module() + inbox = tmp_path / "inbox" + inbox.mkdir() + src = tmp_path / "note.org" + src.write_text("body one") + now = datetime(2026, 7, 2, 5, 42, 0) + first = mod.send_file(inbox, src, "src", None, now) + src.write_text("body two") + second = mod.send_file(inbox, src, "src", None, now) + assert second.name.endswith("note-2.org") + assert first.read_text() == "body one" + assert second.read_text() == "body two" + + def test_cli_two_rapid_sends_lose_nothing(self, project_root, run_script, tmp_path): + project_root("sender") + target = project_root("receiver") + roots = [tmp_path / "projects"] + prefix = "identical leading phrase long enough to fill the whole slug budget entirely" + run_script(["receiver", "--text", prefix + " message one"], + cwd=tmp_path / "projects" / "sender", roots=roots) + run_script(["receiver", "--text", prefix + " message two"], + cwd=tmp_path / "projects" / "sender", roots=roots) + files = list((target / "inbox").iterdir()) + assert len(files) == 2 + bodies = "".join(f.read_text() for f in files) + assert "message one" in bodies and "message two" in bodies |
