from __future__ import annotations from unittest.mock import AsyncMock import pytest from yuxi.channels.adapters.imessage.probe import ( clear_rpc_support_cache, get_rpc_support_cached, set_rpc_support_cached, ) class TestRpcSupportCache: def test_default_not_cached(self): assert get_rpc_support_cached("http://new-server:1234") is None def test_set_and_get(self): set_rpc_support_cached("http://server:1234", True) assert get_rpc_support_cached("http://server:1234") is True def test_set_false(self): set_rpc_support_cached("http://server:1234", False) assert get_rpc_support_cached("http://server:1234") is False def test_different_servers(self): set_rpc_support_cached("http://s1:1234", True) set_rpc_support_cached("http://s2:1234", False) assert get_rpc_support_cached("http://s1:1234") is True assert get_rpc_support_cached("http://s2:1234") is False def test_clear(self): set_rpc_support_cached("http://server:1234", True) clear_rpc_support_cache() assert get_rpc_support_cached("http://server:1234") is None class TestProbeFunctions: @pytest.mark.asyncio async def test_probe_bridge_returns_complete_info(self): from yuxi.channels.adapters.imessage.probe import probe_bridge mock_bridge = AsyncMock() mock_bridge.probe_server = AsyncMock( return_value={"version": "2.0.0", "os_version": "15.2"} ) mock_bridge.get_handle = AsyncMock( return_value={"connected": True, "handle": "bot@icloud.com"} ) result = await probe_bridge(mock_bridge) assert result["bridge_version"] == "2.0.0" assert result["bridge_os_version"] == "15.2" assert result["imessage_connected"] is True assert result["imessage_handle"] == "bot@icloud.com" @pytest.mark.asyncio async def test_probe_bridge_disconnected(self): from yuxi.channels.adapters.imessage.probe import probe_bridge mock_bridge = AsyncMock() mock_bridge.probe_server = AsyncMock(return_value={"version": "1.0"}) mock_bridge.get_handle = AsyncMock( return_value={"connected": False, "handle": None} ) result = await probe_bridge(mock_bridge) assert result["imessage_connected"] is False class TestSentMessageCache: def test_cache_record_and_get(self): from yuxi.channels.adapters.imessage.sent_cache import SentMessageCache cache = SentMessageCache() cache.record("msg_001", "Hello world", "chat_001") entry = cache.get("msg_001") assert entry is not None assert entry["message_id"] == "msg_001" assert entry["content"] == "Hello world" assert entry["chat_guid"] == "chat_001" def test_cache_get_content(self): from yuxi.channels.adapters.imessage.sent_cache import SentMessageCache cache = SentMessageCache() cache.record("msg_001", "Hello world", "chat_001") assert cache.get_content("msg_001") == "Hello world" def test_cache_get_missing(self): from yuxi.channels.adapters.imessage.sent_cache import SentMessageCache cache = SentMessageCache() assert cache.get("nonexistent") is None assert cache.get_content("nonexistent") is None def test_cache_list_recent(self): from yuxi.channels.adapters.imessage.sent_cache import SentMessageCache cache = SentMessageCache() for i in range(10): cache.record(f"msg_{i:03d}", f"Message {i}", "chat_001") recent = cache.list_recent(5) assert len(recent) == 5 recent_all = cache.list_recent(100) assert len(recent_all) == 10 def test_cache_content_truncation(self): from yuxi.channels.adapters.imessage.sent_cache import SentMessageCache cache = SentMessageCache() long_text = "X" * 1000 cache.record("msg_001", long_text, "chat_001") assert len(cache.get_content("msg_001")) <= 500 class TestStickerCache: def test_add_and_get(self, tmp_path): from yuxi.channels.adapters.imessage.sticker_cache import StickerCache cache = StickerCache(cache_dir=str(tmp_path)) cache.add("sticker_001", "https://example.com/sticker.png", {"type": "image"}) entry = cache.get("sticker_001") assert entry is not None assert entry["url"] == "https://example.com/sticker.png" assert entry["metadata"]["type"] == "image" def test_get_url(self, tmp_path): from yuxi.channels.adapters.imessage.sticker_cache import StickerCache cache = StickerCache(cache_dir=str(tmp_path)) cache.add("sticker_001", "https://example.com/sticker.png") assert cache.get_url("sticker_001") == "https://example.com/sticker.png" def test_get_missing(self, tmp_path): from yuxi.channels.adapters.imessage.sticker_cache import StickerCache cache = StickerCache(cache_dir=str(tmp_path)) assert cache.get("nonexistent") is None assert cache.get_url("nonexistent") is None def test_clear(self, tmp_path): from yuxi.channels.adapters.imessage.sticker_cache import StickerCache cache = StickerCache(cache_dir=str(tmp_path)) cache.add("sticker_001", "https://example.com/1.png") cache.add("sticker_002", "https://example.com/2.png") cache.clear() assert cache.get("sticker_001") is None assert cache.get("sticker_002") is None def test_max_entries_eviction(self, tmp_path): from yuxi.channels.adapters.imessage.sticker_cache import StickerCache cache = StickerCache(cache_dir=str(tmp_path), max_entries=3) for i in range(5): cache.add(f"sticker_{i}", f"https://example.com/{i}.png") assert len(cache._index) <= 3