mirror of
https://github.com/priyanshujain/sanderling.git
synced 2026-10-02 11:07:10 +00:00
106 lines
2.6 KiB
Go
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)
|
|
}
|