| Index: common/errors/tags_test.go
|
| diff --git a/common/errors/tags_test.go b/common/errors/tags_test.go
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..1ae01b6ae0bec43f53c6accdc7e2dadf5660c58c
|
| --- /dev/null
|
| +++ b/common/errors/tags_test.go
|
| @@ -0,0 +1,149 @@
|
| +// Copyright 2017 The LUCI Authors. All rights reserved.
|
| +// Use of this source code is governed under the Apache License, Version 2.0
|
| +// that can be found in the LICENSE file.
|
| +
|
| +package errors
|
| +
|
| +import (
|
| + stdErr "errors"
|
| + "testing"
|
| +
|
| + . "github.com/smartystreets/goconvey/convey"
|
| +)
|
| +
|
| +type customInt int
|
| +
|
| +func TestTags(t *testing.T) {
|
| + t.Parallel()
|
| +
|
| + aBoolTag := NewBoolTag("errors.testing tag")
|
| + aValueTag := NewTagger("errors.testing value tag")
|
| + aStringTag := NewTagger("errors.testing string tag", func(v interface{}) {
|
| + _ = v.(string)
|
| + })
|
| + aCustomIntTag := NewTagger("errors.testing string tag", func(v interface{}) {
|
| + _ = v.(customInt)
|
| + })
|
| +
|
| + Convey("Tags", t, func() {
|
| + Convey(`have unique tagKey values`, func() {
|
| + tagSet := map[tagKey]struct{}{}
|
| + tagSet[aBoolTag.(tagKey)] = struct{}{}
|
| + tagSet[aValueTag.(tagKey)] = struct{}{}
|
| + tagSet[aStringTag.(tagKey)] = struct{}{}
|
| + tagSet[aCustomIntTag.(tagKey)] = struct{}{}
|
| + So(tagSet, ShouldHaveLength, 4)
|
| + })
|
| +
|
| + Convey(`can be applied to errors`, func() {
|
| + Convey(`at creation time`, func() {
|
| + err := New("I am an error", aBoolTag, aValueTag.With(100))
|
| + So(aBoolTag.In(err), ShouldBeTrue)
|
| + d, ok := aValueTag.ValueIn(err)
|
| + So(ok, ShouldBeTrue)
|
| + So(d, ShouldEqual, 100)
|
| +
|
| + d, _ = aBoolTag.ValueIn(err)
|
| + So(d, ShouldBeNil)
|
| +
|
| + So(aStringTag.In(err), ShouldBeFalse)
|
| + So(aCustomIntTag.In(err), ShouldBeFalse)
|
| + })
|
| +
|
| + Convey(`added to existing errors`, func() {
|
| + err := New("I am an error")
|
| + err2 := aCustomIntTag.With(customInt(236)).Apply(err)
|
| + err2 = aBoolTag.Apply(err2)
|
| +
|
| + d, ok := aCustomIntTag.ValueIn(err2)
|
| + So(ok, ShouldBeTrue)
|
| + So(d, ShouldEqual, customInt(236))
|
| + So(aBoolTag.In(err2), ShouldBeTrue)
|
| +
|
| + So(aCustomIntTag.In(err), ShouldBeFalse)
|
| + So(aBoolTag.In(err), ShouldBeFalse)
|
| + })
|
| +
|
| + Convey(`added to stdlib errors`, func() {
|
| + err := stdErr.New("I am an error")
|
| + err2 := aStringTag.With("hi").Apply(err)
|
| +
|
| + d, ok := aStringTag.ValueIn(err2)
|
| + So(ok, ShouldBeTrue)
|
| + So(d, ShouldEqual, "hi")
|
| +
|
| + So(aStringTag.In(err), ShouldBeFalse)
|
| + })
|
| +
|
| + Convey(`multiple applications has the last one win`, func() {
|
| + err := New("I am an error")
|
| + err = aStringTag.With("hi").Apply(err)
|
| + err = aStringTag.With("there").Apply(err)
|
| + err = aStringTag.With("winner").Apply(err)
|
| +
|
| + d, ok := aStringTag.ValueIn(err)
|
| + So(ok, ShouldBeTrue)
|
| + So(d, ShouldEqual, "winner")
|
| +
|
| + Convey(`muliterrors are first to last`, func() {
|
| + err = NewMultiError(
|
| + New("a", aStringTag.With("hi"), aBoolTag),
|
| + New("b", aValueTag.With("there"), aStringTag.With("no")),
|
| + New("c", aValueTag.With("nope"), aStringTag.With("nopers")),
|
| + )
|
| +
|
| + So(aBoolTag.In(err), ShouldBeTrue)
|
| +
|
| + d, ok := aStringTag.ValueIn(err)
|
| + So(ok, ShouldBeTrue)
|
| + So(d, ShouldEqual, "hi")
|
| +
|
| + d, ok = aValueTag.ValueIn(err)
|
| + So(ok, ShouldBeTrue)
|
| + So(d, ShouldEqual, "there")
|
| +
|
| + Convey(`and all the correct values show up with GetTags`, func() {
|
| + tags := GetTags(err)
|
| + So(tags, ShouldContainKey, aValueTag)
|
| + So(tags, ShouldContainKey, aStringTag)
|
| + So(tags, ShouldContainKey, aBoolTag)
|
| + So(tags, ShouldNotContainKey, aCustomIntTag)
|
| +
|
| + So(tags[aValueTag], ShouldEqual, "there")
|
| + So(tags[aStringTag], ShouldEqual, "hi")
|
| + So(tags[aBoolTag], ShouldBeNil)
|
| + })
|
| + })
|
| + })
|
| + })
|
| +
|
| + Convey(`only allow simple values`, func() {
|
| + Convey(`numbers, strings OK`, func() {
|
| + aValueTag.With("hi")
|
| + aValueTag.With(100)
|
| + aValueTag.With(false)
|
| + aValueTag.With(34.100)
|
| + aValueTag.With(12 + 100i)
|
| + })
|
| +
|
| + Convey(`no structs, etc.`, func() {
|
| + So(func() { aValueTag.With(struct{}{}) }, ShouldPanic)
|
| + So(func() { aValueTag.With([]int{}) }, ShouldPanic)
|
| + So(func() { aValueTag.With(func() {}) }, ShouldPanic)
|
| + So(func() { aValueTag.With(make(chan int)) }, ShouldPanic)
|
| + So(func() { aValueTag.With([10]byte{}) }, ShouldPanic)
|
| + So(func() { aValueTag.With(map[int]int{}) }, ShouldPanic)
|
| + So(func() { aValueTag.With(&struct{}{}) }, ShouldPanic)
|
| + })
|
| +
|
| + Convey(`and custom validators can add additional constriants`, func() {
|
| + aStringTag.With("sup")
|
| + So(func() { aStringTag.With(100) }, ShouldPanic)
|
| +
|
| + aCustomIntTag.With(customInt(100))
|
| + So(func() { aCustomIntTag.With(100) }, ShouldPanic)
|
| + So(func() { aCustomIntTag.With("hi") }, ShouldPanic)
|
| + })
|
| + })
|
| + })
|
| +}
|
|
|