125 lines
4.4 KiB
Go
125 lines
4.4 KiB
Go
package device
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"runtime"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestUSBDiscoverySelectionAndHotplug(t *testing.T) {
|
|
if runtime.GOOS == "windows" {
|
|
t.Skip("fake ADB uses a POSIX shell")
|
|
}
|
|
dir := t.TempDir()
|
|
state := filepath.Join(dir, "devices")
|
|
calls := filepath.Join(dir, "calls")
|
|
bin := filepath.Join(dir, "adb")
|
|
t.Setenv("FAKE_ADB_DEVICES", state)
|
|
t.Setenv("FAKE_ADB_CALLS", calls)
|
|
script := `#!/bin/sh
|
|
printf '%s\n' "$*" >> "$FAKE_ADB_CALLS"
|
|
if [ "$1" != -P ] || [ "$2" != 17891 ]; then exit 42; fi
|
|
shift 2
|
|
case "$1" in
|
|
devices) printf 'List of devices attached\n'; cat "$FAKE_ADB_DEVICES" ;;
|
|
-s)
|
|
if [ "$4" = wm ]; then printf 'Physical size: 1080x2400\n'; fi
|
|
;;
|
|
esac
|
|
`
|
|
if err := os.WriteFile(bin, []byte(script), 0700); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
previous := adbPathOverride
|
|
SetAdbPath(bin)
|
|
t.Cleanup(func() { SetAdbPath(previous) })
|
|
writeDevices := func(devices string) {
|
|
t.Helper()
|
|
if err := os.WriteFile(state, []byte(devices), 0600); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
const usbA = "USB_A device usb:1 model:Phone_A transport_id:1\n"
|
|
const usbZ = "USB_Z device usb:2 model:Phone_Z transport_id:2\n"
|
|
const locked = "USB_LOCKED unauthorized usb:3 transport_id:3\n"
|
|
const wifiID = "adb-WIFI-random._adb-tls-connect._tcp"
|
|
const wifi = wifiID + " device model:Wireless_Phone transport_id:4\n"
|
|
writeDevices(wifi + usbZ + locked + usbA)
|
|
s := &Service{devices: map[string]DeviceInfo{}}
|
|
devices, err := s.ListDevices()
|
|
if err != nil || len(devices) != 4 {
|
|
t.Fatalf("list: %+v %v", devices, err)
|
|
}
|
|
if devices[0].ID != "USB_A" || devices[1].ID != "USB_Z" || devices[2].ID != wifiID || devices[3].ID != "USB_LOCKED" {
|
|
t.Fatalf("unstable USB/online ordering: %+v", devices)
|
|
}
|
|
if devices[3].Online || devices[3].State != "unauthorized" || devices[3].Mode != ConnUSB || devices[3].Width != 0 {
|
|
t.Fatalf("unauthorized USB not preserved: %+v", devices[3])
|
|
}
|
|
if active := s.GetActiveDevice(); active.ID != "USB_A" || active.Mode != ConnUSB || active.Width != 1080 {
|
|
t.Fatalf("initial USB selection: %+v", active)
|
|
}
|
|
if err := s.SelectDevice(wifiID); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if _, err := s.ListDevices(); err != nil || s.GetActiveDevice().ID != wifiID {
|
|
t.Fatal("refresh changed an explicitly selected online wireless device")
|
|
}
|
|
writeDevices(usbZ + usbA + wifiID + " offline\n" + locked)
|
|
if _, err := s.ListDevices(); err != nil || s.GetActiveDevice().ID != "USB_A" {
|
|
t.Fatal("offline wireless selection did not fall back to online USB")
|
|
}
|
|
if err := s.Tap(TapRequest{DeviceID: "USB_A", X: 10, Y: 20}); err != nil {
|
|
t.Fatalf("USB input: %v", err)
|
|
}
|
|
writeDevices(wifi + locked)
|
|
if _, err := s.ListDevices(); err != nil || s.GetActiveDevice().ID != wifiID {
|
|
t.Fatal("unplugged USB selection did not fall back to online wireless")
|
|
}
|
|
writeDevices("USB_LOCKED device usb:3 model:Authorized_Phone\n")
|
|
if _, err := s.ListDevices(); err != nil || s.GetActiveDevice().ID != "USB_LOCKED" || !s.GetActiveDevice().Online {
|
|
t.Fatal("USB authorization change was not discovered")
|
|
}
|
|
if result := s.DisconnectDevice("USB_LOCKED"); !result.OK {
|
|
t.Fatalf("USB session disconnect: %+v", result)
|
|
}
|
|
if devices, err := s.ListDevices(); err != nil || len(devices) != 1 || devices[0].Online || devices[0].State != "disconnected" {
|
|
t.Fatalf("refresh reconnected USB session: %+v %v", devices, err)
|
|
}
|
|
if result := s.StartPreviewStream("USB_LOCKED", false); result.OK {
|
|
t.Fatal("preview opened a disconnected USB session")
|
|
}
|
|
if err := s.SelectDevice("USB_LOCKED"); err != nil || !s.GetActiveDevice().Online {
|
|
t.Fatalf("USB reconnect failed: %v", err)
|
|
}
|
|
history, err := os.ReadFile(calls)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !strings.Contains(string(history), "-P 17891 -s USB_A shell input tap 10 20\n") {
|
|
t.Fatalf("input did not target USB serial: %s", history)
|
|
}
|
|
if strings.Contains(string(history), "disconnect") || strings.Contains(string(history), "connect ") || strings.Contains(string(history), "kill-server") {
|
|
t.Fatalf("USB discovery interfered with ADB transports: %s", history)
|
|
}
|
|
}
|
|
|
|
func TestInferUSBAndWirelessMode(t *testing.T) {
|
|
for _, tc := range []struct {
|
|
serial string
|
|
want ConnMode
|
|
}{
|
|
{"bdeafa21", ConnUSB},
|
|
{"192.0.2.1:5555", ConnLAN},
|
|
{"[2001:db8::1]:5555", ConnLAN},
|
|
{"adb-serial-random._adb-tls-connect._tcp", ConnLAN},
|
|
{"phone._adb._tcp", ConnLAN},
|
|
} {
|
|
if got := inferMode(tc.serial); got != tc.want {
|
|
t.Errorf("%s: got %s, want %s", tc.serial, got, tc.want)
|
|
}
|
|
}
|
|
}
|