diff options
Diffstat (limited to 'internal/validate/correct_data_craft_validation_test.go')
| -rw-r--r-- | internal/validate/correct_data_craft_validation_test.go | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/internal/validate/correct_data_craft_validation_test.go b/internal/validate/correct_data_craft_validation_test.go new file mode 100644 index 0000000..6b5e7f6 --- /dev/null +++ b/internal/validate/correct_data_craft_validation_test.go @@ -0,0 +1,102 @@ +package validate + +import ( + "testing" +) + +// Regression: CraftDef.Tool was validated against item ids, but it is a tool +// *type* ("knife", "pickaxe", "fire"): runtime consumers match it with +// ItemDef.ToolType() (g.hasToolType). Tool types such as pickaxe, axe, fire, +// big_net and fly_rod have no same-named item file, so the old check rejected +// legitimate recipes. These tests pin the tool-type namespace and the +// byproduct/index pairing rule. + +func TestCraftToolTypeAcceptedWithoutSameNamedItem(t *testing.T) { + dir := t.TempDir() + // A pickaxe item defines tool.type: pickaxe but there is no item "pickaxe". + writeCraftItem(t, dir, "bronze_pickaxe", `id: bronze_pickaxe +name: bronze pickaxe +tool: + type: pickaxe + speed: 2 +`) + writeCraftItem(t, dir, "test_in", "id: test_in\nname: test in\n") + writeCraftItem(t, dir, "test_out", `id: test_out +name: test out +craft: + - type: crafting + tool: pickaxe + ingredients: + - items: [test_in] + quantity: 1 +`) + + issues := validateCraftBlocks(newSource(dir)) + for _, issue := range issues { + if issue.Level == "ERROR" { + t.Fatalf("a bare tool type must validate, got: %+v", issue) + } + } +} + +func TestCraftToolTypeUnknownIsRejected(t *testing.T) { + dir := t.TempDir() + writeCraftItem(t, dir, "bronze_pickaxe", "id: bronze_pickaxe\nname: bronze pickaxe\ntool:\n type: pickaxe\n") + writeCraftItem(t, dir, "test_in", "id: test_in\nname: test in\n") + writeCraftItem(t, dir, "test_out", `id: test_out +name: test out +craft: + - type: crafting + tool: made_up_type + ingredients: + - items: [test_in] + quantity: 1 +`) + + if issues := validateCraftBlocks(newSource(dir)); !containsMsg(issues, "nonexistent tool") { + t.Fatalf("expected nonexistent-tool error, got: %+v", issues) + } +} + +func TestCraftByproductLengthMismatchIsFlagged(t *testing.T) { + dir := t.TempDir() + writeCraftItem(t, dir, "test_in", "id: test_in\nname: test in\n") + writeCraftItem(t, dir, "test_alt", "id: test_alt\nname: test alt\n") + writeCraftItem(t, dir, "empty_container", "id: empty_container\nname: empty container\n") + // Two alternatives paired with a single byproduct: consuming the second + // alternative returns nothing (collectByproducts indexes by position). + writeCraftItem(t, dir, "test_out", `id: test_out +name: test out +craft: + - type: combine + ingredients: + - items: [test_in, test_alt] + quantity: 1 + byproducts: [empty_container] +`) + + if issues := validateCraftBlocks(newSource(dir)); !containsMsg(issues, "pair with items by index") { + t.Fatalf("expected byproduct length-mismatch error, got: %+v", issues) + } +} + +func TestCraftByproductLengthMatchIsAccepted(t *testing.T) { + dir := t.TempDir() + writeCraftItem(t, dir, "test_in", "id: test_in\nname: test in\n") + writeCraftItem(t, dir, "test_alt", "id: test_alt\nname: test alt\n") + writeCraftItem(t, dir, "empty_one", "id: empty_one\nname: empty one\n") + writeCraftItem(t, dir, "empty_two", "id: empty_two\nname: empty two\n") + writeCraftItem(t, dir, "test_out", `id: test_out +name: test out +craft: + - type: combine + ingredients: + - items: [test_in, test_alt] + quantity: 1 + byproducts: [empty_one, empty_two] +`) + + if issues := validateCraftBlocks(newSource(dir)); len(issues) != 0 { + t.Fatalf("positionally paired byproducts must validate cleanly, got: %+v", issues) + } +} |
