go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/common/errors/multierror_test.go (about)

     1  // Copyright 2015 The LUCI Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package errors
    16  
    17  import (
    18  	"errors"
    19  	"fmt"
    20  	"testing"
    21  
    22  	. "github.com/smartystreets/goconvey/convey"
    23  )
    24  
    25  func TestMultiError(t *testing.T) {
    26  	t.Parallel()
    27  
    28  	Convey("MultiError works", t, func() {
    29  		var me error = MultiError{fmt.Errorf("hello"), fmt.Errorf("bob")}
    30  
    31  		So(me.Error(), ShouldEqual, `hello (and 1 other error)`)
    32  	})
    33  }
    34  
    35  func TestUpstreamErrors(t *testing.T) {
    36  	t.Parallel()
    37  
    38  	Convey("Test MultiError", t, func() {
    39  		Convey("nil", func() {
    40  			me := MultiError(nil)
    41  			So(me.Error(), ShouldEqual, "(0 errors)")
    42  			Convey("single", func() {
    43  				So(SingleError(error(me)), ShouldBeNil)
    44  			})
    45  		})
    46  		Convey("one", func() {
    47  			me := MultiError{errors.New("sup")}
    48  			So(me.Error(), ShouldEqual, "sup")
    49  		})
    50  		Convey("two", func() {
    51  			me := MultiError{errors.New("sup"), errors.New("what")}
    52  			So(me.Error(), ShouldEqual, "sup (and 1 other error)")
    53  		})
    54  		Convey("more", func() {
    55  			me := MultiError{errors.New("sup"), errors.New("what"), errors.New("nerds")}
    56  			So(me.Error(), ShouldEqual, "sup (and 2 other errors)")
    57  
    58  			Convey("single", func() {
    59  				So(SingleError(error(me)), ShouldResemble, errors.New("sup"))
    60  			})
    61  		})
    62  	})
    63  
    64  	Convey("MaybeAdd", t, func() {
    65  		me := MultiError(nil)
    66  
    67  		Convey("nil", func() {
    68  			me.MaybeAdd(nil)
    69  			So(me, ShouldHaveLength, 0)
    70  			So(error(me), ShouldBeNil)
    71  		})
    72  
    73  		Convey("thing", func() {
    74  			me.MaybeAdd(errors.New("sup"))
    75  			So(me, ShouldHaveLength, 1)
    76  			So(error(me), ShouldNotBeNil)
    77  
    78  			me.MaybeAdd(errors.New("what"))
    79  			So(me, ShouldHaveLength, 2)
    80  			So(error(me), ShouldNotBeNil)
    81  		})
    82  
    83  	})
    84  
    85  	Convey("AsError", t, func() {
    86  		var me MultiError
    87  		So(me, ShouldBeNil)
    88  
    89  		var err error
    90  		err = me
    91  
    92  		// Unfortunately Go has many nil's :(
    93  		//   So(err == nil, ShouldBeTrue)
    94  		// Note that `ShouldBeNil` won't cut it, since it 'sees through' interfaces.
    95  
    96  		// However!
    97  		err = me.AsError()
    98  		So(err == nil, ShouldBeTrue)
    99  	})
   100  
   101  	Convey("SingleError passes through", t, func() {
   102  		e := errors.New("unique")
   103  		So(SingleError(e), ShouldEqual, e)
   104  	})
   105  }
   106  
   107  func TestFlatten(t *testing.T) {
   108  	t.Parallel()
   109  
   110  	Convey("Flatten works", t, func() {
   111  		Convey("Nil", func() {
   112  			So(Flatten(MultiError{nil, nil, MultiError{nil, nil, nil}}), ShouldBeNil)
   113  		})
   114  
   115  		Convey("2-dim", func() {
   116  			So(Flatten(MultiError{nil, errors.New("1"), nil, MultiError{nil, errors.New("2"), nil}}),
   117  				ShouldResemble, MultiError{errors.New("1"), errors.New("2")})
   118  		})
   119  
   120  		Convey("Doesn't unwrap", func() {
   121  			ann := Annotate(MultiError{nil, nil, nil}, "don't do this").Err()
   122  			merr, yup := Flatten(MultiError{nil, ann, nil, MultiError{nil, errors.New("2"), nil}}).(MultiError)
   123  			So(yup, ShouldBeTrue)
   124  			So(len(merr), ShouldEqual, 2)
   125  			So(merr, ShouldResemble, MultiError{ann, errors.New("2")})
   126  		})
   127  	})
   128  }
   129  
   130  func TestAppend(t *testing.T) {
   131  	t.Parallel()
   132  	Convey("Test Append function", t, func() {
   133  		Convey("combine empty", func() {
   134  			So(Append(), ShouldBeNil)
   135  		})
   136  		Convey("more intricate empty cases", func() {
   137  			So(Append(Append()), ShouldBeNil)
   138  			So(Append(nil), ShouldBeNil)
   139  			So(Append(Append(Append()), Append(), nil, Append(nil, nil)), ShouldBeNil)
   140  		})
   141  		Convey("singleton physical equality", func() {
   142  			e := fmt.Errorf("f59031c1-3d8d-47c4-8cff-b2b5d67ce7e7")
   143  			So(e, ShouldEqual, Append(e))
   144  			So(e, ShouldEqual, Append(Append(e)))
   145  		})
   146  		Convey("doubleton physical equality", func() {
   147  			e := fmt.Errorf("f59031c1-3d8d-47c4-8cff-b2b5d67ce7e7")
   148  			So(Append(e, e).(MultiError)[0], ShouldEqual, e)
   149  		})
   150  		Convey("doubleton physical equality with nils", func() {
   151  			e := fmt.Errorf("2d2a3939-e185-4210-9060-0cb0fdab42be")
   152  			So(Append(nil, e, e, nil).(MultiError)[0], ShouldEqual, e)
   153  		})
   154  	})
   155  }