mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-11-15 06:33:55 +01:00
Enforce output file count and size limits in the Pyodide worker
GitOrigin-RevId: 2cc61613381243d810a8cb9e1c2c32fa9e751da7
This commit is contained in:
committed by
Copybot
parent
d97a659f92
commit
672e01c703
+115
@@ -0,0 +1,115 @@
|
||||
import { expect } from 'chai'
|
||||
import {
|
||||
MAX_OUTPUT_FILES,
|
||||
MAX_OUTPUT_FILE_BYTES,
|
||||
MAX_OUTPUT_TOTAL_BYTES,
|
||||
checkOutputLimits,
|
||||
} from '@/features/ide-react/components/editor/python/pyodide-worker-output-limits'
|
||||
|
||||
const BYTES_PER_MB = 1024 * 1024
|
||||
|
||||
function makeFiles(
|
||||
count: number,
|
||||
sizePerFile: number
|
||||
): { path: string; size: number }[] {
|
||||
return Array.from({ length: count }, (_, i) => ({
|
||||
path: `/project/file${i}.bin`,
|
||||
size: sizePerFile,
|
||||
}))
|
||||
}
|
||||
|
||||
describe('checkOutputLimits', function () {
|
||||
it('returns null when both limits are within bounds', function () {
|
||||
const files = makeFiles(10, 1024)
|
||||
expect(checkOutputLimits(files)).to.equal(null)
|
||||
})
|
||||
|
||||
it('returns null for an empty file list', function () {
|
||||
expect(checkOutputLimits([])).to.equal(null)
|
||||
})
|
||||
|
||||
it('returns null at exactly the file count limit', function () {
|
||||
const files = makeFiles(MAX_OUTPUT_FILES, 1024)
|
||||
expect(checkOutputLimits(files)).to.equal(null)
|
||||
})
|
||||
|
||||
it('returns a count violation when the file count exceeds the limit', function () {
|
||||
const files = makeFiles(MAX_OUTPUT_FILES + 1, 1)
|
||||
const violation = checkOutputLimits(files)
|
||||
expect(violation).to.deep.equal({
|
||||
kind: 'count',
|
||||
message: `Output limit exceeded: ${MAX_OUTPUT_FILES + 1} files generated (max ${MAX_OUTPUT_FILES})`,
|
||||
})
|
||||
})
|
||||
|
||||
it('reports the actual file count in the count violation message', function () {
|
||||
const files = makeFiles(73, 1)
|
||||
const violation = checkOutputLimits(files)
|
||||
expect(violation).to.not.equal(null)
|
||||
expect(violation!.kind).to.equal('count')
|
||||
expect(violation!.message).to.equal(
|
||||
'Output limit exceeded: 73 files generated (max 50)'
|
||||
)
|
||||
})
|
||||
|
||||
it('returns null at exactly the per-file size limit', function () {
|
||||
const files = [{ path: '/project/big.bin', size: MAX_OUTPUT_FILE_BYTES }]
|
||||
expect(checkOutputLimits(files)).to.equal(null)
|
||||
})
|
||||
|
||||
it('returns a single-file-size violation when one file exceeds the per-file limit', function () {
|
||||
const files = [
|
||||
{ path: '/project/big.bin', size: MAX_OUTPUT_FILE_BYTES + 1 },
|
||||
]
|
||||
const violation = checkOutputLimits(files)
|
||||
expect(violation).to.not.equal(null)
|
||||
expect(violation!.kind).to.equal('single-file-size')
|
||||
expect(violation!.message).to.equal(
|
||||
'Output limit exceeded: /project/big.bin is 51MB (max 50MB per file)'
|
||||
)
|
||||
})
|
||||
|
||||
it('reports the offending file path and rounded size in the single-file-size message', function () {
|
||||
const files = [
|
||||
{ path: '/project/small.bin', size: 1 * BYTES_PER_MB },
|
||||
{ path: '/project/huge.bin', size: 80 * BYTES_PER_MB },
|
||||
]
|
||||
const violation = checkOutputLimits(files)
|
||||
expect(violation).to.deep.equal({
|
||||
kind: 'single-file-size',
|
||||
message:
|
||||
'Output limit exceeded: /project/huge.bin is 80MB (max 50MB per file)',
|
||||
})
|
||||
})
|
||||
|
||||
it('returns a total-output-size violation when the summed size exceeds the total limit', function () {
|
||||
const files = [
|
||||
{ path: '/project/a.bin', size: 40 * BYTES_PER_MB },
|
||||
{ path: '/project/b.bin', size: 40 * BYTES_PER_MB },
|
||||
{ path: '/project/c.bin', size: 40 * BYTES_PER_MB },
|
||||
]
|
||||
const violation = checkOutputLimits(files)
|
||||
expect(violation).to.not.equal(null)
|
||||
expect(violation!.kind).to.equal('total-output-size')
|
||||
expect(violation!.message).to.equal(
|
||||
'Output limit exceeded: 120MB total (max 100MB)'
|
||||
)
|
||||
})
|
||||
|
||||
it('returns null at exactly the total size limit', function () {
|
||||
const files = [
|
||||
{ path: '/project/a.bin', size: 50 * BYTES_PER_MB },
|
||||
{ path: '/project/b.bin', size: 50 * BYTES_PER_MB },
|
||||
]
|
||||
expect(checkOutputLimits(files)).to.equal(null)
|
||||
const total = files.reduce((acc, f) => acc + f.size, 0)
|
||||
expect(total).to.equal(MAX_OUTPUT_TOTAL_BYTES)
|
||||
})
|
||||
|
||||
it('reports the count violation when both limits are exceeded', function () {
|
||||
const files = makeFiles(MAX_OUTPUT_FILES + 10, MAX_OUTPUT_TOTAL_BYTES)
|
||||
const violation = checkOutputLimits(files)
|
||||
expect(violation).to.not.equal(null)
|
||||
expect(violation!.kind).to.equal('count')
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user