error_test.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. package errors
  2. import (
  3. "bytes"
  4. "fmt"
  5. "io"
  6. "reflect"
  7. "runtime/debug"
  8. "strings"
  9. "testing"
  10. )
  11. func TestStackFormatMatches(t *testing.T) {
  12. defer func() {
  13. err := recover()
  14. if err != 'a' {
  15. t.Fatal(err)
  16. }
  17. bs := [][]byte{Errorf("hi").Stack(), debug.Stack()}
  18. // Ignore the first line (as it contains the PC of the .Stack() call)
  19. bs[0] = bytes.SplitN(bs[0], []byte("\n"), 2)[1]
  20. bs[1] = bytes.SplitN(bs[1], []byte("\n"), 2)[1]
  21. if bytes.Compare(bs[0], bs[1]) != 0 {
  22. t.Errorf("Stack didn't match")
  23. t.Errorf("%s", bs[0])
  24. t.Errorf("%s", bs[1])
  25. }
  26. }()
  27. a()
  28. }
  29. func TestSkipWorks(t *testing.T) {
  30. defer func() {
  31. err := recover()
  32. if err != 'a' {
  33. t.Fatal(err)
  34. }
  35. bs := [][]byte{Wrap("hi", 2).Stack(), debug.Stack()}
  36. // should skip four lines of debug.Stack()
  37. bs[1] = bytes.SplitN(bs[1], []byte("\n"), 5)[4]
  38. if bytes.Compare(bs[0], bs[1]) != 0 {
  39. t.Errorf("Stack didn't match")
  40. t.Errorf("%s", bs[0])
  41. t.Errorf("%s", bs[1])
  42. }
  43. }()
  44. a()
  45. }
  46. func TestNew(t *testing.T) {
  47. err := New("foo")
  48. if err.Error() != "foo" {
  49. t.Errorf("Wrong message")
  50. }
  51. err = New(fmt.Errorf("foo"))
  52. if err.Error() != "foo" {
  53. t.Errorf("Wrong message")
  54. }
  55. bs := [][]byte{New("foo").Stack(), debug.Stack()}
  56. // Ignore the first line (as it contains the PC of the .Stack() call)
  57. bs[0] = bytes.SplitN(bs[0], []byte("\n"), 2)[1]
  58. bs[1] = bytes.SplitN(bs[1], []byte("\n"), 2)[1]
  59. if bytes.Compare(bs[0], bs[1]) != 0 {
  60. t.Errorf("Stack didn't match")
  61. t.Errorf("%s", bs[0])
  62. t.Errorf("%s", bs[1])
  63. }
  64. if err.ErrorStack() != err.TypeName()+" "+err.Error()+"\n"+string(err.Stack()) {
  65. t.Errorf("ErrorStack is in the wrong format")
  66. }
  67. }
  68. func TestIs(t *testing.T) {
  69. if Is(nil, io.EOF) {
  70. t.Errorf("nil is an error")
  71. }
  72. if !Is(io.EOF, io.EOF) {
  73. t.Errorf("io.EOF is not io.EOF")
  74. }
  75. if !Is(io.EOF, New(io.EOF)) {
  76. t.Errorf("io.EOF is not New(io.EOF)")
  77. }
  78. if !Is(New(io.EOF), New(io.EOF)) {
  79. t.Errorf("New(io.EOF) is not New(io.EOF)")
  80. }
  81. if Is(io.EOF, fmt.Errorf("io.EOF")) {
  82. t.Errorf("io.EOF is fmt.Errorf")
  83. }
  84. }
  85. func TestWrapError(t *testing.T) {
  86. e := func() error {
  87. return Wrap("hi", 1)
  88. }()
  89. if e.Error() != "hi" {
  90. t.Errorf("Constructor with a string failed")
  91. }
  92. if Wrap(fmt.Errorf("yo"), 0).Error() != "yo" {
  93. t.Errorf("Constructor with an error failed")
  94. }
  95. if Wrap(e, 0) != e {
  96. t.Errorf("Constructor with an Error failed")
  97. }
  98. if Wrap(nil, 0).Error() != "<nil>" {
  99. t.Errorf("Constructor with nil failed")
  100. }
  101. }
  102. func TestWrapPrefixError(t *testing.T) {
  103. e := func() error {
  104. return WrapPrefix("hi", "prefix", 1)
  105. }()
  106. if e.Error() != "prefix: hi" {
  107. t.Errorf("Constructor with a string failed")
  108. }
  109. if WrapPrefix(fmt.Errorf("yo"), "prefix", 0).Error() != "prefix: yo" {
  110. t.Errorf("Constructor with an error failed")
  111. }
  112. prefixed := WrapPrefix(e, "prefix", 0)
  113. original := e.(*Error)
  114. if prefixed.Err != original.Err || !reflect.DeepEqual(prefixed.stack, original.stack) || !reflect.DeepEqual(prefixed.frames, original.frames) || prefixed.Error() != "prefix: prefix: hi" {
  115. t.Errorf("Constructor with an Error failed")
  116. }
  117. if original.Error() == prefixed.Error() {
  118. t.Errorf("WrapPrefix changed the original error")
  119. }
  120. if WrapPrefix(nil, "prefix", 0).Error() != "prefix: <nil>" {
  121. t.Errorf("Constructor with nil failed")
  122. }
  123. if !strings.HasSuffix(original.StackFrames()[0].File, "error_test.go") || strings.HasSuffix(original.StackFrames()[1].File, "error_test.go") {
  124. t.Errorf("Skip failed")
  125. }
  126. }
  127. func ExampleErrorf(x int) (int, error) {
  128. if x%2 == 1 {
  129. return 0, Errorf("can only halve even numbers, got %d", x)
  130. }
  131. return x / 2, nil
  132. }
  133. func ExampleWrapError() (error, error) {
  134. // Wrap io.EOF with the current stack-trace and return it
  135. return nil, Wrap(io.EOF, 0)
  136. }
  137. func ExampleWrapError_skip() {
  138. defer func() {
  139. if err := recover(); err != nil {
  140. // skip 1 frame (the deferred function) and then return the wrapped err
  141. err = Wrap(err, 1)
  142. }
  143. }()
  144. }
  145. func ExampleIs(reader io.Reader, buff []byte) {
  146. _, err := reader.Read(buff)
  147. if Is(err, io.EOF) {
  148. return
  149. }
  150. }
  151. func ExampleNew(UnexpectedEOF error) error {
  152. // calling New attaches the current stacktrace to the existing UnexpectedEOF error
  153. return New(UnexpectedEOF)
  154. }
  155. func ExampleWrap() error {
  156. if err := recover(); err != nil {
  157. return Wrap(err, 1)
  158. }
  159. return a()
  160. }
  161. func ExampleError_Error(err error) {
  162. fmt.Println(err.Error())
  163. }
  164. func ExampleError_ErrorStack(err error) {
  165. fmt.Println(err.(*Error).ErrorStack())
  166. }
  167. func ExampleError_Stack(err *Error) {
  168. fmt.Println(err.Stack())
  169. }
  170. func ExampleError_TypeName(err *Error) {
  171. fmt.Println(err.TypeName(), err.Error())
  172. }
  173. func ExampleError_StackFrames(err *Error) {
  174. for _, frame := range err.StackFrames() {
  175. fmt.Println(frame.File, frame.LineNumber, frame.Package, frame.Name)
  176. }
  177. }
  178. func a() error {
  179. b(5)
  180. return nil
  181. }
  182. func b(i int) {
  183. c()
  184. }
  185. func c() {
  186. panic('a')
  187. }