2020-02-19 06:15:37 -05:00
|
|
|
const SandboxedModule = require('sandboxed-module')
|
|
|
|
const sinon = require('sinon')
|
|
|
|
const modulePath = require('path').join(
|
|
|
|
__dirname,
|
|
|
|
'../../../app/js/CompileManager'
|
|
|
|
)
|
|
|
|
const { EventEmitter } = require('events')
|
|
|
|
|
2020-08-10 12:01:11 -04:00
|
|
|
describe('CompileManager', function () {
|
|
|
|
beforeEach(function () {
|
2021-08-30 07:56:13 -04:00
|
|
|
this.callback = sinon.stub()
|
|
|
|
this.projectId = 'project-id-123'
|
|
|
|
this.userId = '1234'
|
|
|
|
this.resources = 'mock-resources'
|
|
|
|
this.outputFiles = [
|
|
|
|
{
|
|
|
|
path: 'output.log',
|
|
|
|
type: 'log',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
path: 'output.pdf',
|
|
|
|
type: 'pdf',
|
|
|
|
},
|
|
|
|
]
|
|
|
|
this.buildFiles = [
|
|
|
|
{
|
|
|
|
path: 'output.log',
|
|
|
|
type: 'log',
|
|
|
|
build: 1234,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
path: 'output.pdf',
|
|
|
|
type: 'pdf',
|
|
|
|
build: 1234,
|
|
|
|
},
|
|
|
|
]
|
|
|
|
this.proc = new EventEmitter()
|
|
|
|
this.proc.stdout = new EventEmitter()
|
|
|
|
this.proc.stderr = new EventEmitter()
|
|
|
|
this.proc.stderr.setEncoding = sinon.stub().returns(this.proc.stderr)
|
|
|
|
|
|
|
|
this.LatexRunner = {
|
|
|
|
runLatex: sinon.stub().yields(),
|
|
|
|
}
|
|
|
|
this.ResourceWriter = {
|
|
|
|
syncResourcesToDisk: sinon.stub().yields(null, this.resources),
|
|
|
|
}
|
|
|
|
this.OutputFileFinder = {
|
|
|
|
findOutputFiles: sinon.stub().yields(null, this.outputFiles),
|
|
|
|
}
|
|
|
|
this.OutputCacheManager = {
|
|
|
|
saveOutputFiles: sinon.stub().yields(null, this.buildFiles),
|
|
|
|
}
|
|
|
|
this.Settings = {
|
|
|
|
path: {
|
|
|
|
compilesDir: '/compiles/dir',
|
|
|
|
outputDir: '/output/dir',
|
|
|
|
},
|
|
|
|
synctexBaseDir() {
|
|
|
|
return '/compile'
|
|
|
|
},
|
|
|
|
clsi: {
|
|
|
|
docker: {
|
|
|
|
image: 'SOMEIMAGE',
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
this.child_process = {
|
|
|
|
exec: sinon.stub(),
|
|
|
|
spawn: sinon.stub().returns(this.proc),
|
|
|
|
}
|
|
|
|
this.CommandRunner = {
|
|
|
|
run: sinon.stub().yields(),
|
|
|
|
}
|
|
|
|
this.DraftModeManager = {
|
|
|
|
injectDraftMode: sinon.stub().yields(),
|
|
|
|
}
|
|
|
|
this.TikzManager = {
|
|
|
|
checkMainFile: sinon.stub().yields(null, false),
|
|
|
|
}
|
|
|
|
this.LockManager = {
|
|
|
|
runWithLock: sinon.stub().callsFake((lockFile, runner, callback) => {
|
|
|
|
runner((err, ...result) => callback(err, ...result))
|
|
|
|
}),
|
|
|
|
}
|
|
|
|
this.fs = {
|
|
|
|
lstat: sinon.stub(),
|
|
|
|
stat: sinon.stub(),
|
|
|
|
readFile: sinon.stub(),
|
|
|
|
}
|
|
|
|
this.fse = {
|
|
|
|
ensureDir: sinon.stub().yields(),
|
|
|
|
}
|
|
|
|
|
2020-02-19 06:15:37 -05:00
|
|
|
this.CompileManager = SandboxedModule.require(modulePath, {
|
|
|
|
requires: {
|
2021-08-30 07:56:13 -04:00
|
|
|
'./LatexRunner': this.LatexRunner,
|
|
|
|
'./ResourceWriter': this.ResourceWriter,
|
|
|
|
'./OutputFileFinder': this.OutputFileFinder,
|
|
|
|
'./OutputCacheManager': this.OutputCacheManager,
|
|
|
|
'@overleaf/settings': this.Settings,
|
|
|
|
child_process: this.child_process,
|
|
|
|
'./CommandRunner': this.CommandRunner,
|
|
|
|
'./DraftModeManager': this.DraftModeManager,
|
|
|
|
'./TikzManager': this.TikzManager,
|
|
|
|
'./LockManager': this.LockManager,
|
|
|
|
fs: this.fs,
|
|
|
|
'fs-extra': this.fse,
|
2021-07-13 07:04:48 -04:00
|
|
|
},
|
2020-02-19 06:15:37 -05:00
|
|
|
})
|
|
|
|
})
|
2021-08-30 07:56:13 -04:00
|
|
|
|
2020-08-10 12:01:11 -04:00
|
|
|
describe('doCompileWithLock', function () {
|
|
|
|
beforeEach(function () {
|
2020-02-19 06:15:37 -05:00
|
|
|
this.request = {
|
2021-08-30 07:56:13 -04:00
|
|
|
resources: this.resources,
|
|
|
|
rootResourcePath: (this.rootResourcePath = 'main.tex'),
|
|
|
|
project_id: this.projectId,
|
|
|
|
user_id: this.userId,
|
|
|
|
compiler: (this.compiler = 'pdflatex'),
|
|
|
|
timeout: (this.timeout = 42000),
|
|
|
|
imageName: (this.image = 'example.com/image'),
|
|
|
|
flags: (this.flags = ['-file-line-error']),
|
|
|
|
compileGroup: (this.compileGroup = 'compile-group'),
|
2020-02-19 06:15:37 -05:00
|
|
|
}
|
2021-08-30 07:56:13 -04:00
|
|
|
this.env = {}
|
2020-02-19 06:15:37 -05:00
|
|
|
this.Settings.compileDir = 'compiles'
|
2021-08-30 07:56:13 -04:00
|
|
|
this.compileDir = `${this.Settings.path.compilesDir}/${this.projectId}-${this.userId}`
|
|
|
|
this.outputDir = `${this.Settings.path.outputDir}/${this.projectId}-${this.userId}`
|
2020-02-19 06:15:37 -05:00
|
|
|
})
|
|
|
|
|
2021-08-30 07:56:13 -04:00
|
|
|
describe('when the project is locked', function () {
|
2020-08-10 12:01:11 -04:00
|
|
|
beforeEach(function () {
|
2021-08-30 07:56:13 -04:00
|
|
|
this.error = new Error('locked')
|
|
|
|
this.LockManager.runWithLock.callsFake((lockFile, runner, callback) => {
|
|
|
|
callback(this.error)
|
|
|
|
})
|
|
|
|
this.CompileManager.doCompileWithLock(this.request, this.callback)
|
2020-02-19 06:15:37 -05:00
|
|
|
})
|
|
|
|
|
2020-08-10 12:01:11 -04:00
|
|
|
it('should ensure that the compile directory exists', function () {
|
2021-08-30 07:56:13 -04:00
|
|
|
this.fse.ensureDir.calledWith(this.compileDir).should.equal(true)
|
2020-02-19 06:15:37 -05:00
|
|
|
})
|
|
|
|
|
2021-08-30 07:56:13 -04:00
|
|
|
it('should not run LaTeX', function () {
|
|
|
|
this.LatexRunner.runLatex.called.should.equal(false)
|
2020-02-19 06:15:37 -05:00
|
|
|
})
|
|
|
|
|
2021-08-30 07:56:13 -04:00
|
|
|
it('should call the callback with the error', function () {
|
|
|
|
this.callback.calledWithExactly(this.error).should.equal(true)
|
2020-02-19 06:15:37 -05:00
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2021-08-30 07:56:13 -04:00
|
|
|
describe('normally', function () {
|
2020-08-10 12:01:11 -04:00
|
|
|
beforeEach(function () {
|
2021-08-30 07:56:13 -04:00
|
|
|
this.CompileManager.doCompileWithLock(this.request, this.callback)
|
2020-02-19 06:15:37 -05:00
|
|
|
})
|
|
|
|
|
2020-08-10 12:01:11 -04:00
|
|
|
it('should ensure that the compile directory exists', function () {
|
2021-08-30 07:56:13 -04:00
|
|
|
this.fse.ensureDir.calledWith(this.compileDir).should.equal(true)
|
2020-02-19 06:15:37 -05:00
|
|
|
})
|
|
|
|
|
2020-08-10 12:01:11 -04:00
|
|
|
it('should write the resources to disk', function () {
|
2021-08-30 07:56:13 -04:00
|
|
|
this.ResourceWriter.syncResourcesToDisk
|
2020-02-19 06:15:37 -05:00
|
|
|
.calledWith(this.request, this.compileDir)
|
|
|
|
.should.equal(true)
|
|
|
|
})
|
|
|
|
|
2020-08-10 12:01:11 -04:00
|
|
|
it('should run LaTeX', function () {
|
2021-08-30 07:56:13 -04:00
|
|
|
this.LatexRunner.runLatex
|
|
|
|
.calledWith(`${this.projectId}-${this.userId}`, {
|
2020-02-19 06:15:37 -05:00
|
|
|
directory: this.compileDir,
|
|
|
|
mainFile: this.rootResourcePath,
|
|
|
|
compiler: this.compiler,
|
|
|
|
timeout: this.timeout,
|
|
|
|
image: this.image,
|
|
|
|
flags: this.flags,
|
2020-06-11 11:01:44 -04:00
|
|
|
environment: this.env,
|
2021-07-13 07:04:48 -04:00
|
|
|
compileGroup: this.compileGroup,
|
2020-02-19 06:15:37 -05:00
|
|
|
})
|
|
|
|
.should.equal(true)
|
|
|
|
})
|
|
|
|
|
2020-08-10 12:01:11 -04:00
|
|
|
it('should find the output files', function () {
|
2021-08-30 07:56:13 -04:00
|
|
|
this.OutputFileFinder.findOutputFiles
|
2020-02-19 06:15:37 -05:00
|
|
|
.calledWith(this.resources, this.compileDir)
|
|
|
|
.should.equal(true)
|
|
|
|
})
|
|
|
|
|
2020-08-10 12:01:11 -04:00
|
|
|
it('should return the output files', function () {
|
2021-08-30 07:56:13 -04:00
|
|
|
this.callback.calledWith(null, this.buildFiles).should.equal(true)
|
2020-02-19 06:15:37 -05:00
|
|
|
})
|
|
|
|
|
2021-08-30 07:56:13 -04:00
|
|
|
it('should not inject draft mode by default', function () {
|
|
|
|
this.DraftModeManager.injectDraftMode.called.should.equal(false)
|
2020-02-19 06:15:37 -05:00
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2020-08-10 12:01:11 -04:00
|
|
|
describe('with draft mode', function () {
|
|
|
|
beforeEach(function () {
|
2020-02-19 06:15:37 -05:00
|
|
|
this.request.draft = true
|
2021-08-30 07:56:13 -04:00
|
|
|
this.CompileManager.doCompileWithLock(this.request, this.callback)
|
2020-02-19 06:15:37 -05:00
|
|
|
})
|
|
|
|
|
2021-08-30 07:56:13 -04:00
|
|
|
it('should inject the draft mode header', function () {
|
|
|
|
this.DraftModeManager.injectDraftMode
|
2020-02-19 06:15:37 -05:00
|
|
|
.calledWith(this.compileDir + '/' + this.rootResourcePath)
|
|
|
|
.should.equal(true)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2020-08-10 12:01:11 -04:00
|
|
|
describe('with a check option', function () {
|
|
|
|
beforeEach(function () {
|
2020-02-19 06:15:37 -05:00
|
|
|
this.request.check = 'error'
|
2021-08-30 07:56:13 -04:00
|
|
|
this.CompileManager.doCompileWithLock(this.request, this.callback)
|
2020-02-19 06:15:37 -05:00
|
|
|
})
|
|
|
|
|
2021-08-30 07:56:13 -04:00
|
|
|
it('should run chktex', function () {
|
|
|
|
this.LatexRunner.runLatex
|
|
|
|
.calledWith(`${this.projectId}-${this.userId}`, {
|
2020-02-19 06:15:37 -05:00
|
|
|
directory: this.compileDir,
|
|
|
|
mainFile: this.rootResourcePath,
|
|
|
|
compiler: this.compiler,
|
|
|
|
timeout: this.timeout,
|
|
|
|
image: this.image,
|
|
|
|
flags: this.flags,
|
|
|
|
environment: {
|
|
|
|
CHKTEX_OPTIONS: '-nall -e9 -e10 -w15 -w16',
|
|
|
|
CHKTEX_EXIT_ON_ERROR: 1,
|
2021-07-13 07:04:48 -04:00
|
|
|
CHKTEX_ULIMIT_OPTIONS: '-t 5 -v 64000',
|
2020-06-11 11:01:44 -04:00
|
|
|
},
|
2021-07-13 07:04:48 -04:00
|
|
|
compileGroup: this.compileGroup,
|
2020-02-19 06:15:37 -05:00
|
|
|
})
|
|
|
|
.should.equal(true)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2021-08-30 07:56:13 -04:00
|
|
|
describe('with a knitr file and check options', function () {
|
2020-08-10 12:01:11 -04:00
|
|
|
beforeEach(function () {
|
2020-02-19 06:15:37 -05:00
|
|
|
this.request.rootResourcePath = 'main.Rtex'
|
|
|
|
this.request.check = 'error'
|
2021-08-30 07:56:13 -04:00
|
|
|
this.CompileManager.doCompileWithLock(this.request, this.callback)
|
2020-02-19 06:15:37 -05:00
|
|
|
})
|
|
|
|
|
2021-08-30 07:56:13 -04:00
|
|
|
it('should not run chktex', function () {
|
|
|
|
this.LatexRunner.runLatex
|
|
|
|
.calledWith(`${this.projectId}-${this.userId}`, {
|
2020-02-19 06:15:37 -05:00
|
|
|
directory: this.compileDir,
|
|
|
|
mainFile: 'main.Rtex',
|
|
|
|
compiler: this.compiler,
|
|
|
|
timeout: this.timeout,
|
|
|
|
image: this.image,
|
|
|
|
flags: this.flags,
|
2020-06-11 11:01:44 -04:00
|
|
|
environment: this.env,
|
2021-07-13 07:04:48 -04:00
|
|
|
compileGroup: this.compileGroup,
|
2020-02-19 06:15:37 -05:00
|
|
|
})
|
|
|
|
.should.equal(true)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2020-08-10 12:01:11 -04:00
|
|
|
describe('clearProject', function () {
|
|
|
|
describe('succesfully', function () {
|
|
|
|
beforeEach(function () {
|
2020-02-19 06:15:37 -05:00
|
|
|
this.Settings.compileDir = 'compiles'
|
2021-08-30 07:56:13 -04:00
|
|
|
this.fs.lstat.yields(null, {
|
2020-02-19 06:15:37 -05:00
|
|
|
isDirectory() {
|
|
|
|
return true
|
2021-07-13 07:04:48 -04:00
|
|
|
},
|
2020-02-19 06:15:37 -05:00
|
|
|
})
|
|
|
|
this.CompileManager.clearProject(
|
2021-08-30 07:56:13 -04:00
|
|
|
this.projectId,
|
|
|
|
this.userId,
|
2020-02-19 06:15:37 -05:00
|
|
|
this.callback
|
|
|
|
)
|
2021-08-30 07:56:13 -04:00
|
|
|
this.proc.emit('close', 0)
|
2020-02-19 06:15:37 -05:00
|
|
|
})
|
|
|
|
|
2020-08-10 12:01:11 -04:00
|
|
|
it('should remove the project directory', function () {
|
2021-08-30 07:56:13 -04:00
|
|
|
this.child_process.spawn
|
2020-02-19 06:15:37 -05:00
|
|
|
.calledWith('rm', [
|
|
|
|
'-r',
|
2020-12-16 10:14:18 -05:00
|
|
|
'-f',
|
|
|
|
'--',
|
2021-08-30 07:56:13 -04:00
|
|
|
`${this.Settings.path.compilesDir}/${this.projectId}-${this.userId}`,
|
|
|
|
`${this.Settings.path.outputDir}/${this.projectId}-${this.userId}`,
|
2020-02-19 06:15:37 -05:00
|
|
|
])
|
|
|
|
.should.equal(true)
|
|
|
|
})
|
|
|
|
|
2021-08-30 07:56:13 -04:00
|
|
|
it('should call the callback', function () {
|
|
|
|
this.callback.called.should.equal(true)
|
2020-02-19 06:15:37 -05:00
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2021-08-30 07:56:13 -04:00
|
|
|
describe('with a non-success status code', function () {
|
2020-08-10 12:01:11 -04:00
|
|
|
beforeEach(function () {
|
2020-02-19 06:15:37 -05:00
|
|
|
this.Settings.compileDir = 'compiles'
|
2021-08-30 07:56:13 -04:00
|
|
|
this.fs.lstat.yields(null, {
|
2020-02-19 06:15:37 -05:00
|
|
|
isDirectory() {
|
|
|
|
return true
|
2021-07-13 07:04:48 -04:00
|
|
|
},
|
2020-02-19 06:15:37 -05:00
|
|
|
})
|
|
|
|
this.CompileManager.clearProject(
|
2021-08-30 07:56:13 -04:00
|
|
|
this.projectId,
|
|
|
|
this.userId,
|
2020-02-19 06:15:37 -05:00
|
|
|
this.callback
|
|
|
|
)
|
|
|
|
this.proc.stderr.emit('data', (this.error = 'oops'))
|
2021-08-30 07:56:13 -04:00
|
|
|
this.proc.emit('close', 1)
|
2020-02-19 06:15:37 -05:00
|
|
|
})
|
|
|
|
|
2020-08-10 12:01:11 -04:00
|
|
|
it('should remove the project directory', function () {
|
2021-08-30 07:56:13 -04:00
|
|
|
this.child_process.spawn
|
2020-02-19 06:15:37 -05:00
|
|
|
.calledWith('rm', [
|
|
|
|
'-r',
|
2020-12-16 10:14:18 -05:00
|
|
|
'-f',
|
|
|
|
'--',
|
2021-08-30 07:56:13 -04:00
|
|
|
`${this.Settings.path.compilesDir}/${this.projectId}-${this.userId}`,
|
|
|
|
`${this.Settings.path.outputDir}/${this.projectId}-${this.userId}`,
|
2020-02-19 06:15:37 -05:00
|
|
|
])
|
|
|
|
.should.equal(true)
|
|
|
|
})
|
|
|
|
|
2020-08-10 12:01:11 -04:00
|
|
|
it('should call the callback with an error from the stderr', function () {
|
2020-03-12 05:35:11 -04:00
|
|
|
this.callback.calledWithExactly(sinon.match(Error)).should.equal(true)
|
2020-02-19 06:15:37 -05:00
|
|
|
|
2020-03-12 05:35:11 -04:00
|
|
|
this.callback.args[0][0].message.should.equal(
|
2021-08-30 07:56:13 -04:00
|
|
|
`rm -r ${this.Settings.path.compilesDir}/${this.projectId}-${this.userId} ${this.Settings.path.outputDir}/${this.projectId}-${this.userId} failed: ${this.error}`
|
2020-02-19 06:15:37 -05:00
|
|
|
)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2020-08-10 12:01:11 -04:00
|
|
|
describe('syncing', function () {
|
|
|
|
beforeEach(function () {
|
2020-02-19 06:15:37 -05:00
|
|
|
this.page = 1
|
|
|
|
this.h = 42.23
|
|
|
|
this.v = 87.56
|
|
|
|
this.width = 100.01
|
|
|
|
this.height = 234.56
|
|
|
|
this.line = 5
|
|
|
|
this.column = 3
|
|
|
|
this.file_name = 'main.tex'
|
2021-08-30 07:56:13 -04:00
|
|
|
this.Settings.path.synctexBaseDir = projectId =>
|
|
|
|
`${this.Settings.path.compilesDir}/${this.projectId}-${this.userId}`
|
2020-02-19 06:15:37 -05:00
|
|
|
})
|
|
|
|
|
2020-08-10 12:01:11 -04:00
|
|
|
describe('syncFromCode', function () {
|
|
|
|
beforeEach(function () {
|
2021-08-30 07:56:13 -04:00
|
|
|
this.fs.stat.yields(null, {
|
2020-02-19 06:15:37 -05:00
|
|
|
isFile() {
|
|
|
|
return true
|
2021-07-13 07:04:48 -04:00
|
|
|
},
|
2020-02-19 06:15:37 -05:00
|
|
|
})
|
|
|
|
this.stdout = `NODE\t${this.page}\t${this.h}\t${this.v}\t${this.width}\t${this.height}\n`
|
2021-08-30 07:56:13 -04:00
|
|
|
this.CommandRunner.run.yields(null, { stdout: this.stdout })
|
|
|
|
this.CompileManager.syncFromCode(
|
|
|
|
this.projectId,
|
|
|
|
this.userId,
|
2020-02-19 06:15:37 -05:00
|
|
|
this.file_name,
|
|
|
|
this.line,
|
|
|
|
this.column,
|
2021-03-30 08:22:11 -04:00
|
|
|
'',
|
2020-02-19 06:15:37 -05:00
|
|
|
this.callback
|
|
|
|
)
|
|
|
|
})
|
|
|
|
|
2020-08-10 12:01:11 -04:00
|
|
|
it('should execute the synctex binary', function () {
|
2021-08-30 07:56:13 -04:00
|
|
|
const synctexPath = `${this.Settings.path.compilesDir}/${this.projectId}-${this.userId}/output.pdf`
|
|
|
|
const filePath = `${this.Settings.path.compilesDir}/${this.projectId}-${this.userId}/${this.file_name}`
|
|
|
|
this.CommandRunner.run
|
2020-02-19 06:15:37 -05:00
|
|
|
.calledWith(
|
2021-08-30 07:56:13 -04:00
|
|
|
`${this.projectId}-${this.userId}`,
|
2020-02-19 06:15:37 -05:00
|
|
|
[
|
|
|
|
'/opt/synctex',
|
|
|
|
'code',
|
2021-08-30 07:56:13 -04:00
|
|
|
synctexPath,
|
|
|
|
filePath,
|
2020-02-19 06:15:37 -05:00
|
|
|
this.line,
|
2021-07-13 07:04:48 -04:00
|
|
|
this.column,
|
2020-02-19 06:15:37 -05:00
|
|
|
],
|
2021-08-30 07:56:13 -04:00
|
|
|
`${this.Settings.path.compilesDir}/${this.projectId}-${this.userId}`,
|
2020-02-19 06:15:37 -05:00
|
|
|
this.Settings.clsi.docker.image,
|
|
|
|
60000,
|
|
|
|
{}
|
|
|
|
)
|
|
|
|
.should.equal(true)
|
|
|
|
})
|
|
|
|
|
2021-03-30 08:22:11 -04:00
|
|
|
it('should call the callback with the parsed output', function () {
|
2021-08-30 07:56:13 -04:00
|
|
|
this.callback
|
2020-02-19 06:15:37 -05:00
|
|
|
.calledWith(null, [
|
|
|
|
{
|
|
|
|
page: this.page,
|
|
|
|
h: this.h,
|
|
|
|
v: this.v,
|
|
|
|
height: this.height,
|
2021-07-13 07:04:48 -04:00
|
|
|
width: this.width,
|
|
|
|
},
|
2020-02-19 06:15:37 -05:00
|
|
|
])
|
|
|
|
.should.equal(true)
|
|
|
|
})
|
2021-03-30 08:22:11 -04:00
|
|
|
|
|
|
|
describe('with a custom imageName', function () {
|
|
|
|
const customImageName = 'foo/bar:tag-0'
|
|
|
|
beforeEach(function () {
|
|
|
|
this.CommandRunner.run.reset()
|
|
|
|
this.CompileManager.syncFromCode(
|
2021-08-30 07:56:13 -04:00
|
|
|
this.projectId,
|
|
|
|
this.userId,
|
2021-03-30 08:22:11 -04:00
|
|
|
this.file_name,
|
|
|
|
this.line,
|
|
|
|
this.column,
|
|
|
|
customImageName,
|
|
|
|
this.callback
|
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should execute the synctex binary in a custom docker image', function () {
|
2021-08-30 07:56:13 -04:00
|
|
|
const synctexPath = `${this.Settings.path.compilesDir}/${this.projectId}-${this.userId}/output.pdf`
|
|
|
|
const filePath = `${this.Settings.path.compilesDir}/${this.projectId}-${this.userId}/${this.file_name}`
|
2021-03-30 08:22:11 -04:00
|
|
|
this.CommandRunner.run
|
|
|
|
.calledWith(
|
2021-08-30 07:56:13 -04:00
|
|
|
`${this.projectId}-${this.userId}`,
|
2021-03-30 08:22:11 -04:00
|
|
|
[
|
|
|
|
'/opt/synctex',
|
|
|
|
'code',
|
2021-08-30 07:56:13 -04:00
|
|
|
synctexPath,
|
|
|
|
filePath,
|
2021-03-30 08:22:11 -04:00
|
|
|
this.line,
|
2021-07-13 07:04:48 -04:00
|
|
|
this.column,
|
2021-03-30 08:22:11 -04:00
|
|
|
],
|
2021-08-30 07:56:13 -04:00
|
|
|
`${this.Settings.path.compilesDir}/${this.projectId}-${this.userId}`,
|
2021-03-30 08:22:11 -04:00
|
|
|
customImageName,
|
|
|
|
60000,
|
|
|
|
{}
|
|
|
|
)
|
|
|
|
.should.equal(true)
|
|
|
|
})
|
|
|
|
})
|
2020-02-19 06:15:37 -05:00
|
|
|
})
|
|
|
|
|
2021-08-30 07:56:13 -04:00
|
|
|
describe('syncFromPdf', function () {
|
2020-08-10 12:01:11 -04:00
|
|
|
beforeEach(function () {
|
2021-08-30 07:56:13 -04:00
|
|
|
this.fs.stat.yields(null, {
|
2020-02-19 06:15:37 -05:00
|
|
|
isFile() {
|
|
|
|
return true
|
2021-07-13 07:04:48 -04:00
|
|
|
},
|
2020-02-19 06:15:37 -05:00
|
|
|
})
|
2021-08-30 07:56:13 -04:00
|
|
|
this.stdout = `NODE\t${this.Settings.path.compilesDir}/${this.projectId}-${this.userId}/${this.file_name}\t${this.line}\t${this.column}\n`
|
|
|
|
this.CommandRunner.run.yields(null, { stdout: this.stdout })
|
|
|
|
this.CompileManager.syncFromPdf(
|
|
|
|
this.projectId,
|
|
|
|
this.userId,
|
2020-02-19 06:15:37 -05:00
|
|
|
this.page,
|
|
|
|
this.h,
|
|
|
|
this.v,
|
2021-03-30 08:22:11 -04:00
|
|
|
'',
|
2020-02-19 06:15:37 -05:00
|
|
|
this.callback
|
|
|
|
)
|
|
|
|
})
|
|
|
|
|
2020-08-10 12:01:11 -04:00
|
|
|
it('should execute the synctex binary', function () {
|
2021-08-30 07:56:13 -04:00
|
|
|
const synctexPath = `${this.Settings.path.compilesDir}/${this.projectId}-${this.userId}/output.pdf`
|
|
|
|
this.CommandRunner.run
|
2020-02-19 06:15:37 -05:00
|
|
|
.calledWith(
|
2021-08-30 07:56:13 -04:00
|
|
|
`${this.projectId}-${this.userId}`,
|
|
|
|
['/opt/synctex', 'pdf', synctexPath, this.page, this.h, this.v],
|
|
|
|
`${this.Settings.path.compilesDir}/${this.projectId}-${this.userId}`,
|
2020-02-19 06:15:37 -05:00
|
|
|
this.Settings.clsi.docker.image,
|
|
|
|
60000,
|
|
|
|
{}
|
|
|
|
)
|
|
|
|
.should.equal(true)
|
|
|
|
})
|
|
|
|
|
2021-03-30 08:22:11 -04:00
|
|
|
it('should call the callback with the parsed output', function () {
|
2021-08-30 07:56:13 -04:00
|
|
|
this.callback
|
2020-02-19 06:15:37 -05:00
|
|
|
.calledWith(null, [
|
|
|
|
{
|
|
|
|
file: this.file_name,
|
|
|
|
line: this.line,
|
2021-07-13 07:04:48 -04:00
|
|
|
column: this.column,
|
|
|
|
},
|
2020-02-19 06:15:37 -05:00
|
|
|
])
|
|
|
|
.should.equal(true)
|
|
|
|
})
|
2021-03-30 08:22:11 -04:00
|
|
|
|
|
|
|
describe('with a custom imageName', function () {
|
|
|
|
const customImageName = 'foo/bar:tag-1'
|
|
|
|
beforeEach(function () {
|
|
|
|
this.CommandRunner.run.reset()
|
|
|
|
this.CompileManager.syncFromPdf(
|
2021-08-30 07:56:13 -04:00
|
|
|
this.projectId,
|
|
|
|
this.userId,
|
2021-03-30 08:22:11 -04:00
|
|
|
this.page,
|
|
|
|
this.h,
|
|
|
|
this.v,
|
|
|
|
customImageName,
|
|
|
|
this.callback
|
|
|
|
)
|
|
|
|
})
|
|
|
|
|
|
|
|
it('should execute the synctex binary in a custom docker image', function () {
|
2021-08-30 07:56:13 -04:00
|
|
|
const synctexPath = `${this.Settings.path.compilesDir}/${this.projectId}-${this.userId}/output.pdf`
|
2021-03-30 08:22:11 -04:00
|
|
|
this.CommandRunner.run
|
|
|
|
.calledWith(
|
2021-08-30 07:56:13 -04:00
|
|
|
`${this.projectId}-${this.userId}`,
|
|
|
|
['/opt/synctex', 'pdf', synctexPath, this.page, this.h, this.v],
|
|
|
|
`${this.Settings.path.compilesDir}/${this.projectId}-${this.userId}`,
|
2021-03-30 08:22:11 -04:00
|
|
|
customImageName,
|
|
|
|
60000,
|
|
|
|
{}
|
|
|
|
)
|
|
|
|
.should.equal(true)
|
|
|
|
})
|
|
|
|
})
|
2020-02-19 06:15:37 -05:00
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2021-08-30 07:56:13 -04:00
|
|
|
describe('wordcount', function () {
|
2020-08-10 12:01:11 -04:00
|
|
|
beforeEach(function () {
|
2021-08-30 07:56:13 -04:00
|
|
|
this.stdout = 'Encoding: ascii\nWords in text: 2'
|
|
|
|
this.fs.readFile.yields(null, this.stdout)
|
2020-02-19 06:15:37 -05:00
|
|
|
|
|
|
|
this.timeout = 60 * 1000
|
|
|
|
this.file_name = 'main.tex'
|
|
|
|
this.Settings.path.compilesDir = '/local/compile/directory'
|
|
|
|
this.image = 'example.com/image'
|
|
|
|
|
2021-08-30 07:56:13 -04:00
|
|
|
this.CompileManager.wordcount(
|
|
|
|
this.projectId,
|
|
|
|
this.userId,
|
2020-02-19 06:15:37 -05:00
|
|
|
this.file_name,
|
|
|
|
this.image,
|
|
|
|
this.callback
|
|
|
|
)
|
|
|
|
})
|
|
|
|
|
2020-08-10 12:01:11 -04:00
|
|
|
it('should run the texcount command', function () {
|
2021-08-30 07:56:13 -04:00
|
|
|
this.directory = `${this.Settings.path.compilesDir}/${this.projectId}-${this.userId}`
|
|
|
|
this.filePath = `$COMPILE_DIR/${this.file_name}`
|
2020-02-19 06:15:37 -05:00
|
|
|
this.command = [
|
|
|
|
'texcount',
|
|
|
|
'-nocol',
|
|
|
|
'-inc',
|
2021-08-30 07:56:13 -04:00
|
|
|
this.filePath,
|
|
|
|
`-out=${this.filePath}.wc`,
|
2020-02-19 06:15:37 -05:00
|
|
|
]
|
|
|
|
|
2021-08-30 07:56:13 -04:00
|
|
|
this.CommandRunner.run
|
2020-02-19 06:15:37 -05:00
|
|
|
.calledWith(
|
2021-08-30 07:56:13 -04:00
|
|
|
`${this.projectId}-${this.userId}`,
|
2020-02-19 06:15:37 -05:00
|
|
|
this.command,
|
|
|
|
this.directory,
|
|
|
|
this.image,
|
|
|
|
this.timeout,
|
|
|
|
{}
|
|
|
|
)
|
|
|
|
.should.equal(true)
|
|
|
|
})
|
|
|
|
|
2021-08-30 07:56:13 -04:00
|
|
|
it('should call the callback with the parsed output', function () {
|
|
|
|
this.callback
|
2020-02-19 06:15:37 -05:00
|
|
|
.calledWith(null, {
|
|
|
|
encode: 'ascii',
|
|
|
|
textWords: 2,
|
|
|
|
headWords: 0,
|
|
|
|
outside: 0,
|
|
|
|
headers: 0,
|
|
|
|
elements: 0,
|
|
|
|
mathInline: 0,
|
|
|
|
mathDisplay: 0,
|
|
|
|
errors: 0,
|
2021-07-13 07:04:48 -04:00
|
|
|
messages: '',
|
2020-02-19 06:15:37 -05:00
|
|
|
})
|
|
|
|
.should.equal(true)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
})
|