Merge pull request #54 from sharelatex/bg-avoid-running-qpdf-on-already-optimised-files

check if file is optimised before running qpdf
This commit is contained in:
Brian Gough 2017-04-05 13:18:32 +01:00 committed by GitHub
commit f84d4f5e5f
2 changed files with 119 additions and 1 deletions

View file

@ -11,10 +11,25 @@ module.exports = OutputFileOptimiser =
# check output file (src) and see if we can optimise it, storing
# the result in the build directory (dst)
if src.match(/\/output\.pdf$/)
OutputFileOptimiser.optimisePDF src, dst, callback
OutputFileOptimiser.checkIfPDFIsOptimised src, (err, isOptimised) ->
return callback(null) if err? or isOptimised
OutputFileOptimiser.optimisePDF src, dst, callback
else
callback (null)
checkIfPDFIsOptimised: (file, callback) ->
SIZE = 16*1024 # check the header of the pdf
result = new Buffer(SIZE)
result.fill(0) # prevent leakage of uninitialised buffer
fs.open file, "r", (err, fd) ->
return callback(err) if err?
fs.read fd, result, 0, SIZE, 0, (errRead, bytesRead, buffer) ->
fs.close fd, (errClose) ->
return callback(errRead) if errRead?
return callback(errClose) if errReadClose?
isOptimised = buffer.toString('ascii').indexOf("/Linearized 1") >= 0
callback(null, isOptimised)
optimisePDF: (src, dst, callback = (error) ->) ->
tmpOutput = dst + '.opt'
args = ["--linearize", src, tmpOutput]

View file

@ -0,0 +1,103 @@
SandboxedModule = require('sandboxed-module')
sinon = require('sinon')
require('chai').should()
modulePath = require('path').join __dirname, '../../../app/js/OutputFileOptimiser'
path = require "path"
expect = require("chai").expect
EventEmitter = require("events").EventEmitter
describe "OutputFileOptimiser", ->
beforeEach ->
@OutputFileOptimiser = SandboxedModule.require modulePath, requires:
"fs": @fs = {}
"path": @Path = {}
"child_process": spawn: @spawn = sinon.stub()
"logger-sharelatex": { log: sinon.stub(), warn: sinon.stub() }
"./Metrics" : {}
@directory = "/test/dir"
@callback = sinon.stub()
describe "optimiseFile", ->
beforeEach ->
@src = "./output.pdf"
@dst = "./output.pdf"
describe "when the file is not a pdf file", ->
beforeEach (done)->
@src = "./output.log"
@OutputFileOptimiser.checkIfPDFIsOptimised = sinon.stub().callsArgWith(1, null, false)
@OutputFileOptimiser.optimisePDF = sinon.stub().callsArgWith(2, null)
@OutputFileOptimiser.optimiseFile @src, @dst, done
it "should not check if the file is optimised", ->
@OutputFileOptimiser.checkIfPDFIsOptimised.calledWith(@src).should.equal false
it "should not optimise the file", ->
@OutputFileOptimiser.optimisePDF.calledWith(@src, @dst).should.equal false
describe "when the pdf file is not optimised", ->
beforeEach (done) ->
@OutputFileOptimiser.checkIfPDFIsOptimised = sinon.stub().callsArgWith(1, null, false)
@OutputFileOptimiser.optimisePDF = sinon.stub().callsArgWith(2, null)
@OutputFileOptimiser.optimiseFile @src, @dst, done
it "should check if the pdf is optimised", ->
@OutputFileOptimiser.checkIfPDFIsOptimised.calledWith(@src).should.equal true
it "should optimise the pdf", ->
@OutputFileOptimiser.optimisePDF.calledWith(@src, @dst).should.equal true
describe "when the pdf file is optimised", ->
beforeEach (done) ->
@OutputFileOptimiser.checkIfPDFIsOptimised = sinon.stub().callsArgWith(1, null, true)
@OutputFileOptimiser.optimisePDF = sinon.stub().callsArgWith(2, null)
@OutputFileOptimiser.optimiseFile @src, @dst, done
it "should check if the pdf is optimised", ->
@OutputFileOptimiser.checkIfPDFIsOptimised.calledWith(@src).should.equal true
it "should not optimise the pdf", ->
@OutputFileOptimiser.optimisePDF.calledWith(@src, @dst).should.equal false
describe "checkIfPDFISOptimised", ->
beforeEach () ->
@callback = sinon.stub()
@fd = 1234
@fs.open = sinon.stub().yields(null, @fd)
@fs.read = sinon.stub().withArgs(@fd).yields(null, 100, new Buffer("hello /Linearized 1"))
@fs.close = sinon.stub().withArgs(@fd).yields(null)
@OutputFileOptimiser.checkIfPDFIsOptimised @src, @callback
describe "for a linearised file", ->
beforeEach () ->
@fs.read = sinon.stub().withArgs(@fd).yields(null, 100, new Buffer("hello /Linearized 1"))
@OutputFileOptimiser.checkIfPDFIsOptimised @src, @callback
it "should open the file", ->
@fs.open.calledWith(@src, "r").should.equal true
it "should read the header", ->
@fs.read.calledWith(@fd).should.equal true
it "should close the file", ->
@fs.close.calledWith(@fd).should.equal true
it "should call the callback with a true result", ->
@callback.calledWith(null, true).should.equal true
describe "for an unlinearised file", ->
beforeEach () ->
@fs.read = sinon.stub().withArgs(@fd).yields(null, 100, new Buffer("hello not linearized 1"))
@OutputFileOptimiser.checkIfPDFIsOptimised @src, @callback
it "should open the file", ->
@fs.open.calledWith(@src, "r").should.equal true
it "should read the header", ->
@fs.read.calledWith(@fd).should.equal true
it "should close the file", ->
@fs.close.calledWith(@fd).should.equal true
it "should call the callback with a false result", ->
@callback.calledWith(null, false).should.equal true