Unit test

This commit is contained in:
2026-05-14 19:59:15 +02:00
parent e39d539585
commit 4199d615a3
2 changed files with 152 additions and 0 deletions
+142
View File
@@ -8897,6 +8897,148 @@ func TestBuildBaseitemsAllowsKeyOnlyOverrideBeforeSameKeyIsRelocatedAndReadded(t
}
}
func TestBuildNativeKeepsGeneratedIDsStableAcrossRepeatedBuilds(t *testing.T) {
root := testProjectRoot(t)
writeFeatGeneratedHarness(t, root, map[string]string{
"skill_focus.json": `{
"family": "skill_focus",
"family_key": "skill_focus",
"template": "masterfeats:skillfocus",
"name_prefix": "Skill Focus",
"label_prefix": "FEAT_SKILL_FOCUS",
"constant_prefix": "FEAT_SKILL_FOCUS",
"default_fields": {
"CRValue": "0.5",
"ReqSkillMinRanks": "1",
"ALLCLASSESCANUSE": "1",
"TOOLSCATEGORIES": "6",
"PreReqEpic": "0",
"ReqAction": "1"
},
"apply_after_modules": true,
"child_ref_field": "REQSKILL",
"child_source": {
"dataset": "skills",
"predicate": "accessible"
}
}` + "\n",
}, map[string]int{
"feat:skill_focus_intimidate": 1333,
})
mkdirAll(t, filepath.Join(root, "topdata", "data", "baseitems", "modules", "10_vanillaoverrides"))
writeFile(t, filepath.Join(root, "topdata", "data", "baseitems", "base.json"), `{
"output": "baseitems.2da",
"columns": ["label", "MaxRange"],
"rows": [
{"id": 58, "key": "baseitems:shortspear", "label": "shortspear", "MaxRange": "100"}
]
}`+"\n")
writeFile(t, filepath.Join(root, "topdata", "data", "baseitems", "lock.json"), `{
"baseitems:shortspear": 126
}`+"\n")
writeFile(t, filepath.Join(root, "topdata", "data", "baseitems", "modules", "10_vanillaoverrides", "ovr_baseitems_spear.json"), `{
"overrides": [
{
"id": 58,
"key": "baseitems:spear",
"label": "spear"
}
]
}`+"\n")
writeFile(t, filepath.Join(root, "topdata", "data", "baseitems", "modules", "add_baseitems_shortspear.json"), `{
"entries": {
"baseitems:shortspear": {
"label": "shortspear",
"MaxRange": "255"
}
}
}`+"\n")
writeFile(t, filepath.Join(root, "topdata", "data", "skills", "base.json"), `{
"output": "skills.2da",
"columns": ["Label", "Name", "Description", "Icon", "Untrained", "KeyAbility", "ArmorCheckPenalty", "AllClassesCanUse", "Category", "MaxCR", "Constant", "HostileSkill", "HideFromLevelUp"],
"rows": [
{"id": 18, "key": "skills:intimidate", "Label": "Intimidate", "Name": "8756", "Description": "8786", "Icon": "isk_x2inti", "Untrained": "1", "KeyAbility": "CHA", "ArmorCheckPenalty": "0", "AllClassesCanUse": "1", "Category": "****", "MaxCR": "****", "Constant": "SKILL_INTIMIDATE", "HostileSkill": "1", "HideFromLevelUp": "0"}
]
}`+"\n")
writeFile(t, filepath.Join(root, "topdata", "data", "skills", "lock.json"), `{
"skills:intimidate": 18
}`+"\n")
writeFile(t, filepath.Join(root, "topdata", "data", "feat", "base.json"), `{
"output": "feat.2da",
"compare_reference": false,
"columns": [
"LABEL","FEAT","DESCRIPTION","ICON","MINATTACKBONUS","MINSTR","MINDEX","MININT","MINWIS","MINCON","MINCHA",
"MINSPELLLVL","PREREQFEAT1","PREREQFEAT2","GAINMULTIPLE","EFFECTSSTACK","ALLCLASSESCANUSE","CATEGORY","MAXCR",
"SPELLID","SUCCESSOR","CRValue","USESPERDAY","MASTERFEAT","TARGETSELF","OrReqFeat0","OrReqFeat1","OrReqFeat2",
"OrReqFeat3","OrReqFeat4","REQSKILL","ReqSkillMinRanks","REQSKILL2","ReqSkillMinRanks2","Constant","TOOLSCATEGORIES",
"HostileFeat","MinLevel","MinLevelClass","MaxLevel","MinFortSave","PreReqEpic","ReqAction"
],
"rows": [
{"id": 39, "key": "feat:stunning_fist", "LABEL": "FEAT_STUNNING_FIST", "MASTERFEAT": "****", "Constant": "FEAT_STUNNING_FIST"},
{"id": 916, "key": "feat:skill_focus_intimidate", "LABEL": "FEAT_SKILL_FOCUS_INTIMIDATE", "REQSKILL": 24, "MASTERFEAT": 4, "Constant": "FEAT_SKILL_FOCUS_INTIMIDATE"}
]
}`+"\n")
writeFile(t, filepath.Join(root, "topdata", "data", "feat", "lock.json"), `{
"feat:skill_focus_intimidate": 1333,
"feat:stunning_fist": 1116
}`+"\n")
mkdirAll(t, filepath.Join(root, "topdata", "data", "feat", "modules", "00_removed"))
writeFile(t, filepath.Join(root, "topdata", "data", "feat", "modules", "00_removed", "rmv_feat_intimidate.json"), `{
"overrides": [
{"id": 916, "null": true, "key": null}
]
}`+"\n")
writeFile(t, filepath.Join(root, "topdata", "data", "feat", "modules", "00_removed", "rmv_feat_stunningfist.json"), `{
"overrides": [
{"id": 39, "null": true, "key": null}
]
}`+"\n")
mkdirAll(t, filepath.Join(root, "topdata", "data", "feat", "modules", "activecombat"))
writeFile(t, filepath.Join(root, "topdata", "data", "feat", "modules", "activecombat", "add_feat_stunning_fist.json"), `{
"entries": {
"feat:stunning_fist": {
"LABEL": "FEAT_STUNNING_FIST",
"Constant": "FEAT_STUNNING_FIST"
}
}
}`+"\n")
mkdirAll(t, filepath.Join(root, "reference"))
writeFile(t, filepath.Join(root, "reference", "build.py"), "print('ok')\n")
expectedBaseitems := map[string]int{
"baseitems:spear": 58,
"baseitems:shortspear": 126,
}
expectedFeat := map[string]int{
"feat:skill_focus_intimidate": 1333,
"feat:stunning_fist": 1116,
}
for run := 1; run <= 10; run++ {
if _, err := BuildNative(testProject(root), nil); err != nil {
t.Fatalf("BuildNative run %d failed: %v", run, err)
}
assertLockIDs(t, run, filepath.Join(root, "topdata", "data", "baseitems", "lock.json"), expectedBaseitems)
assertLockIDs(t, run, filepath.Join(root, "topdata", "data", "feat", "lock.json"), expectedFeat)
}
}
func assertLockIDs(t *testing.T, run int, path string, expected map[string]int) {
t.Helper()
raw, err := os.ReadFile(path)
if err != nil {
t.Fatalf("run %d: read lockfile %s: %v", run, path, err)
}
lockData := map[string]int{}
if err := json.Unmarshal(raw, &lockData); err != nil {
t.Fatalf("run %d: parse lockfile %s: %v\n%s", run, path, err, string(raw))
}
for key, want := range expected {
if got := lockData[key]; got != want {
t.Fatalf("run %d: expected %s to stay locked to id %d, got %d in %s:\n%s", run, key, want, got, path, string(raw))
}
}
}
func TestBuildSkillsIgnoresStaleBaseSpanLockDuringInitialLoad(t *testing.T) {
root := testProjectRoot(t)
mkdirAll(t, filepath.Join(root, "topdata", "data", "skills", "modules"))