|
1 | | -from mnemos import Mnemos |
| 1 | +import pytest |
| 2 | +import os |
| 3 | +import shutil |
| 4 | +from mnemos import Mnemos, MnemosError |
2 | 5 |
|
3 | | -def test_mnemos(): |
4 | | - print("Testing Mnemos PyO3 bindings...") |
5 | | - |
| 6 | +DB_PATH = "/tmp/mnemos_test_py" |
| 7 | + |
| 8 | +@pytest.fixture(autouse=True) |
| 9 | +def cleanup(): |
| 10 | + if os.path.exists(DB_PATH): |
| 11 | + shutil.rmtree(DB_PATH) |
| 12 | + yield |
| 13 | + if os.path.exists(DB_PATH): |
| 14 | + shutil.rmtree(DB_PATH) |
| 15 | + |
| 16 | +def test_mnemos_basic_flow(): |
6 | 17 | # 1. Open with dimension 3 |
7 | | - db = Mnemos.open("/tmp/mnemos_test_py", dimension=3) |
| 18 | + db = Mnemos.open(DB_PATH, dimension=3) |
8 | 19 |
|
9 | 20 | # 2. Store memory |
10 | | - mid = db.remember_embedding([1.0, 0.0, 0.0]) |
11 | | - print(f"Stored memory: {mid}") |
| 21 | + mid = db.remember("Hello world", embedding=[1.0, 0.0, 0.0]) |
12 | 22 |
|
13 | 23 | # 3. Ask |
14 | | - hits = db.ask_embedding([1.0, 0.0, 0.0]) |
15 | | - print(f"Found {len(hits)} hits, top score={hits[0].score:.3f}") |
| 24 | + hits = db.ask("world", embedding=[1.0, 0.0, 0.0]) |
| 25 | + assert len(hits) == 1 |
16 | 26 | assert hits[0].id == mid |
17 | 27 |
|
18 | 28 | # 4. Get full memory |
19 | 29 | mem = db.get(mid) |
20 | | - print(f"Memory: {mem}") |
21 | 30 | assert mem.namespace == "default" |
22 | 31 | assert mem.id == mid |
| 32 | + assert bytes(mem.content).decode("utf-8") == "Hello world" |
23 | 33 |
|
24 | 34 | # 5. Connect |
25 | | - mid2 = db.remember_embedding([0.0, 1.0, 0.0]) |
| 35 | + mid2 = db.remember("Goodbye", embedding=[0.0, 1.0, 0.0]) |
26 | 36 | db.connect(mid, mid2, "related") |
27 | | - print(f"Connected {mid} -> {mid2}") |
28 | 37 |
|
29 | | - # 6. Stats |
| 38 | + # 6. Stats & Len |
30 | 39 | stats = db.stats() |
31 | | - print(f"Stats: {stats}") |
32 | 40 | assert stats.vector_dimension == 3 |
33 | 41 | assert stats.entries == 2 |
| 42 | + assert len(db) == 2 |
34 | 43 |
|
35 | | - # 7. Stress - error handling |
36 | | - try: |
37 | | - db.remember_embedding([1.0, 0.0]) # Wrong dimension |
38 | | - assert False, "Should have raised an error" |
39 | | - except Exception as e: |
40 | | - print(f"Caught expected error: {e}") |
| 44 | + # 7. Compact and Checkpoint |
| 45 | + db.compact() |
| 46 | + db.checkpoint() |
41 | 47 |
|
42 | | - try: |
43 | | - db2 = Mnemos.open("/tmp/mnemos_test_py", dimension=4) # Dimension mismatch on open |
44 | | - assert False, "Should have raised an error" |
45 | | - except Exception as e: |
46 | | - print(f"Caught expected error: {e}") |
47 | 48 |
|
48 | | - # 8. Compact |
49 | | - db.compact() |
50 | | - print("Compacted successfully") |
| 49 | +def test_mnemos_namespaces(): |
| 50 | + db = Mnemos.open(DB_PATH, dimension=3) |
| 51 | + |
| 52 | + agent_a = db.namespace("agent_a") |
| 53 | + agent_b = db.namespace("agent_b") |
51 | 54 |
|
52 | | - # 9. Checkpoint |
53 | | - db.checkpoint() |
54 | | - print("Checkpointed successfully") |
| 55 | + id_a = agent_a.remember("I am Agent A", embedding=[1.0, 0.0, 0.0]) |
| 56 | + agent_b.remember("I am Agent B", embedding=[0.0, 1.0, 0.0]) |
| 57 | + |
| 58 | + assert db.get(id_a).namespace == "agent_a" |
| 59 | + |
| 60 | + # Test ask filters by namespace using the wrapper |
| 61 | + hits_a = agent_a.ask("Agent A", embedding=[1.0, 0.0, 0.0]) |
| 62 | + assert len(hits_a) == 1 |
| 63 | + assert hits_a[0].id == id_a |
| 64 | + |
| 65 | + # Context manager test |
| 66 | + with Mnemos.open(DB_PATH, dimension=3) as db_ctx: |
| 67 | + assert len(db_ctx) == 2 |
| 68 | + |
| 69 | + |
| 70 | +def test_mnemos_error_handling(): |
| 71 | + db = Mnemos.open(DB_PATH, dimension=3) |
55 | 72 |
|
56 | | - print("All tests passed!") |
| 73 | + # Wrong dimension map |
| 74 | + with pytest.raises(MnemosError, match="embedding dimension mismatch"): |
| 75 | + db.remember("Wrong dim", embedding=[1.0, 0.0]) |
| 76 | + |
| 77 | + # Missing embedding required |
| 78 | + with pytest.raises(MnemosError, match="Embedding is currently required natively"): |
| 79 | + db.remember("No embedding") |
57 | 80 |
|
58 | | -if __name__ == "__main__": |
59 | | - import shutil |
60 | | - import os |
61 | | - if os.path.exists("/tmp/mnemos_test_py"): |
62 | | - shutil.rmtree("/tmp/mnemos_test_py") |
63 | | - test_mnemos() |
| 81 | + # Wrong dimension on open — must first write something with dim=3 |
| 82 | + mid = db.remember("Seed", embedding=[1.0, 0.0, 0.0]) |
| 83 | + db.checkpoint() # flush so the mismatch check sees entries > 0 |
| 84 | + with pytest.raises(MnemosError, match="(?i)dimension mismatch"): |
| 85 | + Mnemos.open(DB_PATH, dimension=4) |
0 commit comments