merr: refactor Wrap/WrapSkip/New to take multiple contexts rather than annotations
This commit is contained in:
parent
4303da03cc
commit
4536db8968
5
m/m.go
5
m/m.go
@ -6,7 +6,6 @@ package m
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
|
||||
@ -43,9 +42,9 @@ func ServiceContext() context.Context {
|
||||
ctx, logLevelStr := mcfg.WithString(ctx, "log-level", "info", "Maximum log level which will be printed.")
|
||||
ctx = mrun.WithStartHook(ctx, func(context.Context) error {
|
||||
logLevel := mlog.LevelFromString(*logLevelStr)
|
||||
log.Printf("setting log level to %v", logLevel)
|
||||
if logLevel == nil {
|
||||
return merr.New(ctx, "invalid log level", "log-level", *logLevelStr)
|
||||
ctx := mctx.Annotate(ctx, "log-level", *logLevelStr)
|
||||
return merr.New("invalid log level", ctx)
|
||||
}
|
||||
logger.SetMaxLevel(logLevel)
|
||||
return nil
|
||||
|
@ -90,7 +90,8 @@ func (cli SourceCLI) Parse(params []Param) ([]ParamValue, error) {
|
||||
break
|
||||
}
|
||||
if !pvOk {
|
||||
return nil, merr.New(context.Background(), "unexpected config parameter", "param", arg)
|
||||
ctx := mctx.Annotate(context.Background(), "param", arg)
|
||||
return nil, merr.New("unexpected config parameter", ctx)
|
||||
}
|
||||
}
|
||||
|
||||
@ -121,7 +122,8 @@ func (cli SourceCLI) Parse(params []Param) ([]ParamValue, error) {
|
||||
pvStrValOk = false
|
||||
}
|
||||
if pvOk && !pvStrValOk {
|
||||
return nil, merr.New(p.Context, "param expected a value", "param", key)
|
||||
ctx := mctx.Annotate(p.Context, "param", key)
|
||||
return nil, merr.New("param expected a value", ctx)
|
||||
}
|
||||
return pvs, nil
|
||||
}
|
||||
|
@ -59,7 +59,8 @@ func (env SourceEnv) Parse(params []Param) ([]ParamValue, error) {
|
||||
for _, kv := range kvs {
|
||||
split := strings.SplitN(kv, "=", 2)
|
||||
if len(split) != 2 {
|
||||
return nil, merr.New(context.Background(), "malformed environment key/value pair", "kv", kv)
|
||||
ctx := mctx.Annotate(context.Background(), "kv", kv)
|
||||
return nil, merr.New("malformed environment key/value pair", ctx)
|
||||
}
|
||||
k, v := split[0], split[1]
|
||||
if p, ok := pM[k]; ok {
|
||||
|
@ -110,8 +110,9 @@ func populate(params []Param, src Source) error {
|
||||
if !p.Required {
|
||||
continue
|
||||
} else if _, ok := pvM[hash]; !ok {
|
||||
return merr.New(p.Context, "required parameter is not set",
|
||||
ctx := mctx.Annotate(p.Context,
|
||||
"param", paramFullName(mctx.Path(p.Context), p.Name))
|
||||
return merr.New("required parameter is not set", ctx)
|
||||
}
|
||||
}
|
||||
|
||||
@ -133,7 +134,7 @@ func populate(params []Param, src Source) error {
|
||||
// of the Params which were provided by the respective Source.
|
||||
//
|
||||
// Source may be nil to indicate that no configuration is provided. Only default
|
||||
// values will be used, and if any paramaters are required this will error.
|
||||
// values will be used, and if any parameters are required this will error.
|
||||
func Populate(ctx context.Context, src Source) error {
|
||||
return populate(collectParams(ctx), src)
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import (
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
"github.com/mediocregopher/mediocre-go-lib/mctx"
|
||||
"github.com/mediocregopher/mediocre-go-lib/merr"
|
||||
)
|
||||
|
||||
@ -59,7 +60,8 @@ func (pk PublicKey) verify(s Signature, r io.Reader) error {
|
||||
return err
|
||||
}
|
||||
if err := rsa.VerifyPSS(&pk.PublicKey, crypto.SHA256, h.Sum(nil), s.sig, nil); err != nil {
|
||||
return merr.Wrap(context.Background(), ErrInvalidSig, "sig", s)
|
||||
ctx := mctx.Annotate(context.Background(), "sig", s)
|
||||
return merr.Wrap(ErrInvalidSig, ctx)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -89,12 +91,14 @@ func (pk *PublicKey) UnmarshalText(b []byte) error {
|
||||
str := string(b)
|
||||
strEnc, ok := stripPrefix(str, pubKeyV0)
|
||||
if !ok || len(strEnc) <= hex.EncodedLen(8) {
|
||||
return merr.Wrap(context.Background(), errMalformedPublicKey, "pubKeyStr", str)
|
||||
ctx := mctx.Annotate(context.Background(), "pubKeyStr", str)
|
||||
return merr.Wrap(errMalformedPublicKey, ctx)
|
||||
}
|
||||
|
||||
b, err := hex.DecodeString(strEnc)
|
||||
if err != nil {
|
||||
return merr.Wrap(context.Background(), err, "pubKeyStr", str)
|
||||
ctx := mctx.Annotate(context.Background(), "pubKeyStr", str)
|
||||
return merr.Wrap(err, ctx)
|
||||
}
|
||||
|
||||
pk.E = int(binary.BigEndian.Uint64(b))
|
||||
@ -185,17 +189,17 @@ func (pk *PrivateKey) UnmarshalText(b []byte) error {
|
||||
str := string(b)
|
||||
strEnc, ok := stripPrefix(str, privKeyV0)
|
||||
if !ok {
|
||||
return merr.Wrap(context.Background(), errMalformedPrivateKey)
|
||||
return merr.Wrap(errMalformedPrivateKey)
|
||||
}
|
||||
|
||||
b, err := hex.DecodeString(strEnc)
|
||||
if err != nil {
|
||||
return merr.Wrap(context.Background(), errMalformedPrivateKey)
|
||||
return merr.Wrap(errMalformedPrivateKey)
|
||||
}
|
||||
|
||||
e, n := binary.Uvarint(b)
|
||||
if n <= 0 {
|
||||
return merr.Wrap(context.Background(), errMalformedPrivateKey)
|
||||
return merr.Wrap(errMalformedPrivateKey)
|
||||
}
|
||||
pk.PublicKey.E = int(e)
|
||||
b = b[n:]
|
||||
@ -206,7 +210,7 @@ func (pk *PrivateKey) UnmarshalText(b []byte) error {
|
||||
}
|
||||
l, n := binary.Uvarint(b)
|
||||
if n <= 0 {
|
||||
err = merr.Wrap(context.Background(), errMalformedPrivateKey)
|
||||
err = merr.Wrap(errMalformedPrivateKey)
|
||||
}
|
||||
b = b[n:]
|
||||
i := new(big.Int)
|
||||
|
@ -1,7 +1,6 @@
|
||||
package mcrypto
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/hmac"
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
@ -77,9 +76,9 @@ func (s Secret) sign(r io.Reader) (Signature, error) {
|
||||
func (s Secret) verify(sig Signature, r io.Reader) error {
|
||||
sigB, err := s.signRaw(r, uint8(len(sig.sig)), sig.salt, sig.t)
|
||||
if err != nil {
|
||||
return merr.Wrap(context.Background(), err, "sig", sig)
|
||||
return merr.Wrap(err)
|
||||
} else if !hmac.Equal(sigB, sig.sig) {
|
||||
return merr.Wrap(context.Background(), ErrInvalidSig, "sig", sig)
|
||||
return merr.Wrap(ErrInvalidSig)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ package mcrypto
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
@ -67,12 +66,12 @@ func (s *Signature) UnmarshalText(b []byte) error {
|
||||
str := string(b)
|
||||
strEnc, ok := stripPrefix(str, sigV0)
|
||||
if !ok || len(strEnc) < hex.EncodedLen(10) {
|
||||
return merr.Wrap(context.Background(), errMalformedSig, "sigStr", str)
|
||||
return merr.Wrap(errMalformedSig)
|
||||
}
|
||||
|
||||
b, err := hex.DecodeString(strEnc)
|
||||
if err != nil {
|
||||
return merr.Wrap(context.Background(), err, "sigStr", str)
|
||||
return merr.Wrap(err)
|
||||
}
|
||||
|
||||
unixNano, b := int64(binary.BigEndian.Uint64(b[:8])), b[8:]
|
||||
@ -82,7 +81,7 @@ func (s *Signature) UnmarshalText(b []byte) error {
|
||||
if err != nil {
|
||||
return nil
|
||||
} else if len(b) < 1+int(b[0]) {
|
||||
err = merr.Wrap(context.Background(), errMalformedSig, "sigStr", str)
|
||||
err = merr.Wrap(errMalformedSig)
|
||||
return nil
|
||||
}
|
||||
out := b[1 : 1+b[0]]
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/mediocregopher/mediocre-go-lib/mctx"
|
||||
"github.com/mediocregopher/mediocre-go-lib/merr"
|
||||
)
|
||||
|
||||
@ -69,11 +70,13 @@ func (u *UUID) UnmarshalText(b []byte) error {
|
||||
str := string(b)
|
||||
strEnc, ok := stripPrefix(str, uuidV0)
|
||||
if !ok || len(strEnc) != hex.EncodedLen(16) {
|
||||
return merr.Wrap(context.Background(), errMalformedUUID, "uuidStr", str)
|
||||
ctx := mctx.Annotate(context.Background(), "uuidStr", str)
|
||||
return merr.Wrap(errMalformedUUID, ctx)
|
||||
}
|
||||
b, err := hex.DecodeString(strEnc)
|
||||
if err != nil {
|
||||
return merr.Wrap(context.Background(), err, "uuidStr", str)
|
||||
ctx := mctx.Annotate(context.Background(), "uuidStr", str)
|
||||
return merr.Wrap(errMalformedUUID, ctx)
|
||||
}
|
||||
u.b = b
|
||||
return nil
|
||||
|
@ -278,9 +278,14 @@ func mergeAnnotations(ctxA, ctxB context.Context) context.Context {
|
||||
//
|
||||
// NOTE this will panic if no Contexts are passed in.
|
||||
func MergeAnnotations(ctxs ...context.Context) context.Context {
|
||||
ctxA := ctxs[0]
|
||||
for _, ctxB := range ctxs[1:] {
|
||||
ctxA = mergeAnnotations(ctxA, ctxB)
|
||||
return MergeAnnotationsInto(ctxs[0], ctxs[1:]...)
|
||||
}
|
||||
return ctxA
|
||||
|
||||
// MergeAnnotationsInto is a convenience function which works like
|
||||
// MergeAnnotations.
|
||||
func MergeAnnotationsInto(ctx context.Context, ctxs ...context.Context) context.Context {
|
||||
for _, ctxB := range ctxs {
|
||||
ctx = mergeAnnotations(ctx, ctxB)
|
||||
}
|
||||
return ctx
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ func WithBigQuery(parent context.Context, gce *mdb.GCE) (context.Context, *BigQu
|
||||
mlog.Info("connecting to bigquery", bq.ctx)
|
||||
var err error
|
||||
bq.Client, err = bigquery.NewClient(innerCtx, bq.gce.Project, bq.gce.ClientOptions()...)
|
||||
return merr.Wrap(bq.ctx, err)
|
||||
return merr.Wrap(err, bq.ctx)
|
||||
})
|
||||
ctx = mrun.WithStopHook(ctx, func(context.Context) error {
|
||||
return bq.Client.Close()
|
||||
@ -100,12 +100,12 @@ func (bq *BigQuery) Table(
|
||||
mlog.Debug("creating/grabbing table", bq.ctx)
|
||||
schema, err := bigquery.InferSchema(schemaObj)
|
||||
if err != nil {
|
||||
return nil, nil, merr.Wrap(ctx, err)
|
||||
return nil, nil, merr.Wrap(err, ctx)
|
||||
}
|
||||
|
||||
ds := bq.Dataset(dataset)
|
||||
if err := ds.Create(ctx, nil); err != nil && !isErrAlreadyExists(err) {
|
||||
return nil, nil, merr.Wrap(ctx, err)
|
||||
return nil, nil, merr.Wrap(err, ctx)
|
||||
}
|
||||
|
||||
table := ds.Table(tableName)
|
||||
@ -114,7 +114,7 @@ func (bq *BigQuery) Table(
|
||||
Schema: schema,
|
||||
}
|
||||
if err := table.Create(ctx, meta); err != nil && !isErrAlreadyExists(err) {
|
||||
return nil, nil, merr.Wrap(ctx, err)
|
||||
return nil, nil, merr.Wrap(err, ctx)
|
||||
}
|
||||
uploader := table.Uploader()
|
||||
|
||||
|
@ -74,7 +74,7 @@ func WithBigTable(parent context.Context, gce *mdb.GCE, defaultInstance string)
|
||||
bt.gce.Project, bt.Instance,
|
||||
bt.gce.ClientOptions()...,
|
||||
)
|
||||
return merr.Wrap(bt.ctx, err)
|
||||
return merr.Wrap(err, bt.ctx)
|
||||
})
|
||||
ctx = mrun.WithStopHook(ctx, func(context.Context) error {
|
||||
return bt.Client.Close()
|
||||
@ -95,14 +95,14 @@ func (bt *Bigtable) EnsureTable(ctx context.Context, name string, colFams ...str
|
||||
mlog.Debug("creating admin client", ctx)
|
||||
adminClient, err := bigtable.NewAdminClient(ctx, bt.gce.Project, bt.Instance)
|
||||
if err != nil {
|
||||
return merr.Wrap(ctx, err)
|
||||
return merr.Wrap(err, ctx)
|
||||
}
|
||||
defer adminClient.Close()
|
||||
|
||||
mlog.Debug("creating bigtable table (if needed)", ctx)
|
||||
err = adminClient.CreateTable(ctx, name)
|
||||
if err != nil && !isErrAlreadyExists(err) {
|
||||
return merr.Wrap(ctx, err)
|
||||
return merr.Wrap(err, ctx)
|
||||
}
|
||||
|
||||
for _, colFam := range colFams {
|
||||
@ -110,7 +110,7 @@ func (bt *Bigtable) EnsureTable(ctx context.Context, name string, colFams ...str
|
||||
mlog.Debug("creating bigtable column family (if needed)", ctx)
|
||||
err := adminClient.CreateColumnFamily(ctx, name, colFam)
|
||||
if err != nil && !isErrAlreadyExists(err) {
|
||||
return merr.Wrap(ctx, err)
|
||||
return merr.Wrap(err, ctx)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,7 @@ func WithDatastore(parent context.Context, gce *mdb.GCE) (context.Context, *Data
|
||||
mlog.Info("connecting to datastore", ds.ctx)
|
||||
var err error
|
||||
ds.Client, err = datastore.NewClient(innerCtx, ds.gce.Project, ds.gce.ClientOptions()...)
|
||||
return merr.Wrap(ds.ctx, err)
|
||||
return merr.Wrap(err, ds.ctx)
|
||||
})
|
||||
ctx = mrun.WithStopHook(ctx, func(context.Context) error {
|
||||
return ds.Client.Close()
|
||||
|
@ -62,7 +62,7 @@ func WithPubSub(parent context.Context, gce *mdb.GCE) (context.Context, *PubSub)
|
||||
mlog.Info("connecting to pubsub", ps.ctx)
|
||||
var err error
|
||||
ps.Client, err = pubsub.NewClient(innerCtx, ps.gce.Project, ps.gce.ClientOptions()...)
|
||||
return merr.Wrap(ps.ctx, err)
|
||||
return merr.Wrap(err, ps.ctx)
|
||||
})
|
||||
ctx = mrun.WithStopHook(ctx, func(context.Context) error {
|
||||
return ps.Client.Close()
|
||||
@ -93,14 +93,14 @@ func (ps *PubSub) Topic(ctx context.Context, name string, create bool) (*Topic,
|
||||
if isErrAlreadyExists(err) {
|
||||
t.topic = ps.Client.Topic(name)
|
||||
} else if err != nil {
|
||||
return nil, merr.Wrap(ctx, merr.Wrap(t.ctx, err))
|
||||
return nil, merr.Wrap(err, t.ctx, ctx)
|
||||
}
|
||||
} else {
|
||||
t.topic = ps.Client.Topic(name)
|
||||
if exists, err := t.topic.Exists(t.ctx); err != nil {
|
||||
return nil, merr.Wrap(ctx, merr.Wrap(t.ctx, err))
|
||||
return nil, merr.Wrap(err, t.ctx, ctx)
|
||||
} else if !exists {
|
||||
return nil, merr.Wrap(ctx, merr.New(t.ctx, "topic dne"))
|
||||
return nil, merr.New("topic dne", t.ctx, ctx)
|
||||
}
|
||||
}
|
||||
return t, nil
|
||||
@ -110,7 +110,7 @@ func (ps *PubSub) Topic(ctx context.Context, name string, create bool) (*Topic,
|
||||
func (t *Topic) Publish(ctx context.Context, data []byte) error {
|
||||
_, err := t.topic.Publish(ctx, &Message{Data: data}).Get(ctx)
|
||||
if err != nil {
|
||||
return merr.Wrap(ctx, merr.Wrap(t.ctx, err))
|
||||
return merr.Wrap(err, t.ctx, ctx)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -144,14 +144,14 @@ func (t *Topic) Subscription(ctx context.Context, name string, create bool) (*Su
|
||||
if isErrAlreadyExists(err) {
|
||||
s.sub = t.ps.Subscription(name)
|
||||
} else if err != nil {
|
||||
return nil, merr.Wrap(ctx, merr.Wrap(s.ctx, err))
|
||||
return nil, merr.Wrap(err, s.ctx, ctx)
|
||||
}
|
||||
} else {
|
||||
s.sub = t.ps.Subscription(name)
|
||||
if exists, err := s.sub.Exists(ctx); err != nil {
|
||||
return nil, merr.Wrap(ctx, merr.Wrap(s.ctx, err))
|
||||
return nil, merr.Wrap(err, s.ctx, ctx)
|
||||
} else if !exists {
|
||||
return nil, merr.Wrap(ctx, merr.New(s.ctx, "sub dne"))
|
||||
return nil, merr.New("sub dne", s.ctx, ctx)
|
||||
}
|
||||
}
|
||||
return s, nil
|
||||
@ -350,7 +350,7 @@ func (s *Subscription) BatchConsume(
|
||||
case ret := <-retCh:
|
||||
return ret, nil
|
||||
case <-ctx.Done():
|
||||
return false, merr.Wrap(ctx, merr.New(s.ctx, "reading from batch grouping process timed out"))
|
||||
return false, merr.New("reading from batch grouping process timed out", s.ctx, ctx)
|
||||
}
|
||||
}, opts)
|
||||
|
||||
|
@ -46,7 +46,7 @@ func WithMySQL(parent context.Context, defaultDB string) (context.Context, *SQL)
|
||||
mlog.Info("connecting to mysql server", sql.ctx)
|
||||
var err error
|
||||
sql.DB, err = sqlx.ConnectContext(innerCtx, "mysql", dsn)
|
||||
return merr.Wrap(sql.ctx, err)
|
||||
return merr.Wrap(err, sql.ctx)
|
||||
})
|
||||
ctx = mrun.WithStopHook(ctx, func(innerCtx context.Context) error {
|
||||
mlog.Info("closing connection to sql server", sql.ctx)
|
||||
|
44
merr/merr.go
44
merr/merr.go
@ -57,7 +57,7 @@ func wrap(e error, cp bool) *err {
|
||||
|
||||
er2 := &err{
|
||||
err: er.err,
|
||||
attr: make(map[interface{}]interface{}, len(er.attr)),
|
||||
attr: make(map[interface{}]interface{}, len(er.attr)+1),
|
||||
}
|
||||
for k, v := range er.attr {
|
||||
er2.attr[k] = v
|
||||
@ -102,47 +102,47 @@ func Value(e error, k interface{}) interface{} {
|
||||
|
||||
// WrapSkip is like Wrap but also allows for skipping extra stack frames when
|
||||
// embedding the stack into the error.
|
||||
func WrapSkip(ctx context.Context, e error, skip int, kvs ...interface{}) error {
|
||||
func WrapSkip(e error, skip int, ctxs ...context.Context) error {
|
||||
if e == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
er := wrap(e, true)
|
||||
if _, ok := getStack(er); !ok {
|
||||
setStack(er, skip+1)
|
||||
}
|
||||
|
||||
if prevCtx, _ := er.attr[attrKeyCtx].(context.Context); prevCtx != nil {
|
||||
ctx = mctx.MergeAnnotations(prevCtx, ctx)
|
||||
}
|
||||
|
||||
if len(kvs) > 0 {
|
||||
ctx = mctx.Annotate(ctx, kvs...)
|
||||
ctx, _ := er.attr[attrKeyCtx].(context.Context)
|
||||
if ctx != nil {
|
||||
ctx = mctx.MergeAnnotationsInto(ctx, ctxs...)
|
||||
} else if len(ctxs) > 0 {
|
||||
ctx = mctx.MergeAnnotations(ctxs...)
|
||||
}
|
||||
|
||||
er.attr[attrKeyCtx] = ctx
|
||||
return er
|
||||
}
|
||||
|
||||
// Wrap takes in an error and returns one which wraps it in merr's inner type,
|
||||
// embedding the given Context (which can later be retrieved by Ctx) at the same
|
||||
// time.
|
||||
//
|
||||
// For convenience, extra annotation information can be passed in here as well
|
||||
// via the kvs argument. See mctx.Annotate for more information.
|
||||
// Wrap returns a copy of the given error wrapped in merr's inner type. It will
|
||||
// perform an mctx.MergeAnnotations on the given Contexts to create a new
|
||||
// Context, and embed that in the returned error. If the given error already has
|
||||
// an embedded Context then ctxs will be merged into that.
|
||||
//
|
||||
// This function automatically embeds stack information into the error as it's
|
||||
// being stored, using WithStack, unless the error already has stack information
|
||||
// in it.
|
||||
func Wrap(ctx context.Context, e error, kvs ...interface{}) error {
|
||||
return WrapSkip(ctx, e, 1, kvs...)
|
||||
//
|
||||
// Wrapping nil returns nil.
|
||||
func Wrap(e error, ctx ...context.Context) error {
|
||||
return WrapSkip(e, 1, ctx...)
|
||||
}
|
||||
|
||||
// New is a shortcut for:
|
||||
// merr.Wrap(ctx, errors.New(str), kvs...)
|
||||
func New(ctx context.Context, str string, kvs ...interface{}) error {
|
||||
return WrapSkip(ctx, errors.New(str), 1, kvs...)
|
||||
// merr.Wrap(errors.New(str), ctxs...)
|
||||
func New(str string, ctxs ...context.Context) error {
|
||||
return WrapSkip(errors.New(str), 1, ctxs...)
|
||||
}
|
||||
|
||||
// TODO it would be more convenient in a lot of cases if New and Wrap took in a
|
||||
// list of Contexts.
|
||||
|
||||
type annotateKey string
|
||||
|
||||
func ctx(e error) context.Context {
|
||||
|
@ -10,24 +10,41 @@ import (
|
||||
)
|
||||
|
||||
func TestError(t *T) {
|
||||
e := New(context.Background(), "foo",
|
||||
massert.Fatal(t, massert.Nil(Wrap(nil)))
|
||||
|
||||
ctx := mctx.Annotate(context.Background(),
|
||||
"a", "aaa aaa\n",
|
||||
"c", "ccc\nccc\n",
|
||||
"d\t", "weird key but ok",
|
||||
)
|
||||
"d\t", "weird key but ok")
|
||||
|
||||
{
|
||||
e := New("foo", ctx)
|
||||
exp := `foo
|
||||
* a: aaa aaa
|
||||
* c:
|
||||
ccc
|
||||
ccc
|
||||
* d: weird key but ok
|
||||
* errLoc: merr/merr_test.go:13`
|
||||
* errLoc: merr/merr_test.go:19`
|
||||
massert.Fatal(t, massert.Equal(exp, e.Error()))
|
||||
}
|
||||
|
||||
{
|
||||
e := Wrap(errors.New("foo"), ctx)
|
||||
exp := `foo
|
||||
* a: aaa aaa
|
||||
* c:
|
||||
ccc
|
||||
ccc
|
||||
* d: weird key but ok
|
||||
* errLoc: merr/merr_test.go:31`
|
||||
massert.Fatal(t, massert.Equal(exp, e.Error()))
|
||||
}
|
||||
}
|
||||
|
||||
func TestBase(t *T) {
|
||||
errFoo, errBar := errors.New("foo"), errors.New("bar")
|
||||
erFoo := Wrap(context.Background(), errFoo)
|
||||
erFoo := Wrap(errFoo)
|
||||
massert.Fatal(t, massert.All(
|
||||
massert.Nil(Base(nil)),
|
||||
massert.Equal(errFoo, Base(erFoo)),
|
||||
@ -45,7 +62,7 @@ func TestValue(t *T) {
|
||||
massert.Nil(Value(nil, "foo")),
|
||||
))
|
||||
|
||||
e1 := New(context.Background(), "foo")
|
||||
e1 := New("foo")
|
||||
e1 = WithValue(e1, "a", "A")
|
||||
e2 := WithValue(errors.New("bar"), "a", "A")
|
||||
massert.Fatal(t, massert.All(
|
||||
@ -62,7 +79,7 @@ func TestValue(t *T) {
|
||||
}
|
||||
|
||||
func mkErr(ctx context.Context, err error) error {
|
||||
return Wrap(ctx, err) // it's important that this is line 65
|
||||
return Wrap(err, ctx)
|
||||
}
|
||||
|
||||
func TestCtx(t *T) {
|
||||
@ -72,14 +89,14 @@ func TestCtx(t *T) {
|
||||
// use mkErr so that it's easy to test that the stack info isn't overwritten
|
||||
// when Wrap is called with ctxB.
|
||||
e := mkErr(ctxA, errors.New("hello"))
|
||||
e = Wrap(ctxB, e)
|
||||
e = Wrap(e, ctxB)
|
||||
|
||||
err := massert.Equal(map[string]string{
|
||||
"0": "ZERO",
|
||||
"1": "ONE",
|
||||
"2": "TWO",
|
||||
"err": "hello",
|
||||
"errLoc": "merr/merr_test.go:65",
|
||||
"errLoc": "merr/merr_test.go:80",
|
||||
}, mctx.Annotations(Context(e)).StringMap()).Assert()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -1,7 +1,6 @@
|
||||
package merr
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
. "testing"
|
||||
|
||||
@ -9,7 +8,7 @@ import (
|
||||
)
|
||||
|
||||
func TestStack(t *T) {
|
||||
foo := New(context.Background(), "test")
|
||||
foo := New("test")
|
||||
fooStack, ok := Stack(foo)
|
||||
massert.Fatal(t, massert.Equal(true, ok))
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user