mirror of
https://github.com/NCBM/plyngent.git
synced 2026-07-23 05:55:16 +08:00
test/memory+runtime: cover store and client factory
Enable pytest-asyncio auto mode; assert default user, message round-trip, and provider→client mapping including errors.
This commit is contained in:
@@ -37,6 +37,11 @@ reportExplicitAny = "hint"
|
|||||||
reportImplicitStringConcatenation = "hint"
|
reportImplicitStringConcatenation = "hint"
|
||||||
reportImportCycles = "hint"
|
reportImportCycles = "hint"
|
||||||
|
|
||||||
|
[tool.pytest.ini_options]
|
||||||
|
asyncio_mode = "auto"
|
||||||
|
asyncio_default_fixture_loop_scope = "function"
|
||||||
|
testpaths = ["tests"]
|
||||||
|
|
||||||
[tool.pdm]
|
[tool.pdm]
|
||||||
distribution = true
|
distribution = true
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,61 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from plyngent.config.models import DatabaseConfig
|
||||||
|
from plyngent.lmproto.openai_compatible.model import AssistantChatMessage, UserChatMessage
|
||||||
|
from plyngent.memory import DEFAULT_USER_NAME, MemoryStore
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from collections.abc import AsyncIterator
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
async def store() -> AsyncIterator[MemoryStore]:
|
||||||
|
memory = await MemoryStore.open(DatabaseConfig())
|
||||||
|
yield memory
|
||||||
|
await memory.close()
|
||||||
|
|
||||||
|
|
||||||
|
async def test_open_creates_default_user(store: MemoryStore) -> None:
|
||||||
|
user = await store.get_user_by_name(DEFAULT_USER_NAME)
|
||||||
|
assert user is not None
|
||||||
|
assert user.name == DEFAULT_USER_NAME
|
||||||
|
|
||||||
|
|
||||||
|
async def test_create_session_uses_default_user(store: MemoryStore) -> None:
|
||||||
|
session = await store.create_session(name="chat-1")
|
||||||
|
assert session.sid is not None
|
||||||
|
assert session.name == "chat-1"
|
||||||
|
user = await store.get_user_by_name(DEFAULT_USER_NAME)
|
||||||
|
assert user is not None
|
||||||
|
assert session.uid == user.uid
|
||||||
|
|
||||||
|
|
||||||
|
async def test_append_and_list_messages(store: MemoryStore) -> None:
|
||||||
|
session = await store.create_session()
|
||||||
|
user_msg = UserChatMessage(content="hello")
|
||||||
|
assistant_msg = AssistantChatMessage(content="hi")
|
||||||
|
|
||||||
|
row0 = await store.append_message(session.sid, user_msg)
|
||||||
|
row1 = await store.append_message(session.sid, assistant_msg)
|
||||||
|
assert row0.seq == 0
|
||||||
|
assert row1.seq == 1
|
||||||
|
|
||||||
|
messages = await store.list_messages(session.sid)
|
||||||
|
assert len(messages) == 2 # noqa: PLR2004
|
||||||
|
assert isinstance(messages[0], UserChatMessage)
|
||||||
|
assert messages[0].content == "hello"
|
||||||
|
assert isinstance(messages[1], AssistantChatMessage)
|
||||||
|
assert messages[1].content == "hi"
|
||||||
|
|
||||||
|
|
||||||
|
async def test_list_sessions(store: MemoryStore) -> None:
|
||||||
|
s1 = await store.create_session(name="a")
|
||||||
|
s2 = await store.create_session(name="b")
|
||||||
|
sessions = await store.list_sessions()
|
||||||
|
ids = {s.sid for s in sessions}
|
||||||
|
assert s1.sid in ids
|
||||||
|
assert s2.sid in ids
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from plyngent.config.models import (
|
||||||
|
AnthropicProvider,
|
||||||
|
DeepseekProvider,
|
||||||
|
OpenAICompatibleProvider,
|
||||||
|
OpenAIProvider,
|
||||||
|
)
|
||||||
|
from plyngent.lmproto.deepseek import DeepseekOpenAIClient
|
||||||
|
from plyngent.lmproto.openai_compatible import OpenAIClient
|
||||||
|
from plyngent.runtime import ProviderNotSupportedError, create_client, provider_to_openai_config
|
||||||
|
|
||||||
|
|
||||||
|
def test_openai_provider_defaults_base_url() -> None:
|
||||||
|
provider = OpenAIProvider(access_key_or_token="sk-test")
|
||||||
|
config = provider_to_openai_config(provider)
|
||||||
|
assert config.access_key_or_token == "sk-test"
|
||||||
|
assert config.base_url == "https://api.openai.com/v1"
|
||||||
|
client = create_client(provider)
|
||||||
|
assert isinstance(client, OpenAIClient)
|
||||||
|
|
||||||
|
|
||||||
|
def test_openai_compatible_requires_url() -> None:
|
||||||
|
provider = OpenAICompatibleProvider(access_key_or_token="sk-test")
|
||||||
|
with pytest.raises(ProviderNotSupportedError, match="url"):
|
||||||
|
_ = create_client(provider)
|
||||||
|
|
||||||
|
|
||||||
|
def test_openai_compatible_client() -> None:
|
||||||
|
provider = OpenAICompatibleProvider(
|
||||||
|
access_key_or_token="sk-test",
|
||||||
|
url="https://example.com/v1",
|
||||||
|
)
|
||||||
|
client = create_client(provider)
|
||||||
|
assert isinstance(client, OpenAIClient)
|
||||||
|
assert provider_to_openai_config(provider).base_url == "https://example.com/v1"
|
||||||
|
|
||||||
|
|
||||||
|
def test_deepseek_openai_convention() -> None:
|
||||||
|
provider = DeepseekProvider(access_key_or_token="sk-test")
|
||||||
|
client = create_client(provider)
|
||||||
|
assert isinstance(client, DeepseekOpenAIClient)
|
||||||
|
assert provider_to_openai_config(provider).base_url == "https://api.deepseek.com/v1"
|
||||||
|
|
||||||
|
|
||||||
|
def test_deepseek_anthropic_convention_not_implemented() -> None:
|
||||||
|
provider = DeepseekProvider(
|
||||||
|
access_key_or_token="sk-test",
|
||||||
|
extras={"convention": "anthropic"},
|
||||||
|
)
|
||||||
|
with pytest.raises(ProviderNotSupportedError, match="anthropic"):
|
||||||
|
_ = create_client(provider)
|
||||||
|
|
||||||
|
|
||||||
|
def test_anthropic_not_implemented() -> None:
|
||||||
|
provider = AnthropicProvider(access_key_or_token="sk-test")
|
||||||
|
with pytest.raises(ProviderNotSupportedError, match="anthropic"):
|
||||||
|
_ = create_client(provider)
|
||||||
Reference in New Issue
Block a user