Jonatan Nilsson
4f4bc8cf6a
All checks were successful
continuous-integration/appveyor/branch AppVeyor build succeeded
271 lines
9.3 KiB
JavaScript
271 lines
9.3 KiB
JavaScript
import { Eltro as t, assert, stub } from 'eltro'
|
|
import fs from 'fs/promises'
|
|
import Application from '../core/application.mjs'
|
|
import Util from '../core/util.mjs'
|
|
import lowdb from '../core/db.mjs'
|
|
import StaticProvider from '../core/providers/static.mjs'
|
|
import { createFakeContext } from './helpers.mjs'
|
|
|
|
const util = new Util(import.meta.url)
|
|
|
|
t.describe('#runVersion("static")', function() {
|
|
const assertPort = 22345
|
|
let ctx
|
|
let app
|
|
|
|
const defaultHandler = function(orgHandler) {
|
|
let handler = orgHandler || function (req, res) {
|
|
res.writeHead(204); res.end(JSON.stringify({ a: 1 }))
|
|
}
|
|
return function(http, port, ctx) {
|
|
const server = http.createServer(handler)
|
|
|
|
return server.listenAsync(port)
|
|
}
|
|
}
|
|
|
|
t.beforeEach(function() {
|
|
return createFakeContext()
|
|
.then(function(res) {
|
|
ctx = res
|
|
let provider = new StaticProvider()
|
|
app = new Application(ctx, provider, 'testapp')
|
|
app.config.port = assertPort
|
|
app.registerModule(defaultHandler())
|
|
})
|
|
})
|
|
|
|
t.afterEach(function() {
|
|
return app.http.closeServer()
|
|
})
|
|
|
|
t.test('should throw if http is not called', async function() {
|
|
app.registerModule(function(checkHttp, checkPort, checkCtx) {
|
|
assert.strictEqual(checkHttp, app.http)
|
|
assert.strictEqual(checkPort, assertPort)
|
|
assert.strictEqual(checkCtx.db, ctx.db)
|
|
assert.strictEqual(checkCtx.log, ctx.log)
|
|
assert.strictEqual(checkCtx.app, app)
|
|
})
|
|
|
|
assert.strictEqual(app.fresh, true)
|
|
let err = await assert.isRejected(app.runVersion('static'))
|
|
assert.strictEqual(app.fresh, false)
|
|
|
|
assert.match(err.message, /http/i)
|
|
assert.match(err.message, /createServer/i)
|
|
assert.match(err.message, /call/i)
|
|
assert.strictEqual(ctx.db.data.core.testapp.active, 'static')
|
|
})
|
|
|
|
t.test('should throw if it timeouts waiting for promise to succeed', async function() {
|
|
app.config.startWaitUntilFail = 50
|
|
app.registerModule(function() { return new Promise(function() {}) })
|
|
|
|
assert.strictEqual(app.fresh, true)
|
|
let err = await assert.isRejected(app.runVersion('static'))
|
|
assert.strictEqual(app.fresh, false)
|
|
|
|
assert.match(err.message, /time/i)
|
|
assert.match(err.message, /out/i)
|
|
assert.match(err.message, /50ms/)
|
|
assert.strictEqual(ctx.db.data.core.testapp.active, 'static')
|
|
})
|
|
|
|
t.test('should otherwise succeed if it finished within the time limit', async function() {
|
|
const handler = defaultHandler()
|
|
app.config.startWaitUntilFail = 250
|
|
app.registerModule(function(http, port, ctx) {
|
|
return new Promise(function(res) {
|
|
setTimeout(res, 25)
|
|
}).then(function() {
|
|
return handler(http, port, ctx)
|
|
})
|
|
})
|
|
|
|
assert.strictEqual(app.fresh, true)
|
|
await app.runVersion('static')
|
|
assert.strictEqual(app.fresh, false)
|
|
|
|
assert.strictEqual(ctx.db.data.core.testapp.active, 'static')
|
|
})
|
|
|
|
t.test('should fail if run succeeds but heartbeat errors', async function() {
|
|
let called = 0
|
|
const handler = function(req, res) {
|
|
called++
|
|
res.statusCode = 400
|
|
res.end(JSON.stringify({ a: 1 }))
|
|
}
|
|
app.config.heartbeatAttempts = 3
|
|
app.registerModule(defaultHandler(handler))
|
|
|
|
assert.strictEqual(app.fresh, true)
|
|
let err = await assert.isRejected(app.runVersion('static'))
|
|
assert.strictEqual(app.fresh, false)
|
|
|
|
assert.match(err.message, /failed/i)
|
|
assert.match(err.message, /400/i)
|
|
assert.strictEqual(called, 3)
|
|
assert.strictEqual(ctx.db.data.core.testapp.active, 'static')
|
|
})
|
|
|
|
t.test('should fail if run succeeds but heartbeat times out', async function() {
|
|
let called = 0
|
|
const handler = function(req, res) {
|
|
called++
|
|
}
|
|
app.config.heartbeatAttempts = 2
|
|
app.config.heartbeatAttemptsWait = 30
|
|
app.registerModule(defaultHandler(handler))
|
|
|
|
assert.strictEqual(app.fresh, true)
|
|
let start = performance.now()
|
|
let err = await assert.isRejected(app.runVersion('static'))
|
|
let end = performance.now()
|
|
assert.strictEqual(app.fresh, false)
|
|
|
|
assert.match(err.message, /failed/i)
|
|
assert.match(err.message, /time/i)
|
|
assert.match(err.message, /out/i)
|
|
assert.match(err.message, /30ms/i)
|
|
assert.ok(end - start > app.config.heartbeatAttempts * app.config.heartbeatAttemptsWait)
|
|
assert.strictEqual(called, 2)
|
|
assert.strictEqual(ctx.db.data.core.testapp.active, 'static')
|
|
})
|
|
|
|
t.test('should call with correct path', async function() {
|
|
const assertPath = '/test/something'
|
|
const handler = function(req, res) {
|
|
if (req.url === assertPath) {
|
|
res.writeHead(204); res.end(JSON.stringify({ a: 1 }))
|
|
} else {
|
|
res.statusCode = 400
|
|
res.end(JSON.stringify({ a: 1 }))
|
|
}
|
|
}
|
|
app.config.heartbeatAttempts = 3
|
|
app.registerModule(defaultHandler(handler))
|
|
|
|
let err = await assert.isRejected(app.runVersion('static'))
|
|
assert.match(err.message, /failed/i)
|
|
assert.match(err.message, /400/i)
|
|
|
|
await app.http.closeServer()
|
|
app.registerModule(defaultHandler(handler))
|
|
|
|
app.config.heartbeatPath = assertPath
|
|
await app.runVersion('static')
|
|
|
|
assert.strictEqual(ctx.db.data.core.testapp.active, 'static')
|
|
})
|
|
})
|
|
|
|
t.describe('#runVersion("version")', function() {
|
|
const assertConfig = util.getPathFromRoot('./db_test_applicationrun.json')
|
|
const assertPort = 22345
|
|
let ctx
|
|
let app
|
|
|
|
t.after(function() {
|
|
return Promise.all([
|
|
fs.rm(util.getPathFromRoot('./testnoexisting/v100'), { force: true, recursive: true }),
|
|
fs.rm(util.getPathFromRoot('./testnoexisting/v99'), { force: true, recursive: true }),
|
|
fs.rm(util.getPathFromRoot('./testnoexisting/v98'), { force: true, recursive: true }),
|
|
fs.rm(util.getPathFromRoot('./testnoexisting/v97'), { force: true, recursive: true }),
|
|
])
|
|
})
|
|
|
|
t.beforeEach(function() {
|
|
return createFakeContext({ }, util, assertConfig)
|
|
.then(function(res) {
|
|
ctx = res
|
|
let provider = new StaticProvider()
|
|
app = new Application(ctx, provider, 'testnoexisting')
|
|
app.config.port = assertPort
|
|
return app.ctx.db.write()
|
|
})
|
|
})
|
|
|
|
t.afterEach(function() {
|
|
return Promise.all([
|
|
fs.rm(assertConfig),
|
|
app.http.closeServer(),
|
|
])
|
|
})
|
|
|
|
t.test('when version is specified, should check if index.mjs exists', async function() {
|
|
const assertNotError = new Error('AI DO')
|
|
const assertTarget = util.getPathFromRoot('./testnoexisting/v100/index.mjs')
|
|
let stubFsStat = stub()
|
|
let provider = new StaticProvider()
|
|
app = new Application(ctx, provider, 'testnoexisting', {
|
|
fs: { stat: stubFsStat }
|
|
})
|
|
app.config.port = assertPort
|
|
stubFsStat.rejects(assertNotError)
|
|
|
|
assert.strictEqual(app.fresh, true)
|
|
let err = await assert.isRejected(app.runVersion('v100'))
|
|
assert.strictEqual(app.fresh, true)
|
|
|
|
assert.notStrictEqual(err, assertNotError)
|
|
assert.match(err.message, new RegExp(assertNotError.message))
|
|
assert.match(err.message, /index\.mjs/i)
|
|
assert.match(err.message, /missing/i)
|
|
assert.strictEqual(stubFsStat.firstCall[0], assertTarget)
|
|
|
|
assert.strictEqual(app.ctx.db.data.core.testnoexisting.active, 'v100')
|
|
let checkDb = await lowdb({}, ctx.log, assertConfig)
|
|
assert.strictEqual(checkDb.data.core.testnoexisting.active, 'v100')
|
|
})
|
|
|
|
t.test('when version is specified and file exists, should attempt to load module', async function() {
|
|
const assertError = new Error('Parallel Days')
|
|
await fs.mkdir(util.getPathFromRoot('./testnoexisting/v99'), { recursive: true })
|
|
await fs.writeFile(util.getPathFromRoot('./testnoexisting/v99/index.mjs'), `throw new Error('${assertError.message}')`)
|
|
|
|
assert.strictEqual(app.fresh, true)
|
|
let err = await assert.isRejected(app.runVersion('v99'))
|
|
assert.strictEqual(app.fresh, false)
|
|
|
|
assert.notStrictEqual(err, assertError)
|
|
assert.strictEqual(err.message, assertError.message)
|
|
|
|
assert.strictEqual(app.ctx.db.data.core.testnoexisting.active, 'v99')
|
|
let checkDb = await lowdb({}, ctx.log, assertConfig)
|
|
assert.strictEqual(checkDb.data.core.testnoexisting.active, 'v99')
|
|
})
|
|
|
|
t.test('when version is specified and file exists, should check if it has start', async function() {
|
|
await fs.mkdir(util.getPathFromRoot('./testnoexisting/v98'), { recursive: true })
|
|
await fs.writeFile(util.getPathFromRoot('./testnoexisting/v98/index.mjs'), ``)
|
|
|
|
assert.strictEqual(app.fresh, true)
|
|
let err = await assert.isRejected(app.runVersion('v98'))
|
|
assert.strictEqual(app.fresh, false)
|
|
assert.match(err.message, /start/i)
|
|
|
|
assert.strictEqual(app.ctx.db.data.core.testnoexisting.active, 'v98')
|
|
let checkDb = await lowdb({}, ctx.log, assertConfig)
|
|
assert.strictEqual(checkDb.data.core.testnoexisting.active, 'v98')
|
|
})
|
|
|
|
t.test('when version is specified and file exists and everything is okay, should work normally', async function() {
|
|
await fs.mkdir(util.getPathFromRoot('./testnoexisting/v97'), { recursive: true })
|
|
await fs.copyFile(
|
|
util.getPathFromRoot('./exampleindex.mjs'),
|
|
util.getPathFromRoot('./testnoexisting/v97/index.mjs')
|
|
)
|
|
|
|
app.ctx.log.info.reset()
|
|
app.ctx.log.event.info.reset()
|
|
|
|
assert.strictEqual(app.fresh, true)
|
|
await app.runVersion('v97')
|
|
assert.strictEqual(app.fresh, false)
|
|
|
|
assert.ok(app.ctx.log.info.called)
|
|
assert.ok(app.ctx.log.event.info.called)
|
|
})
|
|
})
|