error_test.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. // Copyright (c) 2017 Uber Technologies, Inc.
  2. //
  3. // Permission is hereby granted, free of charge, to any person obtaining a copy
  4. // of this software and associated documentation files (the "Software"), to deal
  5. // in the Software without restriction, including without limitation the rights
  6. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. // copies of the Software, and to permit persons to whom the Software is
  8. // furnished to do so, subject to the following conditions:
  9. //
  10. // The above copyright notice and this permission notice shall be included in
  11. // all copies or substantial portions of the Software.
  12. //
  13. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19. // THE SOFTWARE.
  20. package zap
  21. import (
  22. "errors"
  23. "fmt"
  24. "testing"
  25. "go.uber.org/zap/zapcore"
  26. "github.com/stretchr/testify/assert"
  27. "github.com/stretchr/testify/require"
  28. )
  29. func TestErrorConstructors(t *testing.T) {
  30. fail := errors.New("fail")
  31. tests := []struct {
  32. name string
  33. field Field
  34. expect Field
  35. }{
  36. {"Error", Skip(), Error(nil)},
  37. {"Error", Field{Key: "error", Type: zapcore.ErrorType, Interface: fail}, Error(fail)},
  38. {"NamedError", Skip(), NamedError("foo", nil)},
  39. {"NamedError", Field{Key: "foo", Type: zapcore.ErrorType, Interface: fail}, NamedError("foo", fail)},
  40. {"Any:Error", Any("k", errors.New("v")), NamedError("k", errors.New("v"))},
  41. {"Any:Errors", Any("k", []error{errors.New("v")}), Errors("k", []error{errors.New("v")})},
  42. }
  43. for _, tt := range tests {
  44. if !assert.Equal(t, tt.expect, tt.field, "Unexpected output from convenience field constructor %s.", tt.name) {
  45. t.Logf("type expected: %T\nGot: %T", tt.expect.Interface, tt.field.Interface)
  46. }
  47. assertCanBeReused(t, tt.field)
  48. }
  49. }
  50. func TestErrorArrayConstructor(t *testing.T) {
  51. tests := []struct {
  52. desc string
  53. field Field
  54. expected []interface{}
  55. }{
  56. {"empty errors", Errors("", []error{}), []interface{}{}},
  57. {
  58. "errors",
  59. Errors("", []error{nil, errors.New("foo"), nil, errors.New("bar")}),
  60. []interface{}{map[string]interface{}{"error": "foo"}, map[string]interface{}{"error": "bar"}},
  61. },
  62. }
  63. for _, tt := range tests {
  64. enc := zapcore.NewMapObjectEncoder()
  65. tt.field.Key = "k"
  66. tt.field.AddTo(enc)
  67. assert.Equal(t, tt.expected, enc.Fields["k"], "%s: unexpected map contents.", tt.desc)
  68. assert.Equal(t, 1, len(enc.Fields), "%s: found extra keys in map: %v", tt.desc, enc.Fields)
  69. }
  70. }
  71. func TestErrorsArraysHandleRichErrors(t *testing.T) {
  72. errs := []error{fmt.Errorf("egad")}
  73. enc := zapcore.NewMapObjectEncoder()
  74. Errors("k", errs).AddTo(enc)
  75. assert.Equal(t, 1, len(enc.Fields), "Expected only top-level field.")
  76. val := enc.Fields["k"]
  77. arr, ok := val.([]interface{})
  78. require.True(t, ok, "Expected top-level field to be an array.")
  79. require.Equal(t, 1, len(arr), "Expected only one error object in array.")
  80. serialized := arr[0]
  81. errMap, ok := serialized.(map[string]interface{})
  82. require.True(t, ok, "Expected serialized error to be a map, got %T.", serialized)
  83. assert.Equal(t, "egad", errMap["error"], "Unexpected standard error string.")
  84. }
  85. func TestErrArrayBrokenEncoder(t *testing.T) {
  86. t.Parallel()
  87. failWith := errors.New("great sadness")
  88. err := (brokenArrayObjectEncoder{
  89. Err: failWith,
  90. ObjectEncoder: zapcore.NewMapObjectEncoder(),
  91. }).AddArray("errors", errArray{
  92. errors.New("foo"),
  93. errors.New("bar"),
  94. })
  95. require.Error(t, err, "Expected error from broken encoder.")
  96. assert.ErrorIs(t, err, failWith, "Unexpected error.")
  97. }
  98. // brokenArrayObjectEncoder is an ObjectEncoder
  99. // that builds a broken ArrayEncoder.
  100. type brokenArrayObjectEncoder struct {
  101. zapcore.ObjectEncoder
  102. zapcore.ArrayEncoder
  103. Err error // error to return
  104. }
  105. func (enc brokenArrayObjectEncoder) AddArray(key string, marshaler zapcore.ArrayMarshaler) error {
  106. return enc.ObjectEncoder.AddArray(key,
  107. zapcore.ArrayMarshalerFunc(func(ae zapcore.ArrayEncoder) error {
  108. enc.ArrayEncoder = ae
  109. return marshaler.MarshalLogArray(enc)
  110. }))
  111. }
  112. func (enc brokenArrayObjectEncoder) AppendObject(zapcore.ObjectMarshaler) error {
  113. return enc.Err
  114. }