v0.1.0 47aaa0f

image_test.go RawHistoryFolder

1//go:build linux
2
3package systemtest
4
5import (
6	"context"
7	"encoding/json"
8	"fmt"
9	"image/color"
10	"os"
11	"path/filepath"
12	"regexp"
13	"sort"
14	"testing"
15	"time"
16
17	"github.com/bnema/nefergui/internal/harness"
18)
19
20func TestListImage(t *testing.T) {
21	requireHarness(t)
22	bin := binary(t)
23	for _, scale := range []int{1, 2} {
24		t.Run(fmt.Sprint(scale), func(t *testing.T) {
25			for _, changing := range []bool{false, true} {
26				name := "static"
27				frames := 24
28				if changing {
29					name = "changing"
30					frames = 120
31				}
32				t.Run(name, func(t *testing.T) {
33					root := filepath.Join(t.TempDir(), "artifacts")
34					args := []string{bin, "--static", "--image", "--scale", fmt.Sprint(scale), "--frames", fmt.Sprint(frames)}
35					if changing {
36						args = append(args, "--changing-image")
37					}
38					res, code := harness.Run(context.Background(), harness.Options{Size: "800x600", Scale: "1", Layout: "us", Background: background, Out: root, Timeout: 60 * time.Second, ReadyTimeout: 10 * time.Second, Client: args})
39					t.Logf("artifacts=%s code=%d status=%s", root, code, res.Status)
40					if code != harness.Pass {
41						data, _ := os.ReadFile(filepath.Join(root, "logs", "client.stderr"))
42						t.Fatalf("harness: %s %s", res.Error, data)
43					}
44					files, _ := filepath.Glob(filepath.Join(res.Artifacts["debug"], "readback-*.png"))
45					sort.Strings(files)
46					if len(files) == 0 {
47						t.Fatal("missing readback")
48					}
49					img, err := harness.LoadPNG(files[len(files)-1])
50					if err != nil {
51						t.Fatal(err)
52					}
53					if !changing {
54						bg := color.NRGBA{17, 17, 17, 255}
55						probes := []struct {
56							name string
57							x, y int
58							want color.NRGBA
59						}{
60							{"red", 108, 108, color.NRGBA{136, 8, 8, 255}},
61							{"green", 148, 108, color.NRGBA{8, 136, 8, 255}},
62							{"blue", 108, 148, color.NRGBA{8, 8, 136, 255}},
63							{"yellow", 148, 148, color.NRGBA{136, 136, 8, 255}},
64							{"round corner", 100, 100, bg},
65							{"between images", 170, 130, bg},
66							{"second image", 220, 120, color.NRGBA{255, 128, 0, 255}},
67						}
68						for _, p := range probes {
69							x, y := p.x*scale, p.y*scale
70							t.Logf("scale=%d %s (%d,%d)=%v want=%v", scale, p.name, x, y, color.NRGBAModel.Convert(img.At(x, y)), p.want)
71							if err := harness.PixelProbe(img, x, y, p.want, 4); err != nil {
72								t.Error(err)
73							}
74						}
75					}
76					if changing {
77						data, err := os.ReadFile(filepath.Join(res.Artifacts["debug"], "resource-summary.json"))
78						if err != nil {
79							t.Fatal(err)
80						}
81						var sum summary
82						if err = json.Unmarshal(data, &sum); err != nil {
83							t.Fatal(err)
84						}
85						t.Logf("resources=%+v", sum)
86						if sum.Frames != 120 || sum.ImagesAfter != 0 || sum.FDPeak-sum.FDStart > 2 || sum.FDAfter > sum.FDStart {
87							t.Errorf("unstable resources: %+v", sum)
88						}
89						rows := jsonLines[timing](t, filepath.Join(res.Artifacts["debug"], "frame-timings.jsonl"))
90						if len(rows) != 120 {
91							t.Errorf("frame timings=%d", len(rows))
92						}
93						for _, row := range rows {
94							if row.Images < 1 || row.Images > 6 || row.FDCount > sum.FDStart+2 {
95								t.Errorf("unstable frame: %+v", row)
96								break
97							}
98						}
99					}
100					if os.Getenv("NEFERGUI_VULKAN_VALIDATION") == "1" {
101						data, err := os.ReadFile(res.Artifacts["client_stderr"])
102						if err != nil {
103							t.Fatal(err)
104						}
105						if regexp.MustCompile(`(?i)(NEFERGUI_VULKAN_VALIDATION_(ERROR|WARNING)|validation (error|warning))`).Match(data) {
106							t.Errorf("validation: %s", data)
107						}
108					}
109				})
110			}
111		})
112	}
113}

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 12

↑↓ moveenter openesc close