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)) }) }