/* jslint node:true */ /* global it:false */ /* global describe:false */ /* global before:false */ /* global after:false */ 'use strict'; const common = require('./common.js'), DataLayout = require('../datalayout.js'), EnsureFileSizeStream = require('../backupformat/tgz.js')._EnsureFileSizeStream, expect = require('expect.js'), fs = require('fs'), os = require('os'), path = require('path'), rsync = require('../backupformat/rsync.js'), safe = require('safetydance'), stream = require('node:stream/promises'); describe('backuptask', function () { const { setup, cleanup, createTree } = common; before(setup); after(cleanup); describe('EnsureFileSizeStream', function () { const name = 'eberswalde.txt'; const data = Buffer.from('This file has 22 bytes'); before(function () { fs.writeFileSync(`/tmp/${name}`, data); }); after(function () { fs.rmSync(`/tmp/${name}`); }); it('correct size', async function () { const efs = new EnsureFileSizeStream({ name, size: 22 }); const ins = fs.createReadStream(`/tmp/${name}`); const outs = fs.createWriteStream('/tmp/out.txt'); const [error] = await safe(stream.pipeline(ins, efs, outs)); expect(error).to.be(null); const out = fs.readFileSync('/tmp/out.txt'); expect(out).to.eql(data); }); it('overflow', async function () { const efs = new EnsureFileSizeStream({ name, size: 20 }); const ins = fs.createReadStream(`/tmp/${name}`); const outs = fs.createWriteStream('/tmp/out.txt'); const [error] = await safe(stream.pipeline(ins, efs, outs)); expect(error).to.be(null); const out = fs.readFileSync('/tmp/out.txt'); expect(out).to.eql(data.subarray(0, 20)); }); it('underflow', async function () { const efs = new EnsureFileSizeStream({ name, size: 30 }); const ins = fs.createReadStream(`/tmp/${name}`); const outs = fs.createWriteStream('/tmp/out.txt'); const [error] = await safe(stream.pipeline(ins, efs, outs)); expect(error).to.be(null); const out = fs.readFileSync('/tmp/out.txt'); expect(out).to.eql(Buffer.concat([data, Buffer.alloc(8)])); }); }); describe('fs meta data', function () { let tmpdir; before(function () { tmpdir = fs.mkdtempSync(path.join(os.tmpdir(), 'backups-test')); }); after(function () { fs.rmSync(tmpdir, { recursive: true, force: true }); }); it('saves special files', async function () { createTree(tmpdir, { 'data': { 'subdir': { 'emptydir': { } } }, 'dir2': { 'file': 'stuff' } }); fs.chmodSync(path.join(tmpdir, 'dir2/file'), parseInt('0755', 8)); let dataLayout = new DataLayout(tmpdir, []); await rsync._saveFsMetadata(dataLayout, `${dataLayout.localRoot()}/fsmetadata.json`); const emptyDirs = JSON.parse(fs.readFileSync(path.join(tmpdir, 'fsmetadata.json'), 'utf8')).emptyDirs; expect(emptyDirs).to.eql(['./data/subdir/emptydir']); const execFiles = JSON.parse(fs.readFileSync(path.join(tmpdir, 'fsmetadata.json'), 'utf8')).execFiles; expect(execFiles).to.eql(['./dir2/file']); }); it('restores special files', async function () { fs.rmSync(path.join(tmpdir, 'data'), { recursive: true, force: true }); expect(fs.existsSync(path.join(tmpdir, 'data/subdir/emptydir'))).to.be(false); // just make sure rimraf worked let dataLayout = new DataLayout(tmpdir, []); await rsync._restoreFsMetadata(dataLayout, `${dataLayout.localRoot()}/fsmetadata.json`); expect(fs.existsSync(path.join(tmpdir, 'data/subdir/emptydir'))).to.be(true); const mode = fs.statSync(path.join(tmpdir, 'dir2/file')).mode; expect(mode & ~fs.constants.S_IFREG).to.be(parseInt('0755', 8)); }); }); });