// Run inside the built image as UID 1000. No downloads or fixture dependencies. import assert from 'node:assert/strict'; import { mkdtemp, writeFile, readFile, rm, readdir } from 'node:fs/promises'; import { join } from 'node:path'; import { tmpdir } from 'node:os'; import { pathToFileURL } from 'node:url'; import { runProcess } from './native-office.mjs'; const installed = '/usr/local/lib/node_modules/@deepseek-ai/dsh/node_modules/@deepseek-ai/dsh-office-to-pdf/lib/'; const { createConverter } = await import(installed + 'dsh-native-office.mjs'); const { OfficeToPdf } = await import(installed + 'index.js'); assert.notEqual(process.getuid(), 0, 'smoke test must run as non-root'); const dir = await mkdtemp(join(tmpdir(), 'office-smoke-')); const signal = new AbortController().signal; const ns = 'xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0"'; const converter = await createConverter(); try { await writeFile(join(dir, 'word.fodt'), '中文预览 Word conversion test'); await writeFile(join(dir, 'slides.fodp'), '中文预览 PPT conversion test'); for (const [source, format] of [['word.fodt', 'docx'], ['slides.fodp', 'pptx'], ['word.fodt', 'doc'], ['slides.fodp', 'ppt']]) { await runProcess('/usr/bin/libreoffice', ['-env:UserInstallation=' + pathToFileURL(join(dir, 'fixture-profile')).href, '--headless', '--convert-to', format, '--outdir', dir, join(dir, source)], signal); } await Promise.all(['word.docx', 'slides.pptx', 'word.doc', 'slides.ppt'].map(async name => { const start = performance.now(); const outputPath = join(dir, name + '.pdf'); const result = await converter.render({ inputPath: join(dir, name), outputPath }); assert.equal(result.backend, 'native-system'); assert.match((await readFile(outputPath)).subarray(0, 8).toString(), /^%PDF-/); console.log(name + ': native PDF in ' + Math.round(performance.now() - start) + 'ms'); })); const small = await createConverter({ maxOutputBytes: 1 }); await assert.rejects(small.render({ inputPath: join(dir, 'word.docx'), outputPath: join(dir, 'small.pdf') }), { code: 'output-too-large' }); await small.dispose(); const timeout = await createConverter({ timeoutMs: 1 }); await assert.rejects(timeout.render({ inputPath: join(dir, 'word.docx'), outputPath: join(dir, 'timeout.pdf') }), { code: 'timeout' }); await timeout.dispose(); const limited = await createConverter({ maxArchiveEntries: 1 }); await assert.rejects(limited.render({ inputPath: join(dir, 'word.docx'), outputPath: join(dir, 'limit.pdf') }), { code: 'invalid-document' }); await limited.dispose(); const provider = { slots: [], options: {}, config: { maxOutputBytes: 100 * 1024 ** 2 } }; const converted = await OfficeToPdf.prototype.convertBytes.call(provider, await readFile(join(dir, 'slides.pptx')), 'pptx', signal); assert.match(Buffer.from(converted.pdf).subarray(0, 8).toString(), /^%PDF-/); await Promise.all(provider.slots.map(async slot => (await slot.converter).dispose())); console.log('installed DSH convertBytes integration passed'); assert.equal((await readdir(tmpdir())).filter(name => name.startsWith('dsh-native-office-')).length, 0); console.log('concurrent DOCX/PPTX/DOC/PPT, output/ZIP limits, timeout and cleanup passed'); } finally { await converter.dispose(); await rm(dir, { recursive: true, force: true }); }