diff options
Diffstat (limited to 'modules/test/test-vfs-checkpoint.js')
| -rw-r--r-- | modules/test/test-vfs-checkpoint.js | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/modules/test/test-vfs-checkpoint.js b/modules/test/test-vfs-checkpoint.js new file mode 100644 index 0000000..03a8c8a --- /dev/null +++ b/modules/test/test-vfs-checkpoint.js @@ -0,0 +1,92 @@ +// modules/test/test-vfs-checkpoint.js — run: node modules/test/test-vfs-checkpoint.js +// Proves the name a checkpoint is SAVED under is the name the UI prints and the name +// `rollback` resolves. RED on v4.6.101: two independent new Date().toISOString() calls +// made the printed name differ from the stored one, so `checkpoint` then +// `rollback <printed name>` failed with "checkpoint not found or invalid". +const fsMod = require('fs'), path = require('path'); +const ROOT = path.join(__dirname, '..', 'core'); + +// ── guarded stubs for the browser globals the VFS touches ────────────────── +const ls = {}; +global.localStorage = { + getItem: k => (k in ls ? ls[k] : null), + setItem: (k, v) => { ls[k] = String(v); }, + removeItem: k => { delete ls[k]; }, +}; +global.indexedDB = { + open() { throw new Error('indexedDB not available in test'); }, + deleteDatabase() { throw new Error('indexedDB not available in test'); }, +}; +global.window = global; + +function loadClass(file, clsName) { + const src = fsMod.readFileSync(path.join(ROOT, file), 'utf8'); + return new Function(src + '\nreturn ' + clsName + ';')(); +} +const VirtualFileSystem = loadClass('virtual-fs.js', 'VirtualFileSystem'); +const SystemModule = loadClass('module-system.js', 'SystemModule'); + +function mkFs() { + const fs = new VirtualFileSystem(); + fs.saveToStorage = () => true; // isolate from timers / compression + return fs; +} + +let fails = 0, passes = 0; +function ok(name, cond, detail) { + if (cond) { passes++; return; } + fails++; + console.log('FAIL ' + name + (detail ? ' — ' + detail : '')); +} + +// A. checkpoint('') must return the resolved name, and two calls must differ +{ + const fs = mkFs(); + const a = fs.checkpoint(''); + const b = fs.checkpoint(''); + ok('A1 checkpoint returns a name string', typeof a === 'string' && a.length > 0, 'got ' + typeof a + ' ' + a); + ok('A2 second name also a string', typeof b === 'string' && b.length > 0, 'got ' + typeof b); + ok('A3 two unnamed checkpoints get distinct names', a !== b, 'both=' + a); + ok('A4 stored under the returned name', !!fs.fsReadJSON('/_snapshots/checkpoint-' + a + '.json')); +} + +// B. rollback with the returned name must succeed +{ + const fs = mkFs(); + fs.mkdirRecursive('/marker'); + const name = fs.checkpoint(''); + ok('B1 checkpoint-list shows the returned name', fs.listCheckpoints().includes(name), 'name=' + name); + ok('B2 rollback(returned name) is true', fs.rollback(name) === true, 'name=' + name); +} + +// C. the `checkpoint` command prints exactly the name it created +{ + const fsv = mkFs(); + const out = []; + const sys = new SystemModule(); + sys.terminal = { print: m => out.push(String(m)), fs: fsv }; + sys.registerCommands(); + + out.length = 0; + sys.commands['checkpoint']([]); + const line = out.join('\n'); + const printed = (line.match(/Checkpoint created:\s*(.+)$/m) || [])[1]; + ok('C1 command prints a created name', !!printed, 'output=' + JSON.stringify(line)); + const listed = fsv.listCheckpoints(); + ok('C2 printed name exists on disk', !!printed && listed.includes(printed.trim()), + 'printed=' + printed + ' listed=' + JSON.stringify(listed)); + ok('C3 rollback of the printed name succeeds', !!printed && fsv.rollback(printed.trim()) === true); + + // C4: an explicit name is echoed verbatim + out.length = 0; + sys.commands['checkpoint'](['myname']); + ok('C4 explicit name echoed verbatim', /Checkpoint created:\s*myname\s*$/.test(out.join('\n')), + 'output=' + JSON.stringify(out.join('\n'))); +} + +if (fails === 0) { + console.log('test-vfs-checkpoint: ' + passes + ' passed, 0 failed'); +} else { + console.log('test-vfs-checkpoint: ' + passes + ' passed, ' + fails + ' FAILED'); + process.exit(1); +} |