Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions tests/unit/test_factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,19 @@ def test_compound_key(self, tmp_path: "Path") -> None:
assert table.count() == 2
assert table.get(("acme", 1)) == {"org": "acme", "id": 1, "name": "alice"}

def test_duplicate_keys_last_wins(self, tmp_path: "Path") -> None:
records = [
{"id": "alice", "role": "admin"},
{"id": "alice", "role": "user"}, # Duplicate key, different value
]
table = Table.from_records(
tmp_path / "test.jsonlt",
records,
key="id",
)
assert table.count() == 1
assert table.get("alice") == {"id": "alice", "role": "user"}

def test_file_has_header(self, tmp_path: "Path") -> None:
table = Table.from_records(
tmp_path / "test.jsonlt",
Expand Down Expand Up @@ -296,6 +309,13 @@ def test_max_file_size_exceeded(self, tmp_path: "Path") -> None:
with pytest.raises(LimitError, match="file size"):
_ = Table.from_file(path, max_file_size=10) # Very small limit

def test_empty_file_with_key(self, tmp_path: "Path") -> None:
path = tmp_path / "test.jsonlt"
_ = path.write_bytes(b"") # 0-byte file

table = Table.from_file(path, key="id")
assert table.count() == 0


class TestFactoryIntegration:
def test_roundtrip_from_records_to_from_file(self, tmp_path: "Path") -> None:
Expand Down
23 changes: 23 additions & 0 deletions tests/unit/test_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -1283,6 +1283,14 @@ def test_getitem_missing_key_raises_keyerror(

assert exc_info.value.args[0] == "nonexistent"

def test_get_with_custom_default(self, make_table: "Callable[..., Table]") -> None:
table = make_table()
default: JSONObject = {"id": "default", "role": "none"}

result = table.get("nonexistent", default)

assert result == default

def test_setitem_with_matching_key(
self, make_table: "Callable[..., Table]"
) -> None:
Expand Down Expand Up @@ -1536,3 +1544,18 @@ def test_table_is_not_hashable(self, make_table: "Callable[..., Table]") -> None

with pytest.raises(TypeError, match="unhashable type"):
_ = hash(table)

def test_eq_with_different_auto_reload_after_external_change(
self, tmp_path: "Path"
) -> None:
table_path = tmp_path / "test.jsonlt"
_ = table_path.write_text('{"id": "alice", "v": 1}\n')

table1 = Table(table_path, key="id", auto_reload=True)
table2 = Table(table_path, key="id", auto_reload=False)

# Wait a bit to ensure mtime changes
time.sleep(0.01)
_ = table_path.write_text('{"id": "alice", "v": 2}\n')

assert table1 != table2
28 changes: 28 additions & 0 deletions tests/unit/test_transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -1425,6 +1425,34 @@ def test_finalized_vs_active_not_equal(self, tmp_path: "Path") -> None:
finally:
tx2.abort()

def test_eq_same_table_different_writes(self, tmp_path: "Path") -> None:
"""Two transactions from same table with different writes are unequal.

Verifies that sequential transactions from the same table with different
write sequences have different snapshots and compare as unequal.
"""
path = tmp_path / "test.jsonlt"
_ = path.write_text('{"id": "alice", "v": 1}\n')

table = Table(path, key="id")

# First transaction: add bob
tx1 = table.transaction()
tx1.put({"id": "bob", "v": 2})
tx1.commit()

# Second transaction: add carol (different write)
tx2 = table.transaction()
tx2.put({"id": "carol", "v": 3})

try:
# tx1 is committed (has alice+bob in snapshot)
# tx2 is active (has alice+bob+carol in snapshot)
# They differ in both finalized status and snapshot content
assert tx1 != tx2
finally:
tx2.abort()

def test_transaction_is_not_hashable(
self, make_table: "Callable[..., Table]"
) -> None:
Expand Down