'use strict'; const assert = require('node:assert/strict'); const test = require('node:test'); const { inspectFtpScanRoot } = require('../../src/services/ftp-scan-root-coverage'); test('a directly listed install root has complete present coverage', async () => { const calls = []; const result = await inspectFtpScanRoot({ list: async root => { calls.push(root); return [{ name: 'PPSA00001', type: 2 }]; }, }, '/user/app/'); assert.deepEqual(calls, ['/user/app/']); assert.equal(result.coverageState, 'complete'); assert.equal(result.namespaceState, 'present'); assert.equal(result.evidence, 'direct-root-listing'); assert.equal(result.entries.length, 1); }); test('an absent install root is complete only after a successful exact parent listing', async () => { const calls = []; const result = await inspectFtpScanRoot({ list: async root => { calls.push(root); if (root === '/mnt/data/app/') throw Object.assign(new Error('550 No such file'), { code: 550 }); if (root === '/mnt/data/') return [{ name: 'other', type: 2 }]; throw new Error(`unexpected ${root}`); }, }, '/mnt/data/app/'); assert.deepEqual(calls, ['/mnt/data/app/', '/mnt/data/']); assert.equal(result.coverageState, 'complete'); assert.equal(result.namespaceState, 'absent'); assert.equal(result.evidence, 'complete-parent-listing'); assert.deepEqual(result.entries, []); }); test('a missing parent is proven only by the nearest readable ancestor and an exact missing segment', async () => { const calls = []; const result = await inspectFtpScanRoot({ list: async root => { calls.push(root); if (root === '/mnt/data/app/' || root === '/mnt/data/') throw new Error('550 unavailable'); if (root === '/mnt/') return [{ name: 'sandbox', type: 2 }]; throw new Error(`unexpected ${root}`); }, }, '/mnt/data/app/'); assert.deepEqual(calls, ['/mnt/data/app/', '/mnt/data/', '/mnt/']); assert.equal(result.coverageState, 'complete'); assert.equal(result.namespaceState, 'absent'); assert.equal(result.evidence, 'complete-ancestor-listing'); assert.equal(result.evidenceRoot, '/mnt/'); assert.equal(result.missingSegment, 'data'); const unreadableExistingParent = await inspectFtpScanRoot({ list: async root => { if (root === '/mnt/data/app/' || root === '/mnt/data/') throw new Error('permission denied'); if (root === '/mnt/') return [{ name: 'data', type: 2 }]; throw new Error(`unexpected ${root}`); }, }, '/mnt/data/app/'); assert.equal(unreadableExistingParent.coverageState, 'inaccessible'); assert.equal(unreadableExistingParent.namespaceState, 'unknown'); assert.equal(unreadableExistingParent.evidence, 'ancestor-path-unreadable'); }); test('parent failure, an existing root entry and unexpected root types remain inaccessible', async () => { const parentFailure = await inspectFtpScanRoot({ list: async root => { if (root === '/mnt/data/app/') throw new Error('root unavailable'); throw new Error('parent unavailable'); }, }, '/mnt/data/app/'); assert.equal(parentFailure.coverageState, 'inaccessible'); const existingDirectory = await inspectFtpScanRoot({ list: async root => { if (root === '/mnt/data/app/') throw new Error('permission denied'); return [{ name: 'app', type: 2 }]; }, }, '/mnt/data/app/'); assert.equal(existingDirectory.coverageState, 'inaccessible'); assert.equal(existingDirectory.namespaceState, 'present-unreadable'); await assert.rejects(() => inspectFtpScanRoot({ list: async () => [] }, '/'), error => error.code === 'FTP_SCAN_ROOT_INVALID'); });