gongxiangp2/lib/__tests__/file-stream-cleanup.test.ts
chenpei 4e89b57798 feat(upload): optimize upload UI and performance
- Expand batch upload list area and optimize preview image layout
- Improve upload speed tracking and display (server-side & client-side)
- Reduce network detection log noise
- Optimize Docker build process (caching, env validation)
- Add shadow environment deployment support
2026-01-28 15:07:50 +08:00

92 lines
3.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* N6修复测试:文件流错误时正确清理
*
* 验证:
* 1. 所有 fileStream.on('error') 回调中都调用了 fileStream.destroy()
* 2. 确保文件描述符不会泄漏
*/
describe('N6: 文件流错误清理测试', () => {
test('所有下载路由的文件流错误处理应该包含 destroy() 调用', async () => {
const fs = require('fs')
const path = require('path')
const downloadRoutes = [
'app/api/materials/download/route.ts',
'app/api/materials/[id]/skus/[skuId]/download/route.ts',
'app/api/external/download/route.ts',
]
for (const routePath of downloadRoutes) {
const filePath = path.join(__dirname, '../..', routePath)
if (!fs.existsSync(filePath)) {
console.log(`跳过测试:文件不存在 ${routePath}`)
continue
}
const content = fs.readFileSync(filePath, 'utf-8')
// 查找所有 fileStream.on('error' 模式
const errorHandlerPattern = /fileStream\.on\('error',\s*\(err\)\s*=>\s*\{[^}]*\}/g
const matches = content.match(errorHandlerPattern)
if (matches) {
for (const match of matches) {
// 每个错误处理回调中都应该有 destroy() 调用
expect(match).toContain('destroy()')
}
}
}
})
test('不应该有只调用 controller.error 而不调用 destroy 的错误处理', async () => {
const fs = require('fs')
const path = require('path')
const downloadRoutes = [
'app/api/materials/download/route.ts',
'app/api/materials/[id]/skus/[skuId]/download/route.ts',
'app/api/external/download/route.ts',
]
for (const routePath of downloadRoutes) {
const filePath = path.join(__dirname, '../..', routePath)
if (!fs.existsSync(filePath)) {
console.log(`跳过测试:文件不存在 ${routePath}`)
continue
}
const content = fs.readFileSync(filePath, 'utf-8')
// 查找简单的错误处理模式(只有 controller.error,没有 destroy)
// 这种模式是有问题的:fileStream.on('error', (err) => controller.error(err))
const badPattern = /fileStream\.on\('error',\s*\(err\)\s*=>\s*controller\.error\(err\)\)/g
const badMatches = content.match(badPattern)
// 不应该有这种简单的错误处理
expect(badMatches).toBeNull()
}
})
test('所有错误处理应该先调用 destroy 再调用 controller.error', async () => {
const fs = require('fs')
const path = require('path')
const filePath = path.join(__dirname, '../../app/api/materials/download/route.ts')
if (!fs.existsSync(filePath)) {
console.log('跳过测试:文件不存在')
return
}
const content = fs.readFileSync(filePath, 'utf-8')
// 检查错误处理的顺序:先 destroy() 再 controller.error()
const correctPattern = /fileStream\.destroy\(\)[\s\S]*?controller\.error\(err\)/
expect(correctPattern.test(content)).toBe(true)
})
})