"""core/huya/anon_device.py 的协议装配与解析测试(mock 网络,不打真实请求)。""" from unittest.mock import Mock import pytest import requests from core.huya.anon_device import ( ANON_LOGIN_URL, AnonymousDeviceError, fetch_anonymous_device_state, ) def _fake_response(status=200, headers=None, text="", json_body=None): resp = Mock(spec=requests.Response) resp.status_code = status resp.headers = headers or {} resp.text = text resp.json = Mock(return_value=json_body) if json_body is not None else Mock( side_effect=ValueError("bad json") ) return resp def _fake_anon_body(uid="1471255709907", biztoken="A" * 344): return { "uri": 10014, "returnCode": 0, "message": "success", "data": {"uid": uid, "biztoken": biztoken}, } def test_fetches_four_fields_from_middle_and_anon(monkeypatch): session = Mock(spec=requests.Session) deviceid = "w_1147246591246680065" session.get.return_value = _fake_response( headers={"Set-Cookie": f"udb_deviceid={deviceid}; Max-Age=315360000; Domain=huya.com"} ) session.post.return_value = _fake_response(json_body=_fake_anon_body()) monkeypatch.setattr("core.huya.anon_device._new_session", lambda **kw: session) state = fetch_anonymous_device_state(session=session) assert state["udb_deviceid"] == deviceid assert state["udb_anouid"] == "1471255709907" assert state["udb_anobiztoken"] == "A" * 344 assert len(state["udb_guiddata"]) == 32 # middle 请求装配:URL 含 8 位随机数与 32hex guiddata get_url = session.get.call_args.args[0] parts = get_url.split("/") assert len(parts[-1]) == 32 assert len(parts[-3]) == 8 assert parts[-3].isdigit() assert state["udb_guiddata"] == parts[-1] # anonymousLogin 装配:必须带 middle Referer;body 含随机 context/csid post_kwargs = session.post.call_args.kwargs assert session.post.call_args.args[0] == ANON_LOGIN_URL assert post_kwargs["headers"]["Referer"] == get_url import json as _json payload = _json.loads(post_kwargs["data"]) assert payload["context"].startswith("WB-") assert payload["sdid"].startswith("csid_") def test_values_are_random_across_calls(monkeypatch): session = Mock(spec=requests.Session) session.get.return_value = _fake_response( headers={"Set-Cookie": "udb_deviceid=w_1147246591246680065; Max-Age=1"} ) session.post.return_value = _fake_response(json_body=_fake_anon_body(uid="1")) monkeypatch.setattr("core.huya.anon_device._new_session", lambda **kw: session) import json as _json a = fetch_anonymous_device_state(session=session) b = fetch_anonymous_device_state(session=session) # 客户端随机部分:guiddata(middle URL) 与 anonymousLogin 的 context/csid assert a["udb_guiddata"] != b["udb_guiddata"] post_a = _json.loads(session.post.call_args_list[0].kwargs["data"]) post_b = _json.loads(session.post.call_args_list[1].kwargs["data"]) assert post_a["context"] != post_b["context"] assert post_a["sdid"] != post_b["sdid"] def test_bad_middle_status_raises(monkeypatch): session = Mock(spec=requests.Session) session.get.return_value = _fake_response(status=403) monkeypatch.setattr("core.huya.anon_device._new_session", lambda **kw: session) with pytest.raises(AnonymousDeviceError): fetch_anonymous_device_state(session=session) def test_missing_deviceid_in_set_cookie_raises(monkeypatch): session = Mock(spec=requests.Session) session.get.return_value = _fake_response(headers={"Set-Cookie": "PHPSESSID=x"}) monkeypatch.setattr("core.huya.anon_device._new_session", lambda **kw: session) with pytest.raises(AnonymousDeviceError, match="udb_deviceid"): fetch_anonymous_device_state(session=session) def test_anon_error_return_code_raises(monkeypatch): session = Mock(spec=requests.Session) session.get.return_value = _fake_response( headers={"Set-Cookie": "udb_deviceid=w_1147246591246680065; Max-Age=1"} ) session.post.return_value = _fake_response( json_body={"uri": 10014, "returnCode": 108, "message": "blocked"} ) monkeypatch.setattr("core.huya.anon_device._new_session", lambda **kw: session) with pytest.raises(AnonymousDeviceError, match="returnCode=108"): fetch_anonymous_device_state(session=session) def test_non_json_anon_body_raises(monkeypatch): session = Mock(spec=requests.Session) session.get.return_value = _fake_response( headers={"Set-Cookie": "udb_deviceid=w_1147246591246680065; Max-Age=1"} ) session.post.return_value = _fake_response(text="error!") monkeypatch.setattr("core.huya.anon_device._new_session", lambda **kw: session) with pytest.raises(AnonymousDeviceError, match="非 JSON"): fetch_anonymous_device_state(session=session)