github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/libraries/juju/errors/functions_test.go (about) 1 // Copyright 2014 Canonical Ltd. 2 // Licensed under the LGPLv3, see LICENCE file for details. 3 4 package errors_test 5 6 import ( 7 "fmt" 8 "os" 9 "path/filepath" 10 "runtime" 11 "strings" 12 13 jc "github.com/insionng/yougam/libraries/juju/testing/checkers" 14 gc "gopkg.in/check.v1" 15 16 "github.com/insionng/yougam/libraries/juju/errors" 17 ) 18 19 type functionSuite struct { 20 } 21 22 var _ = gc.Suite(&functionSuite{}) 23 24 func (*functionSuite) TestNew(c *gc.C) { 25 err := errors.New("testing") //err newTest 26 c.Assert(err.Error(), gc.Equals, "testing") 27 c.Assert(errors.Cause(err), gc.Equals, err) 28 c.Assert(errors.Details(err), jc.Contains, tagToLocation["newTest"].String()) 29 } 30 31 func (*functionSuite) TestErrorf(c *gc.C) { 32 err := errors.Errorf("testing %d", 42) //err errorfTest 33 c.Assert(err.Error(), gc.Equals, "testing 42") 34 c.Assert(errors.Cause(err), gc.Equals, err) 35 c.Assert(errors.Details(err), jc.Contains, tagToLocation["errorfTest"].String()) 36 } 37 38 func (*functionSuite) TestTrace(c *gc.C) { 39 first := errors.New("first") 40 err := errors.Trace(first) //err traceTest 41 c.Assert(err.Error(), gc.Equals, "first") 42 c.Assert(errors.Cause(err), gc.Equals, first) 43 c.Assert(errors.Details(err), jc.Contains, tagToLocation["traceTest"].String()) 44 45 c.Assert(errors.Trace(nil), gc.IsNil) 46 } 47 48 func (*functionSuite) TestAnnotate(c *gc.C) { 49 first := errors.New("first") 50 err := errors.Annotate(first, "annotation") //err annotateTest 51 c.Assert(err.Error(), gc.Equals, "annotation: first") 52 c.Assert(errors.Cause(err), gc.Equals, first) 53 c.Assert(errors.Details(err), jc.Contains, tagToLocation["annotateTest"].String()) 54 55 c.Assert(errors.Annotate(nil, "annotate"), gc.IsNil) 56 } 57 58 func (*functionSuite) TestAnnotatef(c *gc.C) { 59 first := errors.New("first") 60 err := errors.Annotatef(first, "annotation %d", 2) //err annotatefTest 61 c.Assert(err.Error(), gc.Equals, "annotation 2: first") 62 c.Assert(errors.Cause(err), gc.Equals, first) 63 c.Assert(errors.Details(err), jc.Contains, tagToLocation["annotatefTest"].String()) 64 65 c.Assert(errors.Annotatef(nil, "annotate"), gc.IsNil) 66 } 67 68 func (*functionSuite) TestDeferredAnnotatef(c *gc.C) { 69 // NOTE: this test fails with gccgo 70 if runtime.Compiler == "gccgo" { 71 c.Skip("gccgo can't determine the location") 72 } 73 first := errors.New("first") 74 test := func() (err error) { 75 defer errors.DeferredAnnotatef(&err, "deferred %s", "annotate") 76 return first 77 } //err deferredAnnotate 78 err := test() 79 c.Assert(err.Error(), gc.Equals, "deferred annotate: first") 80 c.Assert(errors.Cause(err), gc.Equals, first) 81 c.Assert(errors.Details(err), jc.Contains, tagToLocation["deferredAnnotate"].String()) 82 83 err = nil 84 errors.DeferredAnnotatef(&err, "deferred %s", "annotate") 85 c.Assert(err, gc.IsNil) 86 } 87 88 func (*functionSuite) TestWrap(c *gc.C) { 89 first := errors.New("first") //err wrapFirst 90 detailed := errors.New("detailed") 91 err := errors.Wrap(first, detailed) //err wrapTest 92 c.Assert(err.Error(), gc.Equals, "detailed") 93 c.Assert(errors.Cause(err), gc.Equals, detailed) 94 c.Assert(errors.Details(err), jc.Contains, tagToLocation["wrapFirst"].String()) 95 c.Assert(errors.Details(err), jc.Contains, tagToLocation["wrapTest"].String()) 96 } 97 98 func (*functionSuite) TestWrapOfNil(c *gc.C) { 99 detailed := errors.New("detailed") 100 err := errors.Wrap(nil, detailed) //err nilWrapTest 101 c.Assert(err.Error(), gc.Equals, "detailed") 102 c.Assert(errors.Cause(err), gc.Equals, detailed) 103 c.Assert(errors.Details(err), jc.Contains, tagToLocation["nilWrapTest"].String()) 104 } 105 106 func (*functionSuite) TestWrapf(c *gc.C) { 107 first := errors.New("first") //err wrapfFirst 108 detailed := errors.New("detailed") 109 err := errors.Wrapf(first, detailed, "value %d", 42) //err wrapfTest 110 c.Assert(err.Error(), gc.Equals, "value 42: detailed") 111 c.Assert(errors.Cause(err), gc.Equals, detailed) 112 c.Assert(errors.Details(err), jc.Contains, tagToLocation["wrapfFirst"].String()) 113 c.Assert(errors.Details(err), jc.Contains, tagToLocation["wrapfTest"].String()) 114 } 115 116 func (*functionSuite) TestWrapfOfNil(c *gc.C) { 117 detailed := errors.New("detailed") 118 err := errors.Wrapf(nil, detailed, "value %d", 42) //err nilWrapfTest 119 c.Assert(err.Error(), gc.Equals, "value 42: detailed") 120 c.Assert(errors.Cause(err), gc.Equals, detailed) 121 c.Assert(errors.Details(err), jc.Contains, tagToLocation["nilWrapfTest"].String()) 122 } 123 124 func (*functionSuite) TestMask(c *gc.C) { 125 first := errors.New("first") 126 err := errors.Mask(first) //err maskTest 127 c.Assert(err.Error(), gc.Equals, "first") 128 c.Assert(errors.Cause(err), gc.Equals, err) 129 c.Assert(errors.Details(err), jc.Contains, tagToLocation["maskTest"].String()) 130 131 c.Assert(errors.Mask(nil), gc.IsNil) 132 } 133 134 func (*functionSuite) TestMaskf(c *gc.C) { 135 first := errors.New("first") 136 err := errors.Maskf(first, "masked %d", 42) //err maskfTest 137 c.Assert(err.Error(), gc.Equals, "masked 42: first") 138 c.Assert(errors.Cause(err), gc.Equals, err) 139 c.Assert(errors.Details(err), jc.Contains, tagToLocation["maskfTest"].String()) 140 141 c.Assert(errors.Maskf(nil, "mask"), gc.IsNil) 142 } 143 144 func (*functionSuite) TestCause(c *gc.C) { 145 c.Assert(errors.Cause(nil), gc.IsNil) 146 c.Assert(errors.Cause(someErr), gc.Equals, someErr) 147 148 fmtErr := fmt.Errorf("simple") 149 c.Assert(errors.Cause(fmtErr), gc.Equals, fmtErr) 150 151 err := errors.Wrap(someErr, fmtErr) 152 c.Assert(errors.Cause(err), gc.Equals, fmtErr) 153 154 err = errors.Annotate(err, "annotated") 155 c.Assert(errors.Cause(err), gc.Equals, fmtErr) 156 157 err = errors.Maskf(err, "maksed") 158 c.Assert(errors.Cause(err), gc.Equals, err) 159 160 // Look for a file that we know isn't there. 161 dir := c.MkDir() 162 _, err = os.Stat(filepath.Join(dir, "not-there")) 163 c.Assert(os.IsNotExist(err), jc.IsTrue) 164 165 err = errors.Annotatef(err, "wrap it") 166 // Now the error itself isn't a 'IsNotExist'. 167 c.Assert(os.IsNotExist(err), jc.IsFalse) 168 // However if we use the Check method, it is. 169 c.Assert(os.IsNotExist(errors.Cause(err)), jc.IsTrue) 170 } 171 172 func (s *functionSuite) TestDetails(c *gc.C) { 173 if runtime.Compiler == "gccgo" { 174 c.Skip("gccgo can't determine the location") 175 } 176 c.Assert(errors.Details(nil), gc.Equals, "[]") 177 178 otherErr := fmt.Errorf("other") 179 checkDetails(c, otherErr, "[{other}]") 180 181 err0 := newEmbed("foo") //err TestStack#0 182 checkDetails(c, err0, "[{$TestStack#0$: foo}]") 183 184 err1 := errors.Annotate(err0, "bar") //err TestStack#1 185 checkDetails(c, err1, "[{$TestStack#1$: bar} {$TestStack#0$: foo}]") 186 187 err2 := errors.Trace(err1) //err TestStack#2 188 checkDetails(c, err2, "[{$TestStack#2$: } {$TestStack#1$: bar} {$TestStack#0$: foo}]") 189 } 190 191 type tracer interface { 192 StackTrace() []string 193 } 194 195 func (*functionSuite) TestErrorStack(c *gc.C) { 196 for i, test := range []struct { 197 message string 198 generator func() error 199 expected string 200 tracer bool 201 }{ 202 { 203 message: "nil", 204 generator: func() error { 205 return nil 206 }, 207 }, { 208 message: "raw error", 209 generator: func() error { 210 return fmt.Errorf("raw") 211 }, 212 expected: "raw", 213 }, { 214 message: "single error stack", 215 generator: func() error { 216 return errors.New("first error") //err single 217 }, 218 expected: "$single$: first error", 219 tracer: true, 220 }, { 221 message: "annotated error", 222 generator: func() error { 223 err := errors.New("first error") //err annotated-0 224 return errors.Annotate(err, "annotation") //err annotated-1 225 }, 226 expected: "" + 227 "$annotated-0$: first error\n" + 228 "$annotated-1$: annotation", 229 tracer: true, 230 }, { 231 message: "wrapped error", 232 generator: func() error { 233 err := errors.New("first error") //err wrapped-0 234 return errors.Wrap(err, newError("detailed error")) //err wrapped-1 235 }, 236 expected: "" + 237 "$wrapped-0$: first error\n" + 238 "$wrapped-1$: detailed error", 239 tracer: true, 240 }, { 241 message: "annotated wrapped error", 242 generator: func() error { 243 err := errors.Errorf("first error") //err ann-wrap-0 244 err = errors.Wrap(err, fmt.Errorf("detailed error")) //err ann-wrap-1 245 return errors.Annotatef(err, "annotated") //err ann-wrap-2 246 }, 247 expected: "" + 248 "$ann-wrap-0$: first error\n" + 249 "$ann-wrap-1$: detailed error\n" + 250 "$ann-wrap-2$: annotated", 251 tracer: true, 252 }, { 253 message: "traced, and annotated", 254 generator: func() error { 255 err := errors.New("first error") //err stack-0 256 err = errors.Trace(err) //err stack-1 257 err = errors.Annotate(err, "some context") //err stack-2 258 err = errors.Trace(err) //err stack-3 259 err = errors.Annotate(err, "more context") //err stack-4 260 return errors.Trace(err) //err stack-5 261 }, 262 expected: "" + 263 "$stack-0$: first error\n" + 264 "$stack-1$: \n" + 265 "$stack-2$: some context\n" + 266 "$stack-3$: \n" + 267 "$stack-4$: more context\n" + 268 "$stack-5$: ", 269 tracer: true, 270 }, { 271 message: "uncomparable, wrapped with a value error", 272 generator: func() error { 273 err := newNonComparableError("first error") //err mixed-0 274 err = errors.Trace(err) //err mixed-1 275 err = errors.Wrap(err, newError("value error")) //err mixed-2 276 err = errors.Maskf(err, "masked") //err mixed-3 277 err = errors.Annotate(err, "more context") //err mixed-4 278 return errors.Trace(err) //err mixed-5 279 }, 280 expected: "" + 281 "first error\n" + 282 "$mixed-1$: \n" + 283 "$mixed-2$: value error\n" + 284 "$mixed-3$: masked\n" + 285 "$mixed-4$: more context\n" + 286 "$mixed-5$: ", 287 tracer: true, 288 }, 289 } { 290 c.Logf("%v: %s", i, test.message) 291 err := test.generator() 292 expected := replaceLocations(test.expected) 293 stack := errors.ErrorStack(err) 294 ok := c.Check(stack, gc.Equals, expected) 295 if !ok { 296 c.Logf("%#v", err) 297 } 298 tracer, ok := err.(tracer) 299 c.Check(ok, gc.Equals, test.tracer) 300 if ok { 301 stackTrace := tracer.StackTrace() 302 c.Check(stackTrace, gc.DeepEquals, strings.Split(stack, "\n")) 303 } 304 } 305 }