package xturbo import ( "encoding/binary" "strings" "testing" "bnema.dev/xturbo/internal/xtest" ) // Error goldens are Xvfb's answers to the capture script's GetAtomName(0x0dadbeef), // GetWindowAttributes(base|0x7777) and XFIXES DestroyRegion(base|0x8888). Error // codes are the X11 protocol's (BadAtom 5, BadWindow 3) and XFIXES's first error // plus BadRegion (0); the generated constants are checked in events_test.go. func TestErrorGoldens(t *testing.T) { var ext ExtTable ext.Set(ExtXFixes, 138, 87, 140) for _, tc := range []struct { name string code, rel, major uint8 minor uint16 ext ExtID bad uint32 badMask uint32 }{ {"xproto/BadAtom", 5, 5, 17, 0, ExtCore, 0x0dadbeef, 0xffffffff}, {"xproto/BadWindow", 3, 3, 3, 0, ExtCore, 0x7777, 0x1fffff}, {"xfixes/BadRegion", 140, 0, 138, 10, ExtXFixes, 0x8888, 0x1fffff}, } { raw, err := xtest.LoadHex("testdata/golden/" + tc.name + ".error.hex") if err != nil { t.Fatal(err) } var e XError if !decodeError(raw, &ext, &e) { t.Fatalf("%s: rejected", tc.name) } if e.Code != tc.code || e.Rel != tc.rel || e.Ext != tc.ext || e.Major != tc.major || e.Minor != tc.minor || e.Bad&tc.badMask != tc.bad || e.Seq != Seq(binary.LittleEndian.Uint16(raw[2:])) || e.Raw != [32]byte(raw) || e.Kind != 0 { t.Fatalf("%s: %+v", tc.name, e) } if !strings.Contains(e.Error(), "X error code") { t.Fatal(e.Error()) } // Without a table the extension error stays unresolved. if decodeError(raw, nil, &e); e.Ext != ExtCore || e.Rel != tc.code { t.Fatalf("%s: nil table resolved", tc.name) } } var e XError if decodeError(make([]byte, 31), nil, &e) || decodeError(append([]byte{2}, make([]byte, 31)...), nil, &e) { t.Fatal("non-error packet accepted") } } func TestAllocXError(t *testing.T) { raw, err := xtest.LoadHex("testdata/golden/xfixes/BadRegion.error.hex") if err != nil { t.Fatal(err) } var ext ExtTable ext.Set(ExtXFixes, 138, 87, 140) var e XError if n := testing.AllocsPerRun(1000, func() { decodeError(raw, &ext, &e) }); n != 0 { t.Fatalf("decodeError allocates %v times", n) } }