Merge pull request #20 from zach-klippenstein/cleanup-errors

Moved error definitions to an internal package, deleted the confusing util package.
This commit is contained in:
Zach Klippenstein 2016-05-22 11:16:37 -07:00
commit e87d5c6814
33 changed files with 177 additions and 148 deletions

4
adb.go
View file

@ -3,7 +3,7 @@ package adb
import ( import (
"strconv" "strconv"
"github.com/zach-klippenstein/goadb/util" "github.com/zach-klippenstein/goadb/internal/errors"
"github.com/zach-klippenstein/goadb/wire" "github.com/zach-klippenstein/goadb/wire"
) )
@ -137,7 +137,7 @@ 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 {
return 0, util.WrapErrorf(err, util.ParseError, return 0, errors.WrapErrorf(err, errors.ParseError,
"error parsing server version: %s", versionStr) "error parsing server version: %s", versionStr)
} }
return int(version), nil return int(version), nil

View file

@ -10,7 +10,6 @@ import (
"github.com/cheggaaa/pb" "github.com/cheggaaa/pb"
"github.com/zach-klippenstein/goadb" "github.com/zach-klippenstein/goadb"
"github.com/zach-klippenstein/goadb/util"
"gopkg.in/alecthomas/kingpin.v2" "gopkg.in/alecthomas/kingpin.v2"
) )
@ -162,7 +161,7 @@ func pull(showProgress bool, remotePath, localPath string, device adb.DeviceDesc
client := client.Device(device) client := client.Device(device)
info, err := client.Stat(remotePath) info, err := client.Stat(remotePath)
if util.HasErrCode(err, util.FileNoExistError) { if adb.HasErrCode(err, adb.ErrCode(adb.FileNoExistError)) {
fmt.Fprintln(os.Stderr, "remote file does not exist:", remotePath) fmt.Fprintln(os.Stderr, "remote file does not exist:", remotePath)
return 1 return 1
} else if err != nil { } else if err != nil {
@ -172,7 +171,7 @@ func pull(showProgress bool, remotePath, localPath string, device adb.DeviceDesc
remoteFile, err := client.OpenRead(remotePath) remoteFile, err := client.OpenRead(remotePath)
if err != nil { if err != nil {
fmt.Fprintf(os.Stderr, "error opening remote file %s: %s\n", remotePath, util.ErrorWithCauseChain(err)) fmt.Fprintf(os.Stderr, "error opening remote file %s: %s\n", remotePath, adb.ErrorWithCauseChain(err))
return 1 return 1
} }
defer remoteFile.Close() defer remoteFile.Close()

View file

@ -9,7 +9,7 @@ import (
"time" "time"
adb "github.com/zach-klippenstein/goadb" adb "github.com/zach-klippenstein/goadb"
"github.com/zach-klippenstein/goadb/util" "github.com/zach-klippenstein/goadb/internal/errors"
) )
var ( var (
@ -74,7 +74,7 @@ func main() {
func printErr(err error) { func printErr(err error) {
switch err := err.(type) { switch err := err.(type) {
case *util.Err: case *errors.Err:
fmt.Println(err.Error()) fmt.Println(err.Error())
if err.Cause != nil { if err.Cause != nil {
fmt.Print("caused by ") fmt.Print("caused by ")

View file

@ -7,7 +7,7 @@ import (
"strings" "strings"
"time" "time"
"github.com/zach-klippenstein/goadb/util" "github.com/zach-klippenstein/goadb/internal/errors"
"github.com/zach-klippenstein/goadb/wire" "github.com/zach-klippenstein/goadb/wire"
) )
@ -72,7 +72,7 @@ func (c *Device) DeviceInfo() (*DeviceInfo, error) {
} }
} }
err = util.Errorf(util.DeviceNotFound, "device list doesn't contain serial %s", serial) err = errors.Errorf(errors.DeviceNotFound, "device list doesn't contain serial %s", serial)
return nil, wrapClientError(err, c, "DeviceInfo") return nil, wrapClientError(err, c, "DeviceInfo")
} }
@ -224,7 +224,7 @@ func (c *Device) dialDevice() (*wire.Conn, error) {
req := fmt.Sprintf("host:%s", c.descriptor.getTransportDescriptor()) req := fmt.Sprintf("host:%s", c.descriptor.getTransportDescriptor())
if err = wire.SendMessageString(conn, req); err != nil { if err = wire.SendMessageString(conn, req); err != nil {
conn.Close() conn.Close()
return nil, util.WrapErrf(err, "error connecting to device '%s'", c.descriptor) return nil, errors.WrapErrf(err, "error connecting to device '%s'", c.descriptor)
} }
if _, err = conn.ReadStatus(req); err != nil { if _, err = conn.ReadStatus(req); err != nil {
@ -239,12 +239,12 @@ func (c *Device) dialDevice() (*wire.Conn, error) {
// arguments if required, and joins them into a valid adb command string. // arguments if required, and joins them into a valid adb command string.
func prepareCommandLine(cmd string, args ...string) (string, error) { func prepareCommandLine(cmd string, args ...string) (string, error) {
if isBlank(cmd) { if isBlank(cmd) {
return "", util.AssertionErrorf("command cannot be empty") return "", errors.AssertionErrorf("command cannot be empty")
} }
for i, arg := range args { for i, arg := range args {
if strings.ContainsRune(arg, '"') { if strings.ContainsRune(arg, '"') {
return "", util.Errorf(util.ParseError, "arg at index %d contains an invalid double quote: %s", i, arg) return "", errors.Errorf(errors.ParseError, "arg at index %d contains an invalid double quote: %s", i, arg)
} }
if containsWhitespace(arg) { if containsWhitespace(arg) {
args[i] = fmt.Sprintf("\"%s\"", arg) args[i] = fmt.Sprintf("\"%s\"", arg)

View file

@ -4,7 +4,7 @@ import (
"bufio" "bufio"
"strings" "strings"
"github.com/zach-klippenstein/goadb/util" "github.com/zach-klippenstein/goadb/internal/errors"
) )
type DeviceInfo struct { type DeviceInfo struct {
@ -27,7 +27,7 @@ func (d *DeviceInfo) IsUsb() bool {
func newDevice(serial string, attrs map[string]string) (*DeviceInfo, error) { func newDevice(serial string, attrs map[string]string) (*DeviceInfo, error) {
if serial == "" { if serial == "" {
return nil, util.AssertionErrorf("device serial cannot be blank") return nil, errors.AssertionErrorf("device serial cannot be blank")
} }
return &DeviceInfo{ return &DeviceInfo{
@ -57,7 +57,7 @@ func parseDeviceList(list string, lineParseFunc func(string) (*DeviceInfo, error
func parseDeviceShort(line string) (*DeviceInfo, error) { func parseDeviceShort(line string) (*DeviceInfo, error) {
fields := strings.Fields(line) fields := strings.Fields(line)
if len(fields) != 2 { if len(fields) != 2 {
return nil, util.Errorf(util.ParseError, return nil, errors.Errorf(errors.ParseError,
"malformed device line, expected 2 fields but found %d", len(fields)) "malformed device line, expected 2 fields but found %d", len(fields))
} }
@ -67,7 +67,7 @@ func parseDeviceShort(line string) (*DeviceInfo, error) {
func parseDeviceLong(line string) (*DeviceInfo, error) { func parseDeviceLong(line string) (*DeviceInfo, error) {
fields := strings.Fields(line) fields := strings.Fields(line)
if len(fields) < 5 { if len(fields) < 5 {
return nil, util.Errorf(util.ParseError, return nil, errors.Errorf(errors.ParseError,
"malformed device line, expected at least 5 fields but found %d", len(fields)) "malformed device line, expected at least 5 fields but found %d", len(fields))
} }

View file

@ -1,6 +1,6 @@
package adb package adb
import "github.com/zach-klippenstein/goadb/util" import "github.com/zach-klippenstein/goadb/internal/errors"
// DeviceState represents one of the 3 possible states adb will report devices. // DeviceState represents one of the 3 possible states adb will report devices.
// A device can be communicated with when it's in StateOnline. // A device can be communicated with when it's in StateOnline.
@ -26,7 +26,7 @@ var deviceStateStrings = map[string]DeviceState{
func parseDeviceState(str string) (DeviceState, error) { func parseDeviceState(str string) (DeviceState, error) {
state, ok := deviceStateStrings[str] state, ok := deviceStateStrings[str]
if !ok { if !ok {
return StateInvalid, util.Errorf(util.ParseError, "invalid device state: %q", state) return StateInvalid, errors.Errorf(errors.ParseError, "invalid device state: %q", state)
} }
return state, nil return state, nil
} }

View file

@ -4,7 +4,7 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/zach-klippenstein/goadb/util" "github.com/zach-klippenstein/goadb/internal/errors"
"github.com/zach-klippenstein/goadb/wire" "github.com/zach-klippenstein/goadb/wire"
) )
@ -47,8 +47,8 @@ func TestGetDeviceInfo(t *testing.T) {
client = newDeviceClientWithDeviceLister("serial", deviceLister) client = newDeviceClientWithDeviceLister("serial", deviceLister)
device, err = client.DeviceInfo() device, err = client.DeviceInfo()
assert.True(t, util.HasErrCode(err, util.DeviceNotFound)) assert.True(t, HasErrCode(err, DeviceNotFound))
assert.EqualError(t, err.(*util.Err).Cause, assert.EqualError(t, err.(*errors.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)
} }
@ -84,13 +84,13 @@ func TestPrepareCommandLineNoArgs(t *testing.T) {
func TestPrepareCommandLineEmptyCommand(t *testing.T) { func TestPrepareCommandLineEmptyCommand(t *testing.T) {
_, err := prepareCommandLine("") _, err := prepareCommandLine("")
assert.Equal(t, util.AssertionError, code(err)) assert.Equal(t, errors.AssertionError, code(err))
assert.Equal(t, "command cannot be empty", message(err)) assert.Equal(t, "command cannot be empty", message(err))
} }
func TestPrepareCommandLineBlankCommand(t *testing.T) { func TestPrepareCommandLineBlankCommand(t *testing.T) {
_, err := prepareCommandLine(" ") _, err := prepareCommandLine(" ")
assert.Equal(t, util.AssertionError, code(err)) assert.Equal(t, errors.AssertionError, code(err))
assert.Equal(t, "command cannot be empty", message(err)) assert.Equal(t, "command cannot be empty", message(err))
} }
@ -108,14 +108,14 @@ func TestPrepareCommandLineArgWithWhitespaceQuotes(t *testing.T) {
func TestPrepareCommandLineArgWithDoubleQuoteFails(t *testing.T) { func TestPrepareCommandLineArgWithDoubleQuoteFails(t *testing.T) {
_, err := prepareCommandLine("cmd", "quoted\"arg") _, err := prepareCommandLine("cmd", "quoted\"arg")
assert.Equal(t, util.ParseError, code(err)) assert.Equal(t, errors.ParseError, code(err))
assert.Equal(t, "arg at index 0 contains an invalid double quote: quoted\"arg", message(err)) assert.Equal(t, "arg at index 0 contains an invalid double quote: quoted\"arg", message(err))
} }
func code(err error) util.ErrCode { func code(err error) errors.ErrCode {
return err.(*util.Err).Code return err.(*errors.Err).Code
} }
func message(err error) string { func message(err error) string {
return err.(*util.Err).Message return err.(*errors.Err).Message
} }

View file

@ -8,7 +8,7 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
"github.com/zach-klippenstein/goadb/util" "github.com/zach-klippenstein/goadb/internal/errors"
"github.com/zach-klippenstein/goadb/wire" "github.com/zach-klippenstein/goadb/wire"
) )
@ -124,7 +124,7 @@ func publishDevices(watcher *deviceWatcherImpl) {
return return
} }
if util.HasErrCode(err, util.ConnectionResetError) { if HasErrCode(err, ConnectionResetError) {
// The server died, restart and reconnect. // The server died, restart and reconnect.
// Delay by a random [0ms, 500ms) in case multiple DeviceWatchers are trying to // Delay by a random [0ms, 500ms) in case multiple DeviceWatchers are trying to
@ -194,7 +194,7 @@ func parseDeviceStates(msg string) (states map[string]DeviceState, err error) {
fields := strings.Split(line, "\t") fields := strings.Split(line, "\t")
if len(fields) != 2 { if len(fields) != 2 {
err = util.Errorf(util.ParseError, "invalid device state line %d: %s", lineNum, line) err = errors.Errorf(errors.ParseError, "invalid device state line %d: %s", lineNum, line)
return return
} }

View file

@ -4,7 +4,7 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/zach-klippenstein/goadb/util" "github.com/zach-klippenstein/goadb/internal/errors"
"github.com/zach-klippenstein/goadb/wire" "github.com/zach-klippenstein/goadb/wire"
) )
@ -33,8 +33,8 @@ func TestParseDeviceStatesMalformed(t *testing.T) {
0x0x0x0x 0x0x0x0x
`) `)
assert.True(t, util.HasErrCode(err, util.ParseError)) assert.True(t, HasErrCode(err, ParseError))
assert.Equal(t, "invalid device state line 1: 0x0x0x0x", err.(*util.Err).Message) assert.Equal(t, "invalid device state line 1: 0x0x0x0x", err.(*errors.Err).Message)
} }
func TestCalculateStateDiffsUnchangedEmpty(t *testing.T) { func TestCalculateStateDiffsUnchangedEmpty(t *testing.T) {
@ -210,8 +210,8 @@ func TestPublishDevicesRestartsServer(t *testing.T) {
Status: wire.StatusSuccess, Status: wire.StatusSuccess,
Errs: []error{ Errs: []error{
nil, nil, nil, // Successful dial. nil, nil, nil, // Successful dial.
util.Errorf(util.ConnectionResetError, "failed first read"), errors.Errorf(errors.ConnectionResetError, "failed first read"),
util.Errorf(util.ServerNotAvailable, "failed redial"), errors.Errorf(errors.ServerNotAvailable, "failed redial"),
}, },
} }
watcher := deviceWatcherImpl{ watcher := deviceWatcherImpl{
@ -224,8 +224,8 @@ func TestPublishDevicesRestartsServer(t *testing.T) {
assert.Empty(t, server.Errs) assert.Empty(t, server.Errs)
assert.Equal(t, []string{"host:track-devices"}, server.Requests) assert.Equal(t, []string{"host:track-devices"}, server.Requests)
assert.Equal(t, []string{"Dial", "SendMessage", "ReadStatus", "ReadMessage", "Start", "Dial"}, server.Trace) assert.Equal(t, []string{"Dial", "SendMessage", "ReadStatus", "ReadMessage", "Start", "Dial"}, server.Trace)
err := watcher.err.Load().(*util.Err) err := watcher.err.Load().(*errors.Err)
assert.Equal(t, util.ServerNotAvailable, err.Code) assert.Equal(t, errors.ServerNotAvailable, err.Code)
} }
func assertContainsOnly(t *testing.T, expected, actual []DeviceStateChangedEvent) { func assertContainsOnly(t *testing.T, expected, actual []DeviceStateChangedEvent) {

View file

@ -5,7 +5,7 @@ import (
"net" "net"
"runtime" "runtime"
"github.com/zach-klippenstein/goadb/util" "github.com/zach-klippenstein/goadb/internal/errors"
"github.com/zach-klippenstein/goadb/wire" "github.com/zach-klippenstein/goadb/wire"
) )
@ -21,7 +21,7 @@ type tcpDialer struct{}
func (tcpDialer) Dial(address string) (*wire.Conn, error) { func (tcpDialer) Dial(address string) (*wire.Conn, error) {
netConn, err := net.Dial("tcp", address) netConn, err := net.Dial("tcp", address)
if err != nil { if err != nil {
return nil, util.WrapErrorf(err, util.ServerNotAvailable, "error dialing %s", address) return nil, errors.WrapErrorf(err, errors.ServerNotAvailable, "error dialing %s", address)
} }
// net.Conn can't be closed more than once, but wire.Conn will try to close both sender and scanner // net.Conn can't be closed more than once, but wire.Conn will try to close both sender and scanner

35
error.go Normal file
View file

@ -0,0 +1,35 @@
package adb
import "github.com/zach-klippenstein/goadb/internal/errors"
type ErrCode errors.ErrCode
const (
AssertionError = ErrCode(errors.AssertionError)
ParseError = ErrCode(errors.ParseError)
// The server was not available on the requested port.
ServerNotAvailable = ErrCode(errors.ServerNotAvailable)
// General network error communicating with the server.
NetworkError = ErrCode(errors.NetworkError)
// The connection to the server was reset in the middle of an operation. Server probably died.
ConnectionResetError = ErrCode(errors.ConnectionResetError)
// The server returned an error message, but we couldn't parse it.
AdbError = ErrCode(errors.AdbError)
// The server returned a "device not found" error.
DeviceNotFound = ErrCode(errors.DeviceNotFound)
// Tried to perform an operation on a path that doesn't exist on the device.
FileNoExistError = ErrCode(errors.FileNoExistError)
)
// HasErrCode returns true if err is an *errors.Err and err.Code == code.
func HasErrCode(err error, code ErrCode) bool {
return errors.HasErrCode(err, errors.ErrCode(code))
}
/*
ErrorWithCauseChain formats err and all its causes if it's an *errors.Err, else returns
err.Error().
*/
func ErrorWithCauseChain(err error) string {
return errors.ErrorWithCauseChain(err)
}

View file

@ -1,6 +1,6 @@
// Code generated by "stringer -type=ErrCode"; DO NOT EDIT // Code generated by "stringer -type=ErrCode"; DO NOT EDIT
package util package errors
import "fmt" import "fmt"

View file

@ -1,4 +1,4 @@
package util package errors
import ( import (
"bytes" "bytes"
@ -31,6 +31,7 @@ type Err struct {
var _ error = &Err{} var _ error = &Err{}
// Keep this in sync with ../error.go.
//go:generate stringer -type=ErrCode //go:generate stringer -type=ErrCode
type ErrCode byte type ErrCode byte

View file

@ -1,4 +1,4 @@
package util package errors
import ( import (
"errors" "errors"

View file

@ -1,13 +1,13 @@
package adb package adb
import ( import (
"errors" stderrors "errors"
"fmt" "fmt"
"os" "os"
"os/exec" "os/exec"
"strings" "strings"
"github.com/zach-klippenstein/goadb/util" "github.com/zach-klippenstein/goadb/internal/errors"
"github.com/zach-klippenstein/goadb/wire" "github.com/zach-klippenstein/goadb/wire"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
) )
@ -76,12 +76,12 @@ func newServer(config ServerConfig) (server, error) {
if config.PathToAdb == "" { if config.PathToAdb == "" {
path, err := config.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, errors.WrapErrorf(err, errors.ServerNotAvailable, "could not find %s in PATH", AdbExecutableName)
} }
config.PathToAdb = path config.PathToAdb = path
} }
if err := config.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, errors.WrapErrorf(err, errors.ServerNotAvailable, "invalid adb executable: %s", config.PathToAdb)
} }
return &realServer{ return &realServer{
@ -97,7 +97,7 @@ func (s *realServer) Dial() (*wire.Conn, error) {
if err != nil { if err != nil {
// Attempt to start the server and try again. // Attempt to start the server and try again.
if err = s.Start(); err != nil { if err = s.Start(); err != nil {
return nil, util.WrapErrorf(err, util.ServerNotAvailable, "error starting server for dial") return nil, errors.WrapErrorf(err, errors.ServerNotAvailable, "error starting server for dial")
} }
conn, err = s.config.Dial(s.address) conn, err = s.config.Dial(s.address)
@ -112,7 +112,7 @@ func (s *realServer) Dial() (*wire.Conn, error) {
func (s *realServer) Start() error { func (s *realServer) Start() error {
output, err := s.config.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 errors.WrapErrorf(err, errors.ServerNotAvailable, "error starting server: %s\noutput:\n%s", err, outputStr)
} }
// filesystem abstracts interactions with the local filesystem for testability. // filesystem abstracts interactions with the local filesystem for testability.
@ -135,7 +135,7 @@ var localFilesystem = &filesystem{
return err return err
} }
if !info.Mode().IsRegular() { if !info.Mode().IsRegular() {
return errors.New("not a regular file") return stderrors.New("not a regular file")
} }
return unix.Access(path, unix.X_OK) return unix.Access(path, unix.X_OK)
}, },

View file

@ -4,7 +4,7 @@ import (
"io" "io"
"strings" "strings"
"github.com/zach-klippenstein/goadb/util" "github.com/zach-klippenstein/goadb/internal/errors"
"github.com/zach-klippenstein/goadb/wire" "github.com/zach-klippenstein/goadb/wire"
) )
@ -57,7 +57,7 @@ func (s *MockServer) ReadMessage() ([]byte, error) {
return nil, err return nil, err
} }
if s.nextMsgIndex >= len(s.Messages) { if s.nextMsgIndex >= len(s.Messages) {
return nil, util.WrapErrorf(io.EOF, util.NetworkError, "") return nil, errors.WrapErrorf(io.EOF, errors.NetworkError, "")
} }
s.nextMsgIndex++ s.nextMsgIndex++

View file

@ -5,7 +5,7 @@ import (
"os" "os"
"time" "time"
"github.com/zach-klippenstein/goadb/util" "github.com/zach-klippenstein/goadb/internal/errors"
"github.com/zach-klippenstein/goadb/wire" "github.com/zach-klippenstein/goadb/wire"
) )
@ -24,7 +24,7 @@ func stat(conn *wire.SyncConn, path string) (*DirEntry, error) {
return nil, err return nil, err
} }
if id != "STAT" { if id != "STAT" {
return nil, util.Errorf(util.AssertionError, "expected stat ID 'STAT', but got '%s'", id) return nil, errors.Errorf(errors.AssertionError, "expected stat ID 'STAT', but got '%s'", id)
} }
return readStat(conn) return readStat(conn)
@ -71,24 +71,24 @@ func sendFile(conn *wire.SyncConn, path string, mode os.FileMode, mtime time.Tim
func readStat(s wire.SyncScanner) (entry *DirEntry, err error) { func readStat(s wire.SyncScanner) (entry *DirEntry, err error) {
mode, err := s.ReadFileMode() mode, err := s.ReadFileMode()
if err != nil { if err != nil {
err = util.WrapErrf(err, "error reading file mode: %v", err) err = errors.WrapErrf(err, "error reading file mode: %v", err)
return return
} }
size, err := s.ReadInt32() size, err := s.ReadInt32()
if err != nil { if err != nil {
err = util.WrapErrf(err, "error reading file size: %v", err) err = errors.WrapErrf(err, "error reading file size: %v", err)
return return
} }
mtime, err := s.ReadTime() mtime, err := s.ReadTime()
if err != nil { if err != nil {
err = util.WrapErrf(err, "error reading file time: %v", err) err = errors.WrapErrf(err, "error reading file time: %v", err)
return return
} }
// adb doesn't indicate when a file doesn't exist, but will return all zeros. // adb doesn't indicate when a file doesn't exist, but will return all zeros.
// Theoretically this could be an actual file, but that's very unlikely. // Theoretically this could be an actual file, but that's very unlikely.
if mode == os.FileMode(0) && size == 0 && mtime == zeroTime { if mode == os.FileMode(0) && size == 0 && mtime == zeroTime {
return nil, util.Errorf(util.FileNoExistError, "file doesn't exist") return nil, errors.Errorf(errors.FileNoExistError, "file doesn't exist")
} }
entry = &DirEntry{ entry = &DirEntry{

View file

@ -9,7 +9,7 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/zach-klippenstein/goadb/util" "github.com/zach-klippenstein/goadb/internal/errors"
"github.com/zach-klippenstein/goadb/wire" "github.com/zach-klippenstein/goadb/wire"
) )
@ -57,5 +57,5 @@ func TestStatNoExist(t *testing.T) {
entry, err := stat(conn, "/") entry, err := stat(conn, "/")
assert.Nil(t, entry) assert.Nil(t, entry)
assert.Equal(t, util.FileNoExistError, err.(*util.Err).Code) assert.Equal(t, errors.FileNoExistError, err.(*errors.Err).Code)
} }

View file

@ -3,7 +3,7 @@ package adb
import ( import (
"io" "io"
"github.com/zach-klippenstein/goadb/util" "github.com/zach-klippenstein/goadb/internal/errors"
"github.com/zach-klippenstein/goadb/wire" "github.com/zach-klippenstein/goadb/wire"
) )
@ -85,7 +85,7 @@ func readNextChunk(r wire.SyncScanner) (io.Reader, error) {
status, err := r.ReadStatus("read-chunk") status, err := r.ReadStatus("read-chunk")
if err != nil { if err != nil {
if wire.IsAdbServerErrorMatching(err, readFileNotFoundPredicate) { if wire.IsAdbServerErrorMatching(err, readFileNotFoundPredicate) {
return nil, util.Errorf(util.FileNoExistError, "no such file or directory") return nil, errors.Errorf(errors.FileNoExistError, "no such file or directory")
} }
return nil, err return nil, err
} }
@ -96,7 +96,7 @@ func readNextChunk(r wire.SyncScanner) (io.Reader, error) {
case wire.StatusSyncDone: case wire.StatusSyncDone:
return nil, io.EOF return nil, io.EOF
default: default:
return nil, util.Errorf(util.AssertionError, "expected chunk id '%s' or '%s', but got '%s'", return nil, errors.Errorf(errors.AssertionError, "expected chunk id '%s' or '%s', but got '%s'",
wire.StatusSyncData, wire.StatusSyncDone, []byte(status)) wire.StatusSyncData, wire.StatusSyncDone, []byte(status))
} }
} }

View file

@ -2,13 +2,12 @@ package adb
import ( import (
"io" "io"
"io/ioutil"
"strings" "strings"
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/zach-klippenstein/goadb/util"
"github.com/zach-klippenstein/goadb/wire" "github.com/zach-klippenstein/goadb/wire"
"io/ioutil"
) )
func TestReadNextChunk(t *testing.T) { func TestReadNextChunk(t *testing.T) {
@ -110,6 +109,6 @@ func TestReadErrorNotFound(t *testing.T) {
s := wire.NewSyncScanner(strings.NewReader( s := wire.NewSyncScanner(strings.NewReader(
"FAIL\031\000\000\000No such file or directory")) "FAIL\031\000\000\000No such file or directory"))
_, err := newSyncFileReader(s) _, err := newSyncFileReader(s)
assert.True(t, util.HasErrCode(err, util.FileNoExistError)) assert.True(t, HasErrCode(err, FileNoExistError))
assert.EqualError(t, err, "FileNoExistError: no such file or directory") assert.EqualError(t, err, "FileNoExistError: no such file or directory")
} }

View file

@ -6,7 +6,7 @@ import (
"os" "os"
"time" "time"
"github.com/zach-klippenstein/goadb/util" "github.com/zach-klippenstein/goadb/internal/errors"
"github.com/zach-klippenstein/goadb/wire" "github.com/zach-klippenstein/goadb/wire"
) )
@ -76,11 +76,11 @@ func (w *syncFileWriter) Close() error {
} }
if err := w.sender.SendOctetString(wire.StatusSyncDone); err != nil { if err := w.sender.SendOctetString(wire.StatusSyncDone); err != nil {
return util.WrapErrf(err, "error sending done chunk to close stream") return errors.WrapErrf(err, "error sending done chunk to close stream")
} }
if err := w.sender.SendTime(w.mtime); err != nil { if err := w.sender.SendTime(w.mtime); err != nil {
return util.WrapErrf(err, "error writing file modification time") return errors.WrapErrf(err, "error writing file modification time")
} }
return util.WrapErrf(w.sender.Close(), "error closing FileWriter") return errors.WrapErrf(w.sender.Close(), "error closing FileWriter")
} }

10
util.go
View file

@ -6,7 +6,7 @@ import (
"regexp" "regexp"
"strings" "strings"
"github.com/zach-klippenstein/goadb/util" "github.com/zach-klippenstein/goadb/internal/errors"
) )
var ( var (
@ -25,14 +25,14 @@ func wrapClientError(err error, client interface{}, operation string, args ...in
if err == nil { if err == nil {
return nil return nil
} }
if _, ok := err.(*util.Err); !ok { if _, ok := err.(*errors.Err); !ok {
panic("err is not a *util.Err: " + err.Error()) panic("err is not a *Err: " + err.Error())
} }
clientType := reflect.TypeOf(client) clientType := reflect.TypeOf(client)
return &util.Err{ return &errors.Err{
Code: err.(*util.Err).Code, Code: err.(*errors.Err).Code,
Cause: err, Cause: err,
Message: fmt.Sprintf("error performing %s on %s", fmt.Sprintf(operation, args...), clientType), Message: fmt.Sprintf("error performing %s on %s", fmt.Sprintf(operation, args...), clientType),
Details: client, Details: client,

View file

@ -1,4 +0,0 @@
/*
Contains code shared between the different sub-packages in this project.
*/
package util

View file

@ -1,6 +1,6 @@
package wire package wire
import "github.com/zach-klippenstein/goadb/util" import "github.com/zach-klippenstein/goadb/internal/errors"
const ( const (
// The official implementation of adb imposes an undocumented 255-byte limit // The official implementation of adb imposes an undocumented 255-byte limit
@ -72,8 +72,8 @@ func (conn *Conn) Close() error {
} }
if errs.ScannerErr != nil || errs.SenderErr != nil { if errs.ScannerErr != nil || errs.SenderErr != nil {
return &util.Err{ return &errors.Err{
Code: util.NetworkError, Code: errors.NetworkError,
Message: "error closing connection", Message: "error closing connection",
Details: errs, Details: errs,
} }

View file

@ -6,7 +6,7 @@ import (
"io/ioutil" "io/ioutil"
"strconv" "strconv"
"github.com/zach-klippenstein/goadb/util" "github.com/zach-klippenstein/goadb/internal/errors"
) )
// TODO(zach): All EOF errors returned from networoking calls should use ConnectionResetError. // TODO(zach): All EOF errors returned from networoking calls should use ConnectionResetError.
@ -28,7 +28,7 @@ func isFailureStatus(status string) bool {
type StatusReader interface { type StatusReader interface {
// Reads a 4-byte status string and returns it. // Reads a 4-byte status string and returns it.
// If the status string is StatusFailure, reads the error message from the server // If the status string is StatusFailure, reads the error message from the server
// and returns it as an util.AdbError. // and returns it as an AdbError.
ReadStatus(req string) (string, error) ReadStatus(req string) (string, error)
} }
@ -72,7 +72,7 @@ func (s *realScanner) ReadMessage() ([]byte, error) {
func (s *realScanner) ReadUntilEof() ([]byte, error) { func (s *realScanner) ReadUntilEof() ([]byte, error) {
data, err := ioutil.ReadAll(s.reader) data, err := ioutil.ReadAll(s.reader)
if err != nil { if err != nil {
return nil, util.WrapErrorf(err, util.NetworkError, "error reading until EOF") return nil, errors.WrapErrorf(err, errors.NetworkError, "error reading until EOF")
} }
return data, nil return data, nil
} }
@ -82,7 +82,7 @@ func (s *realScanner) NewSyncScanner() SyncScanner {
} }
func (s *realScanner) Close() error { func (s *realScanner) Close() error {
return util.WrapErrorf(s.reader.Close(), util.NetworkError, "error closing scanner") return errors.WrapErrorf(s.reader.Close(), errors.NetworkError, "error closing scanner")
} }
var _ Scanner = &realScanner{} var _ Scanner = &realScanner{}
@ -98,13 +98,13 @@ type lengthReader func(io.Reader) (int, error)
func readStatusFailureAsError(r io.Reader, req string, messageLengthReader lengthReader) (string, error) { func readStatusFailureAsError(r io.Reader, req string, messageLengthReader lengthReader) (string, error) {
status, err := readOctetString(req, r) status, err := readOctetString(req, r)
if err != nil { if err != nil {
return "", util.WrapErrorf(err, util.NetworkError, "error reading status for %s", req) return "", errors.WrapErrorf(err, errors.NetworkError, "error reading status for %s", req)
} }
if isFailureStatus(status) { if isFailureStatus(status) {
msg, err := readMessage(r, messageLengthReader) msg, err := readMessage(r, messageLengthReader)
if err != nil { if err != nil {
return "", util.WrapErrorf(err, util.NetworkError, return "", errors.WrapErrorf(err, errors.NetworkError,
"server returned error for %s, but couldn't read the error message", req) "server returned error for %s, but couldn't read the error message", req)
} }
@ -121,7 +121,7 @@ func readOctetString(description string, r io.Reader) (string, error) {
if err == io.ErrUnexpectedEOF { if err == io.ErrUnexpectedEOF {
return "", errIncompleteMessage(description, n, 4) return "", errIncompleteMessage(description, n, 4)
} else if err != nil { } else if err != nil {
return "", util.WrapErrorf(err, util.NetworkError, "error reading "+description) return "", errors.WrapErrorf(err, errors.NetworkError, "error reading "+description)
} }
return string(octet), nil return string(octet), nil
@ -143,7 +143,7 @@ func readMessage(r io.Reader, lengthReader lengthReader) ([]byte, error) {
n, err := io.ReadFull(r, data) n, err := io.ReadFull(r, data)
if err != nil && err != io.ErrUnexpectedEOF { if err != nil && err != io.ErrUnexpectedEOF {
return data, util.WrapErrorf(err, util.NetworkError, "error reading message data") return data, errors.WrapErrorf(err, errors.NetworkError, "error reading message data")
} else if err == io.ErrUnexpectedEOF { } else if err == io.ErrUnexpectedEOF {
return data, errIncompleteMessage("message data", n, length) return data, errIncompleteMessage("message data", n, length)
} }
@ -160,7 +160,7 @@ func readHexLength(r io.Reader) (int, error) {
length, err := strconv.ParseInt(string(lengthHex), 16, 64) length, err := strconv.ParseInt(string(lengthHex), 16, 64)
if err != nil { if err != nil {
return 0, util.WrapErrorf(err, util.NetworkError, "could not parse hex length %v", lengthHex) return 0, errors.WrapErrorf(err, errors.NetworkError, "could not parse hex length %v", lengthHex)
} }
// Clip the length to 255, as per the Google implementation. // Clip the length to 255, as per the Google implementation.

View file

@ -8,7 +8,7 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/zach-klippenstein/goadb/util" "github.com/zach-klippenstein/goadb/internal/errors"
) )
func TestReadStatusOkay(t *testing.T) { func TestReadStatusOkay(t *testing.T) {
@ -23,7 +23,7 @@ func TestReadIncompleteStatus(t *testing.T) {
s := newEofReader("oka") s := newEofReader("oka")
_, err := readStatusFailureAsError(s, "", readHexLength) _, err := readStatusFailureAsError(s, "", readHexLength)
assert.EqualError(t, err, "NetworkError: error reading status for ") assert.EqualError(t, err, "NetworkError: error reading status for ")
assert.Equal(t, errIncompleteMessage("", 3, 4), err.(*util.Err).Cause) assert.Equal(t, errIncompleteMessage("", 3, 4), err.(*errors.Err).Cause)
assertEof(t, s) assertEof(t, s)
} }
@ -31,7 +31,7 @@ func TestReadFailureIncompleteStatus(t *testing.T) {
s := newEofReader("FAIL") s := newEofReader("FAIL")
_, err := readStatusFailureAsError(s, "req", readHexLength) _, err := readStatusFailureAsError(s, "req", readHexLength)
assert.EqualError(t, err, "NetworkError: server returned error for req, but couldn't read the error message") assert.EqualError(t, err, "NetworkError: server returned error for req, but couldn't read the error message")
assert.Error(t, err.(*util.Err).Cause) assert.Error(t, err.(*errors.Err).Cause)
assertEof(t, s) assertEof(t, s)
} }
@ -39,7 +39,7 @@ func TestReadFailureEmptyStatus(t *testing.T) {
s := newEofReader("FAIL0000") s := newEofReader("FAIL0000")
_, err := readStatusFailureAsError(s, "", readHexLength) _, err := readStatusFailureAsError(s, "", readHexLength)
assert.EqualError(t, err, "AdbError: server error: ({Request: ServerMsg:})") assert.EqualError(t, err, "AdbError: server error: ({Request: ServerMsg:})")
assert.NoError(t, err.(*util.Err).Cause) assert.NoError(t, err.(*errors.Err).Cause)
assertEof(t, s) assertEof(t, s)
} }
@ -47,7 +47,7 @@ func TestReadFailureStatus(t *testing.T) {
s := newEofReader("FAIL0004fail") s := newEofReader("FAIL0004fail")
_, err := readStatusFailureAsError(s, "", readHexLength) _, err := readStatusFailureAsError(s, "", readHexLength)
assert.EqualError(t, err, "AdbError: server error: fail ({Request: ServerMsg:fail})") assert.EqualError(t, err, "AdbError: server error: fail ({Request: ServerMsg:fail})")
assert.NoError(t, err.(*util.Err).Cause) assert.NoError(t, err.(*errors.Err).Cause)
assertEof(t, s) assertEof(t, s)
} }
@ -112,7 +112,7 @@ func TestReadLengthIncompleteLength(t *testing.T) {
func assertEof(t *testing.T, r io.Reader) { func assertEof(t *testing.T, r io.Reader) {
msg, err := readMessage(r, readHexLength) msg, err := readMessage(r, readHexLength)
assert.True(t, util.HasErrCode(err, util.ConnectionResetError)) assert.True(t, errors.HasErrCode(err, errors.ConnectionResetError))
assert.Nil(t, msg) assert.Nil(t, msg)
} }

View file

@ -4,7 +4,7 @@ import (
"fmt" "fmt"
"io" "io"
"github.com/zach-klippenstein/goadb/util" "github.com/zach-klippenstein/goadb/internal/errors"
) )
// Sender sends messages to the server. // Sender sends messages to the server.
@ -30,7 +30,7 @@ func SendMessageString(s Sender, msg string) error {
func (s *realSender) SendMessage(msg []byte) error { func (s *realSender) SendMessage(msg []byte) error {
if len(msg) > MaxMessageLength { if len(msg) > MaxMessageLength {
return util.AssertionErrorf("message length exceeds maximum: %d", len(msg)) return errors.AssertionErrorf("message length exceeds maximum: %d", len(msg))
} }
lengthAndMsg := fmt.Sprintf("%04x%s", len(msg), msg) lengthAndMsg := fmt.Sprintf("%04x%s", len(msg), msg)
@ -42,7 +42,7 @@ func (s *realSender) NewSyncSender() SyncSender {
} }
func (s *realSender) Close() error { func (s *realSender) Close() error {
return util.WrapErrorf(s.writer.Close(), util.NetworkError, "error closing sender") return errors.WrapErrorf(s.writer.Close(), errors.NetworkError, "error closing sender")
} }
var _ Sender = &realSender{} var _ Sender = &realSender{}

View file

@ -1,6 +1,6 @@
package wire package wire
import "github.com/zach-klippenstein/goadb/util" import "github.com/zach-klippenstein/goadb/internal/errors"
const ( const (
// Chunks cannot be longer than 64k. // Chunks cannot be longer than 64k.
@ -32,6 +32,6 @@ type SyncConn struct {
// Close closes both the sender and the scanner, and returns any errors. // Close closes both the sender and the scanner, and returns any errors.
func (c SyncConn) Close() error { func (c SyncConn) Close() error {
return util.CombineErrs("error closing SyncConn", util.NetworkError, return errors.CombineErrs("error closing SyncConn", errors.NetworkError,
c.SyncScanner.Close(), c.SyncSender.Close()) c.SyncScanner.Close(), c.SyncSender.Close())
} }

View file

@ -6,7 +6,7 @@ import (
"os" "os"
"time" "time"
"github.com/zach-klippenstein/goadb/util" "github.com/zach-klippenstein/goadb/internal/errors"
) )
type SyncScanner interface { type SyncScanner interface {
@ -39,13 +39,13 @@ func (s *realSyncScanner) ReadStatus(req string) (string, error) {
func (s *realSyncScanner) ReadInt32() (int32, error) { func (s *realSyncScanner) ReadInt32() (int32, error) {
value, err := readInt32(s.Reader) value, err := readInt32(s.Reader)
return int32(value), util.WrapErrorf(err, util.NetworkError, "error reading int from sync scanner") return int32(value), errors.WrapErrorf(err, errors.NetworkError, "error reading int from sync scanner")
} }
func (s *realSyncScanner) ReadFileMode() (os.FileMode, error) { func (s *realSyncScanner) ReadFileMode() (os.FileMode, error) {
var value uint32 var value uint32
err := binary.Read(s.Reader, binary.LittleEndian, &value) err := binary.Read(s.Reader, binary.LittleEndian, &value)
if err != nil { if err != nil {
return 0, util.WrapErrorf(err, util.NetworkError, "error reading filemode from sync scanner") return 0, errors.WrapErrorf(err, errors.NetworkError, "error reading filemode from sync scanner")
} }
return ParseFileModeFromAdb(value), nil return ParseFileModeFromAdb(value), nil
@ -53,7 +53,7 @@ func (s *realSyncScanner) ReadFileMode() (os.FileMode, error) {
func (s *realSyncScanner) ReadTime() (time.Time, error) { func (s *realSyncScanner) ReadTime() (time.Time, error) {
seconds, err := s.ReadInt32() seconds, err := s.ReadInt32()
if err != nil { if err != nil {
return time.Time{}, util.WrapErrorf(err, util.NetworkError, "error reading time from sync scanner") return time.Time{}, errors.WrapErrorf(err, errors.NetworkError, "error reading time from sync scanner")
} }
return time.Unix(int64(seconds), 0).UTC(), nil return time.Unix(int64(seconds), 0).UTC(), nil
@ -62,13 +62,13 @@ func (s *realSyncScanner) ReadTime() (time.Time, error) {
func (s *realSyncScanner) ReadString() (string, error) { func (s *realSyncScanner) ReadString() (string, error) {
length, err := s.ReadInt32() length, err := s.ReadInt32()
if err != nil { if err != nil {
return "", util.WrapErrorf(err, util.NetworkError, "error reading length from sync scanner") return "", errors.WrapErrorf(err, errors.NetworkError, "error reading length from sync scanner")
} }
bytes := make([]byte, length) bytes := make([]byte, length)
n, rawErr := io.ReadFull(s.Reader, bytes) n, rawErr := io.ReadFull(s.Reader, bytes)
if rawErr != nil && rawErr != io.ErrUnexpectedEOF { if rawErr != nil && rawErr != io.ErrUnexpectedEOF {
return "", util.WrapErrorf(rawErr, util.NetworkError, "error reading string from sync scanner") return "", errors.WrapErrorf(rawErr, errors.NetworkError, "error reading string from sync scanner")
} else if rawErr == io.ErrUnexpectedEOF { } else if rawErr == io.ErrUnexpectedEOF {
return "", errIncompleteMessage("bytes", n, int(length)) return "", errIncompleteMessage("bytes", n, int(length))
} }
@ -78,7 +78,7 @@ func (s *realSyncScanner) ReadString() (string, error) {
func (s *realSyncScanner) ReadBytes() (io.Reader, error) { func (s *realSyncScanner) ReadBytes() (io.Reader, error) {
length, err := s.ReadInt32() length, err := s.ReadInt32()
if err != nil { if err != nil {
return nil, util.WrapErrorf(err, util.NetworkError, "error reading bytes from sync scanner") return nil, errors.WrapErrorf(err, errors.NetworkError, "error reading bytes from sync scanner")
} }
return io.LimitReader(s.Reader, int64(length)), nil return io.LimitReader(s.Reader, int64(length)), nil
@ -86,7 +86,7 @@ func (s *realSyncScanner) ReadBytes() (io.Reader, error) {
func (s *realSyncScanner) Close() error { func (s *realSyncScanner) Close() error {
if closer, ok := s.Reader.(io.Closer); ok { if closer, ok := s.Reader.(io.Closer); ok {
return util.WrapErrorf(closer.Close(), util.NetworkError, "error closing sync scanner") return errors.WrapErrorf(closer.Close(), errors.NetworkError, "error closing sync scanner")
} }
return nil return nil
} }

View file

@ -6,7 +6,7 @@ import (
"os" "os"
"time" "time"
"github.com/zach-klippenstein/goadb/util" "github.com/zach-klippenstein/goadb/internal/errors"
) )
type SyncSender interface { type SyncSender interface {
@ -33,28 +33,28 @@ func NewSyncSender(w io.Writer) SyncSender {
func (s *realSyncSender) SendOctetString(str string) error { func (s *realSyncSender) SendOctetString(str string) error {
if len(str) != 4 { if len(str) != 4 {
return util.AssertionErrorf("octet string must be exactly 4 bytes: '%s'", str) return errors.AssertionErrorf("octet string must be exactly 4 bytes: '%s'", str)
} }
wrappedErr := util.WrapErrorf(writeFully(s.Writer, []byte(str)), wrappedErr := errors.WrapErrorf(writeFully(s.Writer, []byte(str)),
util.NetworkError, "error sending octet string on sync sender") errors.NetworkError, "error sending octet string on sync sender")
return wrappedErr return wrappedErr
} }
func (s *realSyncSender) SendInt32(val int32) error { func (s *realSyncSender) SendInt32(val int32) error {
return util.WrapErrorf(binary.Write(s.Writer, binary.LittleEndian, val), return errors.WrapErrorf(binary.Write(s.Writer, binary.LittleEndian, val),
util.NetworkError, "error sending int on sync sender") errors.NetworkError, "error sending int on sync sender")
} }
func (s *realSyncSender) SendFileMode(mode os.FileMode) error { func (s *realSyncSender) SendFileMode(mode os.FileMode) error {
return util.WrapErrorf(binary.Write(s.Writer, binary.LittleEndian, mode), return errors.WrapErrorf(binary.Write(s.Writer, binary.LittleEndian, mode),
util.NetworkError, "error sending filemode on sync sender") errors.NetworkError, "error sending filemode on sync sender")
} }
func (s *realSyncSender) SendTime(t time.Time) error { func (s *realSyncSender) SendTime(t time.Time) error {
return util.WrapErrorf(s.SendInt32(int32(t.Unix())), return errors.WrapErrorf(s.SendInt32(int32(t.Unix())),
util.NetworkError, "error sending time on sync sender") errors.NetworkError, "error sending time on sync sender")
} }
func (s *realSyncSender) SendBytes(data []byte) error { func (s *realSyncSender) SendBytes(data []byte) error {
@ -62,18 +62,18 @@ func (s *realSyncSender) SendBytes(data []byte) error {
if length > SyncMaxChunkSize { if length > SyncMaxChunkSize {
// This limit might not apply to filenames, but it's big enough // This limit might not apply to filenames, but it's big enough
// that I don't think it will be a problem. // that I don't think it will be a problem.
return util.AssertionErrorf("data must be <= %d in length", SyncMaxChunkSize) return errors.AssertionErrorf("data must be <= %d in length", SyncMaxChunkSize)
} }
if err := s.SendInt32(int32(length)); err != nil { if err := s.SendInt32(int32(length)); err != nil {
return util.WrapErrorf(err, util.NetworkError, "error sending data length on sync sender") return errors.WrapErrorf(err, errors.NetworkError, "error sending data length on sync sender")
} }
return writeFully(s.Writer, data) return writeFully(s.Writer, data)
} }
func (s *realSyncSender) Close() error { func (s *realSyncSender) Close() error {
if closer, ok := s.Writer.(io.Closer); ok { if closer, ok := s.Writer.(io.Closer); ok {
return util.WrapErrorf(closer.Close(), util.NetworkError, "error closing sync sender") return errors.WrapErrorf(closer.Close(), errors.NetworkError, "error closing sync sender")
} }
return nil return nil
} }

View file

@ -8,7 +8,7 @@ import (
"time" "time"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/zach-klippenstein/goadb/util" "github.com/zach-klippenstein/goadb/internal/errors"
) )
var ( var (
@ -29,7 +29,7 @@ func TestSyncSendOctetStringTooLong(t *testing.T) {
var buf bytes.Buffer var buf bytes.Buffer
s := NewSyncSender(&buf) s := NewSyncSender(&buf)
err := s.SendOctetString("hello") err := s.SendOctetString("hello")
assert.Equal(t, util.AssertionErrorf("octet string must be exactly 4 bytes: 'hello'"), err) assert.Equal(t, errors.AssertionErrorf("octet string must be exactly 4 bytes: 'hello'"), err)
} }
func TestSyncReadTime(t *testing.T) { func TestSyncReadTime(t *testing.T) {

View file

@ -4,10 +4,9 @@ import (
"fmt" "fmt"
"io" "io"
"regexp" "regexp"
"sync" "sync"
"github.com/zach-klippenstein/goadb/util" "github.com/zach-klippenstein/goadb/internal/errors"
) )
// ErrorResponseDetails is an error message returned by the server for a particular request. // ErrorResponseDetails is an error message returned by the server for a particular request.
@ -17,7 +16,7 @@ type ErrorResponseDetails struct {
} }
// deviceNotFoundMessagePattern matches all possible error messages returned by adb servers to // deviceNotFoundMessagePattern matches all possible error messages returned by adb servers to
// report that a matching device was not found. Used to set the util.DeviceNotFound error code on // report that a matching device was not found. Used to set the DeviceNotFound error code on
// error values. // error values.
// //
// Old servers send "device not found", and newer ones "device 'serial' not found". // Old servers send "device not found", and newer ones "device 'serial' not found".
@ -31,12 +30,12 @@ func adbServerError(request string, serverMsg string) error {
msg = fmt.Sprintf("server error for %s request: %s", request, serverMsg) msg = fmt.Sprintf("server error for %s request: %s", request, serverMsg)
} }
errCode := util.AdbError errCode := errors.AdbError
if deviceNotFoundMessagePattern.MatchString(serverMsg) { if deviceNotFoundMessagePattern.MatchString(serverMsg) {
errCode = util.DeviceNotFound errCode = errors.DeviceNotFound
} }
return &util.Err{ return &errors.Err{
Code: errCode, Code: errCode,
Message: msg, Message: msg,
Details: ErrorResponseDetails{ Details: ErrorResponseDetails{
@ -46,18 +45,18 @@ func adbServerError(request string, serverMsg string) error {
} }
} }
// IsAdbServerErrorMatching returns true if err is an *util.Err with code AdbError and for which // IsAdbServerErrorMatching returns true if err is an *Err with code AdbError and for which
// predicate returns true when passed Details.ServerMsg. // predicate returns true when passed Details.ServerMsg.
func IsAdbServerErrorMatching(err error, predicate func(string) bool) bool { func IsAdbServerErrorMatching(err error, predicate func(string) bool) bool {
if err, ok := err.(*util.Err); ok && err.Code == util.AdbError { if err, ok := err.(*errors.Err); ok && err.Code == errors.AdbError {
return predicate(err.Details.(ErrorResponseDetails).ServerMsg) return predicate(err.Details.(ErrorResponseDetails).ServerMsg)
} }
return false return false
} }
func errIncompleteMessage(description string, actual int, expected int) error { func errIncompleteMessage(description string, actual int, expected int) error {
return &util.Err{ return &errors.Err{
Code: util.ConnectionResetError, Code: errors.ConnectionResetError,
Message: fmt.Sprintf("incomplete %s: read %d bytes, expecting %d", description, actual, expected), Message: fmt.Sprintf("incomplete %s: read %d bytes, expecting %d", description, actual, expected),
Details: struct { Details: struct {
ActualReadBytes int ActualReadBytes int
@ -76,7 +75,7 @@ func writeFully(w io.Writer, data []byte) error {
for offset < len(data) { for offset < len(data) {
n, err := w.Write(data[offset:]) n, err := w.Write(data[offset:])
if err != nil { if err != nil {
return util.WrapErrorf(err, util.NetworkError, "error writing %d bytes at offset %d", len(data), offset) return errors.WrapErrorf(err, errors.NetworkError, "error writing %d bytes at offset %d", len(data), offset)
} }
offset += n offset += n
} }

View file

@ -4,53 +4,53 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/zach-klippenstein/goadb/util" "github.com/zach-klippenstein/goadb/internal/errors"
) )
func TestAdbServerError_NoRequest(t *testing.T) { func TestAdbServerError_NoRequest(t *testing.T) {
err := adbServerError("", "fail") err := adbServerError("", "fail")
assert.Equal(t, util.Err{ assert.Equal(t, errors.Err{
Code: util.AdbError, Code: errors.AdbError,
Message: "server error: fail", Message: "server error: fail",
Details: ErrorResponseDetails{ Details: ErrorResponseDetails{
Request: "", Request: "",
ServerMsg: "fail", ServerMsg: "fail",
}, },
}, *(err.(*util.Err))) }, *(err.(*errors.Err)))
} }
func TestAdbServerError_WithRequest(t *testing.T) { func TestAdbServerError_WithRequest(t *testing.T) {
err := adbServerError("polite", "fail") err := adbServerError("polite", "fail")
assert.Equal(t, util.Err{ assert.Equal(t, errors.Err{
Code: util.AdbError, Code: errors.AdbError,
Message: "server error for polite request: fail", Message: "server error for polite request: fail",
Details: ErrorResponseDetails{ Details: ErrorResponseDetails{
Request: "polite", Request: "polite",
ServerMsg: "fail", ServerMsg: "fail",
}, },
}, *(err.(*util.Err))) }, *(err.(*errors.Err)))
} }
func TestAdbServerError_DeviceNotFound(t *testing.T) { func TestAdbServerError_DeviceNotFound(t *testing.T) {
err := adbServerError("", "device not found") err := adbServerError("", "device not found")
assert.Equal(t, util.Err{ assert.Equal(t, errors.Err{
Code: util.DeviceNotFound, Code: errors.DeviceNotFound,
Message: "server error: device not found", Message: "server error: device not found",
Details: ErrorResponseDetails{ Details: ErrorResponseDetails{
Request: "", Request: "",
ServerMsg: "device not found", ServerMsg: "device not found",
}, },
}, *(err.(*util.Err))) }, *(err.(*errors.Err)))
} }
func TestAdbServerError_DeviceSerialNotFound(t *testing.T) { func TestAdbServerError_DeviceSerialNotFound(t *testing.T) {
err := adbServerError("", "device 'LGV4801c74eccd' not found") err := adbServerError("", "device 'LGV4801c74eccd' not found")
assert.Equal(t, util.Err{ assert.Equal(t, errors.Err{
Code: util.DeviceNotFound, Code: errors.DeviceNotFound,
Message: "server error: device 'LGV4801c74eccd' not found", Message: "server error: device 'LGV4801c74eccd' not found",
Details: ErrorResponseDetails{ Details: ErrorResponseDetails{
Request: "", Request: "",
ServerMsg: "device 'LGV4801c74eccd' not found", ServerMsg: "device 'LGV4801c74eccd' not found",
}, },
}, *(err.(*util.Err))) }, *(err.(*errors.Err)))
} }