Replace .golangci.yml with the shared canonical config. The old config's top-level linters-settings block was silently ignored under the v2 schema, so the lll/funlen/cyclop/dupl thresholds now actually apply. The four repo-specific disables (mnd, exhaustive, paralleltest, testpackage) move out of the config into targeted in-code nolint directives carrying their original approval dates, keeping the config byte-identical to the canonical one. Fixes surfaced by the stricter settings: t.Parallel() added to all 32 tests, 24 overlong lines wrapped or their comments tightened, tcell control-code returns rewritten as character literals, dupl markers on the identically-shaped item data tables, and two wsl_v5 defer cuddles. No behavior changes. The repo has no golangci-lint version pin (no Dockerfile or CI; make lint runs the host binary, currently v2.12.2), so there was nothing to bump.
53 lines
1.3 KiB
Go
53 lines
1.3 KiB
Go
//nolint:testpackage // white-box tests reach unexported state (approved 2026-07-07)
|
|
package game
|
|
|
|
import "testing"
|
|
|
|
// ParseDice must keep the exact semantics of the C roll_em parse loop,
|
|
// including its junk-tolerant edges: the bestiary placeholder "%%%x0" and
|
|
// the flytrap reset "000x0" both mean a single 0x0 attack.
|
|
func TestParseDice(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
cases := []struct {
|
|
in string
|
|
want string
|
|
len int
|
|
}{
|
|
{"1x4", "1x4", 1},
|
|
{"1x2/1x5/1x5", "1x2/1x5/1x5", 3},
|
|
{"2x12/2x4", "2x12/2x4", 2},
|
|
{"0x0", "0x0", 1},
|
|
{"000x0", "0x0", 1},
|
|
{"%%%x0", "0x0", 1},
|
|
{"", "", 0},
|
|
{"3", "", 0}, // no 'x': C parses nothing
|
|
}
|
|
for _, c := range cases {
|
|
got := ParseDice(c.in)
|
|
if len(got) != c.len || got.String() != c.want {
|
|
t.Errorf("ParseDice(%q) = %v (len %d), want %q (len %d)",
|
|
c.in, got, len(got), c.want, c.len)
|
|
}
|
|
}
|
|
}
|
|
|
|
// The bestiary and weapon tables must parse to at least one attack each so
|
|
// every creature and weapon actually swings.
|
|
func TestTablesHaveDice(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
data := newGameData()
|
|
for i, m := range data.monsterTable {
|
|
if len(m.Stats.Dmg) == 0 {
|
|
t.Errorf("monster %c (%s) has no attacks", 'A'+i, m.Name)
|
|
}
|
|
}
|
|
|
|
for w, iw := range data.initWeaps {
|
|
if len(iw.dam) == 0 || len(iw.hrl) == 0 {
|
|
t.Errorf("weapon %d has empty dice", w)
|
|
}
|
|
}
|
|
}
|