Files
yetone 06420a7121 tests: a fake program is a file macOS has already let run (testenv.Program), so a fake's first start no longer eats a test's wait under load
macOS checks a newly written executable before its first exec: 0.27s
alone, 2-5s while other new programs start (a go test ./... starting its
test binaries). The same file again takes 0.009s, and the pass is kept
across a rename and an in-place rewrite. 108852b4 worked round this for one
test with /bin/sh -c; the class was every test that writes a `#!/bin/sh`
fake and times its answer.

testenv.Program(t, path, script) replaces os.WriteFile(path, script, 0o755)
for fakes. On macOS it renames a file that has run once from a pool to path
and writes the script into it in place; at the test's cleanup the file goes
back to the pool (only a path the test created; a stand-in it wrote over
stays). Fakes still end with their tests: nothing about how they are
started or waited on changed. Run (and gateway's TestMain) remove the pool
at the end. TestMain's PATH stand-ins are run once in the background
(testenv.StandIns). Other systems write the file as before.

Converted every `#!/bin/sh` fake written by tests under internal/ (agent,
gateway, gui, library, plugin, proc, provider, update). Windows, binary
and node/bun fakes are unchanged.

Under the same load (3 loops each starting 8 freshly written scripts at a
time), 4 rounds each, before (108852b4 / origin/main) vs after:
- provider TestSavedButSignedOutClaudeServed: 4/4 fail (8.01s) -> 4/4 pass
- provider TestClaudeSignInOverStaleCredentials: 4/4 fail (5.00s) -> 4/4 pass
- provider TestDevinSignedInOnlyInMagpie: 3/4 fail ("CLI's own []") -> 4/4 pass
- gateway TestClaudeRunEndsWhenTheClientLeaves: 4/4 fail -> 4/4 pass
  (and 3/3 fail -> 3/3 pass at a third of that load)
- gateway TestClientGoneRecordedAsCanceled: 4/4 fail -> 4/4 pass
- gui TestProvidersAnswerWhileListsComeIn ("cursor found false" at 3.03s):
  4/4 fail -> 4/4 pass. The same class, not bfe8bcaf's test order.
- proc TestUserPath (login shell's PATH never came, 7.01s): 4/4 fail ->
  4/4 pass
Unloaded, every touched package passes; no pool directory or process is
left after a run.
2026-10-07 03:00:47 +08:00

63 lines
2.0 KiB
Go

package testenv
import (
"os"
"os/exec"
"path/filepath"
"runtime"
"testing"
)
// A program Program writes runs what it was given; when its test ends, the
// file goes back to the pool and the next test's program is that same
// file, which macOS has let run already. A file that was there before, such
// as a stand-in TestMain made, stays when the test that wrote over it ends.
func TestProgram(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("shell scripts")
}
t.Cleanup(RemovePrograms) // this package has no TestMain to do it
var first os.FileInfo
t.Run("first", func(t *testing.T) {
p := filepath.Join(t.TempDir(), "fake")
Program(t, p, "#!/bin/sh\necho one \"$@\"\n")
if out, err := exec.Command(p, "a").Output(); err != nil || string(out) != "one a\n" {
t.Fatalf("ran: %q %v", out, err)
}
// written again within the test: the new script runs
Program(t, p, []byte("#!/bin/sh\necho two\n"))
if out, err := exec.Command(p).Output(); err != nil || string(out) != "two\n" {
t.Fatalf("ran again: %q %v", out, err)
}
fi, err := os.Stat(p)
if err != nil || fi.Mode().Perm() != 0o755 {
t.Fatalf("mode: %v %v", fi, err)
}
first = fi
})
p := filepath.Join(t.TempDir(), "next")
Program(t, p, "#!/bin/sh\necho next\n")
if out, err := exec.Command(p).Output(); err != nil || string(out) != "next\n" {
t.Fatalf("the next test's program: %q %v", out, err)
}
fi, _ := os.Stat(p)
if runtime.GOOS == "darwin" && !os.SameFile(first, fi) {
t.Fatal("the next test's program is a new file, which macOS checks before its first run")
}
standIn := filepath.Join(t.TempDir(), "stand-in")
if err := WriteProgram(standIn, "#!/bin/sh\nexit 1\n"); err != nil {
t.Fatal(err)
}
t.Run("over a stand-in", func(t *testing.T) {
Program(t, standIn, "#!/bin/sh\necho test\n")
})
if out, _ := exec.Command(standIn).Output(); string(out) != "test\n" {
t.Fatalf("a stand-in written over is gone or changed back: %q", out)
}
if err := WriteProgram(filepath.Join(t.TempDir(), "bin"), "MZ"); err == nil {
t.Fatal("a binary written as a script")
}
}