@samitouri / QOSami-HFS / commits / 593d2b9d

test: concurrent big uploads

Massimo Melina committed Jan 24, 2025 at 17:05 UTC 593d2b9dcaf18586efb5b35cb557c75b3737166e
2 files changed +16 -4
src/upload.ts
+1 -1
@@ -258,7 +258,7 @@ export function uploadWriter(base: VfsNode, baseUri: string, path: string, ctx:
258 }
259
260 function fail(status?: number, msg?: string) {
261 - console.debug('upload failed', status, msg)
261 + console.debug('upload failed', status||'', msg||'')
262 releaseFile()
263 if (status)
264 ctx.status = status
tests/test.ts
+15 -3
@@ -27,6 +27,15 @@ const BIG_CONTENT = _.repeat(randomId(10), 200_000) // 2MB, big enough to satura
27 const throttle = BIG_CONTENT.length /1000 /0.5 // KB, finish in 0.5s, quick but still overlapping downloads
28 let defaultBaseUrl = BASE_URL
29
30 +class StringRepeaterStream extends Readable {
31 + constructor(private str: string, private n: number, readonly length=n*str.length) {
32 + super()
33 + }
34 + _read() {
35 + this.push(this.n-- > 0 ? this.str : null)
36 + }
37 +}
38 +
39 describe('basics', () => {
40 //before(async () => appStarted)
41 it('frontend', req('/', /<body>/, { headers: { accept: '*/*' } })) // workaround: 'accept' is necessary when running server-for-test-dev, still don't know why
@@ -156,6 +165,10 @@ describe('after-login', () => {
165 await reqUpload(UPLOAD_DEST, 409)() // should conflict
166 await first
167 })
168 + it('upload.concurrent', () => Promise.all([
169 + reqUpload(UPLOAD_DEST, 200, new StringRepeaterStream(BIG_CONTENT, 150))(), // 300MB
170 + ..._.range(3).map(i => reqUpload(UPLOAD_DEST + i, 200, new StringRepeaterStream(BIG_CONTENT, 50))()) // 3 x 100MB
171 + ])).timeout(5000)
172 const renameTo = 'z'
173 it('rename.ok', reqApi('rename', { uri: UPLOAD_DEST, dest: renameTo }, 200))
174 it('delete.miss renamed', reqApi('delete', { uri: UPLOAD_DEST }, 404))
@@ -183,8 +196,7 @@ describe('after-login', () => {
196 await reqUpload(uri, 200, BIG_CONTENT)()
197 await testMaxDl(uri, 2, 1)
198 })
186 - after(() =>
187 - rm(join(__dirname, 'temp'), { recursive: true}).catch(() => 0))
199 + after(() => rm(join(__dirname, 'temp'), { recursive: true }).catch(() => 0))
200 })
201
202 function login(usr: string, pwd=password) {
@@ -265,7 +277,7 @@ function req(url: string, test:Tester, { baseUrl, throttle, ...requestOptions }:
277 })
278 || test.empty && data && 'expected empty body'
279 || length !== undefined && gotLength !== String(length) && "expected content-length " + length + " got " + gotLength
268 - || test.cb?.(data, res) === false && 'error'
280 + || test.cb?.(obj ?? data, res) === false && 'error'
281 || ''
282 if (err)
283 throw Error(err)