mirror of
https://github.com/taigrr/adb.git
synced 2026-04-01 18:48:42 -07:00
fix: replace panic with error return in execute(), fix Pull/Push/Reboot/Root targeting
- execute() no longer panics when adb is not found; returns ErrNotInstalled - Use sync.Once for lazy adb path lookup instead of init() - Fix Pull() checking src (device path) instead of dest (local path) - Add ErrDestExists error for Pull destination conflicts - Add -s serial flag to Push, Pull, Reboot, Root for multi-device support - Root() now parses stdout to determine actual success - Fix Shell() redundant variable redeclaration - Fix 'inconsostency' typo in KillServer doc - Add doc comments to all error variables - Update Go 1.26.0 -> 1.26.1 - Add tests: ConnString, ShortenSleep, GetLength, JSON roundtrip, SequenceImporter.ToInput, insertSleeps, parseDevices edge cases, parseScreenResolution edge cases, filterErr
This commit is contained in:
197
adb_test.go
197
adb_test.go
@@ -1,8 +1,10 @@
|
||||
package adb
|
||||
|
||||
import (
|
||||
"net"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func Test_parseDevices(t *testing.T) {
|
||||
@@ -48,6 +50,33 @@ HT75R0202681 unauthorized`},
|
||||
{IsAuthorized: false, SerialNo: "HT75R0202681"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "empty string",
|
||||
args: args{stdout: ""},
|
||||
wantErr: false,
|
||||
want: []Device{},
|
||||
},
|
||||
{
|
||||
name: "offline device",
|
||||
args: args{stdout: `List of devices attached
|
||||
ABCD1234 offline`},
|
||||
wantErr: false,
|
||||
want: []Device{
|
||||
{IsAuthorized: false, SerialNo: "ABCD1234"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "extra whitespace lines",
|
||||
args: args{stdout: `List of devices attached
|
||||
|
||||
19291FDEE0023W device
|
||||
|
||||
`},
|
||||
wantErr: false,
|
||||
want: []Device{
|
||||
{IsAuthorized: true, SerialNo: "19291FDEE0023W"},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
@@ -62,3 +91,171 @@ HT75R0202681 unauthorized`},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDevice_ConnString(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
dev Device
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "default port",
|
||||
dev: Device{IP: net.IPAddr{IP: net.ParseIP("192.168.1.100")}},
|
||||
want: "192.168.1.100:5555",
|
||||
},
|
||||
{
|
||||
name: "custom port",
|
||||
dev: Device{IP: net.IPAddr{IP: net.ParseIP("10.0.0.5")}, Port: 5556},
|
||||
want: "10.0.0.5:5556",
|
||||
},
|
||||
{
|
||||
name: "ipv6",
|
||||
dev: Device{IP: net.IPAddr{IP: net.ParseIP("::1")}, Port: 5555},
|
||||
want: "::1:5555",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := tt.dev.ConnString()
|
||||
if got != tt.want {
|
||||
t.Errorf("ConnString() = %q, want %q", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestTapSequence_ShortenSleep(t *testing.T) {
|
||||
seq := TapSequence{
|
||||
Events: []Input{
|
||||
SequenceTap{X: 100, Y: 200, Type: SeqTap},
|
||||
SequenceSleep{Duration: time.Second * 4, Type: SeqSleep},
|
||||
SequenceTap{X: 300, Y: 400, Type: SeqTap},
|
||||
},
|
||||
}
|
||||
shortened := seq.ShortenSleep(2)
|
||||
if len(shortened.Events) != 3 {
|
||||
t.Fatalf("expected 3 events, got %d", len(shortened.Events))
|
||||
}
|
||||
sleep, ok := shortened.Events[1].(SequenceSleep)
|
||||
if !ok {
|
||||
t.Fatal("expected second event to be SequenceSleep")
|
||||
}
|
||||
if sleep.Duration != time.Second*2 {
|
||||
t.Errorf("expected sleep duration 2s, got %v", sleep.Duration)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTapSequence_GetLength(t *testing.T) {
|
||||
now := time.Now()
|
||||
seq := TapSequence{
|
||||
Events: []Input{
|
||||
SequenceSleep{Duration: time.Second * 10, Type: SeqSleep},
|
||||
SequenceSwipe{
|
||||
X1: 0, Y1: 0, X2: 100, Y2: 100,
|
||||
Start: now, End: now.Add(time.Second * 5),
|
||||
Type: SeqSwipe,
|
||||
},
|
||||
},
|
||||
}
|
||||
got := seq.GetLength()
|
||||
// 15s * 110/100 = 16.5s
|
||||
want := time.Second * 15 * 110 / 100
|
||||
if got != want {
|
||||
t.Errorf("GetLength() = %v, want %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTapSequence_JSONRoundTrip(t *testing.T) {
|
||||
now := time.UnixMilli(1700000000000)
|
||||
original := TapSequence{
|
||||
Resolution: Resolution{Width: 1080, Height: 2340},
|
||||
Events: []Input{
|
||||
SequenceSwipe{
|
||||
X1: 10, Y1: 20, X2: 30, Y2: 40,
|
||||
Start: now, End: now.Add(time.Millisecond * 500),
|
||||
Type: SeqSwipe,
|
||||
},
|
||||
},
|
||||
}
|
||||
jsonBytes := original.ToJSON()
|
||||
roundTripped, err := TapSequenceFromJSON(jsonBytes)
|
||||
if err != nil {
|
||||
t.Fatalf("TapSequenceFromJSON() error = %v", err)
|
||||
}
|
||||
if roundTripped.Resolution != original.Resolution {
|
||||
t.Errorf("Resolution mismatch: got %v, want %v", roundTripped.Resolution, original.Resolution)
|
||||
}
|
||||
if len(roundTripped.Events) != len(original.Events) {
|
||||
t.Fatalf("Events length mismatch: got %d, want %d", len(roundTripped.Events), len(original.Events))
|
||||
}
|
||||
}
|
||||
|
||||
func TestSequenceImporter_ToInput(t *testing.T) {
|
||||
now := time.UnixMilli(1700000000000)
|
||||
tests := []struct {
|
||||
name string
|
||||
importer SequenceImporter
|
||||
wantType SeqType
|
||||
}{
|
||||
{
|
||||
name: "sleep",
|
||||
importer: SequenceImporter{Type: SeqSleep, Duration: time.Second},
|
||||
wantType: SeqSleep,
|
||||
},
|
||||
{
|
||||
name: "tap",
|
||||
importer: SequenceImporter{Type: SeqTap, X: 10, Y: 20, Start: now, End: now},
|
||||
wantType: SeqTap,
|
||||
},
|
||||
{
|
||||
name: "swipe",
|
||||
importer: SequenceImporter{Type: SeqSwipe, X1: 10, Y1: 20, X2: 30, Y2: 40, Start: now, End: now.Add(time.Second)},
|
||||
wantType: SeqSwipe,
|
||||
},
|
||||
{
|
||||
name: "unknown defaults to sleep",
|
||||
importer: SequenceImporter{Type: SeqType(99)},
|
||||
wantType: SeqSleep,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
input := tt.importer.ToInput()
|
||||
switch tt.wantType {
|
||||
case SeqSleep:
|
||||
if _, ok := input.(SequenceSleep); !ok {
|
||||
t.Errorf("expected SequenceSleep, got %T", input)
|
||||
}
|
||||
case SeqTap:
|
||||
if _, ok := input.(SequenceTap); !ok {
|
||||
t.Errorf("expected SequenceTap, got %T", input)
|
||||
}
|
||||
case SeqSwipe:
|
||||
if _, ok := input.(SequenceSwipe); !ok {
|
||||
t.Errorf("expected SequenceSwipe, got %T", input)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestInsertSleeps(t *testing.T) {
|
||||
now := time.UnixMilli(1000)
|
||||
inputs := []Input{
|
||||
SequenceTap{X: 1, Y: 2, Start: now, End: now.Add(time.Millisecond * 100), Type: SeqTap},
|
||||
SequenceTap{X: 3, Y: 4, Start: now.Add(time.Millisecond * 500), End: now.Add(time.Millisecond * 600), Type: SeqTap},
|
||||
}
|
||||
result := insertSleeps(inputs)
|
||||
// Should be: tap, sleep, tap
|
||||
if len(result) != 3 {
|
||||
t.Fatalf("expected 3 events, got %d", len(result))
|
||||
}
|
||||
sleep, ok := result[1].(SequenceSleep)
|
||||
if !ok {
|
||||
t.Fatal("expected second event to be SequenceSleep")
|
||||
}
|
||||
// Sleep should be from end of first (100ms) to end of second (600ms) = 500ms
|
||||
if sleep.Duration != time.Millisecond*500 {
|
||||
t.Errorf("expected sleep duration 500ms, got %v", sleep.Duration)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user