quad/quad-base/test/smoke.init.luau
qwreey-agent-selene 9c3bfc890a
design: RunInit 재설계(함수를 릴레이션 키로) + darklua 경계 실측 정밀화
New()의 멱등 Init 가드를 파일마다 Relate+센티널을 두던 방식에서
module:RunInit(initFn) 하나로 통합 — 함수 자체를 릴레이션 키로 써서
"이 함수, 이 모듈에 실행했는가"를 (module, initFn) -> boolean? 하나로
표현(사용자 제안). Debug/init.luau는 가드 없이 순수 뮤테이션만 하도록
단순화. smoke.init.luau로 재호출 무시/인스턴스별 독립/함수별 독립 3개
시나리오 검증(luau/luau-analyze/selene 클린).

darklua process를 실제로 돌려 @self/@game은 안 건드리고 커스텀 .luaurc
alias(@pkg)만 script.Parent류로 치환한다는 걸 확인 — project-setup-plan.md의
darklua 기각 근거를 "지금은 커스텀 alias를 안 쓰니 불필요, 나중에 도입하면
그때 필요해짐"으로 정밀화.

⚠️ 미결: RunInit을 backend 설치 진입점(QuadRoblox(Quad))에도 재사용할지
— 함수 identity 추적으로는 "다른 팩토리 재호출은 에러" 계약을 못 만족.
module-lifecycle-plan.md에 반영, M2/M5 착수 전 확인 필요.

Co-authored-by: qwreey <me@qwreey.moe>
2026-08-19 16:17:08 +09:00

67 lines
1.9 KiB
Text

--[[ 임시 스모크 테스트 — New()/RunInit의 멱등 가드가 기대대로 동작하는지 확인 ]]
local Quad = require("../src")
print("=== 1. New()가 만든 module엔 InitDebug가 이미 반영돼 있음 ===")
assert(Quad.debug == false, "top-level require(quad-base)도 New()를 거쳐야 함")
print("PASS")
print()
print("=== 2. RunInit은 같은 함수를 다시 넘겨도 재실행하지 않음 ===")
do
local runCount = 0
local function initFn(module)
runCount += 1
module.marker = true
end
Quad:RunInit(initFn)
Quad:RunInit(initFn)
Quad:RunInit(initFn)
assert(runCount == 1, "같은 initFn을 여러 번 RunInit해도 실제 실행은 1회여야 함")
assert(Quad.marker == true, "실행됐다면 마커가 세팅돼 있어야 함")
print("PASS: " .. runCount .. "회 호출 중 실제 실행 " .. runCount .. "회")
end
print()
print("=== 3. New()로 만든 서로 다른 module은 RunInit 기록을 공유하지 않음 ===")
do
local runCount = 0
local function initFn(_module)
runCount += 1
end
local a = Quad.New()
local b = Quad.New()
assert(a ~= b, "New()는 매번 독립된 module을 만들어야 함")
a:RunInit(initFn)
b:RunInit(initFn)
assert(runCount == 2, "서로 다른 module 인스턴스는 각자 한 번씩 실행돼야 함(총 2회)")
print("PASS: 독립 인스턴스 2개 각각 1회씩, 총 " .. runCount .. "회")
end
print()
print("=== 4. 서로 다른 initFn은 서로의 실행 여부에 영향을 안 줌 ===")
do
local m = Quad.New()
local aRan, bRan = false, false
local function initA(_module)
aRan = true
end
local function initB(_module)
bRan = true
end
m:RunInit(initA)
assert(aRan == true and bRan == false, "initA만 돌았어야 함")
m:RunInit(initB)
assert(aRan == true and bRan == true, "이제 둘 다 돌았어야 함")
m:RunInit(initA) -- no-op이어야 함, 에러 없이 통과하면 충분
print("PASS")
end
print()
print("=== ALL PASS ===")