package main
import (
"strings"
"testing"
)
// TestEventLayouts pins wire offsets that the X11 protocol defines, checked
// against the event containers (independent of generated code).
func TestEventLayouts(t *testing.T) {
want := map[string]map[string]int{
"xproto.MapRequest": {"Parent": 4, "Window": 8},
"xproto.ConfigureRequest": {"StackMode": 1, "Parent": 4, "Window": 8, "Sibling": 12, "X": 16, "Y": 18, "Width": 20, "Height": 22, "BorderWidth": 24, "ValueMask": 26},
"xproto.KeymapNotify": {"Keys": 1},
"xproto.ClientMessage": {"Format": 1, "Window": 4, "Type": 8, "Data": 12},
"xproto.PropertyNotify": {"Window": 4, "Atom": 8, "Time": 12, "State": 16},
"xfixes.SelectionNotify": {"Subtype": 1, "Window": 4, "Owner": 8, "Selection": 12, "Timestamp": 16, "SelectionTimestamp": 20},
"shape.Notify": {"ShapeKind": 1, "AffectedWindow": 4, "ServerTime": 16, "Shaped": 20},
}
copies := 0
for _, m := range testModules(t) {
events, err := resolveEvents(m)
if err != nil {
t.Fatal(err)
}
for _, e := range events {
if e.Copy != nil {
copies++
if e.C != e.Copy.C {
t.Errorf("%s: copy does not share its source layout", e.Name)
}
continue
}
exp := want[m.Pkg+"."+e.Name]
for _, mem := range e.C.Members {
if off, ok := exp[mem.Method]; ok {
if mem.Static != off {
t.Errorf("%s.%s.%s at %d want %d", m.Pkg, e.Name, mem.Method, mem.Static, off)
}
delete(exp, mem.Method)
}
}
if len(exp) != 0 {
t.Errorf("%s.%s: missing %v", m.Pkg, e.Name, exp)
}
}
}
if copies != 5 {
t.Errorf("xproto has 5 eventcopy, got %d", copies)
}
}
func TestEventGeneratorRejects(t *testing.T) {
for _, tc := range []struct{ body, want string }{
{``, "xge evtype"},
{``, "header data byte"},
{``, "unknown event"},
{`n
`, "first 32 bytes"},
} {
// Some constructs are already rejected by the parser; either stage must
// fail with a source location.
n, err := parseXML("ev.xml", strings.NewReader(``+tc.body+``))
if err == nil {
var ms []*Module
if ms, err = resolveModules([]*Node{n}); err != nil {
t.Fatal(err)
}
_, err = resolveEvents(ms[0])
}
if err == nil || !strings.Contains(err.Error(), tc.want) || !strings.Contains(err.Error(), "ev.xml:1:") {
t.Errorf("%s: got %v", tc.want, err)
}
}
}
func TestErrorConstNames(t *testing.T) {
for in, want := range map[string]string{"Window": "BadWindow", "BadRegion": "BadRegion", "PictFormat": "BadPictFormat", "IDChoice": "BadIDChoice"} {
if got := errorConst(in); got != want {
t.Errorf("%s => %s want %s", in, got, want)
}
}
}