Files
sanderling/internal/driver/ioscompanion/transport/integration_test.go
T

106 lines
2.6 KiB
Go

package transport
import (
"context"
"encoding/json"
"net"
"os"
"os/exec"
"strconv"
"strings"
"testing"
"time"
)
// TestIntegrationAccessibilityInfo spawns a local companion against a booted
// simulator and exercises a real AccessibilityInfo call. It is gated behind
// SANDERLING_IOS_INTEGRATION so it never runs by default.
func TestIntegrationAccessibilityInfo(t *testing.T) {
if os.Getenv("SANDERLING_IOS_INTEGRATION") == "" {
t.Skip("set SANDERLING_IOS_INTEGRATION=1 to run the integration smoke test")
}
udid := bootedSimulatorUDID(t)
port := freePort(t)
companionBinary := "/opt/homebrew/bin/idb_companion"
command := exec.Command(companionBinary, "--udid", udid, "--grpc-port", strconv.Itoa(port))
if err := command.Start(); err != nil {
t.Fatalf("start companion: %v", err)
}
defer func() {
_ = command.Process.Kill()
_, _ = command.Process.Wait()
}()
address := net.JoinHostPort("127.0.0.1", strconv.Itoa(port))
waitForListener(t, address)
companion, err := Dial(address)
if err != nil {
t.Fatalf("Dial: %v", err)
}
defer companion.Close()
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
info, err := companion.AccessibilityInfo(ctx)
if err != nil {
t.Fatalf("AccessibilityInfo: %v", err)
}
if strings.TrimSpace(info) == "" {
t.Fatal("AccessibilityInfo returned empty json")
}
}
func bootedSimulatorUDID(t *testing.T) string {
t.Helper()
output, err := exec.Command("xcrun", "simctl", "list", "devices", "booted", "--json").Output()
if err != nil {
t.Fatalf("simctl list: %v", err)
}
var parsed struct {
Devices map[string][]struct {
UDID string `json:"udid"`
State string `json:"state"`
} `json:"devices"`
}
if err := json.Unmarshal(output, &parsed); err != nil {
t.Fatalf("parse simctl json: %v", err)
}
for _, devices := range parsed.Devices {
for _, device := range devices {
if device.State == "Booted" {
return device.UDID
}
}
}
t.Skip("no booted simulator available")
return ""
}
func freePort(t *testing.T) int {
t.Helper()
listener, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatalf("reserve port: %v", err)
}
port := listener.Addr().(*net.TCPAddr).Port
_ = listener.Close()
return port
}
func waitForListener(t *testing.T, address string) {
t.Helper()
deadline := time.Now().Add(20 * time.Second)
for time.Now().Before(deadline) {
conn, err := net.DialTimeout("tcp", address, time.Second)
if err == nil {
_ = conn.Close()
return
}
time.Sleep(200 * time.Millisecond)
}
t.Fatalf("companion did not listen on %s", address)
}