overleaf/services/filestore/test/unit/coffee/FSPersistorManagerTests.js

380 lines
13 KiB
JavaScript
Raw Normal View History

/* eslint-disable
handle-callback-err,
no-return-assign,
no-unused-vars,
*/
// TODO: This file was created by bulk-decaffeinate.
// Fix any style issues and re-enable lint.
/*
* decaffeinate suggestions:
* DS102: Remove unnecessary code created because of implicit returns
* DS207: Consider shorter variations of null checks
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
*/
const {
assert
} = require("chai");
const sinon = require('sinon');
const chai = require('chai');
const {
should
} = chai;
const {
expect
} = chai;
const modulePath = "../../../app/js/FSPersistorManager.js";
const SandboxedModule = require('sandboxed-module');
const fs = require("fs");
const response = require("response");
describe("FSPersistorManagerTests", function() {
beforeEach(function() {
this.Fs = {
rename:sinon.stub(),
createReadStream:sinon.stub(),
createWriteStream:sinon.stub(),
unlink:sinon.stub(),
rmdir:sinon.stub(),
exists:sinon.stub(),
readdir:sinon.stub(),
open:sinon.stub(),
openSync:sinon.stub(),
fstatSync:sinon.stub(),
closeSync:sinon.stub(),
stat:sinon.stub()
};
this.Rimraf = sinon.stub();
this.LocalFileWriter = {
writeStream: sinon.stub(),
2018-11-07 11:51:06 -05:00
deleteFile: sinon.stub()
};
this.requires = {
"./LocalFileWriter":this.LocalFileWriter,
"fs":this.Fs,
"logger-sharelatex": {
log() {},
err() {}
},
"response":response,
"rimraf":this.Rimraf,
"./Errors": (this.Errors =
{NotFoundError: sinon.stub()})
};
this.location = "/tmp";
this.name1 = "530f2407e7ef165704000007/530f838b46d9a9e859000008";
this.name1Filtered ="530f2407e7ef165704000007_530f838b46d9a9e859000008";
this.name2 = "second_file";
this.error = "error_message";
return this.FSPersistorManager = SandboxedModule.require(modulePath, {requires: this.requires});
});
describe("sendFile", function() {
beforeEach(function() {
return this.Fs.createReadStream = sinon.stub().returns({
on() {},
pipe() {}
});
});
it("should copy the file", function(done) {
this.Fs.createWriteStream =sinon.stub().returns({
on(event, handler) {
if (event === 'finish') { return process.nextTick(handler); }
}
});
return this.FSPersistorManager.sendFile(this.location, this.name1, this.name2, err=> {
this.Fs.createReadStream.calledWith(this.name2).should.equal(true);
this.Fs.createWriteStream.calledWith(`${this.location}/${this.name1Filtered}` ).should.equal(true);
return done();
});
});
return it("should return an error if the file cannot be stored", function(done) {
this.Fs.createWriteStream =sinon.stub().returns({
on: (event, handler) => {
if (event === 'error') {
return process.nextTick(() => {
return handler(this.error);
});
}
}
});
return this.FSPersistorManager.sendFile(this.location, this.name1, this.name2, err=> {
this.Fs.createReadStream.calledWith(this.name2).should.equal(true);
this.Fs.createWriteStream.calledWith(`${this.location}/${this.name1Filtered}` ).should.equal(true);
err.should.equal(this.error);
return done();
});
});
});
describe("sendStream", function() {
beforeEach(function() {
this.FSPersistorManager.sendFile = sinon.stub().callsArgWith(3);
this.LocalFileWriter.writeStream.callsArgWith(2, null, this.name1);
this.LocalFileWriter.deleteFile.callsArg(1);
return this.SourceStream =
{on() {}};
});
it("should sent stream to LocalFileWriter", function(done){
return this.FSPersistorManager.sendStream(this.location, this.name1, this.SourceStream, () => {
this.LocalFileWriter.writeStream.calledWith(this.SourceStream).should.equal(true);
return done();
});
});
it("should return the error from LocalFileWriter", function(done){
this.LocalFileWriter.writeStream.callsArgWith(2, this.error);
return this.FSPersistorManager.sendStream(this.location, this.name1, this.SourceStream, err=> {
err.should.equal(this.error);
return done();
});
});
return it("should send the file to the filestore", function(done){
this.LocalFileWriter.writeStream.callsArgWith(2);
return this.FSPersistorManager.sendStream(this.location, this.name1, this.SourceStream, err=> {
this.FSPersistorManager.sendFile.called.should.equal(true);
return done();
});
});
});
describe("getFileStream", function() {
beforeEach(function() {
return this.opts = {};});
it("should use correct file location", function(done) {
this.FSPersistorManager.getFileStream(this.location, this.name1, this.opts, (err,res) => {});
this.Fs.open.calledWith(`${this.location}/${this.name1Filtered}`).should.equal(true);
return done();
});
describe("with start and end options", function() {
beforeEach(function() {
this.fd = 2019;
this.opts_in = {start: 0, end: 8};
this.opts = {start: 0, end: 8, fd: this.fd};
return this.Fs.open.callsArgWith(2, null, this.fd);
});
return it('should pass the options to createReadStream', function(done) {
this.FSPersistorManager.getFileStream(this.location, this.name1, this.opts_in, (err,res)=> {});
this.Fs.createReadStream.calledWith(null, this.opts).should.equal(true);
return done();
});
});
return describe("error conditions", function() {
describe("when the file does not exist", function() {
beforeEach(function() {
this.fakeCode = 'ENOENT';
const err = new Error();
err.code = this.fakeCode;
return this.Fs.open.callsArgWith(2, err, null);
});
return it("should give a NotFoundError", function(done) {
return this.FSPersistorManager.getFileStream(this.location, this.name1, this.opts, (err,res)=> {
expect(res).to.equal(null);
expect(err).to.not.equal(null);
expect(err instanceof this.Errors.NotFoundError).to.equal(true);
return done();
});
});
});
return describe("when some other error happens", function() {
beforeEach(function() {
this.fakeCode = 'SOMETHINGHORRIBLE';
const err = new Error();
err.code = this.fakeCode;
return this.Fs.open.callsArgWith(2, err, null);
});
return it("should give an Error", function(done) {
return this.FSPersistorManager.getFileStream(this.location, this.name1, this.opts, (err,res)=> {
expect(res).to.equal(null);
expect(err).to.not.equal(null);
expect(err instanceof Error).to.equal(true);
return done();
});
});
});
});
});
describe("getFileSize", function() {
it("should return the file size", function(done) {
const expectedFileSize = 75382;
this.Fs.stat.yields(new Error("fs.stat got unexpected arguments"));
this.Fs.stat.withArgs(`${this.location}/${this.name1Filtered}`)
.yields(null, { size: expectedFileSize });
return this.FSPersistorManager.getFileSize(this.location, this.name1, (err, fileSize) => {
if (err != null) {
return done(err);
}
expect(fileSize).to.equal(expectedFileSize);
return done();
});
});
it("should throw a NotFoundError if the file does not exist", function(done) {
const error = new Error();
error.code = "ENOENT";
this.Fs.stat.yields(error);
return this.FSPersistorManager.getFileSize(this.location, this.name1, (err, fileSize) => {
expect(err).to.be.instanceof(this.Errors.NotFoundError);
return done();
});
});
return it("should rethrow any other error", function(done) {
const error = new Error();
this.Fs.stat.yields(error);
return this.FSPersistorManager.getFileSize(this.location, this.name1, (err, fileSize) => {
expect(err).to.equal(error);
return done();
});
});
});
describe("copyFile", function() {
beforeEach(function() {
this.ReadStream= {
on() {},
pipe:sinon.stub()
};
this.WriteStream=
{on() {}};
this.Fs.createReadStream.returns(this.ReadStream);
return this.Fs.createWriteStream.returns(this.WriteStream);
});
it("Should open the source for reading", function(done) {
this.FSPersistorManager.copyFile(this.location, this.name1, this.name2, function() {});
this.Fs.createReadStream.calledWith(`${this.location}/${this.name1Filtered}`).should.equal(true);
return done();
});
it("Should open the target for writing", function(done) {
this.FSPersistorManager.copyFile(this.location, this.name1, this.name2, function() {});
this.Fs.createWriteStream.calledWith(`${this.location}/${this.name2}`).should.equal(true);
return done();
});
return it("Should pipe the source to the target", function(done) {
this.FSPersistorManager.copyFile(this.location, this.name1, this.name2, function() {});
this.ReadStream.pipe.calledWith(this.WriteStream).should.equal(true);
return done();
});
});
describe("deleteFile", function() {
beforeEach(function() {
return this.Fs.unlink.callsArgWith(1,this.error);
});
it("Should call unlink with correct options", function(done) {
return this.FSPersistorManager.deleteFile(this.location, this.name1, err => {
this.Fs.unlink.calledWith(`${this.location}/${this.name1Filtered}`).should.equal(true);
return done();
});
});
return it("Should propogate the error", function(done) {
return this.FSPersistorManager.deleteFile(this.location, this.name1, err => {
err.should.equal(this.error);
return done();
});
});
});
describe("deleteDirectory", function() {
beforeEach(function() {
return this.Rimraf.callsArgWith(1,this.error);
});
it("Should call rmdir(rimraf) with correct options", function(done) {
return this.FSPersistorManager.deleteDirectory(this.location, this.name1, err => {
this.Rimraf.calledWith(`${this.location}/${this.name1Filtered}`).should.equal(true);
return done();
});
});
return it("Should propogate the error", function(done) {
return this.FSPersistorManager.deleteDirectory(this.location, this.name1, err => {
err.should.equal(this.error);
return done();
});
});
});
describe("checkIfFileExists", function() {
beforeEach(function() {
return this.Fs.exists.callsArgWith(1,true);
});
it("Should call exists with correct options", function(done) {
return this.FSPersistorManager.checkIfFileExists(this.location, this.name1, exists => {
this.Fs.exists.calledWith(`${this.location}/${this.name1Filtered}`).should.equal(true);
return done();
});
});
// fs.exists simply returns false on any error, so...
it("should not return an error", function(done) {
return this.FSPersistorManager.checkIfFileExists(this.location, this.name1, (err,exists) => {
expect(err).to.be.null;
return done();
});
});
it("Should return true for existing files", function(done) {
this.Fs.exists.callsArgWith(1,true);
return this.FSPersistorManager.checkIfFileExists(this.location, this.name1, (err,exists) => {
exists.should.be.true;
return done();
});
});
return it("Should return false for non-existing files", function(done) {
this.Fs.exists.callsArgWith(1,false);
return this.FSPersistorManager.checkIfFileExists(this.location, this.name1, (err,exists) => {
exists.should.be.false;
return done();
});
});
});
return describe("directorySize", function() {
it("should propogate the error", function(done) {
this.Fs.readdir.callsArgWith(1, this.error);
return this.FSPersistorManager.directorySize(this.location, this.name1, (err, totalsize) => {
err.should.equal(this.error);
return done();
});
});
return it("should sum directory files size", function(done) {
this.Fs.readdir.callsArgWith(1, null, [ {'file1': 'file1'}, {'file2': 'file2'} ]);
this.Fs.fstatSync.returns({size : 1024});
return this.FSPersistorManager.directorySize(this.location, this.name1, (err, totalsize) => {
expect(totalsize).to.equal(2048);
return done();
});
});
});
});