/** @jest-environment node */ import { mkdir, mkdtemp, rm, symlink, writeFile } from 'fs/promises' import os from 'os' import path from 'path' import { readBoundedRegularFile, readBoundedResponseBuffer, } from '@/lib/bounded-file-reader' describe('bounded-file-reader', () => { let root: string beforeEach(async () => { root = await mkdtemp(path.join(os.tmpdir(), 'bounded-file-reader-')) }) afterEach(async () => { await rm(root, { recursive: true, force: true }) }) test('在分配 Buffer 前拒绝超限、申报不一致和符号链接文件', async () => { const filePath = path.join(root, 'source.bin') await writeFile(filePath, Buffer.from('12345')) await expect(readBoundedRegularFile(filePath, { maxBytes: 4, label: '测试文件', })).rejects.toThrow('超过 1MB 限制') await expect(readBoundedRegularFile(filePath, { maxBytes: 10, expectedBytes: 4, label: '测试文件', })).rejects.toThrow('实际大小与上传记录不一致') const symlinkTarget = path.join(root, 'source-link-target') const symlinkPath = path.join(root, 'source-link') await mkdir(symlinkTarget) await symlink(symlinkTarget, symlinkPath, process.platform === 'win32' ? 'junction' : 'dir') await expect(readBoundedRegularFile(symlinkPath, { maxBytes: 10, expectedBytes: 5, label: '测试文件', })).rejects.toThrow('不是可读取的普通文件') }) test('普通文件仅在实际大小与申报一致时返回完整内容', async () => { const filePath = path.join(root, 'source.bin') await writeFile(filePath, Buffer.from('bounded')) await expect(readBoundedRegularFile(filePath, { maxBytes: 64, expectedBytes: 7, label: '测试文件', })).resolves.toEqual(Buffer.from('bounded')) }) test('远程响应无 Content-Length 时仍按可信大小硬停,且不使用 arrayBuffer', async () => { const stream = new ReadableStream({ start(controller) { controller.enqueue(new Uint8Array([1, 2])) controller.enqueue(new Uint8Array([3, 4])) controller.close() }, }) const response = new Response(stream) await expect(readBoundedResponseBuffer(response, { maxBytes: 4, expectedBytes: 3, label: '远程文件', })).rejects.toThrow('响应超过申报大小') }) test('远程响应先校验 Content-Length,并按申报大小返回单个 Buffer', async () => { const response = new Response(Buffer.from('remote'), { headers: { 'Content-Length': '6' }, }) await expect(readBoundedResponseBuffer(response, { maxBytes: 10, expectedBytes: 6, label: '远程文件', })).resolves.toEqual(Buffer.from('remote')) const mismatched = new Response(Buffer.from('remote'), { headers: { 'Content-Length': '6' }, }) await expect(readBoundedResponseBuffer(mismatched, { maxBytes: 10, expectedBytes: 5, label: '远程文件', })).rejects.toThrow('响应大小与上传记录不一致') }) })