Files
goclaw/internal/skills/package_runtime_paths_test.go

162 lines
4.5 KiB
Go

package skills
import (
"os"
"path/filepath"
"strings"
"testing"
)
func TestNpmCommandEnvUsesRuntimePrefix(t *testing.T) {
runtimeDir := t.TempDir()
t.Setenv("RUNTIME_DIR", runtimeDir)
t.Setenv("NPM_CONFIG_PREFIX", "")
t.Setenv("NODE_PATH", "")
t.Setenv("PATH", "/usr/bin")
env := npmCommandEnv()
wantPrefix := filepath.Join(runtimeDir, "npm-global")
wantBin := npmGlobalBinDir()
wantNodePath := filepath.Join(wantPrefix, "lib", "node_modules")
if !envContainsExact(env, "NPM_CONFIG_PREFIX="+wantPrefix) {
t.Fatalf("npmCommandEnv missing NPM_CONFIG_PREFIX=%q", wantPrefix)
}
if !envContainsPrefixValue(env, "PATH=", wantBin) {
t.Fatalf("npmCommandEnv PATH does not start with %q", wantBin)
}
if !envContainsPrefixValue(env, "NODE_PATH=", wantNodePath) {
t.Fatalf("npmCommandEnv NODE_PATH does not start with %q", wantNodePath)
}
}
func TestEnsureNpmGlobalEnvPrependsProcessPath(t *testing.T) {
runtimeDir := t.TempDir()
t.Setenv("RUNTIME_DIR", runtimeDir)
t.Setenv("NPM_CONFIG_PREFIX", "")
t.Setenv("PATH", "/usr/bin")
ensureNpmGlobalEnv()
wantBin := npmGlobalBinDir()
if got := os.Getenv("PATH"); !strings.HasPrefix(got, wantBin+string(os.PathListSeparator)) {
t.Fatalf("PATH = %q, want prefix %q", got, wantBin)
}
}
func TestFindRuntimeExecutableFindsNpmGlobalBinary(t *testing.T) {
runtimeDir := t.TempDir()
t.Setenv("RUNTIME_DIR", runtimeDir)
t.Setenv("NPM_CONFIG_PREFIX", "")
binDir := npmGlobalBinDir()
if err := os.MkdirAll(binDir, 0o755); err != nil {
t.Fatal(err)
}
wantPath := filepath.Join(binDir, "openrouter")
if err := os.WriteFile(wantPath, []byte("#!/bin/sh\n"), 0o755); err != nil {
t.Fatal(err)
}
got, ok := FindRuntimeExecutable("openrouter")
if !ok {
t.Fatalf("FindRuntimeExecutable did not find npm global binary")
}
if got != wantPath {
t.Fatalf("FindRuntimeExecutable path = %q, want %q", got, wantPath)
}
}
func TestFindRuntimeExecutableFindsGoogleWorkspaceBinary(t *testing.T) {
runtimeDir := t.TempDir()
t.Setenv("RUNTIME_DIR", runtimeDir)
t.Setenv("NPM_CONFIG_PREFIX", "")
binDir := npmGlobalBinDir()
if err := os.MkdirAll(binDir, 0o755); err != nil {
t.Fatal(err)
}
wantPath := filepath.Join(binDir, "gws")
if err := os.WriteFile(wantPath, []byte("#!/bin/sh\n"), 0o755); err != nil {
t.Fatal(err)
}
got, ok := FindRuntimeExecutable("gws")
if !ok {
t.Fatalf("FindRuntimeExecutable did not find gws runtime binary")
}
if got != wantPath {
t.Fatalf("FindRuntimeExecutable path = %q, want %q", got, wantPath)
}
}
func TestFindRuntimeExecutableFindsNpmPackageCliAlias(t *testing.T) {
runtimeDir := t.TempDir()
t.Setenv("RUNTIME_DIR", runtimeDir)
t.Setenv("NPM_CONFIG_PREFIX", "")
pkgDir := filepath.Join(runtimeDir, "npm-global", "lib", "node_modules", "openrouter-cli")
if err := os.MkdirAll(pkgDir, 0o755); err != nil {
t.Fatal(err)
}
manifest := []byte(`{"name":"openrouter-cli","bin":{"orc":"dist/index.js"}}`)
if err := os.WriteFile(filepath.Join(pkgDir, "package.json"), manifest, 0o644); err != nil {
t.Fatal(err)
}
binDir := npmGlobalBinDir()
if err := os.MkdirAll(binDir, 0o755); err != nil {
t.Fatal(err)
}
wantPath := filepath.Join(binDir, "orc")
if err := os.WriteFile(wantPath, []byte("#!/bin/sh\n"), 0o755); err != nil {
t.Fatal(err)
}
got, ok := FindRuntimeExecutable("openrouter")
if !ok {
t.Fatalf("FindRuntimeExecutable did not find npm package CLI alias")
}
if got != wantPath {
t.Fatalf("FindRuntimeExecutable alias path = %q, want %q", got, wantPath)
}
}
func TestFullImagePreinstallsGoogleWorkspaceCLI(t *testing.T) {
raw, err := os.ReadFile(filepath.Join("..", "..", "Dockerfile"))
if err != nil {
t.Fatal(err)
}
dockerfile := string(raw)
if !strings.Contains(dockerfile, "ENABLE_FULL_SKILLS") {
t.Fatal("Dockerfile contract test cannot locate ENABLE_FULL_SKILLS block")
}
if !strings.Contains(dockerfile, "@googleworkspace/cli@0.22.5") {
t.Fatal("full runtime image must preinstall @googleworkspace/cli@0.22.5")
}
}
func TestFindRuntimeExecutableRejectsPathLikeNames(t *testing.T) {
if got, ok := FindRuntimeExecutable("../openrouter"); ok || got != "" {
t.Fatalf("FindRuntimeExecutable path-like name = %q, %v; want empty false", got, ok)
}
}
func envContainsExact(env []string, want string) bool {
for _, item := range env {
if item == want {
return true
}
}
return false
}
func envContainsPrefixValue(env []string, key, wantPrefix string) bool {
for _, item := range env {
if strings.HasPrefix(item, key) {
return strings.HasPrefix(strings.TrimPrefix(item, key), wantPrefix)
}
}
return false
}