mirror of
https://github.com/priyanshujain/sanderling.git
synced 2026-10-03 19:47:10 +00:00
feat(implementation-sweep): run one campaign against every implementation of a requirement
installs, builds and serves each implementation on its own port, then hands the campaign tool the same seed slice, step budget and generator for all of them, so a difference between implementations is not a difference in exploration. the generator and platform are fixed rather than exposed.
This commit is contained in:
1 parent
a45ba76d8e
commit
146152a3af
8 files changed
+1830
No files matched your search
@@ -0,0 +1,119 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// bunSpawningAServer serves from a child process and then waits, which is the
|
||||
// shape of `bun run preview`: the port belongs to something below the process
|
||||
// the sweep started.
|
||||
const bunSpawningAServer = `#!/bin/sh
|
||||
port=""
|
||||
previous=""
|
||||
for argument in "$@"; do
|
||||
if [ "$previous" = "--port" ]; then port="$argument"; fi
|
||||
previous="$argument"
|
||||
done
|
||||
SWEEP_TEST_SERVE_PORT="$port" "%[1]s" &
|
||||
wait
|
||||
`
|
||||
|
||||
func TestServerStop_TakesTheProcessBelowItWithTheServer(t *testing.T) {
|
||||
directory := t.TempDir()
|
||||
testBinary, err := filepath.Abs(os.Args[0])
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
bunPath := writeScript(
|
||||
t,
|
||||
filepath.Join(directory, "stub-bun"),
|
||||
fmt.Sprintf(bunSpawningAServer, testBinary),
|
||||
)
|
||||
port := freePortRange(t, 1)
|
||||
target := implementation{Name: "impl-01", Directory: directory, Port: port}
|
||||
|
||||
// Background rather than the test context: only stop() may end this
|
||||
// server, or a leak would be hidden by the context being cancelled.
|
||||
running, err := startServer(
|
||||
context.Background(),
|
||||
config{bunPath: bunPath},
|
||||
target,
|
||||
filepath.Join(directory, "serve.log"),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Cleanup(
|
||||
func() { syscall.Kill(-running.command.Process.Pid, syscall.SIGKILL) },
|
||||
)
|
||||
if err := running.waitReady(context.Background(), readinessURL(port)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
running.stop()
|
||||
|
||||
client := &http.Client{Timeout: time.Second}
|
||||
deadline := time.Now().Add(5 * time.Second)
|
||||
for time.Now().Before(deadline) {
|
||||
response, err := client.Get(readinessURL(port))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
response.Body.Close()
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
t.Fatalf(
|
||||
"port %d is still served after stop(): the server below bun outlived the sweep and holds the port",
|
||||
port,
|
||||
)
|
||||
}
|
||||
|
||||
func TestServerWaitReady_ReportsAServerThatExited(t *testing.T) {
|
||||
directory := t.TempDir()
|
||||
bunPath := writeScript(
|
||||
t,
|
||||
filepath.Join(directory, "stub-bun"),
|
||||
"#!/bin/sh\necho 'port is already in use' >&2\nexit 1\n",
|
||||
)
|
||||
port := freePortRange(t, 1)
|
||||
|
||||
running, err := startServer(
|
||||
context.Background(),
|
||||
config{bunPath: bunPath},
|
||||
implementation{
|
||||
Name: "impl-01",
|
||||
Directory: directory,
|
||||
Port: port,
|
||||
},
|
||||
filepath.Join(directory, "serve.log"),
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer running.stop()
|
||||
|
||||
started := time.Now()
|
||||
err = running.waitReady(context.Background(), readinessURL(port))
|
||||
if err == nil {
|
||||
t.Fatal(
|
||||
"a server that exited should not be waited on until the start timeout",
|
||||
)
|
||||
}
|
||||
if elapsed := time.Since(started); elapsed > 30*time.Second {
|
||||
t.Errorf("waited %s for a server that had already exited", elapsed)
|
||||
}
|
||||
log, err := os.ReadFile(filepath.Join(directory, "serve.log"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if string(log) == "" {
|
||||
t.Error("serve.log did not capture why the server exited")
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user