1package bootstrap
2
3import "slices"
4
5import "testing"
6
7func TestShouldPreloadLayerShell_WaylandWithoutPreloadReturnsTrue(t *testing.T) {
8 env := map[string]string{
9 "WAYLAND_DISPLAY": "wayland-1",
10 "LD_PRELOAD": "",
11 }
12
13 if !ShouldPreloadLayerShell(env) {
14 t.Fatalf("expected preload to be required")
15 }
16}
17
18func TestFindLayerShellLibrary_UsesLDLibraryPathCandidates(t *testing.T) {
19 customCandidate := "/opt/custom/lib/libgtk4-layer-shell.so.0"
20 got := FindLayerShellLibrary(map[string]string{
21 "LD_LIBRARY_PATH": "/opt/custom/lib",
22 }, func(path string) bool {
23 return path == customCandidate
24 })
25
26 if got != customCandidate {
27 t.Fatalf("expected %q, got %q", customCandidate, got)
28 }
29}
30
31func TestShouldPreloadLayerShell_AlreadyPreloadedReturnsFalse(t *testing.T) {
32 env := map[string]string{
33 "WAYLAND_DISPLAY": "wayland-1",
34 "LD_PRELOAD": "/usr/lib/libgtk4-layer-shell.so.0",
35 }
36
37 if ShouldPreloadLayerShell(env) {
38 t.Fatalf("expected preload to be skipped")
39 }
40}
41
42func TestShouldPreloadLayerShell_NoWaylandReturnsFalse(t *testing.T) {
43 if ShouldPreloadLayerShell(map[string]string{}) {
44 t.Fatalf("expected preload to be skipped outside Wayland")
45 }
46}
47
48func TestLayerShellPreloadPresent_DetectsLoadedLibrarySubstring(t *testing.T) {
49 env := map[string]string{
50 "LD_PRELOAD": "/nix/store/hash-libgtk4-layer-shell.so.0 /tmp/other.so",
51 }
52
53 if !LayerShellPreloadPresent(env) {
54 t.Fatalf("expected preload presence to be detected")
55 }
56}
57
58func TestFindLayerShellLibrary_ReturnsFirstExistingCandidate(t *testing.T) {
59 got := FindLayerShellLibrary(map[string]string{}, func(path string) bool {
60 return path == layerShellLibraryCandidates[1]
61 })
62
63 if got != layerShellLibraryCandidates[1] {
64 t.Fatalf("expected %q, got %q", layerShellLibraryCandidates[1], got)
65 }
66}
67
68func TestFindLayerShellLibrary_ReturnsArm64Candidate(t *testing.T) {
69 arm64Candidate := "/usr/lib/aarch64-linux-gnu/libgtk4-layer-shell.so.0"
70 got := FindLayerShellLibrary(map[string]string{}, func(path string) bool {
71 return path == arm64Candidate
72 })
73
74 if got != arm64Candidate {
75 t.Fatalf("expected %q, got %q", arm64Candidate, got)
76 }
77}
78
79func TestFindLayerShellLibrary_NoMatchReturnsEmpty(t *testing.T) {
80 if got := FindLayerShellLibrary(map[string]string{}, func(string) bool { return false }); got != "" {
81 t.Fatalf("expected empty result, got %q", got)
82 }
83}
84
85func TestLayerShellLibrarySearchPaths_IncludesLDLibraryPathCandidates(t *testing.T) {
86 paths := layerShellLibrarySearchPaths(map[string]string{
87 "LD_LIBRARY_PATH": "/opt/custom/lib:/nix/store/abc/lib",
88 })
89
90 wantCustom := "/opt/custom/lib/libgtk4-layer-shell.so.0"
91 wantNix := "/nix/store/abc/lib/libgtk4-layer-shell.so.0"
92 if !containsString(paths, wantCustom) {
93 t.Fatalf("expected custom search path %q in %#v", wantCustom, paths)
94 }
95 if !containsString(paths, wantNix) {
96 t.Fatalf("expected nix search path %q in %#v", wantNix, paths)
97 }
98}
99
100func TestLayerShellPreloadEnv_SetsLDPreloadWhenEmpty(t *testing.T) {
101 env := LayerShellPreloadEnv(map[string]string{"PATH": "/usr/bin"}, "/usr/lib/libgtk4-layer-shell.so.0")
102
103 if env["LD_PRELOAD"] != "/usr/lib/libgtk4-layer-shell.so.0" {
104 t.Fatalf("expected LD_PRELOAD to be set, got %q", env["LD_PRELOAD"])
105 }
106 if env["PATH"] != "/usr/bin" {
107 t.Fatalf("expected unrelated env to be preserved")
108 }
109}
110
111func TestLayerShellPreloadEnv_PrependsLibraryToExistingLDPreload(t *testing.T) {
112 env := LayerShellPreloadEnv(map[string]string{"LD_PRELOAD": "/tmp/other.so"}, "/usr/lib/libgtk4-layer-shell.so.0")
113
114 want := "/usr/lib/libgtk4-layer-shell.so.0 /tmp/other.so"
115 if env["LD_PRELOAD"] != want {
116 t.Fatalf("expected LD_PRELOAD %q, got %q", want, env["LD_PRELOAD"])
117 }
118}
119
120func containsString(items []string, want string) bool {
121 return slices.Contains(items, want)
122}