Files
EvoFirewall/scripts/ci/image-smoke-marker.test.mjs
T
Denozordec 57b7652d4d
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
fix(ci): support ipset sockets and deployed image smoke checks
2026-10-26 14:14:51 +07:00

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 }) }
})