service-core/test/application.run.test.mjs

315 lines
11 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(200); 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.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.ctx.version, '')
assert.strictEqual(app.fresh, true)
let err = await assert.isRejected(app.runVersion('static'))
assert.strictEqual(app.fresh, false)
assert.strictEqual(app.ctx.version, '')
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.ctx.version, '')
assert.strictEqual(app.fresh, true)
let err = await assert.isRejected(app.runVersion('static'))
assert.strictEqual(app.fresh, false)
assert.strictEqual(app.ctx.version, '')
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.ctx.version, '')
assert.strictEqual(app.fresh, true)
await app.runVersion('static')
assert.strictEqual(app.fresh, false)
assert.strictEqual(app.ctx.version, 'static')
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.config.heartbeatAttemptsWait = 5
app.registerModule(defaultHandler(handler))
assert.strictEqual(app.ctx.version, '')
assert.strictEqual(app.fresh, true)
let err = await assert.isRejected(app.runVersion('static'))
assert.strictEqual(app.fresh, false)
assert.strictEqual(app.ctx.version, '')
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.heartbeatTimeout = 30
app.config.heartbeatAttemptsWait = 10
app.registerModule(defaultHandler(handler))
assert.strictEqual(app.ctx.version, '')
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.strictEqual(app.ctx.version, '')
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.heartbeatTimeout + 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.config.heartbeatAttemptsWait = 5
app.registerModule(defaultHandler(handler))
assert.strictEqual(app.ctx.version, '')
let err = await assert.isRejected(app.runVersion('static'))
assert.match(err.message, /failed/i)
assert.match(err.message, /400/i)
assert.strictEqual(app.ctx.version, '')
await app.closeServer()
app.registerModule(defaultHandler(handler))
app.config.heartbeatPath = assertPath
await app.runVersion('static')
assert.strictEqual(ctx.db.data.core.testapp.active, 'static')
})
t.test('should not check heartbeat if slave', async function() {
let called = 0
const handler = function(req, res) {
called++
res.statusCode = 400
res.end(JSON.stringify({ a: 1 }))
}
app.registerModule(defaultHandler(handler))
app.isSlave = true
assert.strictEqual(app.ctx.version, '')
assert.strictEqual(app.fresh, true)
await app.runVersion('static')
assert.strictEqual(app.fresh, false)
assert.strictEqual(app.ctx.version, 'static')
assert.strictEqual(called, 0)
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.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.ctx.version, '')
assert.strictEqual(app.fresh, true)
let err = await assert.isRejected(app.runVersion('v100'))
assert.strictEqual(app.fresh, true)
assert.strictEqual(app.ctx.version, '')
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.ctx.version, '')
assert.strictEqual(app.fresh, true)
let err = await assert.isRejected(app.runVersion('v99'))
assert.strictEqual(app.fresh, false)
assert.strictEqual(app.ctx.version, '')
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.ctx.version, '')
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.version, '')
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.ctx.version, '')
assert.strictEqual(app.fresh, true)
await app.runVersion('v97')
assert.strictEqual(app.fresh, false)
assert.strictEqual(app.ctx.version, 'v97')
assert.ok(app.ctx.log.info.called)
assert.ok(app.ctx.log.event.info.called)
})
})