"use strict"; const assert = require("assert"); const fs = require("fs"); const path = require("path"); const run = async () => { const source = fs.readFileSync( path.join(__dirname, "../utils/generation-poem.js"), "utf8", ); const moduleUrl = `data:text/javascript;base64,${Buffer.from(source).toString("base64")}`; const { MAX_GENERATION_NO, MAX_GENERATION_COUNT, MAX_GENERATION_TEXT_LENGTH, MAX_GENERATION_POEM_INPUT_LENGTH, GENERATION_POEM_STATUS, normalizeGenerationNumber, validateGenerationPoemText, findFirstGenerationGap, mergeGenerationPoemRows, } = await import(moduleUrl); assert.strictEqual(MAX_GENERATION_COUNT, 500); assert.strictEqual(MAX_GENERATION_TEXT_LENGTH, 50); assert.strictEqual(MAX_GENERATION_POEM_INPUT_LENGTH, 26000); assert.deepStrictEqual(GENERATION_POEM_STATUS, { ACTIVE: "0", DISABLED: "1", }); assert.strictEqual(normalizeGenerationNumber(undefined, 12), 12); assert.strictEqual(normalizeGenerationNumber("300", 12), 300); for (const invalid of [ "0", "1.5", "1e2", "Infinity", Infinity, NaN, MAX_GENERATION_NO + 1, ]) { assert.strictEqual( normalizeGenerationNumber(invalid, 12), null, `非法代次未拒绝:${invalid}`, ); } assert.deepStrictEqual(validateGenerationPoemText("启宗敦本").generations, [ "启", "宗", "敦", "本", ]); assert.deepStrictEqual( validateGenerationPoemText("克勤 克俭,承先;启后、敦本/睦族|传芳").generations, ["克勤", "克俭", "承先", "启后", "敦本", "睦族", "传芳"], "OpenAPI 声明的分隔符必须统一解析多字字辈", ); assert.deepStrictEqual( validateGenerationPoemText("德承家亦\n忠厚传芳").generations, ["德承家亦", "忠厚传芳"], ); assert.strictEqual( validateGenerationPoemText("𠀀").valid, true, "扩展区字符必须按一个 code point 计数", ); assert.strictEqual(validateGenerationPoemText("").valid, false); assert.strictEqual(validateGenerationPoemText("启".repeat(501)).valid, false); assert.strictEqual( validateGenerationPoemText(`${"启".repeat(51)} 宗`).valid, false, ); assert.strictEqual( validateGenerationPoemText("启".repeat(MAX_GENERATION_POEM_INPUT_LENGTH + 1)).valid, false, ); assert.throws( () => mergeGenerationPoemRows({ existingRows: [], generationTexts: ["启", "宗"], startGeneration: MAX_GENERATION_NO, currentGeneration: MAX_GENERATION_NO, disableMissing: false, }), /超出支持范围/, ); assert.throws( () => mergeGenerationPoemRows({ existingRows: [], generationTexts: Array.from({ length: 501 }, () => "启"), startGeneration: 1, currentGeneration: 1, disableMissing: false, }), /最多 500 个世代/, ); assert.throws( () => mergeGenerationPoemRows({ existingRows: [], generationTexts: ["启"], startGeneration: 1, currentGeneration: 1, disableMissing: "false", }), /disableMissing/, ); const contiguous = [ { generationNo: 12, generationText: "启", status: "0" }, { generationNo: 13, generationText: "宗", status: "0" }, { generationNo: 14, generationText: "敦", status: "0" }, ]; assert.strictEqual(findFirstGenerationGap(contiguous, 15), null); assert.strictEqual( findFirstGenerationGap([contiguous[0], contiguous[2]], 15), 13, "历史缺口必须定位到首个缺失世代", ); assert.strictEqual( findFirstGenerationGap([{ generationNo: 5, status: "0" }], 6, 1), 1, "完整序列必须从第一世检查前缀缺口", ); assert.strictEqual( findFirstGenerationGap( [ { generationNo: 1, status: "0" }, { generationNo: 2, status: "0" }, { generationNo: 5, status: "0" }, ], 6, 1, ), 3, "保留后续 ACTIVE 记录时不能留下中间缺口", ); assert.strictEqual( findFirstGenerationGap( [ { generationNo: 1, status: "0" }, { generationNo: 2, status: "1" }, { generationNo: 3, status: "0" }, ], 4, 1, ), 2, "DISABLED 记录不能填补 ACTIVE 序列缺口", ); assert.throws( () => mergeGenerationPoemRows({ existingRows: [ { generationNo: 1, generationText: "启", status: "UNKNOWN" }, ], generationTexts: ["宗"], startGeneration: 2, currentGeneration: 2, disableMissing: false, }), /GenerationPoemView/, ); assert.throws( () => mergeGenerationPoemRows({ existingRows: [ { generationNo: 1, generationText: "启", status: "0" }, { generationNo: 1, generationText: "宗", status: "1" }, ], generationTexts: ["敦"], startGeneration: 2, currentGeneration: 2, disableMissing: false, }), /重复的世代记录/, "同一世代存在多条记录时必须失败关闭,不能静默 last-wins", ); const preserved = mergeGenerationPoemRows({ existingRows: [ ...contiguous, { poemId: "9007199254740993", generationNo: 15, generationText: "本", status: "0" }, { generationNo: 16, generationText: "继", status: "0" }, ], generationTexts: ["克勤"], startGeneration: 15, currentGeneration: 15, disableMissing: false, }); assert.deepStrictEqual( preserved.map(({ generationNo, generationText, status }) => ({ generationNo, generationText, status, })), [ { generationNo: 12, generationText: "启", status: "0" }, { generationNo: 13, generationText: "宗", status: "0" }, { generationNo: 14, generationText: "敦", status: "0" }, { generationNo: 15, generationText: "克勤", status: "0" }, { generationNo: 16, generationText: "继", status: "0" }, ], ); assert.strictEqual( preserved.find((row) => row.generationNo === 15)?.poemId, "9007199254740993", "覆盖文字时必须保留词法 int64 记录身份", ); const disabled = mergeGenerationPoemRows({ existingRows: preserved, generationTexts: ["昭穆"], startGeneration: 15, currentGeneration: 15, disableMissing: true, }); assert.strictEqual( disabled.find((row) => row.generationNo === 12)?.generationText, "启", ); assert.strictEqual( disabled.find((row) => row.generationNo === 16)?.status, "1", ); assert.strictEqual( disabled.find((row) => row.generationNo === 16)?.generationText, "继", ); const maximumBatch = mergeGenerationPoemRows({ existingRows: [], generationTexts: Array.from({ length: MAX_GENERATION_COUNT }, () => "启"), startGeneration: 1, currentGeneration: 500, disableMissing: false, }); assert.strictEqual(maximumBatch.length, 500); assert.strictEqual(maximumBatch[499].generationNo, 500); assert.strictEqual(maximumBatch[499].current, true); process.stdout.write("GENERATION-POEM-RUNTIME-SMOKE PASS\n"); }; run().catch((error) => { process.stderr.write(`${error.stack || error.message}\n`); process.exit(1); });