210 lines
5.0 KiB
Python
210 lines
5.0 KiB
Python
"""
|
|
ⒸAngelaMos | 2025
|
|
Pytest configuration and fixtures for all tests
|
|
"""
|
|
|
|
import asyncio
|
|
from uuid import uuid4
|
|
from typing import Any
|
|
from collections.abc import AsyncGenerator
|
|
|
|
import pytest
|
|
import pytest_asyncio
|
|
from sqlmodel import SQLModel
|
|
from sqlalchemy.ext.asyncio import (
|
|
AsyncSession,
|
|
create_async_engine,
|
|
)
|
|
from sqlalchemy.orm import sessionmaker
|
|
from webauthn.helpers import bytes_to_base64url
|
|
|
|
from app.models.User import User
|
|
from app.models.IdentityKey import IdentityKey
|
|
from app.models.SignedPrekey import SignedPrekey
|
|
from app.models.OneTimePrekey import OneTimePrekey
|
|
from app.core.encryption.x3dh_manager import x3dh_manager
|
|
|
|
|
|
@pytest.fixture(scope = "session")
|
|
def event_loop():
|
|
"""
|
|
Create event loop for async tests
|
|
"""
|
|
loop = asyncio.get_event_loop_policy().new_event_loop()
|
|
yield loop
|
|
loop.close()
|
|
|
|
|
|
@pytest_asyncio.fixture(scope = "function")
|
|
async def db_session() -> AsyncGenerator[AsyncSession]:
|
|
"""
|
|
Create in-memory SQLite database for testing
|
|
"""
|
|
engine = create_async_engine(
|
|
"sqlite+aiosqlite:///:memory:",
|
|
echo = False,
|
|
future = True,
|
|
)
|
|
|
|
async with engine.begin() as conn:
|
|
await conn.run_sync(SQLModel.metadata.create_all)
|
|
|
|
async_session = sessionmaker(
|
|
bind = engine,
|
|
class_ = AsyncSession,
|
|
expire_on_commit = False,
|
|
)
|
|
|
|
async with async_session() as session:
|
|
yield session
|
|
await session.rollback()
|
|
|
|
await engine.dispose()
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def test_user(db_session: AsyncSession) -> User:
|
|
"""
|
|
Create test user
|
|
"""
|
|
user = User(
|
|
username = "testuser",
|
|
display_name = "Test User",
|
|
is_active = True,
|
|
is_verified = True,
|
|
)
|
|
db_session.add(user)
|
|
await db_session.commit()
|
|
await db_session.refresh(user)
|
|
return user
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def test_user_2(db_session: AsyncSession) -> User:
|
|
"""
|
|
Create second test user for conversations
|
|
"""
|
|
user = User(
|
|
username = "testuser2",
|
|
display_name = "Test User 2",
|
|
is_active = True,
|
|
is_verified = True,
|
|
)
|
|
db_session.add(user)
|
|
await db_session.commit()
|
|
await db_session.refresh(user)
|
|
return user
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def test_identity_key(
|
|
db_session: AsyncSession,
|
|
test_user: User
|
|
) -> IdentityKey:
|
|
"""
|
|
Create identity key for test user
|
|
"""
|
|
ik_private_x25519, ik_public_x25519 = (
|
|
x3dh_manager.generate_identity_keypair_x25519()
|
|
)
|
|
ik_private_ed25519, ik_public_ed25519 = (
|
|
x3dh_manager.generate_identity_keypair_ed25519()
|
|
)
|
|
|
|
identity_key = IdentityKey(
|
|
user_id = test_user.id,
|
|
public_key = ik_public_x25519,
|
|
private_key = ik_private_x25519,
|
|
public_key_ed25519 = ik_public_ed25519,
|
|
private_key_ed25519 = ik_private_ed25519,
|
|
)
|
|
|
|
db_session.add(identity_key)
|
|
await db_session.commit()
|
|
await db_session.refresh(identity_key)
|
|
return identity_key
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def test_signed_prekey(
|
|
db_session: AsyncSession,
|
|
test_user: User,
|
|
test_identity_key: IdentityKey
|
|
) -> SignedPrekey:
|
|
"""
|
|
Create signed prekey for test user
|
|
"""
|
|
spk_private, spk_public, spk_signature = x3dh_manager.generate_signed_prekey(
|
|
test_identity_key.private_key_ed25519
|
|
)
|
|
|
|
signed_prekey = SignedPrekey(
|
|
user_id = test_user.id,
|
|
key_id = 1,
|
|
public_key = spk_public,
|
|
private_key = spk_private,
|
|
signature = spk_signature,
|
|
is_active = True,
|
|
)
|
|
|
|
db_session.add(signed_prekey)
|
|
await db_session.commit()
|
|
await db_session.refresh(signed_prekey)
|
|
return signed_prekey
|
|
|
|
|
|
@pytest_asyncio.fixture
|
|
async def test_one_time_prekey(
|
|
db_session: AsyncSession,
|
|
test_user: User
|
|
) -> OneTimePrekey:
|
|
"""
|
|
Create one-time prekey for test user
|
|
"""
|
|
opk_private, opk_public = x3dh_manager.generate_one_time_prekey()
|
|
|
|
one_time_prekey = OneTimePrekey(
|
|
user_id = test_user.id,
|
|
key_id = 1,
|
|
public_key = opk_public,
|
|
private_key = opk_private,
|
|
is_used = False,
|
|
)
|
|
|
|
db_session.add(one_time_prekey)
|
|
await db_session.commit()
|
|
await db_session.refresh(one_time_prekey)
|
|
return one_time_prekey
|
|
|
|
|
|
@pytest.fixture
|
|
def mock_webauthn_credential() -> dict[str, Any]:
|
|
"""
|
|
Mock WebAuthn credential response
|
|
"""
|
|
return {
|
|
"id": bytes_to_base64url(uuid4().bytes),
|
|
"rawId": bytes_to_base64url(uuid4().bytes),
|
|
"type": "public-key",
|
|
"response": {
|
|
"clientDataJSON": bytes_to_base64url(b'{"type":"webauthn.create"}'),
|
|
"attestationObject": bytes_to_base64url(b"mock_attestation"),
|
|
},
|
|
}
|
|
|
|
|
|
@pytest.fixture
|
|
def sample_plaintext() -> str:
|
|
"""
|
|
Sample message for encryption tests
|
|
"""
|
|
return "Hello, this is a test message!"
|
|
|
|
|
|
@pytest.fixture
|
|
def sample_associated_data() -> bytes:
|
|
"""
|
|
Sample associated data for AEAD
|
|
"""
|
|
return b"test_sender:test_recipient"
|