mirror of
https://github.com/priyanshujain/sanderling.git
synced 2026-10-04 20:17:09 +00:00
feat(ioscompanion): pair the legacy companion with the in-simulator runner
This commit is contained in:
1 parent
bbe013b8e4
commit
1220b62f68
2 files changed
+246
-7
No files matched your search
@@ -0,0 +1,89 @@
|
||||
package ioscompanion
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
|
||||
"github.com/priyanshujain/sanderling/internal/driver/ioscompanion/runnerassets"
|
||||
)
|
||||
|
||||
// runnerPortPlaceholder is the marker the prepare script plants in the
|
||||
// packaged test configuration's environment. The spawner substitutes the
|
||||
// session's port before launching.
|
||||
const runnerPortPlaceholder = "__COMPANION_PORT__"
|
||||
|
||||
// realSpawnRunner extracts the embedded runner bundle, writes a test
|
||||
// configuration bound to the session's port, and starts the hosting test
|
||||
// session against the configured simulator. Cancel sends SIGTERM so the
|
||||
// session tears down its in-simulator children cleanly.
|
||||
func (d *Driver) realSpawnRunner(ctx context.Context, address string) (*exec.Cmd, error) {
|
||||
extractDirectory := filepath.Join(os.TempDir(), "sanderling-runner")
|
||||
testRunPath, err := runnerassets.Extract(extractDirectory)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("extract runner: %w", err)
|
||||
}
|
||||
_, port, err := net.SplitHostPort(address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
boundTestRunPath, err := bindTestRunPort(testRunPath, port)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
logPath := filepath.Join(extractDirectory, "runner-session-"+port+".log")
|
||||
logFile, err := os.Create(logPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create runner log: %w", err)
|
||||
}
|
||||
|
||||
command := exec.CommandContext(ctx, "xcrun", "xcodebuild", "test-without-building",
|
||||
"-xctestrun", boundTestRunPath,
|
||||
"-destination", "platform=iOS Simulator,id="+d.udid)
|
||||
// The session log stays out of the run output: the build tool is noisy
|
||||
// and would pollute the run's error scan. The path is reported once so a
|
||||
// failed startup is diagnosable.
|
||||
command.Stdout = logFile
|
||||
command.Stderr = logFile
|
||||
command.Env = []string{
|
||||
"HOME=" + os.Getenv("HOME"),
|
||||
"PATH=/usr/bin:/bin",
|
||||
"TMPDIR=" + os.TempDir(),
|
||||
}
|
||||
command.Cancel = func() error { return command.Process.Signal(syscall.SIGTERM) }
|
||||
command.WaitDelay = shutdownGrace
|
||||
startErr := command.Start()
|
||||
// The child holds its own descriptor after Start, so the parent's copy
|
||||
// closes either way.
|
||||
logFile.Close()
|
||||
if startErr != nil {
|
||||
return nil, fmt.Errorf("start runner session: %w", startErr)
|
||||
}
|
||||
fmt.Fprintf(d.output, "runner session pid=%d listening on %s (log: %s)\n", command.Process.Pid, address, logPath)
|
||||
return command, nil
|
||||
}
|
||||
|
||||
// bindTestRunPort writes a copy of the extracted test configuration with the
|
||||
// port placeholder substituted, next to the original so its relative paths
|
||||
// keep resolving. Returns the bound copy's path.
|
||||
func bindTestRunPort(testRunPath, port string) (string, error) {
|
||||
configuration, err := os.ReadFile(testRunPath)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("read test configuration: %w", err)
|
||||
}
|
||||
if !bytes.Contains(configuration, []byte(runnerPortPlaceholder)) {
|
||||
return "", fmt.Errorf("test configuration %s carries no %s placeholder", testRunPath, runnerPortPlaceholder)
|
||||
}
|
||||
bound := bytes.ReplaceAll(configuration, []byte(runnerPortPlaceholder), []byte(port))
|
||||
boundPath := filepath.Join(filepath.Dir(testRunPath), "runner-"+port+".xctestrun")
|
||||
if err := os.WriteFile(boundPath, bound, 0o644); err != nil {
|
||||
return "", fmt.Errorf("write bound test configuration: %w", err)
|
||||
}
|
||||
return boundPath, nil
|
||||
}
|
||||
Reference in new issue
Block a user