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});} });