quality / changes (push) Successful in 6s
quality / commitlint (push) Skipped
quality / openapi (push) Successful in 28s
quality / web (push) Successful in 57s
quality / api (push) Successful in 1m35s
quality / linux-agent-smoke (push) Successful in 24s
quality / docker-check (push) Failing after 3m20s
CD / quality (push) Failing after 6m56s
CD / publish (push) Skipped
62 lines
3.4 KiB
JavaScript
62 lines
3.4 KiB
JavaScript
import test from 'node:test'
|
|
import assert from 'node:assert/strict'
|
|
import { readFileSync, writeFileSync, mkdtempSync, rmSync } from 'node:fs'
|
|
import { join, resolve } from 'node:path'
|
|
import { tmpdir } from 'node:os'
|
|
import { spawnSync } from 'node:child_process'
|
|
import { pathToFileURL } from 'node:url'
|
|
|
|
test('actual image smoke marker uses the old/new public list API and never recreates missing persisted data', () => {
|
|
const script = readFileSync(resolve('scripts/ci/image-smoke.sh'), 'utf8')
|
|
const program = script.match(/<<'MARKER'\r?\n([\s\S]*?)\r?\nMARKER/)[1]
|
|
const directory = mkdtempSync(join(tmpdir(), 'evofw-marker-'))
|
|
const marker = join(directory, 'marker.mjs'), mock = join(directory, 'fetch.mjs'), state = join(directory, 'state.json')
|
|
writeFileSync(marker, program)
|
|
writeFileSync(mock, `
|
|
import assert from 'node:assert/strict'
|
|
import { existsSync, readFileSync, writeFileSync } from 'node:fs'
|
|
globalThis.fetch = async (url, options = {}) => {
|
|
const state = existsSync(process.env.MARKER_STATE) ? JSON.parse(readFileSync(process.env.MARKER_STATE, 'utf8')) : { creates: 0, entity: null }
|
|
let status = 200, body
|
|
if (options.method === 'POST') {
|
|
assert.equal(url, 'http://127.0.0.1:8080/api/v1/lists')
|
|
const payload = JSON.parse(options.body)
|
|
state.creates++
|
|
state.entity = { id: 'persisted-list-id', name: payload.name, type: payload.type, entries: payload.entries, entry_count: payload.entries.length }
|
|
writeFileSync(process.env.MARKER_STATE, JSON.stringify(state))
|
|
status = Number(process.env.CREATE_STATUS)
|
|
body = { id: state.entity.id, name: state.entity.name, type: state.entity.type }
|
|
} else {
|
|
assert.equal(url, 'http://127.0.0.1:8080/api/v1/lists/persisted-list-id')
|
|
status = state.entity ? 200 : 404
|
|
body = state.entity || { error: 'NOT_FOUND' }
|
|
}
|
|
return { ok: status >= 200 && status < 300, status, json: async () => body }
|
|
}
|
|
`)
|
|
const run = (mode, id, status) => spawnSync(process.execPath, ['--import', pathToFileURL(mock).href, marker, mode, id, 'unique-smoke-marker'], { encoding: 'utf8', env: { ...process.env, MARKER_STATE: state, CREATE_STATUS: String(status) } })
|
|
try {
|
|
// Previous aa47584 returns 200 for POST /lists; newer implementations may use 201.
|
|
for (const status of [200, 201]) {
|
|
rmSync(state, { force: true })
|
|
const created = run('write', '', status)
|
|
assert.equal(created.status, 0, created.stderr)
|
|
assert.equal(created.stdout, 'persisted-list-id')
|
|
for (const phase of ['read', 'write', 'read', 'read']) {
|
|
const verified = run(phase, created.stdout, status)
|
|
assert.equal(verified.status, 0, verified.stderr)
|
|
assert.equal(verified.stdout, created.stdout)
|
|
}
|
|
const saved = JSON.parse(readFileSync(state, 'utf8'))
|
|
assert.equal(saved.creates, 1, 'Upgrade/restart/restore verification must never create replacement data')
|
|
saved.entity.entries = []; saved.entity.entry_count = 0
|
|
writeFileSync(state, JSON.stringify(saved))
|
|
assert.notEqual(run('read', created.stdout, status).status, 0, 'Lost marker entries must fail smoke')
|
|
saved.entity = null
|
|
writeFileSync(state, JSON.stringify(saved))
|
|
assert.notEqual(run('read', created.stdout, status).status, 0, 'Missing marker must fail smoke')
|
|
assert.equal(JSON.parse(readFileSync(state, 'utf8')).creates, 1)
|
|
}
|
|
} finally { rmSync(directory, { recursive: true, force: true }) }
|
|
})
|