mirror of
https://github.com/jkingsman/Remote-Terminal-for-MeshCore.git
synced 2026-08-12 03:33:03 +02:00
Advert-path uses correct identity for dedupe
This commit is contained in:
@@ -214,6 +214,28 @@ class TestAdvertPaths:
|
||||
assert data[0]["path"] == ""
|
||||
assert data[0]["next_hop"] is None
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_contact_advert_paths_distinguishes_same_bytes_by_hop_count(
|
||||
self, test_db, client
|
||||
):
|
||||
repeater_key = KEY_A
|
||||
await _insert_contact(repeater_key, "R1", type=2)
|
||||
await ContactAdvertPathRepository.record_observation(
|
||||
repeater_key, "aa00", 1000, hop_count=1
|
||||
)
|
||||
await ContactAdvertPathRepository.record_observation(
|
||||
repeater_key, "aa00", 1010, hop_count=2
|
||||
)
|
||||
|
||||
response = await client.get(f"/api/contacts/{repeater_key}/advert-paths")
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert [(item["path"], item["path_len"], item["next_hop"]) for item in data] == [
|
||||
("aa00", 2, "aa"),
|
||||
("aa00", 1, "aa00"),
|
||||
]
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_contact_advert_paths_works_for_non_repeater(self, test_db, client):
|
||||
await _insert_contact(KEY_A, "Alice", type=1)
|
||||
|
||||
@@ -1116,8 +1116,8 @@ class TestMigration039:
|
||||
|
||||
applied = await run_migrations(conn)
|
||||
|
||||
assert applied == 1
|
||||
assert await get_version(conn) == 39
|
||||
assert applied == 2
|
||||
assert await get_version(conn) == 40
|
||||
|
||||
cursor = await conn.execute(
|
||||
"""
|
||||
@@ -1186,8 +1186,8 @@ class TestMigration039:
|
||||
|
||||
applied = await run_migrations(conn)
|
||||
|
||||
assert applied == 1
|
||||
assert await get_version(conn) == 39
|
||||
assert applied == 2
|
||||
assert await get_version(conn) == 40
|
||||
|
||||
cursor = await conn.execute(
|
||||
"""
|
||||
@@ -1205,3 +1205,67 @@ class TestMigration039:
|
||||
assert rows[1]["out_path_hash_mode"] == -1
|
||||
finally:
|
||||
await conn.close()
|
||||
|
||||
|
||||
class TestMigration040:
|
||||
"""Test migration 040: include path_len in advert-path identity."""
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_rebuilds_contact_advert_paths_to_distinguish_same_bytes_by_hop_count(self):
|
||||
conn = await aiosqlite.connect(":memory:")
|
||||
conn.row_factory = aiosqlite.Row
|
||||
try:
|
||||
await set_version(conn, 39)
|
||||
await conn.execute("""
|
||||
CREATE TABLE contact_advert_paths (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
public_key TEXT NOT NULL,
|
||||
path_hex TEXT NOT NULL,
|
||||
path_len INTEGER NOT NULL,
|
||||
first_seen INTEGER NOT NULL,
|
||||
last_seen INTEGER NOT NULL,
|
||||
heard_count INTEGER NOT NULL DEFAULT 1,
|
||||
UNIQUE(public_key, path_hex)
|
||||
)
|
||||
""")
|
||||
await conn.execute(
|
||||
"""
|
||||
INSERT INTO contact_advert_paths
|
||||
(public_key, path_hex, path_len, first_seen, last_seen, heard_count)
|
||||
VALUES (?, ?, ?, ?, ?, ?)
|
||||
""",
|
||||
("aa" * 32, "aa00", 1, 1000, 1001, 2),
|
||||
)
|
||||
await conn.commit()
|
||||
|
||||
applied = await run_migrations(conn)
|
||||
|
||||
assert applied == 1
|
||||
assert await get_version(conn) == 40
|
||||
|
||||
await conn.execute(
|
||||
"""
|
||||
INSERT INTO contact_advert_paths
|
||||
(public_key, path_hex, path_len, first_seen, last_seen, heard_count)
|
||||
VALUES (?, ?, ?, ?, ?, ?)
|
||||
""",
|
||||
("aa" * 32, "aa00", 2, 1002, 1002, 1),
|
||||
)
|
||||
await conn.commit()
|
||||
|
||||
cursor = await conn.execute(
|
||||
"""
|
||||
SELECT path_hex, path_len, heard_count
|
||||
FROM contact_advert_paths
|
||||
WHERE public_key = ?
|
||||
ORDER BY path_len ASC
|
||||
""",
|
||||
("aa" * 32,),
|
||||
)
|
||||
rows = await cursor.fetchall()
|
||||
assert [(row["path_hex"], row["path_len"], row["heard_count"]) for row in rows] == [
|
||||
("aa00", 1, 2),
|
||||
("aa00", 2, 1),
|
||||
]
|
||||
finally:
|
||||
await conn.close()
|
||||
|
||||
@@ -286,6 +286,43 @@ class TestContactAdvertPathRepository:
|
||||
assert len(paths) == 1
|
||||
assert paths[0].next_hop == "aa11"
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_same_path_hex_with_different_path_len_is_stored_separately(self, test_db):
|
||||
repeater_key = "ac" * 32
|
||||
await ContactRepository.upsert({"public_key": repeater_key, "name": "Rsplit", "type": 2})
|
||||
|
||||
await ContactAdvertPathRepository.record_observation(
|
||||
repeater_key, "aa00", 1000, hop_count=1
|
||||
)
|
||||
await ContactAdvertPathRepository.record_observation(
|
||||
repeater_key, "aa00", 1010, hop_count=2
|
||||
)
|
||||
|
||||
paths = await ContactAdvertPathRepository.get_recent_for_contact(repeater_key, limit=10)
|
||||
assert len(paths) == 2
|
||||
assert [(p.path, p.path_len, p.next_hop) for p in paths] == [
|
||||
("aa00", 2, "aa"),
|
||||
("aa00", 1, "aa00"),
|
||||
]
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_prune_distinguishes_same_path_hex_with_different_path_len(self, test_db):
|
||||
repeater_key = "ad" * 32
|
||||
await ContactRepository.upsert({"public_key": repeater_key, "name": "Rprune", "type": 2})
|
||||
|
||||
await ContactAdvertPathRepository.record_observation(
|
||||
repeater_key, "aa00", 1000, max_paths=2, hop_count=1
|
||||
)
|
||||
await ContactAdvertPathRepository.record_observation(
|
||||
repeater_key, "aa00", 1001, max_paths=2, hop_count=2
|
||||
)
|
||||
await ContactAdvertPathRepository.record_observation(
|
||||
repeater_key, "bb00", 1002, max_paths=2, hop_count=1
|
||||
)
|
||||
|
||||
paths = await ContactAdvertPathRepository.get_recent_for_contact(repeater_key, limit=10)
|
||||
assert [(p.path, p.path_len) for p in paths] == [("bb00", 1), ("aa00", 2)]
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_prunes_to_most_recent_n_unique_paths(self, test_db):
|
||||
repeater_key = "bb" * 32
|
||||
|
||||
Reference in New Issue
Block a user