package main
import (
"path/filepath"
"strings"
"testing"
)
func TestParseVendored(t *testing.T) {
files, err := filepath.Glob("../../spec/xml/*.xml")
if err != nil {
t.Fatal(err)
}
if len(files) != 9 {
t.Fatalf("got %d XML files, want 9", len(files))
}
for _, file := range files {
t.Run(filepath.Base(file), func(t *testing.T) {
n, err := parseFile(file)
if err != nil {
t.Fatal(err)
}
if n.Kind != "xcb" || len(n.Children) == 0 {
t.Fatal("missing module AST")
}
})
}
}
func TestParseRejects(t *testing.T) {
cases := []struct{ name, body, want string }{
{"unknown element", "", "unsupported element"},
{"unknown attribute", ``, "unknown attribute"},
{"misplaced known element", ``, "unsupported "},
{"sumof", `
`, "sumof"},
{"paramref", `a
`, "paramref"},
{"case", ``, "case"},
{"struct switch", ``, "unsupported "},
{"reply switch", ``, "unsupported "},
{"nested switch", ``, "unsupported "},
{"fd", ``, "fd"},
{"eventstruct", ``, "eventstruct"},
{"required alignment", ``, "required_start_align"},
{"forward length", `n
`, "later field"},
{"xge code", ``, "evtype"},
{"bad opcode", ``, "invalid opcode"},
{"bad operator", `12`, "unsupported operator"},
{"wrong operands", `1`, "two operands"},
{"bad pad", ``, "power of two"},
{"namespace", ``, "unsupported element"},
{"duplicate attr", ``, "duplicate attribute"},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
_, err := parseXML("bad.xml", strings.NewReader("\n"+tc.body+"\n"))
if err == nil || !strings.Contains(err.Error(), tc.want) || !strings.Contains(err.Error(), "bad.xml:2:") {
t.Fatalf("got %v, want file:line and %q", err, tc.want)
}
})
}
}
func TestParseAST(t *testing.T) {
n, err := parseXML("ok.xml", strings.NewReader(`n4
`))
if err != nil {
t.Fatal(err)
}
r := n.Children[1]
if r.Attr["name"] != "R" || r.Children[1].Children[0].Children[0].Text != "n" {
t.Fatal("AST lost order or expression")
}
}
func FuzzParseXML(f *testing.F) {
f.Add(``)
f.Fuzz(func(t *testing.T, raw string) { _, _ = parseXML("fuzz.xml", strings.NewReader(raw)) })
}