mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
3575c89d03
This will be used by the file preview feature when it gets partial content.
284 lines
9.6 KiB
CoffeeScript
284 lines
9.6 KiB
CoffeeScript
assert = require("chai").assert
|
|
sinon = require('sinon')
|
|
chai = require('chai')
|
|
should = chai.should
|
|
expect = chai.expect
|
|
modulePath = "../../../app/js/FSPersistorManager.js"
|
|
SandboxedModule = require('sandboxed-module')
|
|
fs = require("fs")
|
|
response = require("response")
|
|
|
|
describe "FSPersistorManagerTests", ->
|
|
|
|
beforeEach ->
|
|
@Fs =
|
|
rename:sinon.stub()
|
|
createReadStream:sinon.stub()
|
|
createWriteStream:sinon.stub()
|
|
unlink:sinon.stub()
|
|
rmdir:sinon.stub()
|
|
exists:sinon.stub()
|
|
readdir:sinon.stub()
|
|
openSync:sinon.stub()
|
|
fstatSync:sinon.stub()
|
|
closeSync:sinon.stub()
|
|
stat:sinon.stub()
|
|
@Rimraf = sinon.stub()
|
|
@LocalFileWriter =
|
|
writeStream: sinon.stub()
|
|
deleteFile: sinon.stub()
|
|
@requires =
|
|
"./LocalFileWriter":@LocalFileWriter
|
|
"fs":@Fs
|
|
"logger-sharelatex":
|
|
log:->
|
|
err:->
|
|
"response":response
|
|
"rimraf":@Rimraf
|
|
"./Errors": @Errors =
|
|
NotFoundError: sinon.stub()
|
|
@location = "/tmp"
|
|
@name1 = "530f2407e7ef165704000007/530f838b46d9a9e859000008"
|
|
@name1Filtered ="530f2407e7ef165704000007_530f838b46d9a9e859000008"
|
|
@name2 = "second_file"
|
|
@error = "error_message"
|
|
@FSPersistorManager = SandboxedModule.require modulePath, requires: @requires
|
|
|
|
describe "sendFile", ->
|
|
beforeEach ->
|
|
@Fs.createReadStream = sinon.stub().returns({
|
|
on: ->
|
|
pipe: ->
|
|
})
|
|
|
|
it "should copy the file", (done) ->
|
|
@Fs.createWriteStream =sinon.stub().returns({
|
|
on: (event, handler) ->
|
|
process.nextTick(handler) if event is 'finish'
|
|
})
|
|
@FSPersistorManager.sendFile @location, @name1, @name2, (err)=>
|
|
@Fs.createReadStream.calledWith(@name2).should.equal true
|
|
@Fs.createWriteStream.calledWith("#{@location}/#{@name1Filtered}" ).should.equal true
|
|
done()
|
|
|
|
it "should return an error if the file cannot be stored", (done) ->
|
|
@Fs.createWriteStream =sinon.stub().returns({
|
|
on: (event, handler) =>
|
|
if event is 'error'
|
|
process.nextTick () =>
|
|
handler(@error)
|
|
})
|
|
@FSPersistorManager.sendFile @location, @name1, @name2, (err)=>
|
|
@Fs.createReadStream.calledWith(@name2).should.equal true
|
|
@Fs.createWriteStream.calledWith("#{@location}/#{@name1Filtered}" ).should.equal true
|
|
err.should.equal @error
|
|
done()
|
|
|
|
describe "sendStream", ->
|
|
beforeEach ->
|
|
@FSPersistorManager.sendFile = sinon.stub().callsArgWith(3)
|
|
@LocalFileWriter.writeStream.callsArgWith(2, null, @name1)
|
|
@LocalFileWriter.deleteFile.callsArg(1)
|
|
@SourceStream =
|
|
on:->
|
|
|
|
it "should sent stream to LocalFileWriter", (done)->
|
|
@FSPersistorManager.sendStream @location, @name1, @SourceStream, =>
|
|
@LocalFileWriter.writeStream.calledWith(@SourceStream).should.equal true
|
|
done()
|
|
|
|
it "should return the error from LocalFileWriter", (done)->
|
|
@LocalFileWriter.writeStream.callsArgWith(2, @error)
|
|
@FSPersistorManager.sendStream @location, @name1, @SourceStream, (err)=>
|
|
err.should.equal @error
|
|
done()
|
|
|
|
it "should send the file to the filestore", (done)->
|
|
@LocalFileWriter.writeStream.callsArgWith(2)
|
|
@FSPersistorManager.sendStream @location, @name1, @SourceStream, (err)=>
|
|
@FSPersistorManager.sendFile.called.should.equal true
|
|
done()
|
|
|
|
describe "getFileStream", ->
|
|
beforeEach ->
|
|
@opts = {}
|
|
|
|
it "should use correct file location", (done) ->
|
|
@Fs.createReadStream.returns({on: ->})
|
|
@FSPersistorManager.getFileStream @location, @name1, @opts, (err,res) =>
|
|
@Fs.createReadStream.calledWith("#{@location}/#{@name1Filtered}").should.equal true
|
|
done()
|
|
|
|
describe "with start and end options", ->
|
|
|
|
beforeEach ->
|
|
@opts = {start: 0, end: 8}
|
|
|
|
it 'should pass the options to createReadStream', (done) ->
|
|
@Fs.createReadStream.returns({on: ->})
|
|
@FSPersistorManager.getFileStream @location, @name1, @opts, (err,res)=>
|
|
@Fs.createReadStream.calledWith("#{@location}/#{@name1Filtered}", @opts).should.equal true
|
|
done()
|
|
|
|
describe "error conditions", ->
|
|
|
|
describe "when the file does not exist", ->
|
|
|
|
beforeEach ->
|
|
@fakeCode = 'ENOENT'
|
|
@Fs.createReadStream.returns(
|
|
on: (key, callback) =>
|
|
err = new Error()
|
|
err.code = @fakeCode
|
|
callback(err, null)
|
|
)
|
|
it "should give a NotFoundError", (done) ->
|
|
@FSPersistorManager.getFileStream @location, @name1, @opts, (err,res)=>
|
|
expect(res).to.equal null
|
|
expect(err).to.not.equal null
|
|
expect(err instanceof @Errors.NotFoundError).to.equal true
|
|
done()
|
|
|
|
describe "when some other error happens", ->
|
|
|
|
beforeEach ->
|
|
@fakeCode = 'SOMETHINGHORRIBLE'
|
|
@Fs.createReadStream.returns(
|
|
on: (key, callback) =>
|
|
err = new Error()
|
|
err.code = @fakeCode
|
|
callback(err, null)
|
|
)
|
|
|
|
it "should give an Error", (done) ->
|
|
@FSPersistorManager.getFileStream @location, @name1, @opts, (err,res)=>
|
|
expect(res).to.equal null
|
|
expect(err).to.not.equal null
|
|
expect(err instanceof Error).to.equal true
|
|
done()
|
|
|
|
describe "getFileSize", ->
|
|
it "should return the file size", (done) ->
|
|
expectedFileSize = 75382
|
|
@Fs.stat.yields(new Error("fs.stat got unexpected arguments"))
|
|
@Fs.stat.withArgs("#{@location}/#{@name1Filtered}")
|
|
.yields(null, { size: expectedFileSize })
|
|
|
|
@FSPersistorManager.getFileSize @location, @name1, (err, fileSize) =>
|
|
if err?
|
|
return done(err)
|
|
expect(fileSize).to.equal(expectedFileSize)
|
|
done()
|
|
|
|
it "should throw a NotFoundError if the file does not exist", (done) ->
|
|
error = new Error()
|
|
error.code = "ENOENT"
|
|
@Fs.stat.yields(error)
|
|
|
|
@FSPersistorManager.getFileSize @location, @name1, (err, fileSize) =>
|
|
expect(err).to.be.instanceof(@Errors.NotFoundError)
|
|
done()
|
|
|
|
it "should rethrow any other error", (done) ->
|
|
error = new Error()
|
|
@Fs.stat.yields(error)
|
|
|
|
@FSPersistorManager.getFileSize @location, @name1, (err, fileSize) =>
|
|
expect(err).to.equal(error)
|
|
done()
|
|
|
|
describe "copyFile", ->
|
|
beforeEach ->
|
|
@ReadStream=
|
|
on:->
|
|
pipe:sinon.stub()
|
|
@WriteStream=
|
|
on:->
|
|
@Fs.createReadStream.returns(@ReadStream)
|
|
@Fs.createWriteStream.returns(@WriteStream)
|
|
|
|
it "Should open the source for reading", (done) ->
|
|
@FSPersistorManager.copyFile @location, @name1, @name2, ->
|
|
@Fs.createReadStream.calledWith("#{@location}/#{@name1Filtered}").should.equal true
|
|
done()
|
|
|
|
it "Should open the target for writing", (done) ->
|
|
@FSPersistorManager.copyFile @location, @name1, @name2, ->
|
|
@Fs.createWriteStream.calledWith("#{@location}/#{@name2}").should.equal true
|
|
done()
|
|
|
|
it "Should pipe the source to the target", (done) ->
|
|
@FSPersistorManager.copyFile @location, @name1, @name2, ->
|
|
@ReadStream.pipe.calledWith(@WriteStream).should.equal true
|
|
done()
|
|
|
|
describe "deleteFile", ->
|
|
beforeEach ->
|
|
@Fs.unlink.callsArgWith(1,@error)
|
|
|
|
it "Should call unlink with correct options", (done) ->
|
|
@FSPersistorManager.deleteFile @location, @name1, (err) =>
|
|
@Fs.unlink.calledWith("#{@location}/#{@name1Filtered}").should.equal true
|
|
done()
|
|
|
|
it "Should propogate the error", (done) ->
|
|
@FSPersistorManager.deleteFile @location, @name1, (err) =>
|
|
err.should.equal @error
|
|
done()
|
|
|
|
|
|
describe "deleteDirectory", ->
|
|
beforeEach ->
|
|
@Rimraf.callsArgWith(1,@error)
|
|
|
|
it "Should call rmdir(rimraf) with correct options", (done) ->
|
|
@FSPersistorManager.deleteDirectory @location, @name1, (err) =>
|
|
@Rimraf.calledWith("#{@location}/#{@name1Filtered}").should.equal true
|
|
done()
|
|
|
|
it "Should propogate the error", (done) ->
|
|
@FSPersistorManager.deleteDirectory @location, @name1, (err) =>
|
|
err.should.equal @error
|
|
done()
|
|
|
|
describe "checkIfFileExists", ->
|
|
beforeEach ->
|
|
@Fs.exists.callsArgWith(1,true)
|
|
|
|
it "Should call exists with correct options", (done) ->
|
|
@FSPersistorManager.checkIfFileExists @location, @name1, (exists) =>
|
|
@Fs.exists.calledWith("#{@location}/#{@name1Filtered}").should.equal true
|
|
done()
|
|
|
|
# fs.exists simply returns false on any error, so...
|
|
it "should not return an error", (done) ->
|
|
@FSPersistorManager.checkIfFileExists @location, @name1, (err,exists) =>
|
|
expect(err).to.be.null
|
|
done()
|
|
|
|
it "Should return true for existing files", (done) ->
|
|
@Fs.exists.callsArgWith(1,true)
|
|
@FSPersistorManager.checkIfFileExists @location, @name1, (err,exists) =>
|
|
exists.should.be.true
|
|
done()
|
|
|
|
it "Should return false for non-existing files", (done) ->
|
|
@Fs.exists.callsArgWith(1,false)
|
|
@FSPersistorManager.checkIfFileExists @location, @name1, (err,exists) =>
|
|
exists.should.be.false
|
|
done()
|
|
|
|
describe "directorySize", ->
|
|
|
|
it "should propogate the error", (done) ->
|
|
@Fs.readdir.callsArgWith(1, @error)
|
|
@FSPersistorManager.directorySize @location, @name1, (err, totalsize) =>
|
|
err.should.equal @error
|
|
done()
|
|
|
|
it "should sum directory files size", (done) ->
|
|
@Fs.readdir.callsArgWith(1, null, [ {'file1'}, {'file2'} ])
|
|
@Fs.fstatSync.returns({size : 1024})
|
|
@FSPersistorManager.directorySize @location, @name1, (err, totalsize) =>
|
|
expect(totalsize).to.equal 2048
|
|
done()
|