Skip to content

Commit

Permalink
Improve various error handling locations (ava-labs#1399)
Browse files Browse the repository at this point in the history
  • Loading branch information
StephenButtolph authored Apr 21, 2023
1 parent 136bf45 commit 1d78771
Show file tree
Hide file tree
Showing 11 changed files with 128 additions and 53 deletions.
7 changes: 5 additions & 2 deletions database/leveldb/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ var (
_ database.Database = (*Database)(nil)
_ database.Batch = (*batch)(nil)
_ database.Iterator = (*iter)(nil)

ErrInvalidConfig = errors.New("invalid config")
ErrCouldNotOpen = errors.New("could not open")
)

// Database is a persistent key-value store. Apart from basic data storage
Expand Down Expand Up @@ -198,7 +201,7 @@ func New(file string, configBytes []byte, log logging.Logger, namespace string,
}
if len(configBytes) > 0 {
if err := json.Unmarshal(configBytes, &parsedConfig); err != nil {
return nil, fmt.Errorf("failed to parse db config: %w", err)
return nil, fmt.Errorf("%w: %s", ErrInvalidConfig, err)
}
}

Expand Down Expand Up @@ -228,7 +231,7 @@ func New(file string, configBytes []byte, log logging.Logger, namespace string,
db, err = leveldb.RecoverFile(file, nil)
}
if err != nil {
return nil, err
return nil, fmt.Errorf("%w: %s", ErrCouldNotOpen, err)
}

wrappedDB := &Database{
Expand Down
11 changes: 6 additions & 5 deletions database/manager/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"github.com/ava-labs/avalanchego/database/meterdb"
"github.com/ava-labs/avalanchego/database/prefixdb"
"github.com/ava-labs/avalanchego/utils/logging"
"github.com/ava-labs/avalanchego/utils/metric"
"github.com/ava-labs/avalanchego/version"
)

Expand Down Expand Up @@ -102,7 +103,7 @@ func TestNewInvalidMemberPresent(t *testing.T) {
require.NoError(err)

_, err = NewLevelDB(dir, nil, logging.NoLog{}, v2, "", prometheus.NewRegistry())
require.Error(err, "expected to error creating the manager due to an open db")
require.ErrorIs(err, leveldb.ErrCouldNotOpen)

err = db1.Close()
require.NoError(err)
Expand Down Expand Up @@ -314,7 +315,7 @@ func TestMeterDBManager(t *testing.T) {

// Confirm that the error from a name conflict is handled correctly
_, err = m.NewMeterDBManager("", registry)
require.Error(err)
require.ErrorIs(err, metric.ErrFailedRegistering)
}

func TestCompleteMeterDBManager(t *testing.T) {
Expand Down Expand Up @@ -363,7 +364,7 @@ func TestCompleteMeterDBManager(t *testing.T) {

// Confirm that the error from a name conflict is handled correctly
_, err = m.NewCompleteMeterDBManager("", registry)
require.Error(err)
require.ErrorIs(err, metric.ErrFailedRegistering)
}

func TestNewManagerFromDBs(t *testing.T) {
Expand Down Expand Up @@ -414,7 +415,7 @@ func TestNewManagerFromNoDBs(t *testing.T) {
require := require.New(t)
// Should error if no dbs are given
_, err := NewManagerFromDBs(nil)
require.Error(err)
require.ErrorIs(err, errNoDBs)
}

func TestNewManagerFromNonUniqueDBs(t *testing.T) {
Expand Down Expand Up @@ -447,5 +448,5 @@ func TestNewManagerFromNonUniqueDBs(t *testing.T) {
},
},
})
require.Error(err)
require.ErrorIs(err, errNonSortedAndUniqueDBs)
}
19 changes: 8 additions & 11 deletions indexer/index.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,18 @@ import (
"github.com/ava-labs/avalanchego/utils/wrappers"
)

const (
// Maximum number of containers IDs that can be fetched at a time
// in a call to GetContainerRange
MaxFetchedByRange = 1024
)
// Maximum number of containers IDs that can be fetched at a time in a call to
// GetContainerRange
const MaxFetchedByRange = 1024

var (
// Maps to the byte representation of the next accepted index
nextAcceptedIndexKey = []byte{0x00}
indexToContainerPrefix = []byte{0x01}
containerToIDPrefix = []byte{0x02}
errNoneAccepted = errors.New("no containers have been accepted")
errNumToFetchZero = fmt.Errorf("numToFetch must be in [1,%d]", MaxFetchedByRange)
errNumToFetchInvalid = fmt.Errorf("numToFetch must be in [1,%d]", MaxFetchedByRange)
errNoContainerAtIndex = errors.New("no container at index")

_ Index = (*index)(nil)
)
Expand Down Expand Up @@ -195,7 +194,7 @@ func (i *index) GetContainerByIndex(index uint64) (Container, error) {
func (i *index) getContainerByIndex(index uint64) (Container, error) {
lastAcceptedIndex, ok := i.lastAcceptedIndex()
if !ok || index > lastAcceptedIndex {
return Container{}, fmt.Errorf("no container at index %d", index)
return Container{}, fmt.Errorf("%w %d", errNoContainerAtIndex, index)
}
indexBytes := database.PackUInt64(index)
return i.getContainerByIndexBytes(indexBytes)
Expand Down Expand Up @@ -224,10 +223,8 @@ func (i *index) getContainerByIndexBytes(indexBytes []byte) (Container, error) {
// [numToFetch] should be in [0, MaxFetchedByRange]
func (i *index) GetContainerRange(startIndex, numToFetch uint64) ([]Container, error) {
// Check arguments for validity
if numToFetch == 0 {
return nil, errNumToFetchZero
} else if numToFetch > MaxFetchedByRange {
return nil, fmt.Errorf("requested %d but maximum page size is %d", numToFetch, MaxFetchedByRange)
if numToFetch == 0 || numToFetch > MaxFetchedByRange {
return nil, fmt.Errorf("%w but is %d", errNumToFetchInvalid, numToFetch)
}

i.lock.RLock()
Expand Down
4 changes: 2 additions & 2 deletions indexer/index_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ func TestIndexGetContainerByRangeMaxPageSize(t *testing.T) {

// Page size too large
_, err = idx.GetContainerRange(0, MaxFetchedByRange+1)
require.Error(err)
require.ErrorIs(err, errNumToFetchInvalid)

// Make sure data is right
containers, err := idx.GetContainerRange(0, MaxFetchedByRange)
Expand Down Expand Up @@ -170,7 +170,7 @@ func TestDontIndexSameContainerTwice(t *testing.T) {
require.NoError(idx.Accept(ctx, containerID, []byte{1, 2, 3}))
require.NoError(idx.Accept(ctx, containerID, []byte{4, 5, 6}))
_, err = idx.GetContainerByIndex(1)
require.Error(err, "should not have accepted same container twice")
require.ErrorIs(err, errNoContainerAtIndex)
gotContainer, err := idx.GetContainerByID(containerID)
require.NoError(err)
require.EqualValues(gotContainer.Bytes, []byte{1, 2, 3}, "should not have accepted same container twice")
Expand Down
2 changes: 1 addition & 1 deletion network/dialer/dialer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ func TestDialerCancelDial(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
cancel()
_, err = dialer.Dial(ctx, myIP)
require.Error(err)
require.ErrorIs(err, context.Canceled)

// Make an outgoing connection with a non-cancelled context
conn, err := dialer.Dial(context.Background(), myIP)
Expand Down
3 changes: 2 additions & 1 deletion network/network_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package network
import (
"context"
"crypto"
"crypto/rsa"
"net"
"sync"
"testing"
Expand Down Expand Up @@ -420,7 +421,7 @@ func TestTrackVerifiesSignatures(t *testing.T) {
Signature: nil,
}})
// The signature is wrong so this peer tracking info isn't useful.
require.Error(err)
require.ErrorIs(err, rsa.ErrVerification)

network.peersLock.RLock()
require.Empty(network.trackedIPs)
Expand Down
4 changes: 2 additions & 2 deletions network/throttling/dial_throttler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ func TestDialThrottlerCancel(t *testing.T) {
// Should block because 5 already taken within last second
err := throttler.Acquire(ctx)
// Should error because we call cancel() below
require.Error(t, err)
require.ErrorIs(t, err, context.Canceled)
acquiredChan <- struct{}{}
}()

Expand All @@ -95,7 +95,7 @@ func TestDialThrottlerCancel(t *testing.T) {
select {
case <-acquiredChan:
case <-time.After(10 * time.Millisecond):
t.Fatal("Acquire should have returned immediately upon context cancelation")
t.Fatal("Acquire should have returned immediately upon context cancellation")
}
close(acquiredChan)
}
Expand Down
10 changes: 7 additions & 3 deletions network/throttling/inbound_conn_throttler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package throttling

import (
"context"
"net"
"testing"

Expand Down Expand Up @@ -44,6 +45,8 @@ func (ml *MockListener) Addr() net.Addr {
}

func TestInboundConnThrottlerClose(t *testing.T) {
require := require.New(t)

closed := false
l := &MockListener{
t: t,
Expand All @@ -54,8 +57,9 @@ func TestInboundConnThrottlerClose(t *testing.T) {
}
wrappedL := NewThrottledListener(l, 1)
err := wrappedL.Close()
require.NoError(t, err)
require.True(t, closed)
require.NoError(err)
require.True(closed)

select {
case <-wrappedL.(*throttledListener).ctx.Done():
default:
Expand All @@ -64,7 +68,7 @@ func TestInboundConnThrottlerClose(t *testing.T) {

// Accept() should return an error because the context is cancelled
_, err = wrappedL.Accept()
require.Error(t, err)
require.ErrorIs(err, context.Canceled)
}

func TestInboundConnThrottlerAddr(t *testing.T) {
Expand Down
13 changes: 9 additions & 4 deletions utils/metric/averager.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@
package metric

import (
"errors"
"fmt"

"github.com/prometheus/client_golang/prometheus"

"github.com/ava-labs/avalanchego/utils/wrappers"
)

var ErrFailedRegistering = errors.New("failed registering metric")

type Averager interface {
Observe(float64)
}
Expand Down Expand Up @@ -40,10 +43,12 @@ func NewAveragerWithErrs(namespace, name, desc string, reg prometheus.Registerer
}),
}

errs.Add(
reg.Register(a.count),
reg.Register(a.sum),
)
if err := reg.Register(a.count); err != nil {
errs.Add(fmt.Errorf("%w: %s", ErrFailedRegistering, err))
}
if err := reg.Register(a.sum); err != nil {
errs.Add(fmt.Errorf("%w: %s", ErrFailedRegistering, err))
}
return &a
}

Expand Down
15 changes: 11 additions & 4 deletions version/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,21 @@
package version

import (
"errors"
"fmt"
"strconv"
"strings"
)

var (
errMissingVersionPrefix = errors.New("missing required version prefix")
errMissingApplicationPrefix = errors.New("missing required application prefix")
errMissingVersions = errors.New("missing version numbers")
)

func Parse(s string) (*Semantic, error) {
if !strings.HasPrefix(s, "v") {
return nil, fmt.Errorf("version string %q missing required prefix", s)
return nil, fmt.Errorf("%w: %q", errMissingVersionPrefix, s)
}

s = s[1:]
Expand All @@ -29,7 +36,7 @@ func Parse(s string) (*Semantic, error) {

func ParseApplication(s string) (*Application, error) {
if !strings.HasPrefix(s, "avalanche/") {
return nil, fmt.Errorf("application string %q missing required prefix", s)
return nil, fmt.Errorf("%w: %q", errMissingApplicationPrefix, s)
}

s = s[10:]
Expand All @@ -47,8 +54,8 @@ func ParseApplication(s string) (*Application, error) {

func parseVersions(s string) (int, int, int, error) {
splitVersion := strings.SplitN(s, ".", 3)
if len(splitVersion) != 3 {
return 0, 0, 0, fmt.Errorf("failed to parse %s as a version", s)
if numSeperators := len(splitVersion); numSeperators != 3 {
return 0, 0, 0, fmt.Errorf("%w: expected 3 only got %d", errMissingVersions, numSeperators)
}

major, err := strconv.Atoi(splitVersion[0])
Expand Down
Loading

0 comments on commit 1d78771

Please sign in to comment.