Files
gastown/internal/workspace/find_test.go
Johann Dirry 3d5a66f850 Fixing unit tests on windows (#813)
* Add Windows stub for orphan cleanup

* Fix account switch tests on Windows

* Make query session events test portable

* Disable beads daemon in query session events test

* Add Windows bd stubs for sling tests

* Make expandOutputPath test OS-agnostic

* Make role_agents test Windows-friendly

* Make config path tests OS-agnostic

* Make HealthCheckStateFile test OS-agnostic

* Skip orphan process check on Windows

* Normalize sparse checkout detail paths

* Make dog path tests OS-agnostic

* Fix bare repo refspec config on Windows

* Add Windows process detection for locks

* Add Windows CI workflow

* Make mail path tests OS-agnostic

* Skip plugin file mode test on Windows

* Skip tmux-dependent polecat tests on Windows

* Normalize polecat paths and AGENTS.md content

* Make beads init failure test Windows-friendly

* Skip rig agent bead init test on Windows

* Make XDG path tests OS-agnostic

* Make exec tests portable on Windows

* Adjust atomic write tests for Windows

* Make wisp tests Windows-friendly

* Make workspace find tests OS-agnostic

* Fix Windows rig add integration test

* Make sling var logging Windows-friendly

* Fix sling attached molecule update ordering

---------

Co-authored-by: Johann Dirry <johann.dirry@microsea.at>
2026-01-20 14:17:35 -08:00

281 lines
7.1 KiB
Go

package workspace
import (
"os"
"path/filepath"
"testing"
)
func realPath(t *testing.T, path string) string {
t.Helper()
real, err := filepath.EvalSymlinks(path)
if err != nil {
t.Fatalf("realpath: %v", err)
}
return real
}
func TestFindWithPrimaryMarker(t *testing.T) {
// Create temp workspace structure
root := realPath(t, t.TempDir())
mayorDir := filepath.Join(root, "mayor")
if err := os.MkdirAll(mayorDir, 0755); err != nil {
t.Fatalf("mkdir: %v", err)
}
townFile := filepath.Join(mayorDir, "town.json")
if err := os.WriteFile(townFile, []byte(`{"type":"town"}`), 0644); err != nil {
t.Fatalf("write: %v", err)
}
// Create nested directory
nested := filepath.Join(root, "some", "deep", "path")
if err := os.MkdirAll(nested, 0755); err != nil {
t.Fatalf("mkdir nested: %v", err)
}
// Find from nested should return root
found, err := Find(nested)
if err != nil {
t.Fatalf("Find: %v", err)
}
if found != root {
t.Errorf("Find = %q, want %q", found, root)
}
}
func TestFindWithSecondaryMarker(t *testing.T) {
// Create temp workspace with just mayor/ directory
root := realPath(t, t.TempDir())
mayorDir := filepath.Join(root, "mayor")
if err := os.MkdirAll(mayorDir, 0755); err != nil {
t.Fatalf("mkdir: %v", err)
}
// Create nested directory
nested := filepath.Join(root, "rigs", "test")
if err := os.MkdirAll(nested, 0755); err != nil {
t.Fatalf("mkdir nested: %v", err)
}
// Find from nested should return root
found, err := Find(nested)
if err != nil {
t.Fatalf("Find: %v", err)
}
if found != root {
t.Errorf("Find = %q, want %q", found, root)
}
}
func TestFindNotFound(t *testing.T) {
// Create temp dir with no markers
dir := t.TempDir()
found, err := Find(dir)
if err != nil {
t.Fatalf("Find: %v", err)
}
if found != "" {
t.Errorf("Find = %q, want empty string", found)
}
}
func TestFindOrErrorNotFound(t *testing.T) {
dir := t.TempDir()
_, err := FindOrError(dir)
if err != ErrNotFound {
t.Errorf("FindOrError = %v, want ErrNotFound", err)
}
}
func TestFindAtRoot(t *testing.T) {
// Create workspace at temp root level
root := realPath(t, t.TempDir())
mayorDir := filepath.Join(root, "mayor")
if err := os.MkdirAll(mayorDir, 0755); err != nil {
t.Fatalf("mkdir: %v", err)
}
townFile := filepath.Join(mayorDir, "town.json")
if err := os.WriteFile(townFile, []byte(`{"type":"town"}`), 0644); err != nil {
t.Fatalf("write: %v", err)
}
// Find from root should return root
found, err := Find(root)
if err != nil {
t.Fatalf("Find: %v", err)
}
if found != root {
t.Errorf("Find = %q, want %q", found, root)
}
}
func TestIsWorkspace(t *testing.T) {
root := t.TempDir()
// Not a workspace initially
is, err := IsWorkspace(root)
if err != nil {
t.Fatalf("IsWorkspace: %v", err)
}
if is {
t.Error("expected not a workspace initially")
}
// Add primary marker (mayor/town.json)
mayorDir := filepath.Join(root, "mayor")
if err := os.MkdirAll(mayorDir, 0755); err != nil {
t.Fatalf("mkdir: %v", err)
}
townFile := filepath.Join(mayorDir, "town.json")
if err := os.WriteFile(townFile, []byte(`{"type":"town"}`), 0644); err != nil {
t.Fatalf("write: %v", err)
}
// Now is a workspace
is, err = IsWorkspace(root)
if err != nil {
t.Fatalf("IsWorkspace: %v", err)
}
if !is {
t.Error("expected to be a workspace")
}
}
func TestFindFromSymlinkedDir(t *testing.T) {
root := realPath(t, t.TempDir())
mayorDir := filepath.Join(root, "mayor")
if err := os.MkdirAll(mayorDir, 0755); err != nil {
t.Fatalf("mkdir: %v", err)
}
townFile := filepath.Join(mayorDir, "town.json")
if err := os.WriteFile(townFile, []byte(`{"type":"town"}`), 0644); err != nil {
t.Fatalf("write: %v", err)
}
linkTarget := filepath.Join(root, "actual")
if err := os.MkdirAll(linkTarget, 0755); err != nil {
t.Fatalf("mkdir: %v", err)
}
linkName := filepath.Join(root, "linked")
if err := os.Symlink(linkTarget, linkName); err != nil {
t.Skipf("symlink not supported: %v", err)
}
found, err := Find(linkName)
if err != nil {
t.Fatalf("Find: %v", err)
}
if found != root {
t.Errorf("Find = %q, want %q", found, root)
}
}
func TestFindPreservesSymlinkPath(t *testing.T) {
realRoot := t.TempDir()
resolved, err := filepath.EvalSymlinks(realRoot)
if err != nil {
t.Fatalf("EvalSymlinks: %v", err)
}
symRoot := filepath.Join(t.TempDir(), "symlink-workspace")
if err := os.Symlink(resolved, symRoot); err != nil {
t.Skipf("symlink not supported: %v", err)
}
mayorDir := filepath.Join(symRoot, "mayor")
if err := os.MkdirAll(mayorDir, 0755); err != nil {
t.Fatalf("mkdir: %v", err)
}
townFile := filepath.Join(mayorDir, "town.json")
if err := os.WriteFile(townFile, []byte(`{}`), 0644); err != nil {
t.Fatalf("write: %v", err)
}
subdir := filepath.Join(symRoot, "rigs", "project", "polecats", "worker")
if err := os.MkdirAll(subdir, 0755); err != nil {
t.Fatalf("mkdir: %v", err)
}
townRoot, err := Find(subdir)
if err != nil {
t.Fatalf("Find: %v", err)
}
if townRoot != symRoot {
t.Errorf("Find returned %q, want %q (symlink path preserved)", townRoot, symRoot)
}
relPath, err := filepath.Rel(townRoot, subdir)
if err != nil {
t.Fatalf("Rel: %v", err)
}
if filepath.ToSlash(relPath) != "rigs/project/polecats/worker" {
t.Errorf("Rel = %q, want 'rigs/project/polecats/worker'", relPath)
}
}
func TestFindSkipsNestedWorkspaceInWorktree(t *testing.T) {
root := realPath(t, t.TempDir())
if err := os.MkdirAll(filepath.Join(root, "mayor"), 0755); err != nil {
t.Fatalf("mkdir: %v", err)
}
if err := os.WriteFile(filepath.Join(root, "mayor", "town.json"), []byte(`{"name":"outer"}`), 0644); err != nil {
t.Fatalf("write: %v", err)
}
polecatDir := filepath.Join(root, "myrig", "polecats", "worker")
if err := os.MkdirAll(filepath.Join(polecatDir, "mayor"), 0755); err != nil {
t.Fatalf("mkdir: %v", err)
}
if err := os.WriteFile(filepath.Join(polecatDir, "mayor", "town.json"), []byte(`{"name":"inner"}`), 0644); err != nil {
t.Fatalf("write: %v", err)
}
found, err := Find(polecatDir)
if err != nil {
t.Fatalf("Find: %v", err)
}
if found != root {
t.Errorf("Find = %q, want %q (should skip nested workspace in polecats/)", found, root)
}
rel, _ := filepath.Rel(found, polecatDir)
if filepath.ToSlash(rel) != "myrig/polecats/worker" {
t.Errorf("Rel = %q, want 'myrig/polecats/worker'", rel)
}
}
func TestFindSkipsNestedWorkspaceInCrew(t *testing.T) {
root := realPath(t, t.TempDir())
if err := os.MkdirAll(filepath.Join(root, "mayor"), 0755); err != nil {
t.Fatalf("mkdir: %v", err)
}
if err := os.WriteFile(filepath.Join(root, "mayor", "town.json"), []byte(`{"name":"outer"}`), 0644); err != nil {
t.Fatalf("write: %v", err)
}
crewDir := filepath.Join(root, "myrig", "crew", "worker")
if err := os.MkdirAll(filepath.Join(crewDir, "mayor"), 0755); err != nil {
t.Fatalf("mkdir: %v", err)
}
if err := os.WriteFile(filepath.Join(crewDir, "mayor", "town.json"), []byte(`{"name":"inner"}`), 0644); err != nil {
t.Fatalf("write: %v", err)
}
found, err := Find(crewDir)
if err != nil {
t.Fatalf("Find: %v", err)
}
if found != root {
t.Errorf("Find = %q, want %q (should skip nested workspace in crew/)", found, root)
}
}