更新
This commit is contained in:
@@ -30,67 +30,69 @@ class ConversationPollBandwidthTests(unittest.IsolatedAsyncioTestCase):
|
||||
account_id=9,
|
||||
)
|
||||
|
||||
async def test_terminal_token_error_does_not_probe_other_payloads(self):
|
||||
async def test_inbox_is_fetched_with_exactly_one_protobuf_request(self):
|
||||
"""imapi 只认 protobuf;轮询一次就只该发一个请求。"""
|
||||
client = self._make_client()
|
||||
client._request = AsyncMock(
|
||||
return_value={
|
||||
"status_code": 500,
|
||||
"error_desc": "empty token",
|
||||
"body": {},
|
||||
}
|
||||
)
|
||||
client.fetch_inbox_messages = AsyncMock(return_value=[])
|
||||
client._request = AsyncMock()
|
||||
|
||||
self.assertEqual(await client.get_conversations(), [])
|
||||
client._request.assert_awaited_once()
|
||||
self.assertEqual(client._request.await_args.args[0], "POST")
|
||||
client.fetch_inbox_messages.assert_awaited_once()
|
||||
# 不能再退回 JSON 的 /v1/conversation/list:那个请求恒被抖音拒绝。
|
||||
client._request.assert_not_awaited()
|
||||
|
||||
async def test_successful_empty_response_stops_after_first_payload(self):
|
||||
async def test_transport_failure_is_recorded_and_returns_empty(self):
|
||||
client = self._make_client()
|
||||
client._request = AsyncMock(
|
||||
return_value={"status_code": 0, "body": {"conversation_list": []}}
|
||||
)
|
||||
|
||||
self.assertEqual(await client.get_conversations(), [])
|
||||
client._request.assert_awaited_once()
|
||||
|
||||
async def test_parameter_error_can_fall_through_to_compatible_payload(self):
|
||||
client = self._make_client()
|
||||
client._request = AsyncMock(
|
||||
side_effect=[
|
||||
{"status_code": 400, "error_desc": "invalid parameter"},
|
||||
{"status_code": 0, "body": {"conversation_list": []}},
|
||||
]
|
||||
)
|
||||
|
||||
self.assertEqual(await client.get_conversations(), [])
|
||||
self.assertEqual(client._request.await_count, 2)
|
||||
self.assertTrue(
|
||||
all(call.args[0] == "POST" for call in client._request.await_args_list)
|
||||
)
|
||||
|
||||
async def test_get_fallback_only_runs_after_transport_failure(self):
|
||||
client = self._make_client()
|
||||
client._request = AsyncMock(
|
||||
side_effect=[None, {"status_code": 0, "body": {}}]
|
||||
)
|
||||
|
||||
self.assertEqual(await client.get_conversations(), [])
|
||||
self.assertEqual(
|
||||
[call.args[0] for call in client._request.await_args_list],
|
||||
["POST", "GET"],
|
||||
)
|
||||
|
||||
async def test_transport_outage_stops_after_one_post_and_get_pair(self):
|
||||
client = self._make_client()
|
||||
client._request = AsyncMock(return_value=None)
|
||||
client.fetch_inbox_messages = AsyncMock(side_effect=RuntimeError("boom"))
|
||||
|
||||
with self.assertLogs("douyin_im.http", level="WARNING"):
|
||||
self.assertEqual(await client.get_conversations(), [])
|
||||
|
||||
self.assertEqual(client._request.await_count, 2)
|
||||
self.assertIn("boom", client.last_error)
|
||||
|
||||
async def test_inbox_messages_group_into_one_row_per_conversation(self):
|
||||
client = self._make_client()
|
||||
client.fetch_inbox_messages = AsyncMock(
|
||||
return_value=[
|
||||
{
|
||||
"conversation_id": "0:1:10001:20001",
|
||||
"server_message_id": "700",
|
||||
"conversation_short_id": "555",
|
||||
"message_type": 7,
|
||||
"sender": "20001",
|
||||
"content": '{"text":"旧"}',
|
||||
},
|
||||
{
|
||||
"conversation_id": "0:1:10001:20001",
|
||||
"server_message_id": "900",
|
||||
"conversation_short_id": "555",
|
||||
"message_type": 7,
|
||||
"sender": "20001",
|
||||
"content": '{"text":"新"}',
|
||||
},
|
||||
{
|
||||
"conversation_id": "0:1:10001:20002",
|
||||
"server_message_id": "800",
|
||||
"message_type": 7,
|
||||
"sender": "20002",
|
||||
"content": '{"text":"另一个"}',
|
||||
},
|
||||
]
|
||||
)
|
||||
|
||||
rows = await client.get_conversations(enrich_profiles=False)
|
||||
|
||||
by_id = {r["conversation_id"]: r for r in rows}
|
||||
self.assertEqual(len(rows), 2)
|
||||
# 同一会话只保留 server_message_id 最大的那条
|
||||
self.assertEqual(by_id["0:1:10001:20001"]["server_message_id"], "900")
|
||||
self.assertIn("新", by_id["0:1:10001:20001"]["content"])
|
||||
# peer_uid 由 conversation_id 推导,不能直接取 sender(可能是自己)
|
||||
self.assertEqual(by_id["0:1:10001:20002"]["peer_uid"], "20002")
|
||||
# 顺手缓存 short_id,发送时就不必再 create 一次会话
|
||||
self.assertEqual(
|
||||
[call.args[0] for call in client._request.await_args_list],
|
||||
["POST", "GET"],
|
||||
client.session.conv_meta["0:1:10001:20001"]["conversation_short_id"],
|
||||
"555",
|
||||
)
|
||||
|
||||
def test_websocket_reconciliation_is_slow_and_http_fallback_stays_fast(self):
|
||||
@@ -156,6 +158,7 @@ class ConversationPollBandwidthTests(unittest.IsolatedAsyncioTestCase):
|
||||
class _HttpClient:
|
||||
def __init__(self):
|
||||
self.get_conversations = AsyncMock(return_value=[])
|
||||
self.conversation_list_unsupported = False
|
||||
|
||||
async def __aenter__(self):
|
||||
return self
|
||||
@@ -254,6 +257,7 @@ class ConversationPollBandwidthTests(unittest.IsolatedAsyncioTestCase):
|
||||
class _HttpClient:
|
||||
def __init__(self):
|
||||
self.get_conversations = AsyncMock(side_effect=snapshots)
|
||||
self.conversation_list_unsupported = False
|
||||
self.enter_count = 0
|
||||
self.exit_count = 0
|
||||
|
||||
|
||||
Reference in New Issue
Block a user