diff --git a/src/test/storage-test.js b/src/test/storage-test.js new file mode 100644 index 000000000..360c52632 --- /dev/null +++ b/src/test/storage-test.js @@ -0,0 +1,224 @@ +/* global it:false */ +/* global describe:false */ +/* global before:false */ +/* global after:false */ + +'use strict'; + +var async = require('async'), + fs = require('fs'), + os = require('os'), + path = require('path'), + readdirp = require('readdirp'), + rimraf = require('rimraf'), + BackupsError = require('../backups.js').BackupsError, + config = require('../config.js'), + database = require('../database.js'), + caas = require('../storage/caas.js'), + s3 = require('../storage/s3.js'), + filesystem = require('../storage/filesystem.js'), + expect = require('expect.js'), + settings = require('../settings.js'); + +function setup(done) { + config.set('provider', 'caas'); + + async.series([ + database.initialize, + settings.initialize, + function (callback) { + // a cloudron must have a backup config to startup + settings.setBackupConfig({ provider: 'caas', token: 'foo', key: 'key'}, function (error) { + expect(error).to.be(null); + callback(); + }); + } + ], done); +} + +function cleanup(done) { + async.series([ + settings.uninitialize, + database._clear + ], done); +} + +function compareDirectories(one, two, callback) { + readdirp({ root: one }, function (error, treeOne) { + if (error) return callback(error); + + readdirp({ root: two }, function (error, treeTwo) { + if (error) return callback(error); + + var mismatch = []; + + function compareDirs(a, b) { + a.forEach(function (tmpA) { + var found = b.find(function (tmpB) { + return tmpA.path === tmpB.path; + }); + + if (!found) mismatch.push(tmpA); + }); + } + + function compareFiles(a, b) { + a.forEach(function (tmpA) { + var found = b.find(function (tmpB) { + // TODO check file or symbolic link + return tmpA.path === tmpB.path && tmpA.mode === tmpB.mode; + }); + + if (!found) mismatch.push(tmpA); + }); + } + + compareDirs(treeOne.directories, treeTwo.directories); + compareDirs(treeTwo.directories, treeOne.directories); + compareFiles(treeOne.files, treeTwo.files); + compareFiles(treeTwo.files, treeOne.files); + + if (mismatch.length) { + console.error('Files not found in both: %j', mismatch); + return callback(new Error('file mismatch')); + } + + callback(null); + }); + }); +} + +describe('Storage', function () { + describe('filesystem', function () { + var gBackupId_1 = 'someprefix/one'; + var gBackupId_2 = 'someprefix/two'; + var gTmpFolder; + var gSourceFolder; + var gDestinationFolder; + var gBackupConfig = { + provider: 'filesystem', + key: 'key', + backupFolder: null + }; + + before(function (done) { + setup(function (error) { + expect(error).to.be(null); + + gTmpFolder = fs.mkdtempSync(path.join(os.tmpdir(), 'filesystem-backup-test_')); + + gBackupConfig.backupFolder = path.join(gTmpFolder, 'backups/'); + gSourceFolder = path.join(__dirname, 'storage'); + gDestinationFolder = path.join(gTmpFolder, 'destination/'); + + settings.setBackupConfig(gBackupConfig, function (error) { + expect(error).to.be(null); + + done(); + }); + }); + }); + + after(function (done) { + cleanup(function (error) { + expect(error).to.be(null); + rimraf(gTmpFolder, done); + }); + }); + + it('can backup', function (done) { + var backupMapping = [{ + source: path.join(gSourceFolder, 'data'), + destination: '/datadir' + }, { + source: path.join(gSourceFolder, 'addon'), + destination: '/addondir/' + }]; + + filesystem.backup(gBackupConfig, gBackupId_1, backupMapping, function (error) { + expect(error).to.be(null); + + done(); + }); + }); + + it('can restore', function (done) { + var restoreMapping = [{ + source: '/datadir', + destination: path.join(gDestinationFolder, 'data') + }, { + source: '/addondir', + destination: path.join(gDestinationFolder, 'addon') + }]; + + filesystem.restore(gBackupConfig, gBackupId_1, restoreMapping, function (error) { + expect(error).to.be(null); + + compareDirectories(gSourceFolder, gDestinationFolder, function (error) { + expect(error).to.equal(null); + rimraf(gDestinationFolder, done); + }); + }); + }); + + it('can copy backup', function (done) { + // will be verified after removing the first and restoring from the copy + filesystem.copyBackup(gBackupConfig, gBackupId_1, gBackupId_2, done); + }); + + it('can remove backup', function (done) { + // will be verified with next test trying to restore the removed one + filesystem.removeBackup(gBackupConfig, gBackupId_1, [], done); + }); + + it('cannot restore deleted backup', function (done) { + var restoreMapping = [{ + source: '/datadir', + destination: path.join(gDestinationFolder, 'data') + }]; + + filesystem.restore(gBackupConfig, gBackupId_1, restoreMapping, function (error) { + expect(error).to.be.an('object'); + expect(error.reason).to.equal(BackupsError.NOT_FOUND); + + done(); + }); + }); + + it('can restore backup copy', function (done) { + var restoreMapping = [{ + source: '/datadir', + destination: path.join(gDestinationFolder, 'data') + }, { + source: '/addondir', + destination: path.join(gDestinationFolder, 'addon') + }]; + + filesystem.restore(gBackupConfig, gBackupId_2, restoreMapping, function (error) { + expect(error).to.be(null); + + rimraf(gDestinationFolder, done); + }); + }); + + it('cannot get backup download stream from deleted backup', function (done) { + filesystem.getDownloadStream(gBackupConfig, gBackupId_1, function (error) { + expect(error).to.be.an('object'); + expect(error.reason).to.equal(BackupsError.NOT_FOUND); + done(); + }); + }); + + it('can get backup download stream', function (done) { + filesystem.getDownloadStream(gBackupConfig, gBackupId_2, function (error, result) { + expect(error).to.be(null); + expect(result).to.be.a(fs.ReadStream); + done(); + }) + }); + + it('can remove backup copy', function (done) { + filesystem.removeBackup(gBackupConfig, gBackupId_2, [], done); + }); + }); +}); diff --git a/src/test/storage/addon/nonsqldump b/src/test/storage/addon/nonsqldump new file mode 100644 index 000000000..60f653e4a --- /dev/null +++ b/src/test/storage/addon/nonsqldump @@ -0,0 +1 @@ +This is supposed to be a sqldump for example diff --git a/src/test/storage/data/subfolder/program b/src/test/storage/data/subfolder/program new file mode 100755 index 000000000..c97cb20a3 --- /dev/null +++ b/src/test/storage/data/subfolder/program @@ -0,0 +1 @@ +exec this diff --git a/src/test/storage/data/subfolder/symlink b/src/test/storage/data/subfolder/symlink new file mode 120000 index 000000000..df8e29096 --- /dev/null +++ b/src/test/storage/data/subfolder/symlink @@ -0,0 +1 @@ +../test.txt \ No newline at end of file diff --git a/src/test/storage/data/test.txt b/src/test/storage/data/test.txt new file mode 100644 index 000000000..019741c6e --- /dev/null +++ b/src/test/storage/data/test.txt @@ -0,0 +1 @@ +Cloudron on your Server