DeviceWatcher events are more strongly typed and added higher-level methods.
This commit is contained in:
parent
0aa31c0548
commit
af4b3ddcf2
|
@ -18,10 +18,42 @@ type DeviceWatcher struct {
|
|||
*deviceWatcherImpl
|
||||
}
|
||||
|
||||
// DeviceStateChangedEvent represents a device state transition.
|
||||
type DeviceStateChangedEvent struct {
|
||||
Serial string
|
||||
OldState string
|
||||
NewState string
|
||||
OldState DeviceState
|
||||
NewState DeviceState
|
||||
}
|
||||
|
||||
// CameOnline returns true if this event represents a device coming online.
|
||||
func (s DeviceStateChangedEvent) CameOnline() bool {
|
||||
return s.OldState != StateOnline && s.NewState == StateOnline
|
||||
}
|
||||
|
||||
// WentOffline returns true if this event represents a device going offline.
|
||||
func (s DeviceStateChangedEvent) WentOffline() bool {
|
||||
return s.OldState == StateOnline && s.NewState != StateOnline
|
||||
}
|
||||
|
||||
// DeviceState represents one of the 3 possible states adb will report devices.
|
||||
// A device can be communicated with when it's in StateOnline.
|
||||
// A USB device will transition from StateDisconnected->StateOffline->StateOnline when
|
||||
// plugged in, and then StateOnline->StateDisconnected when unplugged.
|
||||
// If code doesn't care about specific states, DeviceStateChangedEvent provides methods
|
||||
// to query at a higher level.
|
||||
//go:generate stringer -type=DeviceState
|
||||
type DeviceState int8
|
||||
|
||||
const (
|
||||
StateDisconnected DeviceState = iota
|
||||
StateOffline
|
||||
StateOnline
|
||||
)
|
||||
|
||||
var deviceStateStrings = map[string]DeviceState{
|
||||
"": StateDisconnected,
|
||||
"offline": StateOffline,
|
||||
"device": StateOnline,
|
||||
}
|
||||
|
||||
type deviceWatcherImpl struct {
|
||||
|
@ -96,7 +128,7 @@ and abort. If true, report no error and stop.
|
|||
func publishDevices(watcher *deviceWatcherImpl) {
|
||||
defer close(watcher.eventChan)
|
||||
|
||||
var lastKnownStates map[string]string
|
||||
var lastKnownStates map[string]DeviceState
|
||||
finished := false
|
||||
|
||||
for {
|
||||
|
@ -148,7 +180,7 @@ func connectToTrackDevices(dialer Dialer) (wire.Scanner, error) {
|
|||
return conn, nil
|
||||
}
|
||||
|
||||
func publishDevicesUntilError(scanner wire.Scanner, eventChan chan<- DeviceStateChangedEvent, lastKnownStates *map[string]string) (finished bool, err error) {
|
||||
func publishDevicesUntilError(scanner wire.Scanner, eventChan chan<- DeviceStateChangedEvent, lastKnownStates *map[string]DeviceState) (finished bool, err error) {
|
||||
for {
|
||||
msg, err := scanner.ReadMessage()
|
||||
if err != nil {
|
||||
|
@ -167,8 +199,8 @@ func publishDevicesUntilError(scanner wire.Scanner, eventChan chan<- DeviceState
|
|||
}
|
||||
}
|
||||
|
||||
func parseDeviceStates(msg string) (states map[string]string, err error) {
|
||||
states = make(map[string]string)
|
||||
func parseDeviceStates(msg string) (states map[string]DeviceState, err error) {
|
||||
states = make(map[string]DeviceState)
|
||||
|
||||
for lineNum, line := range strings.Split(msg, "\n") {
|
||||
if len(line) == 0 {
|
||||
|
@ -181,14 +213,18 @@ func parseDeviceStates(msg string) (states map[string]string, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
serial, state := fields[0], fields[1]
|
||||
serial, stateString := fields[0], fields[1]
|
||||
state, ok := deviceStateStrings[stateString]
|
||||
if !ok {
|
||||
err = util.Errorf(util.ParseError, "invalid device state: %s", state)
|
||||
}
|
||||
states[serial] = state
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func calculateStateDiffs(oldStates, newStates map[string]string) (events []DeviceStateChangedEvent) {
|
||||
func calculateStateDiffs(oldStates, newStates map[string]DeviceState) (events []DeviceStateChangedEvent) {
|
||||
for serial, oldState := range oldStates {
|
||||
newState, ok := newStates[serial]
|
||||
|
||||
|
@ -198,7 +234,7 @@ func calculateStateDiffs(oldStates, newStates map[string]string) (events []Devic
|
|||
events = append(events, DeviceStateChangedEvent{serial, oldState, newState})
|
||||
} else {
|
||||
// Device only present in old list: device removed.
|
||||
events = append(events, DeviceStateChangedEvent{serial, oldState, ""})
|
||||
events = append(events, DeviceStateChangedEvent{serial, oldState, StateDisconnected})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -206,7 +242,7 @@ func calculateStateDiffs(oldStates, newStates map[string]string) (events []Devic
|
|||
for serial, newState := range newStates {
|
||||
if _, ok := oldStates[serial]; !ok {
|
||||
// Device only present in new list: device added.
|
||||
events = append(events, DeviceStateChangedEvent{serial, "", newState})
|
||||
events = append(events, DeviceStateChangedEvent{serial, StateDisconnected, newState})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@ package goadb
|
|||
|
||||
import (
|
||||
"log"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
@ -11,27 +10,27 @@ import (
|
|||
)
|
||||
|
||||
func TestParseDeviceStatesSingle(t *testing.T) {
|
||||
states, err := parseDeviceStates(`192.168.56.101:5555 emulator-state
|
||||
states, err := parseDeviceStates(`192.168.56.101:5555 offline
|
||||
`)
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, states, 1)
|
||||
assert.Equal(t, "emulator-state", states["192.168.56.101:5555"])
|
||||
assert.Equal(t, StateOffline, states["192.168.56.101:5555"])
|
||||
}
|
||||
|
||||
func TestParseDeviceStatesMultiple(t *testing.T) {
|
||||
states, err := parseDeviceStates(`192.168.56.101:5555 emulator-state
|
||||
0x0x0x0x usb-state
|
||||
states, err := parseDeviceStates(`192.168.56.101:5555 offline
|
||||
0x0x0x0x device
|
||||
`)
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, states, 2)
|
||||
assert.Equal(t, "emulator-state", states["192.168.56.101:5555"])
|
||||
assert.Equal(t, "usb-state", states["0x0x0x0x"])
|
||||
assert.Equal(t, StateOffline, states["192.168.56.101:5555"])
|
||||
assert.Equal(t, StateOnline, states["0x0x0x0x"])
|
||||
}
|
||||
|
||||
func TestParseDeviceStatesMalformed(t *testing.T) {
|
||||
_, err := parseDeviceStates(`192.168.56.101:5555 emulator-state
|
||||
_, err := parseDeviceStates(`192.168.56.101:5555 offline
|
||||
0x0x0x0x
|
||||
`)
|
||||
|
||||
|
@ -40,8 +39,8 @@ func TestParseDeviceStatesMalformed(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestCalculateStateDiffsUnchangedEmpty(t *testing.T) {
|
||||
oldStates := map[string]string{}
|
||||
newStates := map[string]string{}
|
||||
oldStates := map[string]DeviceState{}
|
||||
newStates := map[string]DeviceState{}
|
||||
|
||||
diffs := calculateStateDiffs(oldStates, newStates)
|
||||
|
||||
|
@ -49,13 +48,13 @@ func TestCalculateStateDiffsUnchangedEmpty(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestCalculateStateDiffsUnchangedNonEmpty(t *testing.T) {
|
||||
oldStates := map[string]string{
|
||||
"1": "device",
|
||||
"2": "device",
|
||||
oldStates := map[string]DeviceState{
|
||||
"1": StateOnline,
|
||||
"2": StateOnline,
|
||||
}
|
||||
newStates := map[string]string{
|
||||
"1": "device",
|
||||
"2": "device",
|
||||
newStates := map[string]DeviceState{
|
||||
"1": StateOnline,
|
||||
"2": StateOnline,
|
||||
}
|
||||
|
||||
diffs := calculateStateDiffs(oldStates, newStates)
|
||||
|
@ -64,131 +63,147 @@ func TestCalculateStateDiffsUnchangedNonEmpty(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestCalculateStateDiffsOneAdded(t *testing.T) {
|
||||
oldStates := map[string]string{}
|
||||
newStates := map[string]string{
|
||||
"serial": "added",
|
||||
oldStates := map[string]DeviceState{}
|
||||
newStates := map[string]DeviceState{
|
||||
"serial": StateOffline,
|
||||
}
|
||||
|
||||
diffs := calculateStateDiffs(oldStates, newStates)
|
||||
|
||||
assert.Equal(t, []DeviceStateChangedEvent{
|
||||
DeviceStateChangedEvent{"serial", "", "added"},
|
||||
assertContainsOnly(t, []DeviceStateChangedEvent{
|
||||
DeviceStateChangedEvent{"serial", StateDisconnected, StateOffline},
|
||||
}, diffs)
|
||||
}
|
||||
|
||||
func TestCalculateStateDiffsOneRemoved(t *testing.T) {
|
||||
oldStates := map[string]string{
|
||||
"serial": "removed",
|
||||
oldStates := map[string]DeviceState{
|
||||
"serial": StateOffline,
|
||||
}
|
||||
newStates := map[string]string{}
|
||||
newStates := map[string]DeviceState{}
|
||||
|
||||
diffs := calculateStateDiffs(oldStates, newStates)
|
||||
|
||||
assert.Equal(t, []DeviceStateChangedEvent{
|
||||
DeviceStateChangedEvent{"serial", "removed", ""},
|
||||
assertContainsOnly(t, []DeviceStateChangedEvent{
|
||||
DeviceStateChangedEvent{"serial", StateOffline, StateDisconnected},
|
||||
}, diffs)
|
||||
}
|
||||
|
||||
func TestCalculateStateDiffsOneAddedOneUnchanged(t *testing.T) {
|
||||
oldStates := map[string]string{
|
||||
"1": "device",
|
||||
oldStates := map[string]DeviceState{
|
||||
"1": StateOnline,
|
||||
}
|
||||
newStates := map[string]string{
|
||||
"1": "device",
|
||||
"2": "added",
|
||||
newStates := map[string]DeviceState{
|
||||
"1": StateOnline,
|
||||
"2": StateOffline,
|
||||
}
|
||||
|
||||
diffs := calculateStateDiffs(oldStates, newStates)
|
||||
|
||||
assert.Equal(t, []DeviceStateChangedEvent{
|
||||
DeviceStateChangedEvent{"2", "", "added"},
|
||||
assertContainsOnly(t, []DeviceStateChangedEvent{
|
||||
DeviceStateChangedEvent{"2", StateDisconnected, StateOffline},
|
||||
}, diffs)
|
||||
}
|
||||
|
||||
func TestCalculateStateDiffsOneRemovedOneUnchanged(t *testing.T) {
|
||||
oldStates := map[string]string{
|
||||
"1": "removed",
|
||||
"2": "device",
|
||||
oldStates := map[string]DeviceState{
|
||||
"1": StateOffline,
|
||||
"2": StateOnline,
|
||||
}
|
||||
newStates := map[string]string{
|
||||
"2": "device",
|
||||
newStates := map[string]DeviceState{
|
||||
"2": StateOnline,
|
||||
}
|
||||
|
||||
diffs := calculateStateDiffs(oldStates, newStates)
|
||||
|
||||
assert.Equal(t, []DeviceStateChangedEvent{
|
||||
DeviceStateChangedEvent{"1", "removed", ""},
|
||||
assertContainsOnly(t, []DeviceStateChangedEvent{
|
||||
DeviceStateChangedEvent{"1", StateOffline, StateDisconnected},
|
||||
}, diffs)
|
||||
}
|
||||
|
||||
func TestCalculateStateDiffsOneAddedOneRemoved(t *testing.T) {
|
||||
oldStates := map[string]string{
|
||||
"1": "removed",
|
||||
oldStates := map[string]DeviceState{
|
||||
"1": StateOffline,
|
||||
}
|
||||
newStates := map[string]string{
|
||||
"2": "added",
|
||||
newStates := map[string]DeviceState{
|
||||
"2": StateOffline,
|
||||
}
|
||||
|
||||
diffs := calculateStateDiffs(oldStates, newStates)
|
||||
|
||||
assert.Equal(t, []DeviceStateChangedEvent{
|
||||
DeviceStateChangedEvent{"1", "removed", ""},
|
||||
DeviceStateChangedEvent{"2", "", "added"},
|
||||
assertContainsOnly(t, []DeviceStateChangedEvent{
|
||||
DeviceStateChangedEvent{"1", StateOffline, StateDisconnected},
|
||||
DeviceStateChangedEvent{"2", StateDisconnected, StateOffline},
|
||||
}, diffs)
|
||||
}
|
||||
|
||||
func TestCalculateStateDiffsOneChangedOneUnchanged(t *testing.T) {
|
||||
oldStates := map[string]string{
|
||||
"1": "oldState",
|
||||
"2": "device",
|
||||
oldStates := map[string]DeviceState{
|
||||
"1": StateOffline,
|
||||
"2": StateOnline,
|
||||
}
|
||||
newStates := map[string]string{
|
||||
"1": "newState",
|
||||
"2": "device",
|
||||
newStates := map[string]DeviceState{
|
||||
"1": StateOnline,
|
||||
"2": StateOnline,
|
||||
}
|
||||
|
||||
diffs := calculateStateDiffs(oldStates, newStates)
|
||||
|
||||
assert.Equal(t, []DeviceStateChangedEvent{
|
||||
DeviceStateChangedEvent{"1", "oldState", "newState"},
|
||||
assertContainsOnly(t, []DeviceStateChangedEvent{
|
||||
DeviceStateChangedEvent{"1", StateOffline, StateOnline},
|
||||
}, diffs)
|
||||
}
|
||||
|
||||
func TestCalculateStateDiffsMultipleChangedMultipleUnchanged(t *testing.T) {
|
||||
oldStates := map[string]string{
|
||||
"1": "oldState",
|
||||
"2": "oldState",
|
||||
func TestCalculateStateDiffsMultipleChanged(t *testing.T) {
|
||||
oldStates := map[string]DeviceState{
|
||||
"1": StateOffline,
|
||||
"2": StateOnline,
|
||||
}
|
||||
newStates := map[string]string{
|
||||
"1": "newState",
|
||||
"2": "newState",
|
||||
newStates := map[string]DeviceState{
|
||||
"1": StateOnline,
|
||||
"2": StateOffline,
|
||||
}
|
||||
|
||||
diffs := calculateStateDiffs(oldStates, newStates)
|
||||
|
||||
assert.True(t, reflect.DeepEqual([]DeviceStateChangedEvent{
|
||||
DeviceStateChangedEvent{"1", "oldState", "newState"},
|
||||
DeviceStateChangedEvent{"2", "oldState", "newState"},
|
||||
}, diffs))
|
||||
assertContainsOnly(t, []DeviceStateChangedEvent{
|
||||
DeviceStateChangedEvent{"1", StateOffline, StateOnline},
|
||||
DeviceStateChangedEvent{"2", StateOnline, StateOffline},
|
||||
}, diffs)
|
||||
}
|
||||
|
||||
func TestCalculateStateDiffsOneAddedOneRemovedOneChanged(t *testing.T) {
|
||||
oldStates := map[string]string{
|
||||
"1": "oldState",
|
||||
"2": "removed",
|
||||
oldStates := map[string]DeviceState{
|
||||
"1": StateOffline,
|
||||
"2": StateOffline,
|
||||
}
|
||||
newStates := map[string]string{
|
||||
"1": "newState",
|
||||
"3": "added",
|
||||
newStates := map[string]DeviceState{
|
||||
"1": StateOnline,
|
||||
"3": StateOffline,
|
||||
}
|
||||
|
||||
diffs := calculateStateDiffs(oldStates, newStates)
|
||||
|
||||
assert.True(t, reflect.DeepEqual([]DeviceStateChangedEvent{
|
||||
DeviceStateChangedEvent{"1", "oldState", "newState"},
|
||||
DeviceStateChangedEvent{"2", "removed", ""},
|
||||
DeviceStateChangedEvent{"3", "", "added"},
|
||||
}, diffs))
|
||||
assertContainsOnly(t, []DeviceStateChangedEvent{
|
||||
DeviceStateChangedEvent{"1", StateOffline, StateOnline},
|
||||
DeviceStateChangedEvent{"2", StateOffline, StateDisconnected},
|
||||
DeviceStateChangedEvent{"3", StateDisconnected, StateOffline},
|
||||
}, diffs)
|
||||
}
|
||||
|
||||
func TestCameOnline(t *testing.T) {
|
||||
assert.True(t, DeviceStateChangedEvent{"", StateDisconnected, StateOnline}.CameOnline())
|
||||
assert.True(t, DeviceStateChangedEvent{"", StateOffline, StateOnline}.CameOnline())
|
||||
assert.False(t, DeviceStateChangedEvent{"", StateOnline, StateOffline}.CameOnline())
|
||||
assert.False(t, DeviceStateChangedEvent{"", StateOnline, StateDisconnected}.CameOnline())
|
||||
assert.False(t, DeviceStateChangedEvent{"", StateOffline, StateDisconnected}.CameOnline())
|
||||
}
|
||||
|
||||
func TestWentOffline(t *testing.T) {
|
||||
assert.True(t, DeviceStateChangedEvent{"", StateOnline, StateDisconnected}.WentOffline())
|
||||
assert.True(t, DeviceStateChangedEvent{"", StateOnline, StateOffline}.WentOffline())
|
||||
assert.False(t, DeviceStateChangedEvent{"", StateOffline, StateOnline}.WentOffline())
|
||||
assert.False(t, DeviceStateChangedEvent{"", StateDisconnected, StateOnline}.WentOffline())
|
||||
assert.False(t, DeviceStateChangedEvent{"", StateOffline, StateDisconnected}.WentOffline())
|
||||
}
|
||||
|
||||
func TestPublishDevicesRestartsServer(t *testing.T) {
|
||||
|
@ -231,3 +246,19 @@ func (s *MockServerStarter) StartServer() error {
|
|||
return s.err
|
||||
}
|
||||
}
|
||||
|
||||
func assertContainsOnly(t *testing.T, expected, actual []DeviceStateChangedEvent) {
|
||||
assert.Len(t, actual, len(expected))
|
||||
for _, expectedEntry := range expected {
|
||||
assertContains(t, expectedEntry, actual)
|
||||
}
|
||||
}
|
||||
|
||||
func assertContains(t *testing.T, expectedEntry DeviceStateChangedEvent, actual []DeviceStateChangedEvent) {
|
||||
for _, actualEntry := range actual {
|
||||
if expectedEntry == actualEntry {
|
||||
return
|
||||
}
|
||||
}
|
||||
assert.Fail(t, "expected to find %+v in %+v", expectedEntry, actual)
|
||||
}
|
||||
|
|
16
devicestate_string.go
Normal file
16
devicestate_string.go
Normal file
|
@ -0,0 +1,16 @@
|
|||
// generated by stringer -type=DeviceState; DO NOT EDIT
|
||||
|
||||
package goadb
|
||||
|
||||
import "fmt"
|
||||
|
||||
const _DeviceState_name = "StateDisconnectedStateOfflineStateOnline"
|
||||
|
||||
var _DeviceState_index = [...]uint8{0, 17, 29, 40}
|
||||
|
||||
func (i DeviceState) String() string {
|
||||
if i < 0 || i+1 >= DeviceState(len(_DeviceState_index)) {
|
||||
return fmt.Sprintf("DeviceState(%d)", i)
|
||||
}
|
||||
return _DeviceState_name[_DeviceState_index[i]:_DeviceState_index[i+1]]
|
||||
}
|
Loading…
Reference in a new issue