Files
go_bt/tests/proxy_retry_policy.test.js

138 lines
5.1 KiB
JavaScript

const assert = require('assert');
const { shouldRotateProxyForFailure } = require('../src/services/proxy_recovery_service');
const { classifyFailure } = require('../src/utils/error_classifier');
const {
MAX_CHATGPT_BROWSER_ATTEMPTS,
MAX_CHATGPT_LOGIN_WITH_STUCK_BROWSER_ATTEMPTS,
MAX_OPENAI_PHONE_BROWSER_ATTEMPTS,
isChatGPTRouteError,
shouldRestartChatGPTBrowser,
buildChatGPTBrowserRetryMessage,
} = require('../src/services/chatgpt_restart_policy');
assert.strictEqual(
shouldRotateProxyForFailure({ code: 'SIGNIN_REJECTED', shouldRotateProxy: true }, 'SIGNIN_REJECTED'),
true,
);
assert.strictEqual(
shouldRotateProxyForFailure(null, 'SIGNIN_REJECTED'),
true,
'即使页面元数据丢失,明确的signin/rejected结果也应换代理',
);
assert.strictEqual(shouldRotateProxyForFailure(null, 'NETWORK_PROXY'), true);
for (const navigationError of [
'page.goto: net::ERR_FAILED at https://mail.google.com/mail/u/0/#inbox',
'page.goto: net::ERR_ABORTED at https://mail.google.com/mail/u/0/#inbox',
'page.goto: net::ERR_CONNECTION_CLOSED at https://mail.google.com/mail/u/0/#inbox',
'page.reload: net::ERR_ABORTED',
]) {
const navigationFailure = classifyFailure({ message: navigationError, taskType: 'refund_query' });
assert.strictEqual(navigationFailure.code, 'NETWORK_PROXY');
assert.strictEqual(
shouldRotateProxyForFailure(navigationFailure, navigationFailure.code),
true,
`${navigationError} 应在退款查询最终失败后自动换代理`,
);
}
assert.strictEqual(shouldRotateProxyForFailure(null, 'PASSWORD_WRONG'), false);
assert.strictEqual(shouldRotateProxyForFailure(null, 'PASSWORD_CHANGED_RECENTLY'), false);
assert.strictEqual(shouldRotateProxyForFailure(null, 'TOTP_CODE_WRONG'), false);
assert.strictEqual(shouldRotateProxyForFailure(null, 'TOTP_KEY_INCORRECT'), false);
assert.strictEqual(shouldRotateProxyForFailure(null, 'PHONE_VERIFY'), false);
assert.strictEqual(
shouldRotateProxyForFailure({ code: 'CHATGPT_ROUTE_ERROR', restartBrowser: true }, 'CHATGPT_ROUTE_ERROR'),
false,
'ChatGPT Route Error 不能触发代理轮换',
);
assert.strictEqual(
shouldRotateProxyForFailure(null, 'CHATGPT_LOGIN_WITH_STUCK'),
true,
'Google 登录中转页在同代理重开一次后应允许换代理',
);
assert.strictEqual(
shouldRotateProxyForFailure(null, 'CHATGPT_AGE_SUBMIT_STUCK'),
true,
'年龄表单多次提交仍无进展时应允许换代理重试',
);
for (const code of [
'CHATGPT_SESSION_CF_HTML',
'CHATGPT_SESSION_HTTP_403',
'CHATGPT_SESSION_HTTP_429',
'CHATGPT_SESSION_HTTP_5XX',
]) {
assert.strictEqual(
shouldRotateProxyForFailure(null, code),
true,
`${code} 应允许换代理重试`,
);
}
assert.deepStrictEqual(
classifyFailure({ message: 'ChatGPT Route Error 400', taskType: 'chatgpt_register' }).code,
'CHATGPT_ROUTE_ERROR',
);
assert.strictEqual(isChatGPTRouteError('login', { code: 'CHATGPT_ROUTE_ERROR', restartBrowser: true }), false);
assert.strictEqual(isChatGPTRouteError('chatgpt_register', { code: 'CAPTCHA' }), false);
let browserAttempt = 1;
let totalRuns = 0;
while (true) {
totalRuns++;
const failure = { code: 'CHATGPT_ROUTE_ERROR', restartBrowser: true };
if (!shouldRestartChatGPTBrowser('chatgpt_register', failure, browserAttempt)) break;
browserAttempt++;
}
assert.strictEqual(MAX_CHATGPT_BROWSER_ATTEMPTS, 3);
assert.strictEqual(totalRuns, 3, 'Route Error 总登录次数必须为初次加两次重启');
browserAttempt = 1;
totalRuns = 0;
const phoneFailure = { code: 'OPENAI_PHONE_REQUIRED' };
while (true) {
totalRuns++;
if (!shouldRestartChatGPTBrowser('openai_get_auth', phoneFailure, browserAttempt)) break;
browserAttempt++;
}
assert.strictEqual(MAX_OPENAI_PHONE_BROWSER_ATTEMPTS, 3);
assert.strictEqual(totalRuns, 3, '手机号要求总授权次数必须为初次加两次重启');
assert.match(
buildChatGPTBrowserRetryMessage('openai_get_auth', phoneFailure, 2),
/补充手机号.*第2\/3次/,
);
browserAttempt = 1;
totalRuns = 0;
const stuckFailure = { code: 'CHATGPT_LOGIN_WITH_STUCK' };
while (true) {
totalRuns++;
if (!shouldRestartChatGPTBrowser('chatgpt_register', stuckFailure, browserAttempt)) break;
browserAttempt++;
}
assert.strictEqual(MAX_CHATGPT_LOGIN_WITH_STUCK_BROWSER_ATTEMPTS, 2);
assert.strictEqual(totalRuns, 2, '登录中转页卡住时,同一代理只能重开浏览器一次');
assert.strictEqual(
shouldRestartChatGPTBrowser('security_chatgpt', stuckFailure, 1),
false,
'非独立ChatGPT任务不得触发ChatGPT专用浏览器重开',
);
const stuckRetryMessage = buildChatGPTBrowserRetryMessage(
'chatgpt_register',
stuckFailure,
2,
);
assert.match(stuckRetryMessage, /Google 登录中转页卡住/);
assert.match(stuckRetryMessage, /当前代理/);
assert.match(stuckRetryMessage, /第2\/2次/);
assert.doesNotMatch(stuckRetryMessage, /Route Error/);
const routeRetryMessage = buildChatGPTBrowserRetryMessage(
'chatgpt_register',
{ code: 'CHATGPT_ROUTE_ERROR', restartBrowser: true },
2,
);
assert.match(routeRetryMessage, /Route Error/);
assert.match(routeRetryMessage, /第2\/3次/);
console.log('proxy_retry_policy.test.js: PASS');