aboutsummaryrefslogtreecommitdiff
path: root/internal/validate/polish_destructive_fail_test.go
blob: 8c9a0383574a0056fa006ef74173bc4267bb8b0b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
package validate

// Regression: the "a failable recipe must not yield nothing" invariant was
// enforced only for smelting (and only by a shipped-data test), so a future
// cooking/fletching/combine recipe with a success formula (or a declared
// fail_message) and no fail product would silently consume materials and
// return nothing. validateCraftBlocks now warns on it.

import (
	"path/filepath"
	"testing"
)

func writePolishCraftRecipe(t *testing.T, dir, craftBody string) {
	t.Helper()
	writeFile(t, filepath.Join(dir, "items", "polish_in.yaml"), "id: polish_in\nname: polish in\n")
	writeFile(t, filepath.Join(dir, "items", "polish_out.yaml"),
		"id: polish_out\nname: polish out\ncraft:\n  - type: cooking\n"+craftBody+
			"    ingredients:\n      - items: [polish_in]\n        quantity: 1\n")
}

func TestCraftFailableWithoutFailProductIsWarned(t *testing.T) {
	cases := []struct {
		name      string
		craftBody string
	}{
		{"success formula", "    success:\n      base: 0.5\n      cap: 0.95\n      per_level: 0.02\n"},
		{"declared fail_message", "    fail_message: You burn it.\n"},
	}
	for _, c := range cases {
		t.Run(c.name, func(t *testing.T) {
			dir := t.TempDir()
			writePolishCraftRecipe(t, dir, c.craftBody)
			issues := validateCraftBlocks(newSource(dir))
			if !containsMsg(issues, "failure destroys materials with no fail product") {
				t.Fatalf("expected a destructive-failure warning, got: %+v", issues)
			}
			for _, issue := range issues {
				if issue.Level != "WARN" {
					t.Fatalf("destructive failure must be a WARN, got: %+v", issue)
				}
			}
		})
	}
}

func TestCraftWithFailProductOrGuaranteedSuccessDoesNotWarn(t *testing.T) {
	cases := []struct {
		name      string
		craftBody string
	}{
		{"declares a fail product", "    fail: polish_in\n    success:\n      base: 0.5\n      cap: 0.95\n      per_level: 0.02\n"},
		{"success cannot fall below 1", "    success:\n      base: 1.0\n      cap: 1.0\n      per_level: 0\n"},
	}
	for _, c := range cases {
		t.Run(c.name, func(t *testing.T) {
			dir := t.TempDir()
			writePolishCraftRecipe(t, dir, c.craftBody)
			if issues := validateCraftBlocks(newSource(dir)); containsMsg(issues, "failure destroys materials with no fail product") {
				t.Fatalf("did not expect a destructive-failure warning, got: %+v", issues)
			}
		})
	}
}