1package runtimeprofile
2
3import (
4 "errors"
5 "strings"
6 "testing"
7
8 "github.com/stretchr/testify/require"
9)
10
11func TestResolve_ProdPreservesSharedLayout(t *testing.T) {
12 profile, err := Resolve(ResolveInput{
13 Env: func(string) string { return "" },
14 Engine: "webkit",
15 CWD: func() (string, error) { return "/repo", nil },
16 Base: BasePaths{
17 ConfigHome: "/home/u/.config/dumber",
18 DataHome: "/home/u/.local/share/dumber",
19 StateHome: "/home/u/.local/state/dumber",
20 CacheHome: "/home/u/.cache/dumber",
21 },
22 })
23 require.NoError(t, err)
24 require.Equal(t, ModeProd, profile.Mode)
25 require.Equal(t, "/home/u/.config/dumber", profile.Shared.ConfigDir)
26 require.Equal(t, "/home/u/.local/share/dumber", profile.Shared.DataDir)
27 require.Equal(t, "/home/u/.local/state/dumber", profile.Shared.StateDir)
28 require.Equal(t, "/home/u/.cache/dumber", profile.Shared.CacheDir)
29 require.Equal(t, "/home/u/.local/state/dumber/logs", profile.Shared.LogDir)
30 require.Equal(t, "/home/u/.local/share/dumber/cef_user_data", profile.CEFUserDataDir())
31 require.Equal(t, "/home/u/.local/share/dumber", profile.WebKitDataDir())
32 require.Equal(t, "/home/u/.local/state/dumber/webkit-cache", profile.WebKitCacheDir())
33}
34
35func TestResolve_DevCEF_SeparatesSharedEngineAndIPC(t *testing.T) {
36 profile, err := Resolve(ResolveInput{
37 Env: func(key string) string {
38 if key == "ENV" {
39 return "dev"
40 }
41 return ""
42 },
43 Engine: "cef",
44 CWD: func() (string, error) { return "/repo", nil },
45 })
46 require.NoError(t, err)
47 require.Equal(t, ModeDev, profile.Mode)
48 require.Equal(t, "/repo/.dev/dumber/config", profile.Shared.ConfigDir)
49 require.Equal(t, "/repo/.dev/dumber/data", profile.Shared.DataDir)
50 require.Equal(t, "/repo/.dev/dumber/engines/cef/data", profile.CEFUserDataDir())
51 require.Equal(t, "/repo/.dev/dumber/runtime/cef/browser-launch.sock", profile.IPC.BrowserLaunchSocket)
52}
53
54func TestResolve_DevIPCPathStaysShortForLongWorktrees(t *testing.T) {
55 longWorktree := "/tmp/" + strings.Repeat("long-worktree-name-", 5) + "project"
56
57 profile, err := Resolve(ResolveInput{
58 Env: func(key string) string {
59 switch key {
60 case "ENV":
61 return "dev"
62 case "XDG_RUNTIME_DIR":
63 return "/run/user/1000"
64 default:
65 return ""
66 }
67 },
68 Engine: "cef",
69 CWD: func() (string, error) { return longWorktree, nil },
70 })
71
72 require.NoError(t, err)
73 require.Less(t, len(profile.IPC.BrowserLaunchSocket), 108)
74 require.True(t, strings.HasPrefix(profile.IPC.BrowserLaunchSocket, "/run/user/1000/dumber/dev-"))
75 require.Contains(t, profile.IPC.BrowserLaunchSocket, "/cef/browser-launch.sock")
76}
77
78func TestResolve_DevIPCPathFallsBackToTMPDIRWhenRuntimeDirWouldExceedSocketLimit(t *testing.T) {
79 longRuntimeDir := "/tmp/" + strings.Repeat("long-runtime-dir-name-", 5) + "run"
80
81 profile, err := Resolve(ResolveInput{
82 Env: func(key string) string {
83 switch key {
84 case "ENV":
85 return "dev"
86 case "XDG_RUNTIME_DIR":
87 return longRuntimeDir
88 case "TMPDIR":
89 return "/run/user/1000"
90 default:
91 return ""
92 }
93 },
94 Engine: "cef",
95 CWD: func() (string, error) { return "/repo", nil },
96 })
97
98 require.NoError(t, err)
99 require.Less(t, len(profile.IPC.BrowserLaunchSocket), 104)
100 require.NotContains(t, profile.IPC.BrowserLaunchSocket, longRuntimeDir)
101 require.True(t, strings.HasPrefix(profile.IPC.BrowserLaunchSocket, "/run/user/1000/dumber/dev-"))
102 require.Contains(t, profile.IPC.BrowserLaunchSocket, "/cef/browser-launch.sock")
103}
104
105func TestResolve_DevIPCPathErrorsWhenNoShortBaseExists(t *testing.T) {
106 longWorktree := "/tmp/" + strings.Repeat("long-worktree-name-", 8) + "project"
107
108 _, err := Resolve(ResolveInput{
109 Env: func(key string) string {
110 if key == "ENV" {
111 return "dev"
112 }
113 return ""
114 },
115 Engine: "cef",
116 CWD: func() (string, error) { return longWorktree, nil },
117 })
118
119 require.Error(t, err)
120 require.Contains(t, err.Error(), "browser launch socket path too long")
121}
122
123func TestResolve_DevWebKitAndCEF_HaveDifferentTechnicalNamespaces(t *testing.T) {
124 devEnv := func(key string) string {
125 if key == "ENV" {
126 return "dev"
127 }
128 return ""
129 }
130 repoCWD := func() (string, error) { return "/repo", nil }
131
132 cefProfile, err := Resolve(ResolveInput{Env: devEnv, Engine: "cef", CWD: repoCWD})
133 require.NoError(t, err)
134 wkProfile, err := Resolve(ResolveInput{Env: devEnv, Engine: "webkit", CWD: repoCWD})
135 require.NoError(t, err)
136
137 require.NotEqual(t, cefProfile.EnginePaths.RootDir, wkProfile.EnginePaths.RootDir)
138 require.NotEqual(t, cefProfile.IPC.RuntimeDir, wkProfile.IPC.RuntimeDir)
139 require.NotEqual(t, cefProfile.IPC.BrowserLaunchSocket, wkProfile.IPC.BrowserLaunchSocket)
140}
141
142func TestResolve_DefaultsEmptyEngineToWebKit(t *testing.T) {
143 profile, err := Resolve(ResolveInput{
144 Env: func(string) string { return "" },
145 CWD: func() (string, error) { return "/repo", nil },
146 Base: BasePaths{StateHome: "/state", DataHome: "/data"},
147 })
148 require.NoError(t, err)
149 require.Equal(t, "webkit", profile.Engine)
150 require.Equal(t, "/state/runtime/webkit/browser-launch.sock", profile.IPC.BrowserLaunchSocket)
151}
152
153func TestResolve_NormalizesEngineWhitespaceAndCase(t *testing.T) {
154 profile, err := Resolve(ResolveInput{
155 Env: func(string) string { return "" },
156 Engine: " CEF ",
157 CWD: func() (string, error) { return "/repo", nil },
158 Base: BasePaths{StateHome: "/state", DataHome: "/data"},
159 })
160 require.NoError(t, err)
161 require.Equal(t, "cef", profile.Engine)
162 require.Equal(t, "/state/runtime/cef/browser-launch.sock", profile.IPC.BrowserLaunchSocket)
163}
164
165func TestResolve_DefaultsUnknownEngineToWebKit(t *testing.T) {
166 profile, err := Resolve(ResolveInput{
167 Env: func(string) string { return "" },
168 Engine: "wekbit",
169 CWD: func() (string, error) { return "/repo", nil },
170 Base: BasePaths{StateHome: "/state", DataHome: "/data"},
171 })
172 require.NoError(t, err)
173 require.Equal(t, "webkit", profile.Engine)
174 require.Equal(t, "/state/runtime/webkit/browser-launch.sock", profile.IPC.BrowserLaunchSocket)
175}
176
177func TestResolve_DevFailsWhenCWDUnavailable(t *testing.T) {
178 want := errors.New("boom")
179 _, err := Resolve(ResolveInput{
180 Env: func(key string) string {
181 if key == "ENV" {
182 return "dev"
183 }
184 return ""
185 },
186 Engine: "cef",
187 CWD: func() (string, error) { return "", want },
188 })
189 require.ErrorIs(t, err, want)
190}