From 2b807da3245b7ba310060de0d958fb4ba7ed0ad8 Mon Sep 17 00:00:00 2001 From: claude-code Date: Fri, 14 Aug 2026 08:18:46 +0000 Subject: [PATCH] =?UTF-8?q?test(resource-rule):=20=E5=8D=8A=E6=AE=98?= =?UTF-8?q?=E6=83=85=E5=A2=83=E7=9A=84=20D1=20=E5=90=8D=E5=AD=97=E6=94=B9?= =?UTF-8?q?=E7=94=A8=E5=AE=89=E8=A3=9D=E5=99=A8=E7=9C=9F=E6=AD=A3=E6=9C=83?= =?UTF-8?q?=E5=8F=96=E7=9A=84=E9=82=A3=E5=80=8B=EF=BC=88-db=EF=BC=8C?= =?UTF-8?q?=E9=9D=9E=20-kbdb=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 上一筆 commit 之後才發現的:fixture 的 half-finished 情境沿用了 installed/renamed 的歷史 D1 名(-kbdb),但那顆殘骸是安裝器留下的, 安裝器真正會取的名字是 `${baseName}-db`。名字不對,這個情境就測不到 真的那條路(D1 會被判成「不同名 ⇒ 照舊新建」而不是接回來)。 把 d1Title 加進情境定義、installerRequirements 收一個 d1CreateName 參數, half-finished 用 -db、其餘照舊 -kbdb。 實跑:node shared/resource-rule/tests/half-finished-install.mjs → 全部通過 Refs: inkstone/Arcrun#123 --- shared/resource-rule/tests/fixture-account.mjs | 11 +++++++---- shared/resource-rule/tests/half-finished-install.mjs | 4 ++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/shared/resource-rule/tests/fixture-account.mjs b/shared/resource-rule/tests/fixture-account.mjs index 6e9d25a..1706fa6 100644 --- a/shared/resource-rule/tests/fixture-account.mjs +++ b/shared/resource-rule/tests/fixture-account.mjs @@ -59,7 +59,7 @@ export const BASE_NAME = 'arcrun-rag-yuga3bse'; * @typedef {'fresh' | 'installed' | 'renamed' | 'half-finished'} Scenario */ -/** @type {Record string}>} */ +/** @type {Record string}>} */ export const SCENARIOS = { fresh: { label: '沒裝過(全新帳號,一顆 worker 都沒有)', @@ -82,6 +82,9 @@ export const SCENARIOS = { deployed: false, resourcesExist: true, titleFor: (b) => `${BASE_NAME}-kv-${b.toLowerCase()}`, + // 這顆殘骸是**安裝器**留下的 ⇒ 名字要照安裝器真正會取的那個(`-db`), + // 不是上面兩個情境沿用的歷史名(`-kbdb`)。名字不對,這個測試就測不到真的那條路。 + d1Title: `${BASE_NAME}-db`, }, }; @@ -93,7 +96,7 @@ export const SCENARIOS = { * * @param {boolean} [claimOwnership] 預設 true;傳 false 就是「安裝器忘了聲明」的對照組。 */ -export function installerRequirements(claimOwnership = true) { +export function installerRequirements(claimOwnership = true, d1CreateName = `${BASE_NAME}-kbdb`) { const out = []; for (const [worker, need] of Object.entries(WORKER_NEEDS)) { for (const b of need.kv) { @@ -106,7 +109,7 @@ export function installerRequirements(claimOwnership = true) { for (const d of need.d1) { out.push({ kind: 'd1', binding: d.binding, worker, - createName: `${BASE_NAME}-kbdb`, + createName: d1CreateName, ...(claimOwnership ? { createNameIsOurs: true } : {}), }); } @@ -159,7 +162,7 @@ export function makeAccount(scenario) { kv.set(spec.titleFor(b), id); kvIdByBinding.set(b, id); } - d1.set(`${BASE_NAME}-kbdb`, D1_ID); + d1.set(spec.d1Title ?? `${BASE_NAME}-kbdb`, D1_ID); } if (spec.deployed) { diff --git a/shared/resource-rule/tests/half-finished-install.mjs b/shared/resource-rule/tests/half-finished-install.mjs index 63fd9ca..8c11065 100644 --- a/shared/resource-rule/tests/half-finished-install.mjs +++ b/shared/resource-rule/tests/half-finished-install.mjs @@ -70,7 +70,7 @@ section('① 驗收線本身:半殘帳號 + 安裝器再按一次 → 裝得 const api = apiFor(account, cfRejectsDuplicateNames(account)); // mode='init':安裝器看的是自己的紀錄(`deployed::`),上次沒裝完就沒有那筆 // ⇒ 這一輪照定義是「新裝」。半殘狀態必須在 init 這條路上就被處理掉。 - const plan = await planResources(api, installerRequirements(), 'init'); + const plan = await planResources(api, installerRequirements(true, `${BASE_NAME}-db`), 'init'); check(plan.blockers.length === 0, `不該有任何 blocker(實得 ${plan.blockers.length} 條)`); if (plan.blockers.length) console.log(plan.blockers.map((b) => ` · ${b}`).join('\n')); @@ -104,7 +104,7 @@ section('② 對照組:修好之前是什麼下場(沒有聲明 createNameIs // 舊版會直接送 POST,然後被 CF 用「title already exists」打回來。 const account = makeAccount('half-finished'); const api = apiFor(account, cfRejectsDuplicateNames(account)); - const plan = await planResources(api, installerRequirements(false), 'init'); + const plan = await planResources(api, installerRequirements(false, `${BASE_NAME}-db`), 'init'); check(plan.blockers.length > 0, '證明不了是自己的 → 一定要停手(fail-closed)'); check(plan.blockers.join('\n').includes('RES-NAME-TAKEN'), '錯誤碼要在訊息裡(讓用戶回報,而不是自己去後台動手)');