// Print implements internal logger Print method for logrus. func (logrusWrapper *LogrusLogger) Print(v ...interface{}) { defer func() { if err := recover(); err != nil { stdlog.Panicf("Logging error: %v", err) } }() if len(v) == 0 { return } l := logrusWrapper.L if len(v) == 1 { if err, errOk := v[0].(error); errOk { if err2, err2Ok := fail.GetOriginalError(err).(*ErrDirectActionMethod); err2Ok { var stackTrace string if err3, err3Ok := err2.Err.(error); err3Ok { stackTrace = fail.GetStackTrace(err3) } if stackTrace == "" { stackTraceSkip := 1 if err2.isPanic { stackTraceSkip = 4 } stackTrace = fail.StackTrace(stackTraceSkip) } l = l.WithFields(logrus.Fields{ "action": err2.Action, "method": err2.Method, "stack": stackTrace, }) } else { stackTrace := fail.GetStackTrace(err) if stackTrace == "" { stackTrace = fail.StackTrace(1) } l = l.WithFields(logrus.Fields{ "stack": stackTrace, }) } l.Error(err) } else { l.Debug(v[0]) } } else { if len(v) > 2 { l = l.WithFields(v[2].(map[string]interface{})) } m := strings.TrimSpace(v[1].(string)) logLevel := v[0].(string) switch logLevel { case logLevelInfo: l.Info(m) case logLevelWarn: l.Warn(m) default: panic(fmt.Errorf("Unknown log message type: '%v.", logLevel)) } } }
func TestFail(t *testing.T) { Convey("Standard error", t, func() { err := errors.New("Error 1 occurred.") Convey("should have no inner", func() { So(fail.GetInner(err), ShouldBeNil) }) Convey("should have no location", func() { So(fail.GetLocation(err), ShouldBeEmpty) }) Convey("should have no stack trace", func() { So(fail.GetStackTrace(err), ShouldBeEmpty) }) Convey("GetOriginalError() should return itself", func() { So(fail.GetOriginalError(err), ShouldEqual, err) }) Convey("GetType() should return type of itself", func() { So(fail.GetType(err), ShouldEqual, reflect.TypeOf(err)) }) }) Convey("Simple extended error", t, func() { errInner := errors.New("Error 1 occurred.") err := fail.New(errInner) Convey("should have correct message", func() { So(err.Error(), ShouldEqual, "Error 1 occurred.") }) Convey("should have no inner", func() { So(fail.GetInner(err), ShouldBeNil) }) Convey("should have correct location", func() { So(fail.GetLocation(err), ShouldContainSubstring, "github.com/nbgo/fail/fail_test.go:60") So(fail.GetLocation(err), ShouldContainSubstring, "TestFail.") }) Convey("should have correct stack trace", func() { stackTrace := fail.GetStackTrace(err) So(stackTrace, ShouldContainSubstring, "TestFail.") So(stackTrace, ShouldContainSubstring, "fail_test.go:60") So(stackTrace, ShouldContainSubstring, "fail_test.go:77") }) }) Convey("Composite extended error", t, func() { err1 := fail.Newf("Error %v occurred.", 1) err2 := fail.News("Error 2 occurred.") err1c := fail.NewWithInner(err2, err1) err2c := fail.New(&MyError{"Error 3 occured", err1c}) Convey("stack trace 1 check", func() { So(strings.Split(fail.GetStackTrace(err2c), "\n")[0], ShouldContainSubstring, "fail_test.go") }) Convey("stack trace 2 check", func() { So(strings.Split(fail.GetStackTrace(err1c), "\n")[0], ShouldContainSubstring, "fail_test.go") }) Convey("stack trace 3 check", func() { So(strings.Split(fail.GetStackTrace(err2), "\n")[0], ShouldContainSubstring, "fail_test.go") }) Convey("stack trace 4 check", func() { So(strings.Split(fail.GetStackTrace(err1), "\n")[0], ShouldContainSubstring, "fail_test.go") }) Convey("should have correct full details", func() { details := fail.GetFullDetails(err2c) fmt.Println("\n" + details) So(details, ShouldNotContainSubstring, "fail.extendedError") }) Convey("should have correct message", func() { So(err2c.Error(), ShouldEqual, "MyError: Error 3 occured. Reason: Error 2 occurred.") }) Convey("should have correct inner 1 level error", func() { inner := fail.GetInner(err2c) So(inner, ShouldNotBeNil) So(inner.Error(), ShouldEqual, "Error 2 occurred.") Convey("should have correct inner 2 level error", func() { inner2 := fail.GetInner(inner) So(inner2, ShouldNotBeNil) So(inner2.Error(), ShouldEqual, "Error 1 occurred.") }) }) Convey("GetOriginalError() should return correct error", func() { So(fail.GetOriginalError(err1c), ShouldEqual, fail.GetOriginalError(err2)) }) }) Convey("ErrWithReason", t, func() { innerErr := fail.News("inner error") err := fail.NewErrWithReason("some error", innerErr) Convey("should have its own text and reason", func() { So(err.Error(), ShouldEqual, "some error: inner error") }) Convey("should return correct inner error", func() { gotInnerErr := fail.GetInner(err) So(gotInnerErr, ShouldNotBeNil) So(gotInnerErr.Error(), ShouldEqual, "inner error") So(gotInnerErr, ShouldEqual, innerErr) }) Convey("should have correct stack trace", func() { So(strings.Split(fail.GetStackTrace(err), "\n")[0], ShouldContainSubstring, "fail_test.go") }) }) Convey("StackTrace()", t, func() { stackTrace := fail.StackTrace() fmt.Println("\n" + stackTrace) So(strings.Split(stackTrace, "\n")[0], ShouldContainSubstring, "fail_test.go") func() { stackTrace := fail.StackTrace(1) fmt.Println("\n" + stackTrace) So(strings.Split(stackTrace, "\n")[0], ShouldContainSubstring, "fail_test.go") }() }) Convey("IsError()", t, func() { innerErr := errors.New("test1") err2 := fail.NewErrWithReason("test2", innerErr) err3 := fail.NewErrWithReason("test3", err2) err4 := fail.News("test4") Convey("should return true when composite error has checked error in its hierarchy", func() { So(fail.IsError(err3, innerErr), ShouldBeTrue) }) Convey("should return true when checked error is itself", func() { So(fail.IsError(innerErr, innerErr), ShouldBeTrue) }) Convey("should return false when composite error does not have checked error in its hierarchy", func() { So(fail.IsError(err4, innerErr), ShouldBeFalse) }) }) Convey("AreErrorsOfEqualType()", t, func() { err1 := &MyError{} err2 := &MyError{} err3 := MyError{} err4 := fail.News("test") So(fail.AreErrorsOfEqualType(err1, err2), ShouldBeTrue) So(fail.AreErrorsOfEqualType(err1, err3), ShouldBeTrue) So(fail.AreErrorsOfEqualType(err3, err2), ShouldBeTrue) So(fail.AreErrorsOfEqualType(err1, err4), ShouldBeFalse) So(fail.AreErrorsOfEqualType(err3, err4), ShouldBeFalse) }) Convey("GetErrorByType()", t, func() { innerErr := &MyError{} err2 := fail.NewErrWithReason("test2", innerErr) err3 := fail.NewErrWithReason("test3", err2) err4 := fail.News("test4") So(fail.GetErrorByType(err3, MyError{}), ShouldEqual, innerErr) So(fail.GetErrorByType(err4, MyError{}), ShouldBeNil) }) Convey("ErrWithFields", t, func() { err := fail.New(fail.New(MyErrWithFields{"p1", "p2"})) So(err.Error(), ShouldEqual, "This is an error with fields: p1, p2") errWithFields := err.(fail.ErrorWithFields) fields := errWithFields.Fields() So(fields, ShouldNotBeNil) So(errWithFields.Fields(), ShouldResemble, map[string]interface{}{"param1": "p1", "param2": "p2"}) err = fail.News("test") errWithFields = err.(fail.ErrorWithFields) fields = errWithFields.Fields() So(fields, ShouldBeNil) }) }