diff options
Diffstat (limited to 'fastify-busboy/test/dicer-multipart.test.js')
-rw-r--r-- | fastify-busboy/test/dicer-multipart.test.js | 223 |
1 files changed, 223 insertions, 0 deletions
diff --git a/fastify-busboy/test/dicer-multipart.test.js b/fastify-busboy/test/dicer-multipart.test.js new file mode 100644 index 0000000..c35c4d0 --- /dev/null +++ b/fastify-busboy/test/dicer-multipart.test.js @@ -0,0 +1,223 @@ +'use strict' + +const Dicer = require('../deps/dicer/lib/Dicer') +const assert = require('node:assert') +const fs = require('node:fs') +const path = require('node:path') +const inspect = require('node:util').inspect +const { test } = require('tap') + +const FIXTURES_ROOT = path.join(__dirname, 'fixtures/') + +test('dicer-multipart', t => { + const tests = + [ + { + source: 'nested', + opts: { boundary: 'AaB03x' }, + chsize: 32, + nparts: 2, + what: 'One nested multipart' + }, + { + source: 'many', + opts: { boundary: '----WebKitFormBoundaryWLHCs9qmcJJoyjKR' }, + chsize: 16, + nparts: 7, + what: 'Many parts' + }, + { + source: 'many-wrongboundary', + opts: { boundary: 'LOLOLOL' }, + chsize: 8, + nparts: 0, + dicerError: true, + what: 'Many parts, wrong boundary' + }, + { + source: 'many-noend', + opts: { boundary: '----WebKitFormBoundaryWLHCs9qmcJJoyjKR' }, + chsize: 16, + nparts: 7, + npartErrors: 1, + dicerError: true, + what: 'Many parts, end boundary missing, 1 file open' + }, + { + source: 'nested-full', + opts: { boundary: 'AaB03x', headerFirst: true }, + chsize: 32, + nparts: 2, + what: 'One nested multipart with preceding header' + }, + { + source: 'nested-full', + opts: { headerFirst: true }, + chsize: 32, + nparts: 2, + setBoundary: 'AaB03x', + what: 'One nested multipart with preceding header, using setBoundary' + } + ] + + t.plan(tests.length) + + tests.forEach(function (v) { + t.test(v.what, t => { + t.plan(1) + const fixtureBase = FIXTURES_ROOT + v.source + const state = { parts: [], preamble: undefined } + + const dicer = new Dicer(v.opts) + let error + let partErrors = 0 + let finishes = 0 + + dicer.on('preamble', function (p) { + const preamble = { + body: undefined, + bodylen: 0, + error: undefined, + header: undefined + } + + p.on('header', function (h) { + preamble.header = h + if (v.setBoundary) { dicer.setBoundary(v.setBoundary) } + }).on('data', function (data) { + // make a copy because we are using readSync which re-uses a buffer ... + const copy = Buffer.allocUnsafe(data.length) + data.copy(copy) + data = copy + if (!preamble.body) { preamble.body = [data] } else { preamble.body.push(data) } + preamble.bodylen += data.length + }).on('error', function (err) { + preamble.error = err + }).on('end', function () { + if (preamble.body) { preamble.body = Buffer.concat(preamble.body, preamble.bodylen) } + if (preamble.body || preamble.header) { state.preamble = preamble } + }) + }) + dicer.on('part', function (p) { + const part = { + body: undefined, + bodylen: 0, + error: undefined, + header: undefined + } + + p.on('header', function (h) { + part.header = h + }).on('data', function (data) { + if (!part.body) { part.body = [data] } else { part.body.push(data) } + part.bodylen += data.length + }).on('error', function (err) { + part.error = err + ++partErrors + }).on('end', function () { + if (part.body) { part.body = Buffer.concat(part.body, part.bodylen) } + state.parts.push(part) + }) + }).on('error', function (err) { + error = err + }).on('finish', function () { + assert(finishes++ === 0, makeMsg(v.what, 'finish emitted multiple times')) + + if (v.dicerError) { assert(error !== undefined, makeMsg(v.what, 'Expected error')) } else { assert(error === undefined, makeMsg(v.what, 'Unexpected error: ' + error)) } + + let preamble + if (fs.existsSync(fixtureBase + '/preamble')) { + const prebody = fs.readFileSync(fixtureBase + '/preamble') + if (prebody.length) { + preamble = { + body: prebody, + bodylen: prebody.length, + error: undefined, + header: undefined + } + } + } + if (fs.existsSync(fixtureBase + '/preamble.header')) { + const prehead = JSON.parse(fs.readFileSync(fixtureBase + + '/preamble.header', 'binary')) + if (!preamble) { + preamble = { + body: undefined, + bodylen: 0, + error: undefined, + header: prehead + } + } else { preamble.header = prehead } + } + if (fs.existsSync(fixtureBase + '/preamble.error')) { + const err = new Error(fs.readFileSync(fixtureBase + + '/preamble.error', 'binary')) + if (!preamble) { + preamble = { + body: undefined, + bodylen: 0, + error: err, + header: undefined + } + } else { preamble.error = err } + } + + assert.deepEqual(state.preamble, + preamble, + makeMsg(v.what, + 'Preamble mismatch:\nActual:' + + inspect(state.preamble) + + '\nExpected: ' + + inspect(preamble))) + + assert.equal(state.parts.length, + v.nparts, + makeMsg(v.what, + 'Part count mismatch:\nActual: ' + + state.parts.length + + '\nExpected: ' + + v.nparts)) + + if (!v.npartErrors) { v.npartErrors = 0 } + assert.equal(partErrors, + v.npartErrors, + makeMsg(v.what, + 'Part errors mismatch:\nActual: ' + + partErrors + + '\nExpected: ' + + v.npartErrors)) + + for (let i = 0, header, body; i < v.nparts; ++i) { + if (fs.existsSync(fixtureBase + '/part' + (i + 1))) { + body = fs.readFileSync(fixtureBase + '/part' + (i + 1)) + if (body.length === 0) { body = undefined } + } else { body = undefined } + assert.deepEqual(state.parts[i].body, + body, + makeMsg(v.what, + 'Part #' + (i + 1) + ' body mismatch')) + if (fs.existsSync(fixtureBase + '/part' + (i + 1) + '.header')) { + header = fs.readFileSync(fixtureBase + + '/part' + (i + 1) + '.header', 'binary') + header = JSON.parse(header) + } else { header = undefined } + assert.deepEqual(state.parts[i].header, + header, + makeMsg(v.what, + 'Part #' + (i + 1) + + ' parsed header mismatch:\nActual: ' + + inspect(state.parts[i].header) + + '\nExpected: ' + + inspect(header))) + } + t.pass() + }) + + fs.createReadStream(fixtureBase + '/original').pipe(dicer) + }) + }) +}) + +function makeMsg (what, msg) { + return what + ': ' + msg +} |