Skip to content

Commit db493fb

Browse files
authored
test: add edge case coverage for factories and equality (#18)
Add tests for: - Duplicate keys behavior in from_records (last-wins) - Empty file handling with key parameter in from_file - Custom default value in Table.get() - Equality with different auto_reload after external changes - Transaction equality with different write sequences
1 parent 29c19df commit db493fb

3 files changed

Lines changed: 71 additions & 0 deletions

File tree

tests/unit/test_factories.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,19 @@ def test_compound_key(self, tmp_path: "Path") -> None:
6060
assert table.count() == 2
6161
assert table.get(("acme", 1)) == {"org": "acme", "id": 1, "name": "alice"}
6262

63+
def test_duplicate_keys_last_wins(self, tmp_path: "Path") -> None:
64+
records = [
65+
{"id": "alice", "role": "admin"},
66+
{"id": "alice", "role": "user"}, # Duplicate key, different value
67+
]
68+
table = Table.from_records(
69+
tmp_path / "test.jsonlt",
70+
records,
71+
key="id",
72+
)
73+
assert table.count() == 1
74+
assert table.get("alice") == {"id": "alice", "role": "user"}
75+
6376
def test_file_has_header(self, tmp_path: "Path") -> None:
6477
table = Table.from_records(
6578
tmp_path / "test.jsonlt",
@@ -296,6 +309,13 @@ def test_max_file_size_exceeded(self, tmp_path: "Path") -> None:
296309
with pytest.raises(LimitError, match="file size"):
297310
_ = Table.from_file(path, max_file_size=10) # Very small limit
298311

312+
def test_empty_file_with_key(self, tmp_path: "Path") -> None:
313+
path = tmp_path / "test.jsonlt"
314+
_ = path.write_bytes(b"") # 0-byte file
315+
316+
table = Table.from_file(path, key="id")
317+
assert table.count() == 0
318+
299319

300320
class TestFactoryIntegration:
301321
def test_roundtrip_from_records_to_from_file(self, tmp_path: "Path") -> None:

tests/unit/test_table.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1283,6 +1283,14 @@ def test_getitem_missing_key_raises_keyerror(
12831283

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

1286+
def test_get_with_custom_default(self, make_table: "Callable[..., Table]") -> None:
1287+
table = make_table()
1288+
default: JSONObject = {"id": "default", "role": "none"}
1289+
1290+
result = table.get("nonexistent", default)
1291+
1292+
assert result == default
1293+
12861294
def test_setitem_with_matching_key(
12871295
self, make_table: "Callable[..., Table]"
12881296
) -> None:
@@ -1536,3 +1544,18 @@ def test_table_is_not_hashable(self, make_table: "Callable[..., Table]") -> None
15361544

15371545
with pytest.raises(TypeError, match="unhashable type"):
15381546
_ = hash(table)
1547+
1548+
def test_eq_with_different_auto_reload_after_external_change(
1549+
self, tmp_path: "Path"
1550+
) -> None:
1551+
table_path = tmp_path / "test.jsonlt"
1552+
_ = table_path.write_text('{"id": "alice", "v": 1}\n')
1553+
1554+
table1 = Table(table_path, key="id", auto_reload=True)
1555+
table2 = Table(table_path, key="id", auto_reload=False)
1556+
1557+
# Wait a bit to ensure mtime changes
1558+
time.sleep(0.01)
1559+
_ = table_path.write_text('{"id": "alice", "v": 2}\n')
1560+
1561+
assert table1 != table2

tests/unit/test_transaction.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1425,6 +1425,34 @@ def test_finalized_vs_active_not_equal(self, tmp_path: "Path") -> None:
14251425
finally:
14261426
tx2.abort()
14271427

1428+
def test_eq_same_table_different_writes(self, tmp_path: "Path") -> None:
1429+
"""Two transactions from same table with different writes are unequal.
1430+
1431+
Verifies that sequential transactions from the same table with different
1432+
write sequences have different snapshots and compare as unequal.
1433+
"""
1434+
path = tmp_path / "test.jsonlt"
1435+
_ = path.write_text('{"id": "alice", "v": 1}\n')
1436+
1437+
table = Table(path, key="id")
1438+
1439+
# First transaction: add bob
1440+
tx1 = table.transaction()
1441+
tx1.put({"id": "bob", "v": 2})
1442+
tx1.commit()
1443+
1444+
# Second transaction: add carol (different write)
1445+
tx2 = table.transaction()
1446+
tx2.put({"id": "carol", "v": 3})
1447+
1448+
try:
1449+
# tx1 is committed (has alice+bob in snapshot)
1450+
# tx2 is active (has alice+bob+carol in snapshot)
1451+
# They differ in both finalized status and snapshot content
1452+
assert tx1 != tx2
1453+
finally:
1454+
tx2.abort()
1455+
14281456
def test_transaction_is_not_hashable(
14291457
self, make_table: "Callable[..., Table]"
14301458
) -> None:

0 commit comments

Comments
 (0)