gabriel / muse public
test_commit_record_schema.py python
169 lines 5.4 KB
Raw
sha256:1900655993c83c4107067375548a7be823e471d2515830842f1a12cba4bd3cdf fix: unified object store migration — idempotent writes, JS… Sonnet 4.6 minor ⚠ breaking 29 days ago
1 """Tests for CommitRecord and CommitDict schema contract.
2
3 Canonical field names:
4 - ``branch`` — the branch the commit was made on (not ``created_on_branch``)
5 - ``format_version`` — removed entirely; not stored, not serialised
6 """
7
8 from __future__ import annotations
9
10 import datetime
11
12 import pytest
13
14 from muse.core.store import CommitRecord, CommitDict
15 from muse.core.types import MsgpackDict, long_id
16
17
18 # ---------------------------------------------------------------------------
19 # Helpers
20 # ---------------------------------------------------------------------------
21
22 _NOW = datetime.datetime(2025, 1, 1, 0, 0, 0, tzinfo=datetime.timezone.utc)
23 _TS = _NOW.isoformat()
24 _CID = long_id("a" * 64)
25 _SID = long_id("b" * 64)
26
27
28 def _minimal_msgpack(branch_key: str = "branch") -> MsgpackDict:
29 """Minimal raw dict for CommitRecord.from_msgpack."""
30 return {
31 "commit_id": _CID,
32 "repo_id": "test-repo",
33 branch_key: "main",
34 "snapshot_id": _SID,
35 "message": "test commit",
36 "committed_at": _TS,
37 }
38
39
40 # ---------------------------------------------------------------------------
41 # CommitRecord field existence
42 # ---------------------------------------------------------------------------
43
44
45 class TestCommitRecordFields:
46 def test_has_branch_field(self) -> None:
47 rec = CommitRecord(
48 commit_id=_CID,
49 branch="main",
50 snapshot_id=_SID,
51 message="m",
52 committed_at=_NOW,
53 )
54 assert rec.branch == "main"
55
56 def test_has_no_created_on_branch_field(self) -> None:
57 rec = CommitRecord(
58 commit_id=_CID,
59 branch="main",
60 snapshot_id=_SID,
61 message="m",
62 committed_at=_NOW,
63 )
64 assert not hasattr(rec, "created_on_branch"), (
65 "CommitRecord must not have a 'created_on_branch' field"
66 )
67
68 def test_has_no_format_version_field(self) -> None:
69 rec = CommitRecord(
70 commit_id=_CID,
71 branch="main",
72 snapshot_id=_SID,
73 message="m",
74 committed_at=_NOW,
75 )
76 assert not hasattr(rec, "format_version"), (
77 "CommitRecord must not have a 'format_version' field"
78 )
79
80
81 # ---------------------------------------------------------------------------
82 # to_dict serialisation
83 # ---------------------------------------------------------------------------
84
85
86 class TestCommitRecordToDict:
87 def _make(self) -> CommitRecord:
88 return CommitRecord(
89 commit_id=_CID,
90 branch="dev",
91 snapshot_id=_SID,
92 message="m",
93 committed_at=_NOW,
94 )
95
96 def test_to_dict_has_branch_key(self) -> None:
97 d = self._make().to_dict()
98 assert d["branch"] == "dev"
99
100 def test_to_dict_has_no_created_on_branch_key(self) -> None:
101 d = self._make().to_dict()
102 assert "created_on_branch" not in d, (
103 "to_dict() must not emit 'created_on_branch' key"
104 )
105
106 def test_to_dict_has_no_format_version_key(self) -> None:
107 d = self._make().to_dict()
108 assert "format_version" not in d, (
109 "to_dict() must not emit 'format_version' key"
110 )
111
112
113 # ---------------------------------------------------------------------------
114 # from_msgpack deserialisation
115 # ---------------------------------------------------------------------------
116
117
118 class TestCommitRecordFromMsgpack:
119 def test_reads_branch_key(self) -> None:
120 raw = _minimal_msgpack("branch")
121 rec = CommitRecord.from_msgpack(raw)
122 assert rec.branch == "main"
123
124 def test_falls_back_to_created_on_branch_for_old_records(self) -> None:
125 """Old stored msgpack files with 'created_on_branch' key must still deserialise.
126
127 This shim supports repos not yet migrated via 'muse code migrate'.
128 New commits are always written with 'branch'.
129 """
130 raw = _minimal_msgpack("created_on_branch")
131 rec = CommitRecord.from_msgpack(raw)
132 assert rec.branch == "main"
133
134 def test_raises_when_neither_key_present(self) -> None:
135 raw = _minimal_msgpack("branch")
136 del raw["branch"]
137 with pytest.raises(TypeError, match="branch"):
138 CommitRecord.from_msgpack(raw)
139
140 def test_from_msgpack_ignores_format_version_key(self) -> None:
141 """Old records with format_version in the dict must still deserialise
142 without storing the field on the returned record."""
143 raw = _minimal_msgpack("branch")
144 raw["format_version"] = 8
145 rec = CommitRecord.from_msgpack(raw)
146 assert not hasattr(rec, "format_version")
147
148
149 # ---------------------------------------------------------------------------
150 # CommitDict TypedDict
151 # ---------------------------------------------------------------------------
152
153
154 class TestCommitDict:
155 def test_commit_dict_has_branch_key(self) -> None:
156 """CommitDict must declare 'branch', not 'created_on_branch'."""
157 annotations = CommitDict.__annotations__
158 assert "branch" in annotations, (
159 "CommitDict must have 'branch' key"
160 )
161 assert "created_on_branch" not in annotations, (
162 "CommitDict must not have 'created_on_branch' key"
163 )
164
165 def test_commit_dict_has_no_format_version_key(self) -> None:
166 annotations = CommitDict.__annotations__
167 assert "format_version" not in annotations, (
168 "CommitDict must not have 'format_version' key"
169 )
File History 1 commit
sha256:1900655993c83c4107067375548a7be823e471d2515830842f1a12cba4bd3cdf fix: unified object store migration — idempotent writes, JS… Sonnet 4.6 minor 29 days ago