mirror of
https://github.com/Twigpine/zero.git
synced 2026-11-09 18:08:31 -10:00
* feat(sandbox): unify command execution and enforcement * test(sandbox): make platform contracts portable * fix(sandbox): close execution lifecycle races Bound retained interactive output, preserve interruption state, and start workspace observation before process launch. Protect active runtime roots with cross-platform leases, capture transient protected-path creation events, and restore process attributes after PTY fallback. * fix(sandbox): restore strict macOS isolation Remove Seatbelt host-local network allowances after native validation showed localhost filters can reach host interfaces. Track process reap completion so retained sessions cannot signal a stale numeric PID.
68 lines
2.0 KiB
Go
68 lines
2.0 KiB
Go
package execution
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"reflect"
|
|
"testing"
|
|
)
|
|
|
|
func TestChangeObserverReportsCreateModifyAndDelete(t *testing.T) {
|
|
root := t.TempDir()
|
|
modified := filepath.Join(root, "modified.txt")
|
|
deleted := filepath.Join(root, "deleted.txt")
|
|
if err := os.WriteFile(modified, []byte("before"), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(deleted, []byte("delete"), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
observer := NewChangeObserver(root)
|
|
if err := os.WriteFile(modified, []byte("after!"), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.Remove(deleted); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.MkdirAll(filepath.Join(root, "src"), 0o755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(filepath.Join(root, "src", "created.ts"), []byte("export {}"), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
want := []Change{
|
|
{Path: "deleted.txt", Kind: ChangeDeleted},
|
|
{Path: "modified.txt", Kind: ChangeModified},
|
|
{Path: "src/created.ts", Kind: ChangeCreated},
|
|
}
|
|
if got := observer.Changes(); !reflect.DeepEqual(got, want) {
|
|
t.Fatalf("Changes() = %#v, want %#v", got, want)
|
|
}
|
|
}
|
|
|
|
func TestChangeObserverSkipsControlMetadataAndSummarizesGeneratedTrees(t *testing.T) {
|
|
root := t.TempDir()
|
|
observer := NewChangeObserver(root)
|
|
for _, path := range []string{
|
|
filepath.Join(root, ".zero", "config.json"),
|
|
filepath.Join(root, ".agents", "skills", "x"),
|
|
filepath.Join(root, ".git", "config"),
|
|
filepath.Join(root, "node_modules", "pkg", "index.js"),
|
|
filepath.Join(root, "dist", "bundle.js"),
|
|
} {
|
|
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(path, []byte("generated"), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
want := []Change{
|
|
{Path: "dist/", Kind: ChangeCreated, Aggregated: true, Count: 1},
|
|
{Path: "node_modules/", Kind: ChangeCreated, Aggregated: true, Count: 1},
|
|
}
|
|
if got := observer.Changes(); !reflect.DeepEqual(got, want) {
|
|
t.Fatalf("Changes() = %#v, want generated summaries without control metadata %#v", got, want)
|
|
}
|
|
}
|