Merge pull request #166 from overleaf/jpa-port-smoke-test-patch

[misc] simplify the smoke test and process shutdown
This commit is contained in:
Henry Oswald 2020-05-19 10:31:32 +01:00 committed by GitHub
commit b450a6e097
4 changed files with 67 additions and 189 deletions

View file

@ -17,7 +17,7 @@ if ((Settings.sentry != null ? Settings.sentry.dsn : undefined) != null) {
logger.initializeErrorReporting(Settings.sentry.dsn) logger.initializeErrorReporting(Settings.sentry.dsn)
} }
const smokeTest = require('smoke-test-sharelatex') const smokeTest = require('./test/smoke/js/SmokeTests')
const ContentTypeMapper = require('./app/js/ContentTypeMapper') const ContentTypeMapper = require('./app/js/ContentTypeMapper')
const Errors = require('./app/js/Errors') const Errors = require('./app/js/Errors')
@ -192,64 +192,41 @@ app.get('/oops', function(req, res, next) {
app.get('/status', (req, res, next) => res.send('CLSI is alive\n')) app.get('/status', (req, res, next) => res.send('CLSI is alive\n'))
const resCacher = { Settings.processTooOld = false
contentType(setContentType) {
this.setContentType = setContentType
},
send(code, body) {
this.code = code
this.body = body
},
// default the server to be down
code: 500,
body: {},
setContentType: 'application/json'
}
let shutdownTime
if (Settings.processLifespanLimitMs) { if (Settings.processLifespanLimitMs) {
Settings.processLifespanLimitMs += Settings.processLifespanLimitMs +=
Settings.processLifespanLimitMs * (Math.random() / 10) Settings.processLifespanLimitMs * (Math.random() / 10)
shutdownTime = Date.now() + Settings.processLifespanLimitMs logger.info(
logger.info('Lifespan limited to ', shutdownTime) 'Lifespan limited to ',
} Date.now() + Settings.processLifespanLimitMs
)
const checkIfProcessIsTooOld = function(cont) { setTimeout(() => {
if (shutdownTime && shutdownTime < Date.now()) {
logger.log('shutting down, process is too old') logger.log('shutting down, process is too old')
resCacher.send = function() {} Settings.processTooOld = true
resCacher.code = 500 }, Settings.processLifespanLimitMs)
resCacher.body = { processToOld: true }
} else {
cont()
}
} }
if (Settings.smokeTest) { if (Settings.smokeTest) {
const runSmokeTest = function() { function runSmokeTest() {
checkIfProcessIsTooOld(function() { if (Settings.processTooOld) return
logger.log('running smoke tests') logger.log('running smoke tests')
smokeTest.run( smokeTest.triggerRun(err => {
require.resolve(__dirname + '/test/smoke/js/SmokeTests.js') if (err) logger.error({ err }, 'smoke tests failed')
)({}, resCacher) setTimeout(runSmokeTest, 30 * 1000)
return setTimeout(runSmokeTest, 30 * 1000)
}) })
} }
runSmokeTest() runSmokeTest()
} }
app.get('/health_check', function(req, res) { app.get('/health_check', function(req, res) {
res.contentType(resCacher.setContentType) if (Settings.processTooOld) {
return res.status(resCacher.code).send(resCacher.body) return res.status(500).json({ processTooOld: true })
}
smokeTest.sendLastResult(res)
}) })
app.get('/smoke_test_force', (req, res) => app.get('/smoke_test_force', (req, res) => smokeTest.sendNewResult(res))
smokeTest.run(require.resolve(__dirname + '/test/smoke/js/SmokeTests.js'))(
req,
res
)
)
app.use(function(error, req, res, next) { app.use(function(error, req, res, next) {
if (error instanceof Errors.NotFoundError) { if (error instanceof Errors.NotFoundError) {

View file

@ -1669,11 +1669,6 @@
"delayed-stream": "~1.0.0" "delayed-stream": "~1.0.0"
} }
}, },
"commander": {
"version": "2.0.0",
"resolved": "http://registry.npmjs.org/commander/-/commander-2.0.0.tgz",
"integrity": "sha1-0bhvkB+LZL2UG96tr5JFMDk76Sg="
},
"common-tags": { "common-tags": {
"version": "1.8.0", "version": "1.8.0",
"resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.0.tgz", "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.0.tgz",
@ -1878,11 +1873,6 @@
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
"integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups="
}, },
"diff": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/diff/-/diff-1.0.7.tgz",
"integrity": "sha1-JLuwAcSn1VIhaefKvbLCgU7ZHPQ="
},
"diskusage": { "diskusage": {
"version": "1.1.3", "version": "1.1.3",
"resolved": "https://registry.npmjs.org/diskusage/-/diskusage-1.1.3.tgz", "resolved": "https://registry.npmjs.org/diskusage/-/diskusage-1.1.3.tgz",
@ -3066,11 +3056,6 @@
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz",
"integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==" "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ=="
}, },
"growl": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/growl/-/growl-1.7.0.tgz",
"integrity": "sha1-3i1mE20ALhErpw8/EMMc98NQsto="
},
"gtoken": { "gtoken": {
"version": "4.1.0", "version": "4.1.0",
"resolved": "https://registry.npmjs.org/gtoken/-/gtoken-4.1.0.tgz", "resolved": "https://registry.npmjs.org/gtoken/-/gtoken-4.1.0.tgz",
@ -3576,27 +3561,6 @@
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
}, },
"jade": {
"version": "0.26.3",
"resolved": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz",
"integrity": "sha1-jxDXl32NefL2/4YqgbBRPMslaGw=",
"requires": {
"commander": "0.6.1",
"mkdirp": "0.3.0"
},
"dependencies": {
"commander": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz",
"integrity": "sha1-+mihT2qUXVTbvlDYzbMyDp47GgY="
},
"mkdirp": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz",
"integrity": "sha1-G79asbqCevI1dRQ0kEJkVfSB/h4="
}
}
},
"js-tokens": { "js-tokens": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@ -6062,11 +6026,6 @@
"object-inspect": "^1.7.0" "object-inspect": "^1.7.0"
} }
}, },
"sigmund": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz",
"integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA="
},
"signal-exit": { "signal-exit": {
"version": "3.0.2", "version": "3.0.2",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
@ -6129,65 +6088,6 @@
} }
} }
}, },
"smoke-test-sharelatex": {
"version": "git+https://github.com/sharelatex/smoke-test-sharelatex.git#bc3e93d18ccee219c0d99e8b02c984ccdd842e1c",
"from": "git+https://github.com/sharelatex/smoke-test-sharelatex.git#v0.2.0",
"requires": {
"mocha": "~1.17.0"
},
"dependencies": {
"glob": {
"version": "3.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-3.2.3.tgz",
"integrity": "sha1-4xPusknHr/qlxHUoaw4RW1mDlGc=",
"requires": {
"graceful-fs": "~2.0.0",
"inherits": "2",
"minimatch": "~0.2.11"
}
},
"graceful-fs": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz",
"integrity": "sha1-fNLNsiiko/Nule+mzBQt59GhNtA="
},
"lru-cache": {
"version": "2.7.3",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz",
"integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI="
},
"minimatch": {
"version": "0.2.14",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz",
"integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=",
"requires": {
"lru-cache": "2",
"sigmund": "~1.0.0"
}
},
"mocha": {
"version": "1.17.1",
"resolved": "https://registry.npmjs.org/mocha/-/mocha-1.17.1.tgz",
"integrity": "sha1-f3Zx1oUm0HS3uuZgyQmfh+DqHMs=",
"requires": {
"commander": "2.0.0",
"debug": "*",
"diff": "1.0.7",
"glob": "3.2.3",
"growl": "1.7.x",
"jade": "0.26.3",
"mkdirp": "0.3.5"
},
"dependencies": {
"mkdirp": {
"version": "0.3.5",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz",
"integrity": "sha1-3j5fiWHIjHh+4TaN+EmsRBPsqNc="
}
}
}
}
},
"snakecase-keys": { "snakecase-keys": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/snakecase-keys/-/snakecase-keys-3.1.0.tgz", "resolved": "https://registry.npmjs.org/snakecase-keys/-/snakecase-keys-3.1.0.tgz",

View file

@ -34,7 +34,6 @@
"request": "^2.88.2", "request": "^2.88.2",
"sequelize": "^5.21.5", "sequelize": "^5.21.5",
"settings-sharelatex": "git+https://github.com/sharelatex/settings-sharelatex.git#v1.1.0", "settings-sharelatex": "git+https://github.com/sharelatex/settings-sharelatex.git#v1.1.0",
"smoke-test-sharelatex": "git+https://github.com/sharelatex/smoke-test-sharelatex.git#v0.2.0",
"sqlite3": "^4.1.1", "sqlite3": "^4.1.1",
"underscore": "^1.9.2", "underscore": "^1.9.2",
"v8-profiler-node8": "^6.1.1", "v8-profiler-node8": "^6.1.1",

View file

@ -1,20 +1,3 @@
/* eslint-disable
no-unused-vars,
*/
// TODO: This file was created by bulk-decaffeinate.
// Fix any style issues and re-enable lint.
/*
* decaffeinate suggestions:
* DS101: Remove unnecessary use of Array.from
* 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 chai = require('chai')
if (Object.prototype.should == null) {
chai.should()
}
const { expect } = chai
const request = require('request') const request = require('request')
const Settings = require('settings-sharelatex') const Settings = require('settings-sharelatex')
@ -23,9 +6,35 @@ const buildUrl = path =>
const url = buildUrl(`project/smoketest-${process.pid}/compile`) const url = buildUrl(`project/smoketest-${process.pid}/compile`)
describe('Running a compile', function() { module.exports = {
before(function(done) { sendNewResult(res) {
return request.post( this._run(error => this._sendResponse(res, error))
},
sendLastResult(res) {
this._sendResponse(res, this._lastError)
},
triggerRun(cb) {
this._run(error => {
this._lastError = error
cb(error)
})
},
_lastError: new Error('SmokeTestsPending'),
_sendResponse(res, error) {
let code, body
if (error) {
code = 500
body = error.message
} else {
code = 200
body = 'OK'
}
res.contentType('text/plain')
res.status(code).send(body)
},
_run(done) {
request.post(
{ {
url, url,
json: { json: {
@ -72,29 +81,22 @@ describe('Running a compile', function() {
} }
}, },
(error, response, body) => { (error, response, body) => {
this.error = error if (error) return done(error)
this.response = response if (!body || !body.compile || !body.compile.outputFiles) {
this.body = body return done(new Error('response payload incomplete'))
return done() }
let pdfFound = false
let logFound = false
for (const file of body.compile.outputFiles) {
if (file.type === 'pdf') pdfFound = true
if (file.type === 'log') logFound = true
}
if (!pdfFound) return done(new Error('no pdf returned'))
if (!logFound) return done(new Error('no log returned'))
done()
} }
) )
})
it('should return the pdf', function() {
for (const file of Array.from(this.body.compile.outputFiles)) {
if (file.type === 'pdf') {
return
} }
} }
throw new Error('no pdf returned')
})
return it('should return the log', function() {
for (const file of Array.from(this.body.compile.outputFiles)) {
if (file.type === 'log') {
return
}
}
throw new Error('no log returned')
})
})