Add verified backup and restore for shared data volumes
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import fs from 'node:fs';
|
||||
import {tmpdir} from 'node:os';
|
||||
import {join} from 'node:path';
|
||||
import {DatabaseSync} from 'node:sqlite';
|
||||
import {backupDataVolume,verifyDataVolume,restoreDataVolume} from '../server/backup-data-volume.mjs';
|
||||
|
||||
test('shared volume backup captures multiple SQLite stores, committed WAL and nested files',async()=>{
|
||||
const dir=fs.mkdtempSync(join(tmpdir(),'ihaleist-volume-')),source=join(dir,'source'),backup=join(dir,'backup'),restored=join(dir,'restored');
|
||||
fs.mkdirSync(source);let live;
|
||||
try {
|
||||
for(const name of ['kalem.sqlite','tender-history.sqlite']) {
|
||||
const db=new DatabaseSync(join(source,name));db.exec('PRAGMA journal_mode=WAL;CREATE TABLE records(value TEXT);');db.prepare('INSERT INTO records VALUES (?)').run('Son Türkçe kayıt');
|
||||
if(name==='kalem.sqlite')live=db;else db.close();
|
||||
}
|
||||
fs.mkdirSync(join(source,'nested'));fs.writeFileSync(join(source,'nested','cache.json'),'["İhale"]');
|
||||
const manifest=await backupDataVolume(source,backup,{offline:true});
|
||||
assert.equal(manifest.files.length,3);assert.equal(manifest.files.filter(f=>f.sqlite).length,2);
|
||||
assert.equal(manifest.files.some(f=>/-wal$|-shm$/.test(f.name)),false);
|
||||
await restoreDataVolume(backup,restored);
|
||||
const db=new DatabaseSync(join(restored,'kalem.sqlite'));assert.equal(db.prepare('SELECT value FROM records').get().value,'Son Türkçe kayıt');db.close();
|
||||
assert.equal(fs.readFileSync(join(restored,'nested','cache.json'),'utf8'),'["İhale"]');
|
||||
await assert.rejects(restoreDataVolume(backup,restored),/EEXIST/);
|
||||
fs.appendFileSync(join(backup,'nested','cache.json'),'changed');
|
||||
await assert.rejects(verifyDataVolume(backup),/değişmiş/);
|
||||
} finally {live?.close();fs.rmSync(dir,{recursive:true,force:true});}
|
||||
});
|
||||
test('volume backup refuses unconfirmed offline, symlinks, nested output and unlisted files',async()=>{
|
||||
const dir=fs.mkdtempSync(join(tmpdir(),'ihaleist-volume-')),source=join(dir,'source'),backup=join(dir,'backup');fs.mkdirSync(source);
|
||||
try {
|
||||
fs.writeFileSync(join(source,'data.json'),'{}');
|
||||
await assert.rejects(backupDataVolume(source,backup),/offline/);
|
||||
await assert.rejects(backupDataVolume(source,join(source,'inside'),{offline:true}),/iç içe/);
|
||||
fs.symlinkSync(join(source,'data.json'),join(source,'link'));
|
||||
await assert.rejects(backupDataVolume(source,backup,{offline:true}),/sembolik/);
|
||||
fs.unlinkSync(join(source,'link'));
|
||||
await backupDataVolume(source,backup,{offline:true});
|
||||
fs.writeFileSync(join(backup,'unlisted'),'extra');
|
||||
await assert.rejects(verifyDataVolume(backup),/Manifest dışında/);
|
||||
} finally {fs.rmSync(dir,{recursive:true,force:true});}
|
||||
});
|
||||
Reference in New Issue
Block a user