main 602baa7

resolve_test.go RawHistoryFolder

1package main
2
3import (
4	"os"
5	"strings"
6	"testing"
7)
8
9func testModules(t *testing.T) []*Module {
10	t.Helper()
11	old, err := os.Getwd()
12	if err != nil {
13		t.Fatal(err)
14	}
15	if err = os.Chdir("../.."); err != nil {
16		t.Fatal(err)
17	}
18	defer func() {
19		if err := os.Chdir(old); err != nil {
20			t.Fatal(err)
21		}
22	}()
23	ms, err := loadModules()
24	if err != nil {
25		t.Fatal(err)
26	}
27	return ms
28}
29func TestResolveLayouts(t *testing.T) {
30	ms := testModules(t)
31	expected := map[string]int{"Setup": 40, "Screen": 40, "Rectangle": 8, "Point": 4, "Arc": 12, "Visualtype": 24, "Format": 8, "Depth": 8, "ClientMessageData": 20}
32	for _, typ := range ms[0].Types {
33		if want, ok := expected[typ.GoType]; ok {
34			if typ.Size != want {
35				t.Errorf("%s size=%d want %d", typ.GoType, typ.Size, want)
36			}
37			delete(expected, typ.GoType)
38		}
39		if typ.GoType == "Rectangle" {
40			for i, want := range []int{0, 2, 4, 6} {
41				if typ.Fields[i].Off != want {
42					t.Errorf("rectangle field %d offset", i)
43				}
44			}
45		}
46	}
47	if len(expected) != 0 {
48		t.Fatal("missing types", expected)
49	}
50	for _, name := range []string{"Window", "Atom", "Cursor", "Pixmap", "Font"} {
51		found := false
52		for _, e := range ms[0].Enums {
53			if e.Name == name {
54				found = e.Existing
55			}
56		}
57		if !found {
58			t.Errorf("%s must reuse XID type", name)
59		}
60	}
61	for _, m := range ms {
62		if err := packetSizeChecks(m); err != nil {
63			t.Fatal(err)
64		}
65	}
66}
67func TestResolveRejectsCollisions(t *testing.T) {
68	for _, body := range []string{
69		`<struct name="A"/><enum name="A"><item name="B"><value>0</value></item></enum>`,
70		`<xidtype name="A"/><xidtype name="a"/>`,
71		`<enum name="A"><item name="B"><value>0</value></item></enum><enum name="A"><item name="C"><value>0</value></item></enum>`,
72	} {
73		n, err := parseXML("collision.xml", strings.NewReader(`<xcb header="test">`+body+`</xcb>`))
74		if err != nil {
75			t.Fatal(err)
76		}
77		_, err = resolveModules([]*Node{n})
78		if err == nil || !strings.Contains(err.Error(), "collision.xml:1:") || !strings.Contains(err.Error(), "collision") {
79			t.Fatalf("got %v", err)
80		}
81	}
82}
83func TestNaming(t *testing.T) {
84	for in, want := range map[string]string{"WINDOW": "Window", "data_len": "DataLen", "ClientIdSpec": "ClientIdSpec", "2d": "X2d", "BOOL32": "Bool32"} {
85		if got := goName(in); got != want {
86			t.Errorf("%s => %s want %s", in, got, want)
87		}
88	}
89	if paramName("type") != "type_" {
90		t.Fatal("keyword parameter")
91	}
92}
93
94func TestRenderExpr(t *testing.T) {
95	n, err := parseXML("expr.xml", strings.NewReader(`<xcb header="test"><request name="R" opcode="1"><exprfield name="x" type="CARD32"><op op="*"><fieldref>n</fieldref><value>4</value></op></exprfield></request></xcb>`))
96	if err != nil {
97		t.Fatal(err)
98	}
99	got, err := renderExpr(n.Children[0].Children[0].Children[0], func(s string) string { return "int(v." + goName(s) + ")" }, nil)
100	if err != nil || got != "(int(v.N) * 4)" {
101		t.Fatalf("%s %v", got, err)
102	}
103}
104
105func TestFixedRequests(t *testing.T) {
106	ms := testModules(t)
107	for _, m := range ms {
108		requests, err := resolveRequests(m)
109		if err != nil {
110			t.Fatal(err)
111		}
112		for _, r := range requests {
113			decl, err := requestDecl(m, r)
114			if err != nil {
115				t.Fatal(err)
116			}
117			if !strings.Contains(decl, "if p==nil { return 0 }") {
118				t.Fatal("missing sticky-error guard")
119			}
120			if m.Header == "xproto" && r.Name == "MapWindow" {
121				if r.Fixed != 4 || len(r.Params) != 1 || r.Fields[0].Off != 0 {
122					t.Fatal("MapWindow layout")
123				}
124			}
125			if m.Header == "xfixes" && r.Name == "QueryVersion" {
126				if r.Fixed != 8 || r.DataByte != nil || r.Fields[1].Off != 4 {
127					t.Fatal("extension layout")
128				}
129			}
130		}
131	}
132}
133
134func TestListResolution(t *testing.T) {
135	for _, m := range testModules(t) {
136		rs, err := resolveRequests(m)
137		if err != nil {
138			t.Fatal(err)
139		}
140		for _, r := range rs {
141			switch r.Name {
142			case "InternAtom":
143				if r.Derived["name_len"] != "name" || len(r.Params) != 2 {
144					t.Fatal("InternAtom derived length")
145				}
146			case "ChangeProperty":
147				if len(r.Derived) != 0 || len(r.Params) != 7 {
148					t.Fatal("ChangeProperty explicit expression fields")
149				}
150			case "AddGlyphs":
151				if r.Derived["glyphs_len"] != "" {
152					t.Fatal("shared count must remain explicit")
153				}
154			case "QueryClientIds":
155				if r.Derived["num_specs"] != "specs" || r.Params[0].GoType != "[]ClientIdSpec" {
156					t.Fatal("fixed struct list")
157				}
158			case "SetFontPath":
159				if r.Params[0].GoType != "[]Str" || !r.Lists[0].Type.Variable {
160					t.Fatal("variable struct list")
161				}
162			}
163		}
164	}
165}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 1

Tags 1

↑↓ moveenter openesc close