Merge pull request #17 from zach-klippenstein/more-renames

Renamed: HostClient -> Adb, DeviceClient -> Device, Server -> server.
This commit is contained in:
Zach Klippenstein 2016-05-22 08:03:18 -07:00
commit 02ccca28d2
12 changed files with 134 additions and 118 deletions

View file

@ -8,26 +8,56 @@ import (
) )
/* /*
HostClient communicates with host services on the adb server. Adb communicates with host services on the adb server.
Eg. Eg.
StartServer() client := adb.New()
client := NewHostClient()
client.ListDevices() client.ListDevices()
See list of services at https://android.googlesource.com/platform/system/core/+/master/adb/SERVICES.TXT. See list of services at https://android.googlesource.com/platform/system/core/+/master/adb/SERVICES.TXT.
*/ */
// TODO(z): Finish implementing host services. // TODO(z): Finish implementing host services.
type HostClient struct { type Adb struct {
server Server server server
} }
func NewHostClient(server Server) *HostClient { // New creates a new Adb client that uses the default ServerConfig.
return &HostClient{server} func New() (*Adb, error) {
return NewWithConfig(ServerConfig{})
} }
// GetServerVersion asks the ADB server for its internal version number. func NewWithConfig(config ServerConfig) (*Adb, error) {
func (c *HostClient) GetServerVersion() (int, error) { server, err := newServer(config)
if err != nil {
return nil, err
}
return &Adb{server}, nil
}
// Dial establishes a connection with the adb server.
func (c *Adb) Dial() (*wire.Conn, error) {
return c.server.Dial()
}
// Starts the adb server if its not running.
func (c *Adb) StartServer() error {
return c.server.Start()
}
func (c *Adb) Device(descriptor DeviceDescriptor) *Device {
return &Device{
server: c.server,
descriptor: descriptor,
deviceListFunc: c.ListDevices,
}
}
func (c *Adb) NewDeviceWatcher() *DeviceWatcher {
return newDeviceWatcher(c.server)
}
// ServerVersion asks the ADB server for its internal version number.
func (c *Adb) ServerVersion() (int, error) {
resp, err := roundTripSingleResponse(c.server, "host:version") resp, err := roundTripSingleResponse(c.server, "host:version")
if err != nil { if err != nil {
return 0, wrapClientError(err, c, "GetServerVersion") return 0, wrapClientError(err, c, "GetServerVersion")
@ -46,7 +76,7 @@ KillServer tells the server to quit immediately.
Corresponds to the command: Corresponds to the command:
adb kill-server adb kill-server
*/ */
func (c *HostClient) KillServer() error { func (c *Adb) KillServer() error {
conn, err := c.server.Dial() conn, err := c.server.Dial()
if err != nil { if err != nil {
return wrapClientError(err, c, "KillServer") return wrapClientError(err, c, "KillServer")
@ -66,7 +96,7 @@ ListDeviceSerials returns the serial numbers of all attached devices.
Corresponds to the command: Corresponds to the command:
adb devices adb devices
*/ */
func (c *HostClient) ListDeviceSerials() ([]string, error) { func (c *Adb) ListDeviceSerials() ([]string, error) {
resp, err := roundTripSingleResponse(c.server, "host:devices") resp, err := roundTripSingleResponse(c.server, "host:devices")
if err != nil { if err != nil {
return nil, wrapClientError(err, c, "ListDeviceSerials") return nil, wrapClientError(err, c, "ListDeviceSerials")
@ -90,7 +120,7 @@ ListDevices returns the list of connected devices.
Corresponds to the command: Corresponds to the command:
adb devices -l adb devices -l
*/ */
func (c *HostClient) ListDevices() ([]*DeviceInfo, error) { func (c *Adb) ListDevices() ([]*DeviceInfo, error) {
resp, err := roundTripSingleResponse(c.server, "host:devices-l") resp, err := roundTripSingleResponse(c.server, "host:devices-l")
if err != nil { if err != nil {
return nil, wrapClientError(err, c, "ListDevices") return nil, wrapClientError(err, c, "ListDevices")
@ -103,7 +133,7 @@ func (c *HostClient) ListDevices() ([]*DeviceInfo, error) {
return devices, nil return devices, nil
} }
func (c *HostClient) parseServerVersion(versionRaw []byte) (int, error) { func (c *Adb) parseServerVersion(versionRaw []byte) (int, error) {
versionStr := string(versionRaw) versionStr := string(versionRaw)
version, err := strconv.ParseInt(versionStr, 16, 32) version, err := strconv.ParseInt(versionStr, 16, 32)
if err != nil { if err != nil {

View file

@ -12,9 +12,9 @@ func TestGetServerVersion(t *testing.T) {
Status: wire.StatusSuccess, Status: wire.StatusSuccess,
Messages: []string{"000a"}, Messages: []string{"000a"},
} }
client := NewHostClient(s) client := &Adb{s}
v, err := client.GetServerVersion() v, err := client.ServerVersion()
assert.Equal(t, "host:version", s.Requests[0]) assert.Equal(t, "host:version", s.Requests[0])
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, 10, v) assert.Equal(t, 10, v)

View file

@ -65,13 +65,13 @@ var (
String() String()
) )
var server adb.Server var client *adb.Adb
func main() { func main() {
var exitCode int var exitCode int
var err error var err error
server, err = adb.NewServer(adb.ServerConfig{}) client, err = adb.NewWithConfig(adb.ServerConfig{})
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "error:", err) fmt.Fprintln(os.Stderr, "error:", err)
os.Exit(1) os.Exit(1)
@ -100,7 +100,7 @@ func parseDevice() adb.DeviceDescriptor {
} }
func listDevices(long bool) int { func listDevices(long bool) int {
client := adb.NewHostClient(server) //client := adb.New(server)
devices, err := client.ListDevices() devices, err := client.ListDevices()
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "error:", err) fmt.Fprintln(os.Stderr, "error:", err)
@ -137,7 +137,7 @@ func runShellCommand(commandAndArgs []string, device adb.DeviceDescriptor) int {
args = commandAndArgs[1:] args = commandAndArgs[1:]
} }
client := adb.NewDeviceClient(server, device) client := client.Device(device)
output, err := client.RunCommand(command, args...) output, err := client.RunCommand(command, args...)
if err != nil { if err != nil {
fmt.Fprintln(os.Stderr, "error:", err) fmt.Fprintln(os.Stderr, "error:", err)
@ -159,7 +159,7 @@ func pull(showProgress bool, remotePath, localPath string, device adb.DeviceDesc
localPath = filepath.Base(remotePath) localPath = filepath.Base(remotePath)
} }
client := adb.NewDeviceClient(server, device) client := client.Device(device)
info, err := client.Stat(remotePath) info, err := client.Stat(remotePath)
if util.HasErrCode(err, util.FileNoExistError) { if util.HasErrCode(err, util.FileNoExistError) {
@ -232,7 +232,7 @@ func push(showProgress bool, localPath, remotePath string, device adb.DeviceDesc
} }
defer localFile.Close() defer localFile.Close()
client := adb.NewDeviceClient(server, device) client := client.Device(device)
writer, err := client.OpenWrite(remotePath, perms, mtime) writer, err := client.OpenWrite(remotePath, perms, mtime)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "error opening remote file %s: %s\n", remotePath, err) fmt.Fprintf(os.Stderr, "error opening remote file %s: %s\n", remotePath, err)

View file

@ -15,25 +15,23 @@ import (
var ( var (
port = flag.Int("p", adb.AdbPort, "") port = flag.Int("p", adb.AdbPort, "")
server adb.Server client *adb.Adb
) )
func main() { func main() {
flag.Parse() flag.Parse()
var err error var err error
server, err = adb.NewServer(adb.ServerConfig{ client, err = adb.NewWithConfig(adb.ServerConfig{
Port: *port, Port: *port,
}) })
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
fmt.Println("Starting server…") fmt.Println("Starting server…")
server.Start() client.StartServer()
client := adb.NewHostClient(server) serverVersion, err := client.ServerVersion()
serverVersion, err := client.GetServerVersion()
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
@ -62,7 +60,7 @@ func main() {
fmt.Println() fmt.Println()
fmt.Println("Watching for device state changes.") fmt.Println("Watching for device state changes.")
watcher := adb.NewDeviceWatcher(server) watcher := client.NewDeviceWatcher()
for event := range watcher.C() { for event := range watcher.C() {
fmt.Printf("\t[%s]%+v\n", time.Now(), event) fmt.Printf("\t[%s]%+v\n", time.Now(), event)
} }
@ -88,22 +86,22 @@ func printErr(err error) {
} }
func PrintDeviceInfoAndError(descriptor adb.DeviceDescriptor) { func PrintDeviceInfoAndError(descriptor adb.DeviceDescriptor) {
device := adb.NewDeviceClient(server, descriptor) device := client.Device(descriptor)
if err := PrintDeviceInfo(device); err != nil { if err := PrintDeviceInfo(device); err != nil {
log.Println(err) log.Println(err)
} }
} }
func PrintDeviceInfo(device *adb.DeviceClient) error { func PrintDeviceInfo(device *adb.Device) error {
serialNo, err := device.GetSerial() serialNo, err := device.Serial()
if err != nil { if err != nil {
return err return err
} }
devPath, err := device.GetDevicePath() devPath, err := device.DevicePath()
if err != nil { if err != nil {
return err return err
} }
state, err := device.GetState() state, err := device.State()
if err != nil { if err != nil {
return err return err
} }

View file

@ -14,7 +14,7 @@ import (
"github.com/zach-klippenstein/goadb/wire" "github.com/zach-klippenstein/goadb/wire"
) )
var port = flag.Int("p", adb.AdbPort, "port the adb server is listening on") var port = flag.Int("p", adb.AdbPort, "`port` the adb server is listening on")
func main() { func main() {
flag.Parse() flag.Parse()
@ -49,7 +49,7 @@ func readLine() string {
} }
func doCommand(cmd string) error { func doCommand(cmd string) error {
server, err := adb.NewServer(adb.ServerConfig{ server, err := adb.NewWithConfig(adb.ServerConfig{
Port: *port, Port: *port,
}) })
if err != nil { if err != nil {

View file

@ -15,61 +15,55 @@ import (
// method is called. // method is called.
var MtimeOfClose = time.Time{} var MtimeOfClose = time.Time{}
// DeviceClient communicates with a specific Android device. // Device communicates with a specific Android device.
type DeviceClient struct { // To get an instance, call Device() on an Adb.
server Server type Device struct {
server server
descriptor DeviceDescriptor descriptor DeviceDescriptor
// Used to get device info. // Used to get device info.
deviceListFunc func() ([]*DeviceInfo, error) deviceListFunc func() ([]*DeviceInfo, error)
} }
func NewDeviceClient(server Server, descriptor DeviceDescriptor) *DeviceClient { func (c *Device) String() string {
return &DeviceClient{
server: server,
descriptor: descriptor,
deviceListFunc: NewHostClient(server).ListDevices,
}
}
func (c *DeviceClient) String() string {
return c.descriptor.String() return c.descriptor.String()
} }
// get-product is documented, but not implemented in the server. // get-product is documented, but not implemented, in the server.
// TODO(z): Make getProduct exported if get-product is ever implemented in adb. // TODO(z): Make product exported if get-product is ever implemented in adb.
func (c *DeviceClient) getProduct() (string, error) { func (c *Device) product() (string, error) {
attr, err := c.getAttribute("get-product") attr, err := c.getAttribute("get-product")
return attr, wrapClientError(err, c, "GetProduct") return attr, wrapClientError(err, c, "Product")
} }
func (c *DeviceClient) GetSerial() (string, error) { func (c *Device) Serial() (string, error) {
attr, err := c.getAttribute("get-serialno") attr, err := c.getAttribute("get-serialno")
return attr, wrapClientError(err, c, "GetSerial") return attr, wrapClientError(err, c, "Serial")
} }
func (c *DeviceClient) GetDevicePath() (string, error) { func (c *Device) DevicePath() (string, error) {
attr, err := c.getAttribute("get-devpath") attr, err := c.getAttribute("get-devpath")
return attr, wrapClientError(err, c, "GetDevicePath") return attr, wrapClientError(err, c, "DevicePath")
} }
func (c *DeviceClient) GetState() (string, error) { // State returns the connection state of the device (e.g. "device").
func (c *Device) State() (string, error) {
attr, err := c.getAttribute("get-state") attr, err := c.getAttribute("get-state")
return attr, wrapClientError(err, c, "GetState") return attr, wrapClientError(err, c, "State")
} }
func (c *DeviceClient) GetDeviceInfo() (*DeviceInfo, error) { func (c *Device) DeviceInfo() (*DeviceInfo, error) {
// Adb doesn't actually provide a way to get this for an individual device, // Adb doesn't actually provide a way to get this for an individual device,
// so we have to just list devices and find ourselves. // so we have to just list devices and find ourselves.
serial, err := c.GetSerial() serial, err := c.Serial()
if err != nil { if err != nil {
return nil, wrapClientError(err, c, "GetDeviceInfo(GetSerial)") return nil, wrapClientError(err, c, "GetDeviceInfo(GetSerial)")
} }
devices, err := c.deviceListFunc() devices, err := c.deviceListFunc()
if err != nil { if err != nil {
return nil, wrapClientError(err, c, "GetDeviceInfo(ListDevices)") return nil, wrapClientError(err, c, "DeviceInfo(ListDevices)")
} }
for _, deviceInfo := range devices { for _, deviceInfo := range devices {
@ -79,7 +73,7 @@ func (c *DeviceClient) GetDeviceInfo() (*DeviceInfo, error) {
} }
err = util.Errorf(util.DeviceNotFound, "device list doesn't contain serial %s", serial) err = util.Errorf(util.DeviceNotFound, "device list doesn't contain serial %s", serial)
return nil, wrapClientError(err, c, "GetDeviceInfo") return nil, wrapClientError(err, c, "DeviceInfo")
} }
/* /*
@ -98,7 +92,7 @@ Source: https://android.googlesource.com/platform/system/core/+/master/adb/SERVI
This method quotes the arguments for you, and will return an error if any of them This method quotes the arguments for you, and will return an error if any of them
contain double quotes. contain double quotes.
*/ */
func (c *DeviceClient) RunCommand(cmd string, args ...string) (string, error) { func (c *Device) RunCommand(cmd string, args ...string) (string, error) {
cmd, err := prepareCommandLine(cmd, args...) cmd, err := prepareCommandLine(cmd, args...)
if err != nil { if err != nil {
return "", wrapClientError(err, c, "RunCommand") return "", wrapClientError(err, c, "RunCommand")
@ -127,7 +121,7 @@ func (c *DeviceClient) RunCommand(cmd string, args ...string) (string, error) {
} }
/* /*
Remount, from the docs, Remount, from the official adb commands docs:
Ask adbd to remount the device's filesystem in read-write mode, Ask adbd to remount the device's filesystem in read-write mode,
instead of read-only. This is usually necessary before performing instead of read-only. This is usually necessary before performing
an "adb sync" or "adb push" request. an "adb sync" or "adb push" request.
@ -135,7 +129,7 @@ Remount, from the docs,
that. that.
Source: https://android.googlesource.com/platform/system/core/+/master/adb/SERVICES.TXT Source: https://android.googlesource.com/platform/system/core/+/master/adb/SERVICES.TXT
*/ */
func (c *DeviceClient) Remount() (string, error) { func (c *Device) Remount() (string, error) {
conn, err := c.dialDevice() conn, err := c.dialDevice()
if err != nil { if err != nil {
return "", wrapClientError(err, c, "Remount") return "", wrapClientError(err, c, "Remount")
@ -146,7 +140,7 @@ func (c *DeviceClient) Remount() (string, error) {
return string(resp), wrapClientError(err, c, "Remount") return string(resp), wrapClientError(err, c, "Remount")
} }
func (c *DeviceClient) ListDirEntries(path string) (*DirEntries, error) { func (c *Device) ListDirEntries(path string) (*DirEntries, error) {
conn, err := c.getSyncConn() conn, err := c.getSyncConn()
if err != nil { if err != nil {
return nil, wrapClientError(err, c, "ListDirEntries(%s)", path) return nil, wrapClientError(err, c, "ListDirEntries(%s)", path)
@ -156,7 +150,7 @@ func (c *DeviceClient) ListDirEntries(path string) (*DirEntries, error) {
return entries, wrapClientError(err, c, "ListDirEntries(%s)", path) return entries, wrapClientError(err, c, "ListDirEntries(%s)", path)
} }
func (c *DeviceClient) Stat(path string) (*DirEntry, error) { func (c *Device) Stat(path string) (*DirEntry, error) {
conn, err := c.getSyncConn() conn, err := c.getSyncConn()
if err != nil { if err != nil {
return nil, wrapClientError(err, c, "Stat(%s)", path) return nil, wrapClientError(err, c, "Stat(%s)", path)
@ -167,7 +161,7 @@ func (c *DeviceClient) Stat(path string) (*DirEntry, error) {
return entry, wrapClientError(err, c, "Stat(%s)", path) return entry, wrapClientError(err, c, "Stat(%s)", path)
} }
func (c *DeviceClient) OpenRead(path string) (io.ReadCloser, error) { func (c *Device) OpenRead(path string) (io.ReadCloser, error) {
conn, err := c.getSyncConn() conn, err := c.getSyncConn()
if err != nil { if err != nil {
return nil, wrapClientError(err, c, "OpenRead(%s)", path) return nil, wrapClientError(err, c, "OpenRead(%s)", path)
@ -181,7 +175,7 @@ func (c *DeviceClient) OpenRead(path string) (io.ReadCloser, error) {
// by perms if necessary, and returns a writer that writes to the file. // by perms if necessary, and returns a writer that writes to the file.
// The files modification time will be set to mtime when the WriterCloser is closed. The zero value // The files modification time will be set to mtime when the WriterCloser is closed. The zero value
// is TimeOfClose, which will use the time the Close method is called as the modification time. // is TimeOfClose, which will use the time the Close method is called as the modification time.
func (c *DeviceClient) OpenWrite(path string, perms os.FileMode, mtime time.Time) (io.WriteCloser, error) { func (c *Device) OpenWrite(path string, perms os.FileMode, mtime time.Time) (io.WriteCloser, error) {
conn, err := c.getSyncConn() conn, err := c.getSyncConn()
if err != nil { if err != nil {
return nil, wrapClientError(err, c, "OpenWrite(%s)", path) return nil, wrapClientError(err, c, "OpenWrite(%s)", path)
@ -193,7 +187,7 @@ func (c *DeviceClient) OpenWrite(path string, perms os.FileMode, mtime time.Time
// getAttribute returns the first message returned by the server by running // getAttribute returns the first message returned by the server by running
// <host-prefix>:<attr>, where host-prefix is determined from the DeviceDescriptor. // <host-prefix>:<attr>, where host-prefix is determined from the DeviceDescriptor.
func (c *DeviceClient) getAttribute(attr string) (string, error) { func (c *Device) getAttribute(attr string) (string, error) {
resp, err := roundTripSingleResponse(c.server, resp, err := roundTripSingleResponse(c.server,
fmt.Sprintf("%s:%s", c.descriptor.getHostPrefix(), attr)) fmt.Sprintf("%s:%s", c.descriptor.getHostPrefix(), attr))
if err != nil { if err != nil {
@ -202,7 +196,7 @@ func (c *DeviceClient) getAttribute(attr string) (string, error) {
return string(resp), nil return string(resp), nil
} }
func (c *DeviceClient) getSyncConn() (*wire.SyncConn, error) { func (c *Device) getSyncConn() (*wire.SyncConn, error) {
conn, err := c.dialDevice() conn, err := c.dialDevice()
if err != nil { if err != nil {
return nil, err return nil, err
@ -221,7 +215,7 @@ func (c *DeviceClient) getSyncConn() (*wire.SyncConn, error) {
// dialDevice switches the connection to communicate directly with the device // dialDevice switches the connection to communicate directly with the device
// by requesting the transport defined by the DeviceDescriptor. // by requesting the transport defined by the DeviceDescriptor.
func (c *DeviceClient) dialDevice() (*wire.Conn, error) { func (c *Device) dialDevice() (*wire.Conn, error) {
conn, err := c.server.Dial() conn, err := c.server.Dial()
if err != nil { if err != nil {
return nil, err return nil, err

View file

@ -13,7 +13,7 @@ func TestGetAttribute(t *testing.T) {
Status: wire.StatusSuccess, Status: wire.StatusSuccess,
Messages: []string{"value"}, Messages: []string{"value"},
} }
client := NewDeviceClient(s, DeviceWithSerial("serial")) client := (&Adb{s}).Device(DeviceWithSerial("serial"))
v, err := client.getAttribute("attr") v, err := client.getAttribute("attr")
assert.Equal(t, "host-serial:serial:attr", s.Requests[0]) assert.Equal(t, "host-serial:serial:attr", s.Requests[0])
@ -36,31 +36,28 @@ func TestGetDeviceInfo(t *testing.T) {
} }
client := newDeviceClientWithDeviceLister("abc", deviceLister) client := newDeviceClientWithDeviceLister("abc", deviceLister)
device, err := client.GetDeviceInfo() device, err := client.DeviceInfo()
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, "Foo", device.Product) assert.Equal(t, "Foo", device.Product)
client = newDeviceClientWithDeviceLister("def", deviceLister) client = newDeviceClientWithDeviceLister("def", deviceLister)
device, err = client.GetDeviceInfo() device, err = client.DeviceInfo()
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, "Bar", device.Product) assert.Equal(t, "Bar", device.Product)
client = newDeviceClientWithDeviceLister("serial", deviceLister) client = newDeviceClientWithDeviceLister("serial", deviceLister)
device, err = client.GetDeviceInfo() device, err = client.DeviceInfo()
assert.True(t, util.HasErrCode(err, util.DeviceNotFound)) assert.True(t, util.HasErrCode(err, util.DeviceNotFound))
assert.EqualError(t, err.(*util.Err).Cause, assert.EqualError(t, err.(*util.Err).Cause,
"DeviceNotFound: device list doesn't contain serial serial") "DeviceNotFound: device list doesn't contain serial serial")
assert.Nil(t, device) assert.Nil(t, device)
} }
func newDeviceClientWithDeviceLister(serial string, deviceLister func() ([]*DeviceInfo, error)) *DeviceClient { func newDeviceClientWithDeviceLister(serial string, deviceLister func() ([]*DeviceInfo, error)) *Device {
client := NewDeviceClient( client := (&Adb{&MockServer{
&MockServer{ Status: wire.StatusSuccess,
Status: wire.StatusSuccess, Messages: []string{serial},
Messages: []string{serial}, }}).Device(DeviceWithSerial(serial))
},
DeviceWithSerial(serial),
)
client.deviceListFunc = deviceLister client.deviceListFunc = deviceLister
return client return client
} }
@ -70,7 +67,7 @@ func TestRunCommandNoArgs(t *testing.T) {
Status: wire.StatusSuccess, Status: wire.StatusSuccess,
Messages: []string{"output"}, Messages: []string{"output"},
} }
client := NewDeviceClient(s, AnyDevice()) client := (&Adb{s}).Device(AnyDevice())
v, err := client.RunCommand("cmd") v, err := client.RunCommand("cmd")
assert.Equal(t, "host:transport-any", s.Requests[0]) assert.Equal(t, "host:transport-any", s.Requests[0])

View file

@ -59,7 +59,7 @@ var deviceStateStrings = map[string]DeviceState{
} }
type deviceWatcherImpl struct { type deviceWatcherImpl struct {
server Server server server
// If an error occurs, it is stored here and eventChan is close immediately after. // If an error occurs, it is stored here and eventChan is close immediately after.
err atomic.Value err atomic.Value
@ -67,7 +67,7 @@ type deviceWatcherImpl struct {
eventChan chan DeviceStateChangedEvent eventChan chan DeviceStateChangedEvent
} }
func NewDeviceWatcher(server Server) *DeviceWatcher { func newDeviceWatcher(server server) *DeviceWatcher {
watcher := &DeviceWatcher{&deviceWatcherImpl{ watcher := &DeviceWatcher{&deviceWatcherImpl{
server: server, server: server,
eventChan: make(chan DeviceStateChangedEvent), eventChan: make(chan DeviceStateChangedEvent),
@ -165,7 +165,7 @@ func publishDevices(watcher *deviceWatcherImpl) {
} }
} }
func connectToTrackDevices(server Server) (wire.Scanner, error) { func connectToTrackDevices(server server) (wire.Scanner, error) {
conn, err := server.Dial() conn, err := server.Dial()
if err != nil { if err != nil {
return nil, err return nil, err

View file

@ -30,15 +30,17 @@ type ServerConfig struct {
// Dialer used to connect to the adb server. // Dialer used to connect to the adb server.
Dialer Dialer
fs *filesystem
} }
// Server knows how to start the adb server and connect to it. // Server knows how to start the adb server and connect to it.
type Server interface { type server interface {
Start() error Start() error
Dial() (*wire.Conn, error) Dial() (*wire.Conn, error)
} }
func roundTripSingleResponse(s Server, req string) ([]byte, error) { func roundTripSingleResponse(s server, req string) ([]byte, error) {
conn, err := s.Dial() conn, err := s.Dial()
if err != nil { if err != nil {
return nil, err return nil, err
@ -50,18 +52,12 @@ func roundTripSingleResponse(s Server, req string) ([]byte, error) {
type realServer struct { type realServer struct {
config ServerConfig config ServerConfig
fs *filesystem
// Caches Host:Port so they don't have to be concatenated for every dial. // Caches Host:Port so they don't have to be concatenated for every dial.
address string address string
} }
// NewServer creates a new Server instance. func newServer(config ServerConfig) (server, error) {
func NewServer(config ServerConfig) (Server, error) {
return newServer(config, localFilesystem)
}
func newServer(config ServerConfig, fs *filesystem) (Server, error) {
if config.Dialer == nil { if config.Dialer == nil {
config.Dialer = tcpDialer{} config.Dialer = tcpDialer{}
} }
@ -73,20 +69,23 @@ func newServer(config ServerConfig, fs *filesystem) (Server, error) {
config.Port = AdbPort config.Port = AdbPort
} }
if config.fs == nil {
config.fs = localFilesystem
}
if config.PathToAdb == "" { if config.PathToAdb == "" {
path, err := fs.LookPath(AdbExecutableName) path, err := config.fs.LookPath(AdbExecutableName)
if err != nil { if err != nil {
return nil, util.WrapErrorf(err, util.ServerNotAvailable, "could not find %s in PATH", AdbExecutableName) return nil, util.WrapErrorf(err, util.ServerNotAvailable, "could not find %s in PATH", AdbExecutableName)
} }
config.PathToAdb = path config.PathToAdb = path
} }
if err := fs.IsExecutableFile(config.PathToAdb); err != nil { if err := config.fs.IsExecutableFile(config.PathToAdb); err != nil {
return nil, util.WrapErrorf(err, util.ServerNotAvailable, "invalid adb executable: %s", config.PathToAdb) return nil, util.WrapErrorf(err, util.ServerNotAvailable, "invalid adb executable: %s", config.PathToAdb)
} }
return &realServer{ return &realServer{
config: config, config: config,
fs: fs,
address: fmt.Sprintf("%s:%d", config.Host, config.Port), address: fmt.Sprintf("%s:%d", config.Host, config.Port),
}, nil }, nil
} }
@ -111,7 +110,7 @@ func (s *realServer) Dial() (*wire.Conn, error) {
// StartServer ensures there is a server running. // StartServer ensures there is a server running.
func (s *realServer) Start() error { func (s *realServer) Start() error {
output, err := s.fs.CmdCombinedOutput(s.config.PathToAdb, "start-server") output, err := s.config.fs.CmdCombinedOutput(s.config.PathToAdb, "start-server")
outputStr := strings.TrimSpace(string(output)) outputStr := strings.TrimSpace(string(output))
return util.WrapErrorf(err, util.ServerNotAvailable, "error starting server: %s\noutput:\n%s", err, outputStr) return util.WrapErrorf(err, util.ServerNotAvailable, "error starting server: %s\noutput:\n%s", err, outputStr)
} }

View file

@ -28,7 +28,7 @@ type MockServer struct {
Trace []string Trace []string
} }
var _ Server = &MockServer{} var _ server = &MockServer{}
func (s *MockServer) Dial() (*wire.Conn, error) { func (s *MockServer) Dial() (*wire.Conn, error) {
s.logMethod("Dial") s.logMethod("Dial")

View file

@ -9,8 +9,7 @@ import (
) )
func TestNewServer_ZeroConfig(t *testing.T) { func TestNewServer_ZeroConfig(t *testing.T) {
config := ServerConfig{} config := ServerConfig{fs: &filesystem{
fs := &filesystem{
LookPath: func(name string) (string, error) { LookPath: func(name string) (string, error) {
if name == AdbExecutableName { if name == AdbExecutableName {
return "/bin/adb", nil return "/bin/adb", nil
@ -23,9 +22,9 @@ func TestNewServer_ZeroConfig(t *testing.T) {
} }
return fmt.Errorf("wrong path: %s", path) return fmt.Errorf("wrong path: %s", path)
}, },
} }}
serverIf, err := newServer(config, fs) serverIf, err := newServer(config)
server := serverIf.(*realServer) server := serverIf.(*realServer)
assert.NoError(t, err) assert.NoError(t, err)
assert.IsType(t, tcpDialer{}, server.config.Dialer) assert.IsType(t, tcpDialer{}, server.config.Dialer)
@ -47,17 +46,17 @@ func TestNewServer_CustomConfig(t *testing.T) {
Host: "foobar", Host: "foobar",
Port: 1, Port: 1,
PathToAdb: "/bin/adb", PathToAdb: "/bin/adb",
} fs: &filesystem{
fs := &filesystem{ IsExecutableFile: func(path string) error {
IsExecutableFile: func(path string) error { if path == "/bin/adb" {
if path == "/bin/adb" { return nil
return nil }
} return fmt.Errorf("wrong path: %s", path)
return fmt.Errorf("wrong path: %s", path) },
}, },
} }
serverIf, err := newServer(config, fs) serverIf, err := newServer(config)
server := serverIf.(*realServer) server := serverIf.(*realServer)
assert.NoError(t, err) assert.NoError(t, err)
assert.IsType(t, MockDialer{}, server.config.Dialer) assert.IsType(t, MockDialer{}, server.config.Dialer)
@ -68,13 +67,12 @@ func TestNewServer_CustomConfig(t *testing.T) {
} }
func TestNewServer_AdbNotFound(t *testing.T) { func TestNewServer_AdbNotFound(t *testing.T) {
config := ServerConfig{} config := ServerConfig{fs: &filesystem{
fs := &filesystem{
LookPath: func(name string) (string, error) { LookPath: func(name string) (string, error) {
return "", fmt.Errorf("executable not found: %s", name) return "", fmt.Errorf("executable not found: %s", name)
}, },
} }}
_, err := newServer(config, fs) _, err := newServer(config)
assert.EqualError(t, err, "ServerNotAvailable: could not find adb in PATH") assert.EqualError(t, err, "ServerNotAvailable: could not find adb in PATH")
} }

View file

@ -2,7 +2,7 @@
Package wire implements the low-level part of the client/server wire protocol. Package wire implements the low-level part of the client/server wire protocol.
It also implements the "sync" wire format for file transfers. It also implements the "sync" wire format for file transfers.
This package is not intended to be used directly. adb.HostClient and adb.DeviceClient This package is not intended to be used directly. adb.Adb and adb.Device
use it to abstract away the bit-twiddling details of the protocol. You should only ever use it to abstract away the bit-twiddling details of the protocol. You should only ever
need to work with the goadb package. Also, this package's API may change more frequently need to work with the goadb package. Also, this package's API may change more frequently
than goadb's. than goadb's.