88 lines
3.6 KiB
JavaScript
88 lines
3.6 KiB
JavaScript
'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');
|
|
});
|