v0.23.3 fc8669a

manager_test.go RawHistoryFolder

1package env_test
2
3import (
4	"context"
5	"os"
6	"os/exec"
7	"testing"
8
9	"github.com/bnema/dumber/internal/application/port"
10	"github.com/bnema/dumber/internal/infrastructure/env"
11	"github.com/stretchr/testify/assert"
12	"github.com/stretchr/testify/require"
13)
14
15func TestManager_ApplyEnvironment_SkiaEnv(t *testing.T) {
16	// Save original env vars and restore after test
17	origCPU := os.Getenv("WEBKIT_SKIA_CPU_PAINTING_THREADS")
18	origGPU := os.Getenv("WEBKIT_SKIA_GPU_PAINTING_THREADS")
19	origCPURender := os.Getenv("WEBKIT_SKIA_ENABLE_CPU_RENDERING")
20	t.Cleanup(func() {
21		restoreEnv("WEBKIT_SKIA_CPU_PAINTING_THREADS", origCPU)
22		restoreEnv("WEBKIT_SKIA_GPU_PAINTING_THREADS", origGPU)
23		restoreEnv("WEBKIT_SKIA_ENABLE_CPU_RENDERING", origCPURender)
24	})
25
26	tests := []struct {
27		name           string
28		settings       port.RenderingEnvSettings
29		presetEnv      map[string]string
30		expectedVars   map[string]string
31		unexpectedVars []string
32	}{
33		{
34			name: "CPU threads set when > 0",
35			settings: port.RenderingEnvSettings{
36				SkiaCPUPaintingThreads: 4,
37				SkiaGPUPaintingThreads: -1, // unset
38			},
39			expectedVars: map[string]string{
40				"WEBKIT_SKIA_CPU_PAINTING_THREADS": "4",
41			},
42			unexpectedVars: []string{"WEBKIT_SKIA_GPU_PAINTING_THREADS"},
43		},
44		{
45			name: "GPU threads set when >= 0",
46			settings: port.RenderingEnvSettings{
47				SkiaCPUPaintingThreads: 0, // unset
48				SkiaGPUPaintingThreads: 2,
49			},
50			expectedVars: map[string]string{
51				"WEBKIT_SKIA_GPU_PAINTING_THREADS": "2",
52			},
53			unexpectedVars: []string{"WEBKIT_SKIA_CPU_PAINTING_THREADS"},
54		},
55		{
56			name: "GPU threads 0 disables GPU tile painting",
57			settings: port.RenderingEnvSettings{
58				SkiaGPUPaintingThreads: 0,
59			},
60			expectedVars: map[string]string{
61				"WEBKIT_SKIA_GPU_PAINTING_THREADS": "0",
62			},
63		},
64		{
65			name: "CPU rendering enabled",
66			settings: port.RenderingEnvSettings{
67				SkiaEnableCPURendering: true,
68			},
69			expectedVars: map[string]string{
70				"WEBKIT_SKIA_ENABLE_CPU_RENDERING": "1",
71			},
72		},
73		{
74			name: "CPU rendering disabled (default)",
75			settings: port.RenderingEnvSettings{
76				SkiaEnableCPURendering: false,
77			},
78			unexpectedVars: []string{"WEBKIT_SKIA_ENABLE_CPU_RENDERING"},
79		},
80		{
81			name: "does not override existing CPU threads env var",
82			settings: port.RenderingEnvSettings{
83				SkiaCPUPaintingThreads: 8,
84			},
85			presetEnv: map[string]string{
86				"WEBKIT_SKIA_CPU_PAINTING_THREADS": "2",
87			},
88			expectedVars: map[string]string{
89				"WEBKIT_SKIA_CPU_PAINTING_THREADS": "2", // keeps original
90			},
91		},
92		{
93			name: "does not override existing GPU threads env var",
94			settings: port.RenderingEnvSettings{
95				SkiaGPUPaintingThreads: 4,
96			},
97			presetEnv: map[string]string{
98				"WEBKIT_SKIA_GPU_PAINTING_THREADS": "1",
99			},
100			expectedVars: map[string]string{
101				"WEBKIT_SKIA_GPU_PAINTING_THREADS": "1", // keeps original
102			},
103		},
104		{
105			name: "does not override existing CPU rendering env var",
106			settings: port.RenderingEnvSettings{
107				SkiaEnableCPURendering: true,
108			},
109			presetEnv: map[string]string{
110				"WEBKIT_SKIA_ENABLE_CPU_RENDERING": "0",
111			},
112			expectedVars: map[string]string{
113				"WEBKIT_SKIA_ENABLE_CPU_RENDERING": "0", // keeps original
114			},
115		},
116		{
117			name: "all unset by default",
118			settings: port.RenderingEnvSettings{
119				SkiaCPUPaintingThreads: 0,  // unset
120				SkiaGPUPaintingThreads: -1, // unset
121				SkiaEnableCPURendering: false,
122			},
123			unexpectedVars: []string{
124				"WEBKIT_SKIA_CPU_PAINTING_THREADS",
125				"WEBKIT_SKIA_GPU_PAINTING_THREADS",
126				"WEBKIT_SKIA_ENABLE_CPU_RENDERING",
127			},
128		},
129	}
130
131	for _, tt := range tests {
132		t.Run(tt.name, func(t *testing.T) {
133			// Clear env vars before each test
134			os.Unsetenv("WEBKIT_SKIA_CPU_PAINTING_THREADS")
135			os.Unsetenv("WEBKIT_SKIA_GPU_PAINTING_THREADS")
136			os.Unsetenv("WEBKIT_SKIA_ENABLE_CPU_RENDERING")
137
138			// Set any preset env vars
139			for k, v := range tt.presetEnv {
140				os.Setenv(k, v)
141			}
142
143			manager := env.NewManager()
144			ctx := context.Background()
145
146			err := manager.ApplyEnvironment(ctx, tt.settings)
147			require.NoError(t, err)
148
149			// Check expected vars are set correctly
150			for k, v := range tt.expectedVars {
151				actual := os.Getenv(k)
152				assert.Equal(t, v, actual, "env var %s", k)
153			}
154
155			// Check unexpected vars are not set (or were not set by us)
156			appliedVars := manager.GetAppliedVars()
157			for _, k := range tt.unexpectedVars {
158				_, wasApplied := appliedVars[k]
159				if tt.presetEnv[k] == "" {
160					assert.False(t, wasApplied, "env var %s should not be applied", k)
161				}
162			}
163		})
164	}
165}
166
167func restoreEnv(key, value string) {
168	if value == "" {
169		os.Unsetenv(key)
170	} else {
171		os.Setenv(key, value)
172	}
173}
174
175func TestIsFlatpak(t *testing.T) {
176	// IsFlatpak checks for /.flatpak-info file existence
177	// In normal test environment, this should return false
178	result := env.IsFlatpak()
179
180	// We can't easily mock filesystem, so just verify it returns a boolean
181	// and doesn't panic. In CI/dev environment it should be false.
182	assert.False(t, result, "should not detect Flatpak in test environment")
183}
184
185func TestIsPacman(t *testing.T) {
186	// Only run these tests on Arch-based systems with pacman
187	if _, err := os.Stat("/usr/bin/pacman"); os.IsNotExist(err) {
188		t.Skip("pacman not found, skipping Arch-specific tests")
189	}
190
191	tests := []struct {
192		name     string
193		binary   string
194		expected bool
195	}{
196		{
197			name:     "system binary owned by pacman",
198			binary:   "/usr/bin/bash",
199			expected: true, // bash is always installed via pacman on Arch
200		},
201		{
202			name:     "non-existent binary",
203			binary:   "/nonexistent/path/to/binary",
204			expected: false,
205		},
206	}
207
208	for _, tt := range tests {
209		t.Run(tt.name, func(t *testing.T) {
210			// We can't easily test IsPacman directly since it uses os.Executable()
211			// but we can test the underlying pacman -Qo logic with exec.Command
212			cmd := exec.Command("pacman", "-Qo", tt.binary)
213			err := cmd.Run()
214			if tt.expected {
215				assert.NoError(t, err, "pacman should own %s", tt.binary)
216			} else {
217				assert.Error(t, err, "pacman should not own %s", tt.binary)
218			}
219		})
220	}
221}
222
223func TestIsPacman_NonArchSystem(t *testing.T) {
224	// On non-Arch systems, IsPacman should return false (pacman not found)
225	if _, err := os.Stat("/usr/bin/pacman"); err == nil {
226		t.Skip("pacman found, skipping non-Arch test")
227	}
228
229	result := env.IsPacman()
230	assert.False(t, result, "should return false when pacman is not installed")
231}

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 8

Tags 42

↑↓ moveenter openesc close