diff --git a/internal/sandbox/adapters.go b/internal/sandbox/adapters.go index d65ac457d..30e1395fb 100644 --- a/internal/sandbox/adapters.go +++ b/internal/sandbox/adapters.go @@ -7,6 +7,7 @@ import ( type BackendOptions struct { GOOS string LookupExecutable func(string) (string, error) + DetectWSL func() WSLInfo } type Backend struct { @@ -53,6 +54,7 @@ func SelectBackend(options BackendOptions) Backend { return NewSandboxManager(SandboxManagerOptions{ GOOS: options.GOOS, LookupExecutable: options.LookupExecutable, + DetectWSL: options.DetectWSL, }).Backend() } diff --git a/internal/sandbox/adapters_test.go b/internal/sandbox/adapters_test.go index 10288f6a2..4306902b1 100644 --- a/internal/sandbox/adapters_test.go +++ b/internal/sandbox/adapters_test.go @@ -45,6 +45,7 @@ func TestSelectBackendChoosesPlatformAdapterWithFallback(t *testing.T) { } return "", errors.New("missing") }, + DetectWSL: func() WSLInfo { return WSLInfo{} }, }) if backend.Name != BackendUnavailable || backend.Available { t.Fatalf("linux backend = %#v, want native sandbox unavailable without Linux helper", backend) @@ -54,6 +55,20 @@ func TestSelectBackendChoosesPlatformAdapterWithFallback(t *testing.T) { } }) + t.Run("linux helper missing under WSL reports WSL fallback", func(t *testing.T) { + backend := SelectBackend(BackendOptions{ + GOOS: "linux", + LookupExecutable: func(string) (string, error) { return "", errors.New("missing") }, + DetectWSL: func() WSLInfo { return WSLInfo{IsWSL: true, IsWSL2: true} }, + }) + if backend.Name != BackendWSL || backend.Available || !backend.Fallback { + t.Fatalf("linux backend = %#v, want explicit WSL fallback", backend) + } + if !strings.Contains(backend.Message, "WSL2") { + t.Fatalf("linux fallback message = %q, want WSL2 diagnostic", backend.Message) + } + }) + t.Run("darwin sandbox exec available", func(t *testing.T) { backend := SelectBackend(BackendOptions{ GOOS: "darwin", diff --git a/internal/sandbox/manager.go b/internal/sandbox/manager.go index 44fd6f0a0..eaf604b00 100644 --- a/internal/sandbox/manager.go +++ b/internal/sandbox/manager.go @@ -51,6 +51,7 @@ const ( type SandboxManagerOptions struct { GOOS string LookupExecutable func(string) (string, error) + DetectWSL func() WSLInfo Backend Backend } @@ -96,7 +97,7 @@ func NewSandboxManager(options SandboxManagerOptions) SandboxManager { goos = runtime.GOOS } if backend.Name == "" { - backend = selectPlatformBackend(goos, options.LookupExecutable) + backend = selectPlatformBackend(goos, options.LookupExecutable, options.DetectWSL) } if backend.Platform == "" { backend.Platform = goos @@ -168,10 +169,13 @@ func lookupExecutable(name string) (string, error) { return "", errors.New("executable file not found") } -func selectPlatformBackend(goos string, lookup func(string) (string, error)) Backend { +func selectPlatformBackend(goos string, lookup func(string) (string, error), detect func() WSLInfo) Backend { if lookup == nil { lookup = lookupExecutable } + if detect == nil { + detect = detectWSL + } switch goos { case "linux": if helper, err := lookup(LinuxSandboxHelperName); err == nil && helper != "" { @@ -180,7 +184,7 @@ func selectPlatformBackend(goos string, lookup func(string) (string, error)) Bac } return nativeBackend(goos, BackendLinuxBwrap, helper, "Linux sandbox helper available") } - if info := detectWSL(); info.IsWSL { + if info := detect(); info.IsWSL { return wslBackend(goos, info) } return unavailableBackend(goos, "Linux sandbox helper is not available")