error_test.go 3.8 KB

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