Updated core logic and how stable is calculated.
Some checks failed
continuous-integration/appveyor/branch AppVeyor build failed
Some checks failed
continuous-integration/appveyor/branch AppVeyor build failed
Fixed some minor bugs. Will now no longer travel through history but instead stop at last stable version.
This commit is contained in:
parent
57be8a144a
commit
47344c5e7a
10 changed files with 185 additions and 95 deletions
|
@ -19,13 +19,13 @@ export function request(config, path, filePath = null, redirects, fastRaw = fals
|
||||||
}
|
}
|
||||||
let newRedirects = (redirects || 0) + 1
|
let newRedirects = (redirects || 0) + 1
|
||||||
if (!path || typeof(path) !== 'string' || !path.startsWith('http')) {
|
if (!path || typeof(path) !== 'string' || !path.startsWith('http')) {
|
||||||
return Promise.reject(new Error('URL was empty or invalid'))
|
return Promise.reject(new Error('URL was empty or invalid' + (typeof(path) === 'string' ? ': ' + path : '')))
|
||||||
}
|
}
|
||||||
let parsed
|
let parsed
|
||||||
try {
|
try {
|
||||||
parsed = new URL(path)
|
parsed = new URL(path)
|
||||||
} catch {
|
} catch {
|
||||||
return Promise.reject(new Error('URL was empty or invalid'))
|
return Promise.reject(new Error('URL was empty or invalid: ' + path))
|
||||||
}
|
}
|
||||||
|
|
||||||
let h = http
|
let h = http
|
||||||
|
|
|
@ -22,7 +22,7 @@ export default class Core {
|
||||||
Core.providers.set(name, provider)
|
Core.providers.set(name, provider)
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(db, util, log) {
|
constructor(db, util, log, restart = function() {}) {
|
||||||
// some sanity checks
|
// some sanity checks
|
||||||
if (!log || typeof(log) !== 'object') throw new Error('log parameter was invalid')
|
if (!log || typeof(log) !== 'object') throw new Error('log parameter was invalid')
|
||||||
if (typeof(log.event) !== 'object') throw new Error('log parameter was invalid')
|
if (typeof(log.event) !== 'object') throw new Error('log parameter was invalid')
|
||||||
|
@ -34,11 +34,13 @@ export default class Core {
|
||||||
|| typeof(log.event.error) !== 'function') throw new Error('log parameter was invalid')
|
|| typeof(log.event.error) !== 'function') throw new Error('log parameter was invalid')
|
||||||
if (!util || !(util instanceof Util)) throw new Error('util not instance of Util')
|
if (!util || !(util instanceof Util)) throw new Error('util not instance of Util')
|
||||||
if (!db || !(db instanceof Low)) throw new Error('db not instance of Low')
|
if (!db || !(db instanceof Low)) throw new Error('db not instance of Low')
|
||||||
|
if (typeof(restart) !== 'function') throw new Error('restart was not a function')
|
||||||
|
|
||||||
this.running = false
|
this.running = false
|
||||||
this.db = db
|
this.db = db
|
||||||
this.util = util
|
this.util = util
|
||||||
this.log = log
|
this.log = log
|
||||||
|
this.restart = restart
|
||||||
this.applications = []
|
this.applications = []
|
||||||
this.applicationMap = new Map()
|
this.applicationMap = new Map()
|
||||||
this._applicationFatalCrash = null
|
this._applicationFatalCrash = null
|
||||||
|
@ -130,12 +132,17 @@ export default class Core {
|
||||||
for (let i = 0; i < this.db.data.core[name].versions.length; i++) {
|
for (let i = 0; i < this.db.data.core[name].versions.length; i++) {
|
||||||
let version = this.db.data.core[name].versions[i]
|
let version = this.db.data.core[name].versions[i]
|
||||||
if (!version.installed || version.stable < -1) continue
|
if (!version.installed || version.stable < -1) continue
|
||||||
if (version.stable < 0 && !application.fresh) continue
|
if (version.stable < 0 && !application.fresh) {
|
||||||
|
application.ctx.log.warn(`Restarting for ${version.version} due to last run failing while not being in fresh state`)
|
||||||
|
return this.restart(`Application ${name} has fresh false while attempting to run ${version.version} with stable -1`)
|
||||||
|
}
|
||||||
await application.closeServer()
|
await application.closeServer()
|
||||||
|
|
||||||
this._applicationFatalCrash = this.criticalError.bind(this, application, version)
|
this._applicationFatalCrash = this.criticalError.bind(this, application, version)
|
||||||
process.once('exit', this._applicationFatalCrash)
|
process.once('exit', this._applicationFatalCrash)
|
||||||
|
|
||||||
|
let wasFresh = application.fresh
|
||||||
|
|
||||||
try {
|
try {
|
||||||
application.ctx.log.info(`Attempting to run version ${version.version}`)
|
application.ctx.log.info(`Attempting to run version ${version.version}`)
|
||||||
await application.runVersion(version.version)
|
await application.runVersion(version.version)
|
||||||
|
@ -144,13 +151,23 @@ export default class Core {
|
||||||
await this.db.write()
|
await this.db.write()
|
||||||
break
|
break
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
if (application.fresh) {
|
|
||||||
version.stable = -2
|
|
||||||
} else {
|
|
||||||
version.stable = Math.min(version.stable, 0) - 1
|
|
||||||
}
|
|
||||||
await this.db.write()
|
|
||||||
application.ctx.log.error(err, `Error starting ${version.version}: ${err.message}`)
|
application.ctx.log.error(err, `Error starting ${version.version}: ${err.message}`)
|
||||||
|
process.off('exit', this._applicationFatalCrash)
|
||||||
|
|
||||||
|
if (version.stable < 1) {
|
||||||
|
if (wasFresh) {
|
||||||
|
version.stable = -2
|
||||||
|
} else {
|
||||||
|
version.stable = -1
|
||||||
|
}
|
||||||
|
await this.db.write()
|
||||||
|
if (version.stable === -1) {
|
||||||
|
return this.restart(`Application ${name} version ${version.version} failed to start but application was dirty, check if restarting fixes it`)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
await this.db.write()
|
||||||
|
return this.restart(`Application ${name} version ${version.version} previously stable but now failing`)
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
process.off('exit', this._applicationFatalCrash)
|
process.off('exit', this._applicationFatalCrash)
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,8 +25,7 @@ export default class GitProvider {
|
||||||
checked++
|
checked++
|
||||||
|
|
||||||
for (let asset of item.assets) {
|
for (let asset of item.assets) {
|
||||||
if (!asset.name.endsWith('-sc.7z')
|
if (!asset.name.endsWith('-sc.7z')) continue
|
||||||
&& !asset.name.endsWith('-sc.zip')) continue
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
version: item.name,
|
version: item.name,
|
||||||
|
|
|
@ -26,7 +26,14 @@ export async function runner(root_import_meta_url, configname = 'config.json', d
|
||||||
runner.log = log
|
runner.log = log
|
||||||
const db = await GetDB(config, log, util.getPathFromRoot('./' + dbname))
|
const db = await GetDB(config, log, util.getPathFromRoot('./' + dbname))
|
||||||
|
|
||||||
const core = new Core(db, util, log)
|
const core = new Core(db, util, log, function(msg) {
|
||||||
|
if (msg) {
|
||||||
|
runner.log.warn('Got a restart request: ' + msg)
|
||||||
|
} else {
|
||||||
|
runner.log.warn('Got a restart request with no message or reason')
|
||||||
|
}
|
||||||
|
process.exit(1)
|
||||||
|
})
|
||||||
await core.init()
|
await core.init()
|
||||||
await core.run()
|
await core.run()
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@ t.timeout(10000).test('should run update and install correctly', async function(
|
||||||
try {
|
try {
|
||||||
await app.update()
|
await app.update()
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
console.log()
|
||||||
console.log(err)
|
console.log(err)
|
||||||
if (ctx.db.data.core.testapp.versions.length) {
|
if (ctx.db.data.core.testapp.versions.length) {
|
||||||
console.log(ctx.db.data.core.testapp.versions[0].log)
|
console.log(ctx.db.data.core.testapp.versions[0].log)
|
||||||
|
|
|
@ -51,17 +51,20 @@ t.describe('Basics', function() {
|
||||||
})
|
})
|
||||||
|
|
||||||
t.test('should fail if url is invalid', async function() {
|
t.test('should fail if url is invalid', async function() {
|
||||||
function checkError(err) {
|
function checkError(check, err) {
|
||||||
assert.match(err.message, /invalid/i)
|
assert.match(err.message, /invalid/i)
|
||||||
assert.match(err.message, /url/i)
|
assert.match(err.message, /url/i)
|
||||||
|
if (check) {
|
||||||
|
assert.match(err.message, new RegExp(check))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await assert.isRejected(request({}, 123)).then(checkError)
|
await assert.isRejected(request({}, 123)).then(checkError.bind(this, null))
|
||||||
await assert.isRejected(request({}, [])).then(checkError)
|
await assert.isRejected(request({}, [])).then(checkError.bind(this, null))
|
||||||
await assert.isRejected(request({}, {})).then(checkError)
|
await assert.isRejected(request({}, {})).then(checkError.bind(this, null))
|
||||||
await assert.isRejected(request({}, '')).then(checkError)
|
await assert.isRejected(request({}, '')).then(checkError.bind(this, null))
|
||||||
await assert.isRejected(request({}, 'asdf')).then(checkError)
|
await assert.isRejected(request({}, 'asdf')).then(checkError.bind(this, 'asdf'))
|
||||||
await assert.isRejected(request({}, 'httpppp')).then(checkError)
|
await assert.isRejected(request({}, 'httpppp')).then(checkError.bind(this, 'httpppp'))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -151,12 +151,15 @@ t.timeout(10000).describe('', function() {
|
||||||
|
|
||||||
|
|
||||||
let logIndex = 0
|
let logIndex = 0
|
||||||
function catchupLog() {
|
function catchupLog(ms = 0) {
|
||||||
if (logs.length > logIndex) {
|
if (logs.length > logIndex) {
|
||||||
for (; logIndex < logs.length; logIndex++) {
|
for (; logIndex < logs.length; logIndex++) {
|
||||||
prettyPrintMessage(logs[logIndex])
|
prettyPrintMessage(logs[logIndex])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (ms > 0) {
|
||||||
|
return setTimeout(ms)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
integrationLog.on('newlog', function(record) {
|
integrationLog.on('newlog', function(record) {
|
||||||
|
@ -195,11 +198,14 @@ t.timeout(10000).describe('', function() {
|
||||||
let listeningLine = null
|
let listeningLine = null
|
||||||
while (processor.exitCode == null
|
while (processor.exitCode == null
|
||||||
&& !hasLogLine((rec) => { listeningLine = rec; return rec.listening && rec.port })) {
|
&& !hasLogLine((rec) => { listeningLine = rec; return rec.listening && rec.port })) {
|
||||||
catchupLog()
|
await catchupLog(10)
|
||||||
await setTimeout(10)
|
|
||||||
}
|
}
|
||||||
catchupLog()
|
catchupLog()
|
||||||
return listeningLine
|
if (listeningLine.listening && listeningLine.port) {
|
||||||
|
return listeningLine
|
||||||
|
} else {
|
||||||
|
return null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function waitUntilClosed(listening) {
|
async function waitUntilClosed(listening) {
|
||||||
|
@ -232,8 +238,7 @@ t.timeout(10000).describe('', function() {
|
||||||
|
|
||||||
|
|
||||||
while (processor.exitCode == null) {
|
while (processor.exitCode == null) {
|
||||||
catchupLog()
|
await catchupLog(10)
|
||||||
await setTimeout(10)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
catchupLog()
|
catchupLog()
|
||||||
|
@ -263,8 +268,7 @@ t.timeout(10000).describe('', function() {
|
||||||
assert.strictEqual(checkListening.body.version, 'v1')
|
assert.strictEqual(checkListening.body.version, 'v1')
|
||||||
|
|
||||||
while (!hasLogLine(/core is running/)) {
|
while (!hasLogLine(/core is running/)) {
|
||||||
catchupLog()
|
await catchupLog(10)
|
||||||
await setTimeout(10)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
catchupLog()
|
catchupLog()
|
||||||
|
@ -288,48 +292,43 @@ t.timeout(10000).describe('', function() {
|
||||||
await setTimeout(500)
|
await setTimeout(500)
|
||||||
|
|
||||||
while (!hasLogLine(/Error starting v2_nolisten/)) {
|
while (!hasLogLine(/Error starting v2_nolisten/)) {
|
||||||
catchupLog()
|
await catchupLog(10)
|
||||||
await setTimeout(10)
|
|
||||||
}
|
}
|
||||||
|
while (!hasLogLine(/restart request.*v2_nolisten.*dirty/)) {
|
||||||
while (!hasLogLine(/Attempting to run version v1_ok/)) {
|
await catchupLog(10)
|
||||||
catchupLog()
|
|
||||||
await setTimeout(10)
|
|
||||||
}
|
}
|
||||||
|
while (processor.exitCode == null) {
|
||||||
while (!hasLogLine(/Server is listening on 31313 serving v1/)) {
|
await catchupLog(10)
|
||||||
catchupLog()
|
|
||||||
await setTimeout(10)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
catchupLog()
|
catchupLog()
|
||||||
|
|
||||||
checkListening = await request({}, `http://localhost:${listening.port}/`)
|
|
||||||
assert.strictEqual(checkListening.body.version, 'v1')
|
|
||||||
|
|
||||||
await setTimeout(10)
|
|
||||||
|
|
||||||
db = JSON.parse(await fs.readFile(util.getPathFromRoot('./db.json')))
|
db = JSON.parse(await fs.readFile(util.getPathFromRoot('./db.json')))
|
||||||
assert.strictEqual(db.core.testapp.active, assertNameVersion1)
|
assert.strictEqual(db.core.testapp.active, assertNameVersion2)
|
||||||
assert.strictEqual(db.core.testapp.versions.length, 2)
|
assert.strictEqual(db.core.testapp.versions.length, 2)
|
||||||
assert.strictEqual(db.core.testapp.versions[0].stable, -1)
|
assert.strictEqual(db.core.testapp.versions[0].stable, -1)
|
||||||
assert.strictEqual(db.core.testapp.versions[0].installed, true)
|
assert.strictEqual(db.core.testapp.versions[0].installed, true)
|
||||||
assert.strictEqual(db.core.testapp.versions[1].stable, 1)
|
assert.strictEqual(db.core.testapp.versions[1].stable, 1)
|
||||||
assert.strictEqual(db.core.testapp.versions[1].installed, true)
|
assert.strictEqual(db.core.testapp.versions[1].installed, true)
|
||||||
|
|
||||||
processor.kill()
|
// Since application was in dirty state, on next attempt should attempt to
|
||||||
// Wait for ports to be marked as closed
|
// run v2 again and then falling back to v1
|
||||||
|
|
||||||
await waitUntilClosed()
|
await waitUntilClosed()
|
||||||
|
|
||||||
processor = startRunner()
|
processor = startRunner()
|
||||||
|
await catchupLog(10)
|
||||||
|
|
||||||
|
while (!hasLogLine(/Attempting to run version v2_nolisten/)) {
|
||||||
|
await catchupLog(10)
|
||||||
|
}
|
||||||
|
while (!hasLogLine(/Attempting to run version v1_ok/)) {
|
||||||
|
await catchupLog(10)
|
||||||
|
}
|
||||||
|
|
||||||
listening = await waitUntilListening()
|
listening = await waitUntilListening()
|
||||||
|
|
||||||
assert.ok(listening)
|
assert.ok(listening)
|
||||||
|
|
||||||
checkListening = await request({}, `http://localhost:${listening.port}/`)
|
checkListening = await request({}, `http://localhost:${listening.port}/`)
|
||||||
assert.strictEqual(checkListening.body.version, 'v1')
|
assert.strictEqual(checkListening.body.version, 'v1')
|
||||||
|
|
||||||
while (!hasLogLine(/core is running/)) {
|
while (!hasLogLine(/core is running/)) {
|
||||||
await setTimeout(10)
|
await setTimeout(10)
|
||||||
}
|
}
|
||||||
|
@ -381,13 +380,11 @@ t.timeout(10000).describe('', function() {
|
||||||
await setTimeout(500)
|
await setTimeout(500)
|
||||||
|
|
||||||
while (!hasLogLine(/Attempting to run version v3_crash/)) {
|
while (!hasLogLine(/Attempting to run version v3_crash/)) {
|
||||||
catchupLog()
|
await catchupLog(10)
|
||||||
await setTimeout(10)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (processor.exitCode == null) {
|
while (processor.exitCode == null) {
|
||||||
catchupLog()
|
await catchupLog(10)
|
||||||
await setTimeout(10)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
db = JSON.parse(await fs.readFile(util.getPathFromRoot('./db.json')))
|
db = JSON.parse(await fs.readFile(util.getPathFromRoot('./db.json')))
|
||||||
|
@ -427,13 +424,11 @@ t.timeout(10000).describe('', function() {
|
||||||
await setTimeout(500)
|
await setTimeout(500)
|
||||||
|
|
||||||
while (!hasLogLine(/Attempting to run version v4_stable/)) {
|
while (!hasLogLine(/Attempting to run version v4_stable/)) {
|
||||||
catchupLog()
|
await catchupLog(10)
|
||||||
await setTimeout(10)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!hasLogLine(/Server is listening on 31313 serving v4/)) {
|
while (!hasLogLine(/Server is listening on 31313 serving v4/)) {
|
||||||
catchupLog()
|
await catchupLog(10)
|
||||||
await setTimeout(10)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
catchupLog()
|
catchupLog()
|
||||||
|
|
|
@ -207,13 +207,36 @@ t.describe('#constructor()', function() {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.test('should throw if restart is not a function', function() {
|
||||||
|
let tests = [
|
||||||
|
[1, 'number'],
|
||||||
|
[0, 'false number'],
|
||||||
|
['asdf', 'string'],
|
||||||
|
['', 'false string'],
|
||||||
|
[[], 'array'],
|
||||||
|
[{}, 'object'],
|
||||||
|
]
|
||||||
|
|
||||||
|
tests.forEach(function(check) {
|
||||||
|
assert.throws(function() {
|
||||||
|
new Core(db, util, log, check[0])
|
||||||
|
}, function(err) {
|
||||||
|
assert.match(err.message, /restart/i)
|
||||||
|
assert.match(err.message, /function/i)
|
||||||
|
return true
|
||||||
|
}, `throw if restart is ${check[1]}`)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
t.test('should accept log, util and close function', function() {
|
t.test('should accept log, util and close function', function() {
|
||||||
const assertLog = log
|
const assertLog = log
|
||||||
|
const assertRestarter = function() { }
|
||||||
|
|
||||||
let core = new Core(db, util, assertLog)
|
let core = new Core(db, util, assertLog, assertRestarter)
|
||||||
assert.strictEqual(core.db, db)
|
assert.strictEqual(core.db, db)
|
||||||
assert.strictEqual(core.util, util)
|
assert.strictEqual(core.util, util)
|
||||||
assert.strictEqual(core.log, assertLog)
|
assert.strictEqual(core.log, assertLog)
|
||||||
|
assert.strictEqual(core.restart, assertRestarter)
|
||||||
assert.deepStrictEqual(core.applications, [])
|
assert.deepStrictEqual(core.applications, [])
|
||||||
assert.ok(core.applicationMap)
|
assert.ok(core.applicationMap)
|
||||||
})
|
})
|
||||||
|
@ -626,6 +649,7 @@ t.describe('#runApplication()', function() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
core = new Core(db, util, log)
|
core = new Core(db, util, log)
|
||||||
|
core.restart = stub()
|
||||||
db.write = stubWrite = stub().resolves()
|
db.write = stubWrite = stub().resolves()
|
||||||
log.info.reset()
|
log.info.reset()
|
||||||
log.warn.reset()
|
log.warn.reset()
|
||||||
|
@ -667,6 +691,7 @@ t.describe('#runApplication()', function() {
|
||||||
const assertVersion = 'v50'
|
const assertVersion = 'v50'
|
||||||
const assertError = new Error('jellyfish')
|
const assertError = new Error('jellyfish')
|
||||||
testApp.runVersion.rejects(assertError)
|
testApp.runVersion.rejects(assertError)
|
||||||
|
testApp.fresh = true
|
||||||
db.data.core[testAppName].versions.push({
|
db.data.core[testAppName].versions.push({
|
||||||
id: assertVersion,
|
id: assertVersion,
|
||||||
version: assertVersion + 'asdf',
|
version: assertVersion + 'asdf',
|
||||||
|
@ -690,6 +715,7 @@ t.describe('#runApplication()', function() {
|
||||||
t.test('should skip versions that have not been installed or high error', async function() {
|
t.test('should skip versions that have not been installed or high error', async function() {
|
||||||
const assertError = new Error('Daikichi to Rin')
|
const assertError = new Error('Daikichi to Rin')
|
||||||
testApp.runVersion.rejects(assertError)
|
testApp.runVersion.rejects(assertError)
|
||||||
|
testApp.fresh = true
|
||||||
db.data.core[testAppName].versions.push({
|
db.data.core[testAppName].versions.push({
|
||||||
id: '40',
|
id: '40',
|
||||||
version: 'v40',
|
version: 'v40',
|
||||||
|
@ -721,7 +747,10 @@ t.describe('#runApplication()', function() {
|
||||||
|
|
||||||
t.test('should attempt to run version with stable of -1 if fresh is true', async function() {
|
t.test('should attempt to run version with stable of -1 if fresh is true', async function() {
|
||||||
const assertError = new Error('Daikichi to Rin')
|
const assertError = new Error('Daikichi to Rin')
|
||||||
testApp.runVersion.rejects(assertError)
|
testApp.runVersion.returnWith(function() {
|
||||||
|
testApp.fresh = false
|
||||||
|
return Promise.reject(assertError)
|
||||||
|
})
|
||||||
testApp.fresh = true
|
testApp.fresh = true
|
||||||
db.data.core[testAppName].versions.push({
|
db.data.core[testAppName].versions.push({
|
||||||
id: '30',
|
id: '30',
|
||||||
|
@ -740,8 +769,7 @@ t.describe('#runApplication()', function() {
|
||||||
stable: 0,
|
stable: 0,
|
||||||
}, )
|
}, )
|
||||||
|
|
||||||
let err = await assert.isRejected(core.runApplication(testApp))
|
await core.runApplication(testApp)
|
||||||
assert.notStrictEqual(err, assertError)
|
|
||||||
assert.notOk(log.error.called)
|
assert.notOk(log.error.called)
|
||||||
assert.ok(testApp.ctx.log.error.called)
|
assert.ok(testApp.ctx.log.error.called)
|
||||||
|
|
||||||
|
@ -751,11 +779,15 @@ t.describe('#runApplication()', function() {
|
||||||
assert.match(testApp.ctx.log.error.firstCall[1], new RegExp(assertError.message))
|
assert.match(testApp.ctx.log.error.firstCall[1], new RegExp(assertError.message))
|
||||||
assert.strict(testApp.runVersion.firstCall[0], '31')
|
assert.strict(testApp.runVersion.firstCall[0], '31')
|
||||||
assert.strict(testApp.runVersion.firstCall[0], '32')
|
assert.strict(testApp.runVersion.firstCall[0], '32')
|
||||||
|
assert.strictEqual(db.data.core[testAppName].versions[1].stable, -2)
|
||||||
|
assert.strictEqual(db.data.core[testAppName].versions[2].stable, -1)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.test('should skip version with stable of -1 if fresh is false', async function() {
|
t.test('should call restart if program crashes and fresh is false', async function() {
|
||||||
const assertError = new Error('Daikichi to Rin')
|
const assertErrorMessage = new Error('Daikichi to Rin')
|
||||||
testApp.runVersion.rejects(assertError)
|
const assertError = new Error('Country Lane')
|
||||||
|
testApp.runVersion.rejects(assertErrorMessage)
|
||||||
|
core.restart.rejects(assertError)
|
||||||
testApp.fresh = false
|
testApp.fresh = false
|
||||||
db.data.core[testAppName].versions.push({
|
db.data.core[testAppName].versions.push({
|
||||||
id: '30',
|
id: '30',
|
||||||
|
@ -775,22 +807,22 @@ t.describe('#runApplication()', function() {
|
||||||
}, )
|
}, )
|
||||||
|
|
||||||
let err = await assert.isRejected(core.runApplication(testApp))
|
let err = await assert.isRejected(core.runApplication(testApp))
|
||||||
assert.notStrictEqual(err, assertError)
|
assert.strictEqual(err, assertError)
|
||||||
assert.notOk(log.error.called)
|
assert.notOk(log.error.called)
|
||||||
assert.ok(testApp.ctx.log.error.called)
|
assert.ok(testApp.ctx.log.error.called)
|
||||||
|
|
||||||
assert.strictEqual(testApp.ctx.log.error.callCount, 2)
|
assert.strictEqual(testApp.ctx.log.error.callCount, 1)
|
||||||
assert.strictEqual(testApp.ctx.log.error.firstCall[0], assertError)
|
assert.strictEqual(testApp.ctx.log.error.firstCall[0], assertErrorMessage)
|
||||||
assert.match(testApp.ctx.log.error.firstCall[1], new RegExp('30'))
|
assert.match(testApp.ctx.log.error.firstCall[1], new RegExp('30'))
|
||||||
assert.match(testApp.ctx.log.error.firstCall[1], new RegExp(assertError.message))
|
assert.match(testApp.ctx.log.error.firstCall[1], new RegExp(assertErrorMessage.message))
|
||||||
assert.strictEqual(testApp.ctx.log.error.secondCall[0], assertError)
|
assert.strictEqual(db.data.core[testAppName].versions[0].stable, -1)
|
||||||
assert.match(testApp.ctx.log.error.secondCall[1], new RegExp('32'))
|
assert.ok(core.restart.called)
|
||||||
assert.match(testApp.ctx.log.error.secondCall[1], new RegExp(assertError.message))
|
assert.match(core.restart.firstCall[0], new RegExp(testAppName))
|
||||||
assert.strict(testApp.runVersion.firstCall[0], '30')
|
assert.match(core.restart.firstCall[0], /v30/)
|
||||||
assert.strict(testApp.runVersion.firstCall[0], '32')
|
assert.match(core.restart.firstCall[0], /dirty/)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.test('should change status accordingly when application is fresh', async function() {
|
t.test('should attempt next non-tested version if fresh is true', async function() {
|
||||||
const assertError = new Error('Daikichi to Rin')
|
const assertError = new Error('Daikichi to Rin')
|
||||||
testApp.runVersion.rejects(assertError)
|
testApp.runVersion.rejects(assertError)
|
||||||
testApp.fresh = true
|
testApp.fresh = true
|
||||||
|
@ -829,9 +861,49 @@ t.describe('#runApplication()', function() {
|
||||||
assert.ok(stubWrite.callCount, 2)
|
assert.ok(stubWrite.callCount, 2)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.test('should always go to -1 minimum on crash', async function() {
|
t.test('should exit immediately if next version is -1 and fresh is false', async function() {
|
||||||
const assertError = new Error('Daikichi to Rin')
|
const assertError = new Error('Daikichi to Rin')
|
||||||
testApp.runVersion.rejects(assertError)
|
core.restart.rejects(assertError)
|
||||||
|
testApp.fresh = false
|
||||||
|
db.data.core[testAppName].versions.push({
|
||||||
|
id: '30',
|
||||||
|
version: 'v30',
|
||||||
|
installed: true,
|
||||||
|
stable: -1,
|
||||||
|
}, {
|
||||||
|
id: '31',
|
||||||
|
version: 'v31',
|
||||||
|
installed: true,
|
||||||
|
stable: 0,
|
||||||
|
}, {
|
||||||
|
id: '32',
|
||||||
|
version: 'v32',
|
||||||
|
installed: true,
|
||||||
|
stable: -2,
|
||||||
|
})
|
||||||
|
|
||||||
|
let err = await assert.isRejected(core.runApplication(testApp))
|
||||||
|
assert.strictEqual(err, assertError)
|
||||||
|
assert.notOk(log.error.called)
|
||||||
|
assert.ok(testApp.ctx.log.warn.called)
|
||||||
|
|
||||||
|
assert.strictEqual(testApp.ctx.log.warn.callCount, 1)
|
||||||
|
assert.match(testApp.ctx.log.warn.firstCall[0], /restart/i)
|
||||||
|
assert.match(testApp.ctx.log.warn.firstCall[0], /fresh/i)
|
||||||
|
assert.match(testApp.ctx.log.warn.firstCall[0], /v30/i)
|
||||||
|
assert.match(core.restart.firstCall[0], /v30/i)
|
||||||
|
assert.match(core.restart.firstCall[0], /fresh/i)
|
||||||
|
assert.match(core.restart.firstCall[0], /-1/i)
|
||||||
|
assert.match(core.restart.firstCall[0], new RegExp(testAppName))
|
||||||
|
|
||||||
|
assert.strictEqual(db.data.core[testAppName].versions[0].stable, -1)
|
||||||
|
assert.strictEqual(db.data.core[testAppName].versions[1].stable, 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.test('should stop on first stable and call core.restart if crash occurs', async function() {
|
||||||
|
const assertError = new Error('Daikichi to Rin')
|
||||||
|
testApp.runVersion.rejects(new Error('empty message'))
|
||||||
|
core.restart.rejects(assertError)
|
||||||
testApp.fresh = false
|
testApp.fresh = false
|
||||||
db.data.core[testAppName].versions.push({
|
db.data.core[testAppName].versions.push({
|
||||||
id: '28',
|
id: '28',
|
||||||
|
@ -856,18 +928,16 @@ t.describe('#runApplication()', function() {
|
||||||
})
|
})
|
||||||
|
|
||||||
let err = await assert.isRejected(core.runApplication(testApp))
|
let err = await assert.isRejected(core.runApplication(testApp))
|
||||||
assert.notStrictEqual(err, assertError)
|
assert.strictEqual(err, assertError)
|
||||||
assert.notOk(log.error.called)
|
assert.notOk(log.error.called)
|
||||||
assert.ok(testApp.ctx.log.error.called)
|
assert.ok(testApp.ctx.log.error.called)
|
||||||
|
assert.strictEqual(testApp.ctx.log.error.callCount, 1)
|
||||||
assert.strictEqual(testApp.ctx.log.error.callCount, 3)
|
assert.strictEqual(db.data.core[testAppName].versions[0].stable, 5)
|
||||||
|
assert.strictEqual(stubWrite.callCount, 1)
|
||||||
assert.strictEqual(db.data.core[testAppName].versions[0].stable, -1)
|
assert.ok(core.restart.called)
|
||||||
assert.strictEqual(db.data.core[testAppName].versions[1].stable, -1)
|
assert.match(core.restart.firstCall[0], new RegExp(testAppName))
|
||||||
assert.strictEqual(db.data.core[testAppName].versions[2].stable, -1)
|
assert.match(core.restart.firstCall[0], /v28/)
|
||||||
assert.strictEqual(db.data.core[testAppName].versions[3].stable, -1)
|
assert.match(core.restart.firstCall[0], /stable/)
|
||||||
|
|
||||||
assert.ok(stubWrite.callCount, 2)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
t.test('should throw if no stable version is found', async function() {
|
t.test('should throw if no stable version is found', async function() {
|
||||||
|
|
|
@ -44,7 +44,7 @@ t.timeout(5000).describe('#checkConfig()', function() {
|
||||||
})
|
})
|
||||||
|
|
||||||
t.test('should otherwise succeed', function() {
|
t.test('should otherwise succeed', function() {
|
||||||
return new GitProvider({ url: 'https://git.nfp.is/api/v1/repos/TheThing/sc-manager/releases' })
|
return new GitProvider({ url: 'https://git.nfp.is/api/v1/repos/TheThing/sc-helloworld/releases' })
|
||||||
.checkConfig()
|
.checkConfig()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ t.describe('#getLatestVersion()', function() {
|
||||||
assert.strictEqual(version.log, '')
|
assert.strictEqual(version.log, '')
|
||||||
})
|
})
|
||||||
|
|
||||||
t.test('should support multiple extension', async function() {
|
t.test('should skip zip files for now', async function() {
|
||||||
const assertName = 'Karen'
|
const assertName = 'Karen'
|
||||||
const assertLink = 'My Wings'
|
const assertLink = 'My Wings'
|
||||||
const assertFilename = 'test-sc.zip'
|
const assertFilename = 'test-sc.zip'
|
||||||
|
@ -31,11 +31,9 @@ t.describe('#getLatestVersion()', function() {
|
||||||
{ name: assertName, assets: [{ name: assertFilename, browser_download_url: assertLink }] },
|
{ name: assertName, assets: [{ name: assertFilename, browser_download_url: assertLink }] },
|
||||||
]})
|
]})
|
||||||
|
|
||||||
let version = await provider.getLatestVersion()
|
let err = await assert.isRejected(provider.getLatestVersion())
|
||||||
assert.strictEqual(version.version, assertName)
|
assert.match(err.message, /release/)
|
||||||
assert.strictEqual(version.link, assertLink)
|
assert.match(err.message, /found/)
|
||||||
assert.strictEqual(version.filename, assertFilename)
|
|
||||||
assert.strictEqual(version.log, '')
|
|
||||||
})
|
})
|
||||||
|
|
||||||
t.test('should skip versions with no assets', async function() {
|
t.test('should skip versions with no assets', async function() {
|
||||||
|
|
Loading…
Reference in a new issue