fix(douyu): 补齐拆分后支付轮询常量导入 + 代理三模式断言测试
- douyu_runner_manual/gold: 导入 core 的 DOUYU_PAYMENT_POLL_* 常量
(之前仅在 douyu_runner.py 单文件内可见, 拆分后到账轮询会 NameError)
- 新增 tests/test_douyu_runner_proxy.py: 静态/API/关闭三模式 + 降级直连 +
activity_client session 级 proxies, 兑现 8fe9fdf 提交说明中的行为断言
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
"""斗鱼任务代理接入三模式行为测试(静态 / API / 关闭)。"""
|
||||
|
||||
import os
|
||||
import unittest
|
||||
from unittest.mock import Mock
|
||||
|
||||
os.environ.setdefault("DATABASE_URL", "sqlite://")
|
||||
os.environ.setdefault("APP_ENCRYPTION_KEY", "MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY=")
|
||||
|
||||
from core.douyu.activity_client import DouyuActivityClient
|
||||
from web.backend.services.douyu_runner import DouyuBatchRunner
|
||||
from web.backend.services.douyu_runner_core import DouyuBatchRunnerCore
|
||||
from web.backend.models import ProxyConfig
|
||||
|
||||
|
||||
def _cfg(**overrides) -> ProxyConfig:
|
||||
values = {
|
||||
"enabled": False,
|
||||
"api_url": "",
|
||||
"http": "",
|
||||
"https": "",
|
||||
"whitelist_enabled": False,
|
||||
"whitelist_platform": "xiequ",
|
||||
"whitelist_credentials": None,
|
||||
"whitelist_uid": "",
|
||||
"whitelist_ukey": "",
|
||||
}
|
||||
values.update(overrides)
|
||||
cfg = ProxyConfig()
|
||||
for key, value in values.items():
|
||||
setattr(cfg, key, value)
|
||||
return cfg
|
||||
|
||||
|
||||
def _runner(db_cfg: ProxyConfig):
|
||||
db = Mock()
|
||||
db.query.return_value.first.return_value = db_cfg
|
||||
runner = DouyuBatchRunner.__new__(DouyuBatchRunner)
|
||||
DouyuBatchRunnerCore.__init__(runner, db, "batch", "query_points")
|
||||
return runner
|
||||
|
||||
|
||||
class DouyuProxyModeTests(unittest.TestCase):
|
||||
def test_disabled_mode_goes_direct(self):
|
||||
runner = _runner(_cfg(enabled=False))
|
||||
self.assertIsNone(runner._proxies_for_task())
|
||||
self.assertIsNone(runner._proxy_fetcher)
|
||||
client = runner._client("acf_uid=100")
|
||||
self.assertEqual(client.session.proxies, {})
|
||||
# 未开启代理时 execute 客户端不带 proxies 参数
|
||||
self.assertIsInstance(client, DouyuActivityClient)
|
||||
|
||||
def test_static_mode_uses_configured_proxies(self):
|
||||
runner = _runner(_cfg(enabled=True, http="http://10.0.0.1:8080"))
|
||||
proxies = runner._proxies_for_task()
|
||||
self.assertEqual(proxies, {"http": "http://10.0.0.1:8080", "https": "http://10.0.0.1:8080"})
|
||||
client = runner._client("acf_uid=100")
|
||||
self.assertEqual(client.session.proxies["https"], "http://10.0.0.1:8080")
|
||||
# 每次任务都取同一静态代理
|
||||
self.assertEqual(runner._proxies_for_task(), proxies)
|
||||
|
||||
def test_api_mode_fetches_new_proxy_per_task(self):
|
||||
cfg = _cfg(enabled=True, api_url="https://proxy-api.example/fetch")
|
||||
runner = _runner(cfg)
|
||||
self.assertIsNotNone(runner._proxy_fetcher)
|
||||
fake = Mock()
|
||||
fake.fetch_new_proxy.return_value = "http://10.0.0.2:3128"
|
||||
runner._proxy_fetcher = fake
|
||||
|
||||
proxies = runner._proxies_for_task()
|
||||
self.assertEqual(proxies, {"http": "http://10.0.0.2:3128", "https": "http://10.0.0.2:3128"})
|
||||
client = runner._client("acf_uid=100")
|
||||
self.assertEqual(client.session.proxies["http"], "http://10.0.0.2:3128")
|
||||
|
||||
# 每任务取新代理:_client 也会再 fetch 一次(客户端构造即取代理)
|
||||
fake.fetch_new_proxy.return_value = "http://10.0.0.3:3128"
|
||||
self.assertEqual(runner._proxies_for_task()["http"], "http://10.0.0.3:3128")
|
||||
self.assertEqual(fake.fetch_new_proxy.call_count, 3)
|
||||
|
||||
def test_api_mode_failure_falls_back_to_direct(self):
|
||||
runner = _runner(_cfg(enabled=True, api_url="https://proxy-api.example/fetch"))
|
||||
runner._proxy_fetcher = Mock()
|
||||
runner._proxy_fetcher.fetch_new_proxy.return_value = None
|
||||
runner._push_log = Mock()
|
||||
|
||||
self.assertIsNone(runner._proxies_for_task())
|
||||
client = runner._client("acf_uid=100")
|
||||
self.assertEqual(client.session.proxies, {})
|
||||
runner._push_log.assert_called()
|
||||
|
||||
def test_activity_client_accepts_proxies_at_session_level(self):
|
||||
client = DouyuActivityClient(
|
||||
"acf_uid=100",
|
||||
proxies={"http": "http://10.0.0.9:7890", "https": "http://10.0.0.9:7890"},
|
||||
)
|
||||
self.assertEqual(client.session.proxies["http"], "http://10.0.0.9:7890")
|
||||
# trust_env=False 维持不变:不受环境变量代理影响
|
||||
self.assertFalse(client.session.trust_env)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -10,6 +10,7 @@ from sqlalchemy.orm import Session
|
||||
from core.douyu import DouyuActivityClient, FishFinRechargeClient, FishFinRechargeConfig, FishFinRechargeError
|
||||
from ..models import Account, DouyuTask
|
||||
from .douyu_service import update_account_profile_from_cookie
|
||||
from .douyu_runner_core import DOUYU_PAYMENT_POLL_INTERVAL, DOUYU_PAYMENT_POLL_SECONDS
|
||||
|
||||
class GoldMixin:
|
||||
"""鱼翅充值域:扫码充值、供应商直充与到账轮询。"""
|
||||
|
||||
@@ -8,6 +8,7 @@ from sqlalchemy.orm import Session
|
||||
from core.douyu import DouyuActivityClient, DouyuActivityError
|
||||
from ..models import Account, DouyuTask
|
||||
from .douyu_service import account_uid, update_account_profile_from_cookie
|
||||
from .douyu_runner_core import DOUYU_PAYMENT_POLL_INTERVAL, DOUYU_PAYMENT_POLL_SECONDS
|
||||
|
||||
class ManualMixin:
|
||||
"""手册域:精英/电竞手册开通支付、积分查询与到账轮询。"""
|
||||
|
||||
Reference in New Issue
Block a user