UNPKG

rest-fs

Version:
832 lines (778 loc) 22.5 kB
var Lab = require('lab'); var lab = exports.lab = Lab.script(); var fs = require('fs'); var express = require('express'); var server = express(); var restfs = require('../fileserver.js'); restfs(server); var supertest = require('supertest'); var baseDir = __dirname+"/dir_test"; var async = require('async'); var rimraf = require('rimraf'); var walk = require('walkdir'); var _ = require('lodash'); // attach the .compare method to Array's prototype to call it on any array Array.prototype.compare = function (array) { if (!array) return false; if (this.length != array.length) return false; var isMatch = false; for (var me in this) { isMatch = false; for (var other in array) { if (me === other) { isMatch = true; break; } } if(!isMatch) { return false; } } return true; }; lab.before(function (done) { cleanBase(done); }); lab.after(function (done) { rimraf(baseDir, done); }); function cleanBase(cb) { rimraf(baseDir, function(err) { fs.mkdir(baseDir, cb); }); } function createDir(dirpath, opts, cb) { if(typeof opts === 'function') { cb = opts; opts = null; } var req = supertest(server).put(dirpath); if (opts) { req.send(opts); } req.expect(201).end(function(err, res){ if (err) { return cb(err); } fs.stat(dirpath, function (err, stats) { if (err) { return cb(err); } else if (!stats.isDirectory()) { return cb(new Error('dir did not get created')); } else { return cb(); } }); }); } function createDirPost(dirpath, opts, cb) { if(typeof opts === 'function') { cb = opts; opts = null; } var req = supertest(server).post(dirpath); if (opts) { req.send(opts); } req.expect(201).end(function(err, res){ if (err) { return cb(err); } fs.stat(dirpath, function (err, stats) { if (err) { return cb(err); } else if (!stats.isDirectory()) { return cb(new Error('dir did not get created')); } else { return cb(); } }); }); } function createFile(filepath, text, cb) { var data = text || ''; fs.writeFile(filepath, data, cb); } function moveDir(oldpath, newPath, doClobber, doMkdirp, cb) { getDirContents(oldpath, function(err, oldPaths) { if(err) return cb(err); supertest(server) .post(oldpath) .send({ newPath: newPath, clobber: doClobber, mkdirp: doMkdirp }) .end(function(err, res) { if (err) { return cb(err); } else if (200 !== res.statusCode) { return cb(res.body); } async.series([ function(next) { // old path should not exist fs.stat(oldpath, function (err, stats) { if (err) { if (err.code === 'ENOENT') { return next(); } return next(err); } else { return next(new Error('old dir did not move')); } }); }, function(next) { // new path should exist fs.stat(newPath, function (err, stats) { if (err) { return next(err); } else if (stats.isDirectory()) { return next(); } else { return next(new Error('dir did not get moved correctly')); } }); }, function(next) { // new dir structure should match old structure getDirContents(newPath, function(err, newPaths) { if(err) return next(err); if(newPaths.compare(oldPaths)) { return next(); } else { return next(new Error('new dir does not match moved one')); } }); } ], cb); }); }); } function getDirContents(dirPath, cb) { // remove trailing slash if (dirPath.substr(-1) === '/') { dirPath = dirPath.substr(0, dirPath.length - 1); } var error = null; var paths = []; var emitter = walk(dirPath, function(path,stat){ paths.push(path.substr(dirPath.length)); }); emitter.on('end', function() { return cb(error, paths); }); emitter.on('error', function(err) { error = new Error("error on file: "+err); error.code = 'EINVAL'; emitter.end(); }); } /* START TEST */ lab.experiment('create tests', function () { lab.beforeEach(function (done) { cleanBase(done); }); lab.test('create dir POST', function (done) { var dirpath = baseDir+'/dir2/'; createDirPost(dirpath, done); }); lab.test('create dir POST with mode 400', function (done) { var dirpath = baseDir+'/dir2/'; createDirPost(dirpath, {mode: 400}, done); }); lab.test('create dir PUT', function (done) { var dirpath = baseDir+'/dir2/'; createDir(dirpath, done); }); lab.test('create dir PUT with mode 400', function (done) { var dirpath = baseDir+'/dir2/'; createDir(dirpath, {mode: 400}, done); }); }); lab.experiment('delete tests', function () { lab.beforeEach(function (done) { cleanBase(done); }); lab.test('delete dir', function (done) { var dirpath = baseDir+'/dir2/'; createDir(dirpath, function(err) { if (err) { return done(err); } supertest(server) .del(dirpath) .expect(200) .end(function(err, res){ if (err) { return done(err); } fs.stat(dirpath, function (err, stats) { if (err) { if (err.code === 'ENOENT') { return done(); } return done(err); } else { return done(new Error('dir did not get deleted')); } }); }); }); }); lab.test('delete nonexiting dir', function (done) { var dirpath = baseDir+'/dir2/fake/'; supertest(server) .del(dirpath) .expect(404) .end(function(err, res){ if (err) { return done(err); } fs.stat(dirpath, function (err, stats) { if (err) { if (err.code === 'ENOENT') { return done(); } return done(err); } else { return done(new Error('remove returned unexpected error')); } }); }); }); lab.test('attempt to delete file with trailing slash', function (done) { var filePath = baseDir+'/file'; createFile(filePath, "test", function (err) { if(err) return done(err); supertest(server) .del(filePath+'/') .expect(400) .end(done); }); }); lab.test('attempt to a folder with files and folders in it without clobber', function (done) { var dir1 = baseDir+'/dir1/'; var file1 = dir1+'/file1'; var file2 = dir1+'/file2'; var dir1_dir1 = dir1+'/dir1/'; var dir1_file1 = dir1_dir1+'/file1'; var dir1_file2 = dir1_dir1+'/file2'; var fileContent = "testing one two three and I am stopping now"; async.series([ function(cb) { cleanBase(cb); }, function(cb) { createDir(dir1, cb); }, function(cb) { createDir(dir1_dir1, cb); }, function(cb) { createFile(file1, fileContent, cb); }, function(cb) { createFile(file2, fileContent, cb); }, function(cb) { createFile(dir1_file1, fileContent, cb); }, function(cb) { createFile(dir1_file2, fileContent, cb); } ], function (err) { if (err) { return done(err); } supertest(server) .del(dir1) .expect(409) .end(function(err, res){ if (err) { return done(err); } if (res.body.code !== 'ENOTEMPTY') { return done(new Error('should have returned ENOTEMPTY')); } fs.stat(dir1, function (err, stats) { if (err) { return done(new Error('dir got deleted')); } else { return done(); } }); }); }); }); lab.test('attempt to a folder with files and folders in it with clobber', function (done) { var dir1 = baseDir+'/dir1/'; var file1 = dir1+'/file1'; var file2 = dir1+'/file2'; var dir1_dir1 = dir1+'/dir1/'; var dir1_file1 = dir1_dir1+'/file1'; var dir1_file2 = dir1_dir1+'/file2'; var fileContent = "testing one two three and I am stopping now"; async.series([ function(cb) { cleanBase(cb); }, function(cb) { createDir(dir1, cb); }, function(cb) { createDir(dir1_dir1, cb); }, function(cb) { createFile(file1, fileContent, cb); }, function(cb) { createFile(file2, fileContent, cb); }, function(cb) { createFile(dir1_file1, fileContent, cb); }, function(cb) { createFile(dir1_file2, fileContent, cb); } ], function (err) { if (err) { return done(err); } supertest(server) .del(dir1) .send({clobber: true}) .expect(200) .end(function(err, res){ if (err) { return done(err); } fs.stat(dir1, function (err, stats) { if (err) { if (err.code === 'ENOENT') { return done(); } return done(err); } return done(new Error('dir did not get deleted')); }); }); }); }); }); lab.experiment('read tests', function () { var dir2R = baseDir+'/dir2'; var dir2 = dir2R+'/'; var dir1D = baseDir+'/dir1'; var dir1 = dir1D+'/'; var dir1_symlink1 = dir1+'symlink.txt'; var file1 = baseDir+'/file1.txt'; var dir1_file1 = dir2+'file2.txt'; var fileContent = "test"; var testFilePath = baseDir+'/../testfile'; var linkTargetFile = baseDir+'/testfile'; lab.beforeEach(function (done) { async.series([ function(cb) { cleanBase(cb); }, function(cb) { createDir(dir2, cb); }, function(cb) { createDir(dir1, cb); }, function(cb) { createFile(file1, fileContent, cb); }, function(cb) { createFile(dir1_file1, fileContent, cb); }, function(cb) { fs.writeFileSync(testFilePath, 'foo'); fs.linkSync(testFilePath, linkTargetFile); cb(); } ], done); }); lab.afterEach(function (done) { async.series([ function (cb) { fs.unlinkSync(testFilePath); cb(); } ], done); }); lab.test('get dir ls', function (done) { supertest(server) .get(dir2) .expect(200) .end(function(err, res){ if (err) { return done(err); } if (res.body.length !== 1) { return done(new Error('file list incorrect')); } Lab.expect(res.body).to.contain(dir1_file1); return done(); }); }); lab.test('test setModifyOut', function (done) { var server2 = express(); server2.use(function(req, res, next) { req.modifyOut = function (file) { return 'anand'; }; next(); }); var restfs = require('../fileserver.js'); restfs(server2); supertest(server2) .get(dir2) .expect(200) .end(function(err, res){ if (err) { return done(err); } if (res.body.length !== 1) { return done(new Error('file list incorrect')); } Lab.expect(res.body).to.contain('anand'); return done(); }); }); lab.test('get filled dir ls', function (done) { supertest(server) .get(baseDir+'/') .expect(200) .end(function(err, res){ if (err) { return done(err); } else if (res.body.length !== 4) { return done(new Error('file list incorrect')); } Lab.expect(res.body).to.contain(dir1); Lab.expect(res.body).to.contain(dir2); Lab.expect(res.body).to.contain(file1); Lab.expect(res.body).to.contain(linkTargetFile); return done(); }); }); lab.test('get dir ls recursive', function (done) { supertest(server) .get(baseDir+'/') .query({recursive: "true"}) .expect(200) .end(function(err, res){ if (err) { return done(err); } else if (res.body.length != 6) { return done(new Error('file list incorrect')); } Lab.expect(res.body).to.contain(baseDir+'/'); Lab.expect(res.body).to.contain(dir1); Lab.expect(res.body).to.contain(dir2); Lab.expect(res.body).to.contain(file1); Lab.expect(res.body).to.contain(linkTargetFile); Lab.expect(res.body).to.contain(dir2+'file2.txt'); return done(); }); }); lab.test('get empty dir ls', function (done) { supertest(server) .get(dir1) .expect(200) .end(function(err, res){ if (err) { return done(err); } else if (res.body.length) { return done(new Error('file list incorrect')); } return done(); }); }); lab.test('get dir ls with redirect', function (done) { supertest(server) .get(dir2R) .expect(303) .end(function(err, res){ if (err) { return done(err); } else if (!~res.text.indexOf('Redirecting to '+dir2)) { return done(new Error('not redirecting')); } return done(); }); }); lab.test('get empty dir ls with redirect', function (done) { supertest(server) .get(dir1D) .expect(303) .end(function(err, res){ if (err) { return done(err); } else if (!~res.text.indexOf('Redirecting to '+dir1)) { return done(new Error('not redirecting')); } return done(); }); }); lab.test('get dir which does not exist', function (done) { supertest(server) .get(dir1D+"/fake/") .expect(404) .end(done); }); }); lab.experiment('move tests', function () { var dir1 = baseDir+'/dir1/'; var dir2 = baseDir+'/dir2/'; // empty var dir3 = baseDir+'/dir3/'; var dir1_file1 = dir1+'test_file1.txt'; var dir1_dir1 = dir1+'dir1/'; var dir1_dir1_file1 = dir1_dir1+'test_file2.txt'; var dir3_file1 = dir3+'test_file1.txt'; var fileContent = "test"; lab.beforeEach(function (done) { async.series([ function(cb) { cleanBase(cb); }, function(cb) { createDir(dir1, cb); }, function(cb) { createDir(dir2, cb); }, function(cb) { createDir(dir3, cb); }, function(cb) { createDir(dir1_dir1, cb); }, function(cb) { createFile(dir1_file1, fileContent, cb); }, function(cb) { createFile(dir3_file1, fileContent, cb); }, function(cb) { createFile(dir1_dir1_file1, fileContent, cb); } ], done); }); lab.test('move empty dir in same dir (rename) with trailing slash', function (done) { moveDir(dir2, baseDir+'/new/', false, false, done); }); lab.test('move empty dir in same dir (rename) without trailing slash', function (done) { moveDir(dir2, baseDir+'/new', false, false, done); }); lab.test('move empty dir to itself', function (done) { moveDir(dir2, dir2, false, false, function(err) { if(err) { if (err.code === 'EEXIST') { return done(); } return done(err); } return done(new Error('dir was moved on top of itself')); }); }); lab.test('move empty dir to same dir with similar name', function (done) { moveDir(dir2, dir2.substr(0, dir2.length - 1)+"add", false, false, done); }); lab.test('move empty dir into a dir with trailing slash', function (done) { moveDir(dir2, dir1+'new/', false, false, done); }); lab.test('move empty dir into a dir without trailing slash', function (done) { moveDir(dir2, dir1+'new', false, false, done); }); lab.test('move empty dir into itself', function (done) { moveDir(dir2, dir2+'new/', false, false, function(err) { if(err) { if (err.code === 'EPERM') { return done(); } return done(err); } return done(new Error('dir was moved into itself')); }); }); lab.test('move empty dir out of dir', function (done) { moveDir(dir2, dir1+'new/', false, false, function(err) { if (err) return done(err); moveDir(dir1+'new/', dir2, false, false, done); }); }); lab.test('move empty dir onto existing dir', function (done) { moveDir(dir2, dir1, false, false, function(err) { if(err) { if (err.code === 'EEXIST') { return done(); } return done(err); } return done(new Error('dir was overritting without clobber')); }); }); lab.test('move empty dir onto existing dir with clobber', function (done) { moveDir(dir2, dir1, true, false, done); }); lab.test('move empty dir into non existing dir', function (done) { moveDir(dir2, dir1+'fake/dir/', false, false, function(err) { if(err) { if (err.code === 'ENOENT') { return done(); } return done(err); } return done(new Error('dir was created without mkdirp')); }); }); lab.test('move non existing dir into existing dir', function (done) { moveDir(dir2+'fake/dir/', dir1, false, false, function(err) { if(err) { if (err.code === 'EINVAL') { return done(); } return done(err); } return done(new Error('dir was created without mkdirp')); }); }); lab.test('move non existing dir into non existing dir', function (done) { moveDir(dir2+'fake/dir/', dir1+'fake/dir/', false, false, function(err) { if(err) { if (err.code === 'EINVAL') { return done(); } return done(err); } return done(new Error('dir was created without mkdirp')); }); }); lab.test('move empty dir into non existing dir with mkdirp', function (done) { moveDir(dir2, dir1+'fake/dir/', false, true, done); }); lab.test('move empty dir into non existing long dir with mkdirp', function (done) { moveDir(dir2, dir1+'fake/long/long/long/dir/', false, true, done); }); // now try with full dir lab.test('move dir in same dir (rename) with trailing slash', function (done) { moveDir(dir1, baseDir+'/new/', false, false, done); }); lab.test('move dir in same dir (rename) without trailing slash', function (done) { moveDir(dir1, baseDir+'/new', false, false, done); }); lab.test('move dir into a dir with trailing slash', function (done) { moveDir(dir1, dir2+'new/', false, false, done); }); lab.test('move dir into a dir without trailing slash', function (done) { moveDir(dir1, dir2+'new', false, false, done); }); lab.test('move dir to itself', function (done) { moveDir(dir1, dir1, false, false, function(err) { if(err) { if (err.code === 'EEXIST') { return done(); } return done(err); } return done(new Error('dir was moved on top of itself')); }); }); lab.test('move dir to same dir with similar name', function (done) { moveDir(dir1, dir1.substr(0, dir2.length - 1)+"add", false, false, done); }); lab.test('move dir to itself', function (done) { moveDir(dir1, dir1, false, false, function(err) { if(err) { if (err.code === 'EEXIST') { return done(); } return done(err); } return done(new Error('dir was moved on top of itself')); }); }); lab.test('move dir into itself', function (done) { moveDir(dir1, dir1+'new/', false, false, function(err) { if(err) { if (err.code === 'EPERM') { return done(); } return done(err); } return done(new Error('dir was moved into itself')); }); }); lab.test('move dir out of dir', function (done) { moveDir(dir1, dir2+'new/', false, false, function(err) { if (err) return done(err); moveDir(dir2+'new/', dir1, false, false, done); }); }); lab.test('move dir onto existing dir', function (done) { moveDir(dir1, dir2, false, false, function(err) { if(err) { if (err.code === 'EEXIST') { return done(); } return done(err); } return done(new Error('dir was overritting without clobber')); }); }); lab.test('move dir onto existing dir with clobber', function (done) { moveDir(dir1, dir2, true, false, done); }); lab.test('move dir into non existing dir', function (done) { moveDir(dir1, dir2+'fake/dir/', false, false, function(err) { if(err) { if (err.code === 'ENOENT') { return done(); } return done(err); } return done(new Error('dir was created without mkdirp')); }); }); lab.test('move dir into non existing dir with mkdirp', function (done) { moveDir(dir1, dir2+'fake/dir/', false, true, done); }); lab.test('move dir into non existing long dir with mkdirp', function (done) { moveDir(dir1, dir2+'fake/long/long/long/dir/', false, true, done); }); lab.test('clober from inside dir to an empty one above it', function (done) { moveDir(dir1_dir1, dir2, false, false, function(err) { if(err) { if (err.code === 'EEXIST') { return done(); } return done(err); } return done(new Error('dir was overwritten without clober')); }); }); lab.test('clober from inside dir to an empty one above it with clober', function (done) { moveDir(dir1_dir1, dir2, true, false, done); }); lab.test('clober from inside dir to an full one above it', function (done) { moveDir(dir1_dir1, dir3, false, false, function(err) { if(err) { if (err.code === 'EEXIST') { return done(); } return done(err); } return done(new Error('dir was overwritten without clober')); }); }); lab.test('clober from inside dir to an full one above it with clobber', function (done) { moveDir(dir1_dir1, dir3, true, false, done); }); });