~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/github.com/juju/errors/functions_test.go

  • Committer: Nicholas Skaggs
  • Date: 2016-10-24 20:56:05 UTC
  • Revision ID: nicholas.skaggs@canonical.com-20161024205605-z8lta0uvuhtxwzwl
Initi with beta15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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/juju/testing/checkers"
 
14
        gc "gopkg.in/check.v1"
 
15
 
 
16
        "github.com/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
}