1package main
2
3import (
4 "strings"
5 "testing"
6)
7
8func TestResolvePinnedValues(t *testing.T) {
9 found := map[string]bool{}
10 for _, m := range testModules(t) {
11 rs, err := resolveRequests(m)
12 if err != nil {
13 t.Fatal(err)
14 }
15 for _, r := range rs {
16 if r.Values != nil {
17 found[m.Pkg+"/"+r.Name] = true
18 if len(r.Values.Fields) == 0 {
19 t.Fatal("empty values")
20 }
21 for i, f := range r.Values.Fields {
22 if i > 0 && r.Values.Fields[i-1].Value >= f.Value {
23 t.Fatal("not in bit order")
24 }
25 }
26 for _, p := range r.Params {
27 if p.Param == "valueMask" {
28 t.Fatal("mask leaked into params")
29 }
30 }
31 }
32 }
33 }
34 for _, name := range []string{"xproto/CreateWindow", "xproto/ChangeWindowAttributes", "xproto/ConfigureWindow", "xproto/CreateGC", "xproto/ChangeGC", "xproto/ChangeKeyboardControl", "render/CreatePicture", "render/ChangePicture"} {
35 if !found[name] {
36 t.Error("missing", name)
37 }
38 }
39 if len(found) != 8 {
40 t.Fatal(found)
41 }
42}
43
44func TestResolveValueSwitches(t *testing.T) {
45 prefix := `<xcb header="test"><enum name="Mask"><item name="Low"><bit>0</bit></item><item name="High"><bit>3</bit></item></enum><request name="Configure" opcode="1"><pad bytes="1"/><field name="value_mask" type="CARD32" mask="Mask"/>`
46 high := `<bitcase><enumref ref="Mask">High</enumref><field name="high" type="BOOL32"/></bitcase>`
47 low := `<bitcase><enumref ref="Mask">Low</enumref><field name="low" type="INT32"/></bitcase>`
48 good := `<switch name="value_list"><fieldref>value_mask</fieldref>` + high + low + `</switch>`
49 for _, tc := range []struct {
50 name, body string
51 valid bool
52 }{
53 {"sorted", good, true},
54 {"expression", strings.Replace(good, "<fieldref>value_mask</fieldref>", "<popcount><fieldref>value_mask</fieldref></popcount>", 1), false},
55 {"duplicate", strings.Replace(good, low, high, 1), false},
56 {"unknown bit", strings.Replace(good, ">Low<", ">Missing<", 1), false},
57 {"non scalar", strings.Replace(good, `type="INT32"`, `type="Pair"`, 1), false},
58 {"trailing field", good + `<field name="extra" type="CARD32"/>`, false},
59 } {
60 t.Run(tc.name, func(t *testing.T) {
61 xml := strings.Replace(prefix, `<request name=`, `<struct name="Pair"><field name="a" type="CARD32"/></struct><request name=`, 1) + tc.body + `</request></xcb>`
62 n, err := parseXML("values.xml", strings.NewReader(xml))
63 if err != nil {
64 t.Fatal(err)
65 }
66 ms, err := resolveModules([]*Node{n})
67 if err != nil {
68 t.Fatal(err)
69 }
70 rs, err := resolveRequests(ms[0])
71 if !tc.valid {
72 if err == nil || !strings.Contains(err.Error(), "values.xml:1:") {
73 t.Fatalf("got %v", err)
74 }
75 return
76 }
77 if err != nil {
78 t.Fatal(err)
79 }
80 v := rs[0].Values
81 if v.Fields[0].Field.Name != "Low" || v.Fields[1].Field.Name != "High" {
82 t.Fatal("XML order used instead of bit order")
83 }
84 decl, err := requestDecl(ms[0], rs[0])
85 if err != nil {
86 t.Fatal(err)
87 }
88 if !strings.Contains(decl, "uint32(v.Low)") || !strings.Contains(decl, "if v.High") {
89 t.Fatal(decl)
90 }
91 })
92 }
93}