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  }