mirror of
https://github.com/turnstonelabs/turnstone.git
synced 2026-08-27 14:24:47 -06:00
ab1a71c86c
* feat: add PostgreSQL CI integration tests Add --storage-backend pytest option and shared storage_backend fixture in conftest.py that creates SQLiteBackend or PostgreSQLBackend based on the flag. Migrate 13 storage test files to use shared fixture instead of local SQLiteBackend fixtures. Add test-postgres CI job with PostgreSQL 17 service container that runs the full test suite against real PostgreSQL. * fix: use TRUNCATE CASCADE for PG cleanup, wrap in try/finally TRUNCATE is faster than per-table DELETE and resets autoincrement sequences. try/except ensures reset_storage() always runs even if cleanup fails due to a corrupted connection from a failing test. * fix: document _engine coupling in PG cleanup comment
78 lines
3.2 KiB
Python
78 lines
3.2 KiB
Python
"""Tests for the services registry storage methods."""
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
class TestServiceRegistry:
|
|
def test_register_and_list(self, storage):
|
|
storage.register_service("channel", "ch-1", "http://localhost:8091")
|
|
services = storage.list_services("channel", max_age_seconds=120)
|
|
assert len(services) == 1
|
|
assert services[0]["service_type"] == "channel"
|
|
assert services[0]["service_id"] == "ch-1"
|
|
assert services[0]["url"] == "http://localhost:8091"
|
|
|
|
def test_register_upsert(self, storage):
|
|
storage.register_service("channel", "ch-1", "http://old:8091")
|
|
storage.register_service("channel", "ch-1", "http://new:8091")
|
|
services = storage.list_services("channel", max_age_seconds=120)
|
|
assert len(services) == 1
|
|
assert services[0]["url"] == "http://new:8091"
|
|
|
|
def test_heartbeat(self, storage):
|
|
storage.register_service("channel", "ch-1", "http://localhost:8091")
|
|
result = storage.heartbeat_service("channel", "ch-1")
|
|
assert result is True
|
|
|
|
def test_heartbeat_nonexistent(self, storage):
|
|
result = storage.heartbeat_service("channel", "nonexistent")
|
|
assert result is False
|
|
|
|
def test_list_filters_stale(self, storage):
|
|
storage.register_service("channel", "ch-1", "http://localhost:8091")
|
|
# Manually set heartbeat to the past so it's stale
|
|
from datetime import UTC, datetime, timedelta
|
|
|
|
import sqlalchemy as sa
|
|
|
|
from turnstone.core.storage._schema import services
|
|
|
|
old_time = (datetime.now(UTC) - timedelta(seconds=300)).strftime("%Y-%m-%dT%H:%M:%S")
|
|
with storage._engine.connect() as conn:
|
|
conn.execute(sa.update(services).values(last_heartbeat=old_time))
|
|
conn.commit()
|
|
|
|
# Should be excluded with 120s max age
|
|
result = storage.list_services("channel", max_age_seconds=120)
|
|
assert len(result) == 0
|
|
|
|
def test_list_empty(self, storage):
|
|
services = storage.list_services("channel", max_age_seconds=120)
|
|
assert services == []
|
|
|
|
def test_list_filters_by_type(self, storage):
|
|
storage.register_service("channel", "ch-1", "http://localhost:8091")
|
|
storage.register_service("bridge", "br-1", "http://localhost:8080")
|
|
channels = storage.list_services("channel", max_age_seconds=120)
|
|
bridges = storage.list_services("bridge", max_age_seconds=120)
|
|
assert len(channels) == 1
|
|
assert len(bridges) == 1
|
|
|
|
def test_deregister(self, storage):
|
|
storage.register_service("channel", "ch-1", "http://localhost:8091")
|
|
result = storage.deregister_service("channel", "ch-1")
|
|
assert result is True
|
|
services = storage.list_services("channel", max_age_seconds=120)
|
|
assert services == []
|
|
|
|
def test_deregister_nonexistent(self, storage):
|
|
result = storage.deregister_service("channel", "nonexistent")
|
|
assert result is False
|
|
|
|
def test_metadata(self, storage):
|
|
storage.register_service(
|
|
"channel", "ch-1", "http://localhost:8091", metadata='{"adapter": "discord"}'
|
|
)
|
|
services = storage.list_services("channel", max_age_seconds=120)
|
|
assert services[0]["metadata"] == '{"adapter": "discord"}'
|