overleaf/services/filestore/test/unit/js/SafeExecTests.js

111 lines
3.1 KiB
JavaScript
Raw Normal View History

const chai = require('chai')
const should = chai.should()
const { expect } = chai
2019-12-18 05:01:59 -05:00
const modulePath = '../../../app/js/SafeExec'
const { Errors } = require('@overleaf/object-persistor')
const SandboxedModule = require('sandboxed-module')
2020-08-10 12:01:12 -04:00
describe('SafeExec', function () {
2019-12-18 05:01:59 -05:00
let settings, options, safeExec
2020-08-10 12:01:12 -04:00
beforeEach(function () {
2019-12-18 05:01:59 -05:00
settings = { enableConversions: true }
options = { timeout: 10 * 1000, killSignal: 'SIGTERM' }
const ObjectPersistor = { Errors }
2019-12-18 05:01:59 -05:00
safeExec = SandboxedModule.require(modulePath, {
globals: { process },
requires: {
'settings-sharelatex': settings,
'@overleaf/object-persistor': ObjectPersistor
}
})
})
2020-08-10 12:01:12 -04:00
describe('safeExec', function () {
it('should execute a valid command', function (done) {
2019-12-18 05:01:59 -05:00
safeExec(['/bin/echo', 'hello'], options, (err, stdout, stderr) => {
stdout.should.equal('hello\n')
stderr.should.equal('')
should.not.exist(err)
done()
})
})
2020-08-10 12:01:12 -04:00
it('should error when conversions are disabled', function (done) {
2019-12-18 05:01:59 -05:00
settings.enableConversions = false
2020-08-10 12:01:12 -04:00
safeExec(['/bin/echo', 'hello'], options, (err) => {
2019-12-18 05:01:59 -05:00
expect(err).to.exist
done()
})
})
2020-08-10 12:01:12 -04:00
it('should execute a command with non-zero exit status', function (done) {
safeExec(['/usr/bin/env', 'false'], options, (err) => {
2019-12-18 05:01:59 -05:00
expect(err).to.exist
expect(err.name).to.equal('FailedCommandError')
expect(err.code).to.equal(1)
expect(err.stdout).to.equal('')
expect(err.stderr).to.equal('')
done()
})
})
2020-08-10 12:01:12 -04:00
it('should handle an invalid command', function (done) {
safeExec(['/bin/foobar'], options, (err) => {
2019-12-18 05:01:59 -05:00
err.code.should.equal('ENOENT')
done()
})
})
2020-08-10 12:01:12 -04:00
it('should handle a command that runs too long', function (done) {
2019-12-18 05:01:59 -05:00
safeExec(
['/bin/sleep', '10'],
{ timeout: 500, killSignal: 'SIGTERM' },
2020-08-10 12:01:12 -04:00
(err) => {
2019-12-18 05:01:59 -05:00
expect(err).to.exist
expect(err.name).to.equal('FailedCommandError')
expect(err.code).to.equal('SIGTERM')
done()
}
)
})
})
2019-12-18 05:01:59 -05:00
2020-08-10 12:01:12 -04:00
describe('as a promise', function () {
beforeEach(function () {
2019-12-18 05:01:59 -05:00
safeExec = safeExec.promises
})
2020-08-10 12:01:12 -04:00
it('should execute a valid command', async function () {
2019-12-18 05:01:59 -05:00
const { stdout, stderr } = await safeExec(['/bin/echo', 'hello'], options)
stdout.should.equal('hello\n')
stderr.should.equal('')
})
2020-08-10 12:01:12 -04:00
it('should throw a ConversionsDisabledError when appropriate', async function () {
2019-12-18 05:01:59 -05:00
settings.enableConversions = false
try {
await safeExec(['/bin/echo', 'hello'], options)
} catch (err) {
expect(err.name).to.equal('ConversionsDisabledError')
return
}
expect('method did not throw an error').not.to.exist
})
2020-08-10 12:01:12 -04:00
it('should throw a FailedCommandError when appropriate', async function () {
2019-12-18 05:01:59 -05:00
try {
await safeExec(['/usr/bin/env', 'false'], options)
} catch (err) {
expect(err.name).to.equal('FailedCommandError')
expect(err.code).to.equal(1)
return
}
expect('method did not throw an error').not.to.exist
})
})
})