const assert = require('assert'); const { parseDateTimeValue, formatDateTimeForSqlite, getDateKeyFromDate, getRecentDateKeys, getNextDownloadResetTime, normalizeTimeHHmm, isCurrentTimeInWindow } = require('../utils/datetime'); const { MAX_DOWNLOAD_TRAFFIC_BYTES, normalizeDownloadTrafficQuota, normalizeDownloadTrafficUsed, getDownloadTrafficState, resolveDownloadTrafficPolicyUpdates } = require('../utils/download-quota'); const { expressErrorHandler } = require('../middleware/error-handler'); const results = { passed: 0, failed: 0 }; function test(name, fn) { try { fn(); results.passed += 1; console.log(` [PASS] ${name}`); } catch (error) { results.failed += 1; console.error(` [FAIL] ${name}: ${error.message}`); } } function createResponse(headersSent = false) { return { headersSent, statusCode: null, payload: null, status(code) { this.statusCode = code; return this; }, json(payload) { this.payload = payload; return this; } }; } console.log('\n========== 生产工具模块测试 ==========\n'); test('SQLite 日期时间可以被解析', () => { const parsed = parseDateTimeValue('2026-07-27 12:34:56'); assert.ok(parsed instanceof Date); assert.strictEqual(parsed.getFullYear(), 2026); assert.strictEqual(parsed.getMonth(), 6); assert.strictEqual(parsed.getDate(), 27); }); test('非法日期时间返回 null', () => { assert.strictEqual(parseDateTimeValue('not-a-date'), null); assert.strictEqual(parseDateTimeValue(null), null); }); test('日期时间按 SQLite 格式输出', () => { const value = new Date(2026, 6, 27, 3, 4, 5); assert.strictEqual(formatDateTimeForSqlite(value), '2026-07-27 03:04:05'); }); test('日期键校验有效和无效日期', () => { assert.strictEqual(getDateKeyFromDate(new Date(2026, 0, 2)), '2026-01-02'); assert.strictEqual(getDateKeyFromDate('invalid'), null); }); test('最近日期键按时间顺序生成', () => { const keys = getRecentDateKeys(3, new Date(2026, 0, 2, 12, 0, 0)); assert.deepStrictEqual(keys, ['2025-12-31', '2026-01-01', '2026-01-02']); }); test('下载配额重置时间支持日周月周期', () => { assert.strictEqual( formatDateTimeForSqlite(getNextDownloadResetTime('2026-01-01 00:00:00', 'daily')), '2026-01-02 00:00:00' ); assert.strictEqual( formatDateTimeForSqlite(getNextDownloadResetTime('2026-01-01 00:00:00', 'weekly')), '2026-01-08 00:00:00' ); assert.strictEqual( formatDateTimeForSqlite(getNextDownloadResetTime('2026-01-01 00:00:00', 'monthly')), '2026-02-01 00:00:00' ); assert.strictEqual(getNextDownloadResetTime('2026-01-01 00:00:00', 'none'), null); }); test('访问时间格式被严格规范化', () => { assert.strictEqual(normalizeTimeHHmm(' 09:05 '), '09:05'); assert.strictEqual(normalizeTimeHHmm('9:05'), null); assert.strictEqual(normalizeTimeHHmm('24:00'), null); }); test('同日访问时间窗口正确判断', () => { assert.strictEqual(isCurrentTimeInWindow('09:00', '18:00', new Date(2026, 0, 1, 12, 0)), true); assert.strictEqual(isCurrentTimeInWindow('09:00', '18:00', new Date(2026, 0, 1, 18, 0)), false); }); test('跨日访问时间窗口正确判断', () => { assert.strictEqual(isCurrentTimeInWindow('22:00', '06:00', new Date(2026, 0, 1, 23, 0)), true); assert.strictEqual(isCurrentTimeInWindow('22:00', '06:00', new Date(2026, 0, 1, 12, 0)), false); }); test('非法下载配额被禁止而负数统一为不限', () => { assert.strictEqual(normalizeDownloadTrafficQuota('invalid'), 0); assert.strictEqual(normalizeDownloadTrafficQuota(-99), -1); }); test('下载配额被取整并限制在 10TB', () => { assert.strictEqual(normalizeDownloadTrafficQuota(10.9), 10); assert.strictEqual(normalizeDownloadTrafficQuota(MAX_DOWNLOAD_TRAFFIC_BYTES + 1), MAX_DOWNLOAD_TRAFFIC_BYTES); }); test('已用流量按有限配额封顶', () => { assert.strictEqual(normalizeDownloadTrafficUsed(150, 100), 100); assert.strictEqual(normalizeDownloadTrafficUsed(150, -1), 150); assert.strictEqual(normalizeDownloadTrafficUsed(-1, 100), 0); }); test('不限流量状态保留无限剩余额度', () => { const state = getDownloadTrafficState({ download_traffic_quota: -1, download_traffic_used: 123 }); assert.strictEqual(state.isUnlimited, true); assert.strictEqual(state.used, 123); assert.strictEqual(state.remaining, Number.POSITIVE_INFINITY); }); test('空用户不会产生配额更新', () => { assert.deepStrictEqual(resolveDownloadTrafficPolicyUpdates(null), { updates: {}, hasUpdates: false, expired: false, resetApplied: false }); }); test('非法重置周期会被规范化', () => { const result = resolveDownloadTrafficPolicyUpdates({ download_traffic_quota: 100, download_traffic_used: 0, download_traffic_reset_cycle: 'yearly' }); assert.strictEqual(result.updates.download_traffic_reset_cycle, 'none'); }); test('周期配额首次运行时记录重置时间', () => { const now = new Date(2026, 6, 27, 12, 0, 0); const result = resolveDownloadTrafficPolicyUpdates({ download_traffic_quota: 100, download_traffic_used: 10, download_traffic_reset_cycle: 'daily', download_traffic_last_reset_at: null }, now); assert.strictEqual(result.updates.download_traffic_last_reset_at, '2026-07-27 12:00:00'); }); test('到达周期时已用流量归零', () => { const result = resolveDownloadTrafficPolicyUpdates({ download_traffic_quota: 100, download_traffic_used: 90, download_traffic_reset_cycle: 'daily', download_traffic_last_reset_at: '2026-07-26 12:00:00' }, new Date(2026, 6, 27, 12, 0, 0)); assert.strictEqual(result.resetApplied, true); assert.strictEqual(result.updates.download_traffic_used, 0); }); test('限时配额到期后恢复为不限流量', () => { const result = resolveDownloadTrafficPolicyUpdates({ download_traffic_quota: 100, download_traffic_used: 90, download_traffic_quota_expires_at: '2026-07-26 12:00:00', download_traffic_reset_cycle: 'daily', download_traffic_last_reset_at: '2026-07-26 12:00:00' }, new Date(2026, 6, 27, 12, 0, 0)); assert.strictEqual(result.expired, true); assert.strictEqual(result.updates.download_traffic_quota, -1); assert.strictEqual(result.updates.download_traffic_used, 0); assert.strictEqual(result.updates.download_traffic_quota_expires_at, null); }); test('Express 错误处理器保留四参数签名', () => { assert.strictEqual(expressErrorHandler.length, 4); }); test('Express 错误处理器返回客户端错误 JSON', () => { const response = createResponse(); const originalConsoleError = console.error; console.error = () => {}; try { expressErrorHandler( Object.assign(new Error('请求 JSON 无效'), { status: 400 }), { method: 'POST', originalUrl: '/api/login' }, response, () => assert.fail('不应调用 next') ); } finally { console.error = originalConsoleError; } assert.strictEqual(response.statusCode, 400); assert.deepStrictEqual(response.payload, { success: false, message: '请求 JSON 无效' }); }); test('Express 错误处理器隐藏服务端异常详情', () => { const response = createResponse(); const originalConsoleError = console.error; console.error = () => {}; try { expressErrorHandler( new Error('sensitive detail'), { method: 'GET', originalUrl: '/api/example' }, response, () => assert.fail('不应调用 next') ); } finally { console.error = originalConsoleError; } assert.strictEqual(response.statusCode, 500); assert.deepStrictEqual(response.payload, { success: false, message: '服务器内部错误' }); }); test('响应头已发送时错误处理器继续交给 Express', () => { const response = createResponse(true); const error = new Error('stream failed'); let forwarded = null; expressErrorHandler(error, {}, response, (received) => { forwarded = received; }); assert.strictEqual(forwarded, error); }); console.log('\n========================================'); console.log('测试总结'); console.log('========================================'); console.log(`通过: ${results.passed}`); console.log(`失败: ${results.failed}`); process.exit(results.failed > 0 ? 1 : 0);