field_test.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. // Copyright (c) 2016 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. "math"
  23. "net"
  24. "sync"
  25. "testing"
  26. "time"
  27. "github.com/stretchr/testify/assert"
  28. "go.uber.org/zap/zapcore"
  29. )
  30. type username string
  31. func (n username) MarshalLogObject(enc zapcore.ObjectEncoder) error {
  32. enc.AddString("username", string(n))
  33. return nil
  34. }
  35. func assertCanBeReused(t testing.TB, field Field) {
  36. var wg sync.WaitGroup
  37. for i := 0; i < 100; i++ {
  38. enc := zapcore.NewMapObjectEncoder()
  39. // Ensure using the field in multiple encoders in separate goroutines
  40. // does not cause any races or panics.
  41. wg.Add(1)
  42. go func() {
  43. defer wg.Done()
  44. assert.NotPanics(t, func() {
  45. field.AddTo(enc)
  46. }, "Reusing a field should not cause issues")
  47. }()
  48. }
  49. wg.Wait()
  50. }
  51. func TestFieldConstructors(t *testing.T) {
  52. // Interface types.
  53. addr := net.ParseIP("1.2.3.4")
  54. name := username("phil")
  55. ints := []int{5, 6}
  56. // Helpful values for use in constructing pointers to primitives below.
  57. var (
  58. boolVal bool = true
  59. complex128Val complex128 = complex(0, 0)
  60. complex64Val complex64 = complex(0, 0)
  61. durationVal time.Duration = time.Second
  62. float64Val float64 = 1.0
  63. float32Val float32 = 1.0
  64. intVal int = 1
  65. int64Val int64 = 1
  66. int32Val int32 = 1
  67. int16Val int16 = 1
  68. int8Val int8 = 1
  69. stringVal string = "hello"
  70. timeVal time.Time = time.Unix(100000, 0)
  71. uintVal uint = 1
  72. uint64Val uint64 = 1
  73. uint32Val uint32 = 1
  74. uint16Val uint16 = 1
  75. uint8Val uint8 = 1
  76. uintptrVal uintptr = 1
  77. )
  78. tests := []struct {
  79. name string
  80. field Field
  81. expect Field
  82. }{
  83. {"Skip", Field{Type: zapcore.SkipType}, Skip()},
  84. {"Binary", Field{Key: "k", Type: zapcore.BinaryType, Interface: []byte("ab12")}, Binary("k", []byte("ab12"))},
  85. {"Bool", Field{Key: "k", Type: zapcore.BoolType, Integer: 1}, Bool("k", true)},
  86. {"Bool", Field{Key: "k", Type: zapcore.BoolType, Integer: 1}, Bool("k", true)},
  87. {"ByteString", Field{Key: "k", Type: zapcore.ByteStringType, Interface: []byte("ab12")}, ByteString("k", []byte("ab12"))},
  88. {"Complex128", Field{Key: "k", Type: zapcore.Complex128Type, Interface: 1 + 2i}, Complex128("k", 1+2i)},
  89. {"Complex64", Field{Key: "k", Type: zapcore.Complex64Type, Interface: complex64(1 + 2i)}, Complex64("k", 1+2i)},
  90. {"Duration", Field{Key: "k", Type: zapcore.DurationType, Integer: 1}, Duration("k", 1)},
  91. {"Int", Field{Key: "k", Type: zapcore.Int64Type, Integer: 1}, Int("k", 1)},
  92. {"Int64", Field{Key: "k", Type: zapcore.Int64Type, Integer: 1}, Int64("k", 1)},
  93. {"Int32", Field{Key: "k", Type: zapcore.Int32Type, Integer: 1}, Int32("k", 1)},
  94. {"Int16", Field{Key: "k", Type: zapcore.Int16Type, Integer: 1}, Int16("k", 1)},
  95. {"Int8", Field{Key: "k", Type: zapcore.Int8Type, Integer: 1}, Int8("k", 1)},
  96. {"String", Field{Key: "k", Type: zapcore.StringType, String: "foo"}, String("k", "foo")},
  97. {"Time", Field{Key: "k", Type: zapcore.TimeType, Integer: 0, Interface: time.UTC}, Time("k", time.Unix(0, 0).In(time.UTC))},
  98. {"Time", Field{Key: "k", Type: zapcore.TimeType, Integer: 1000, Interface: time.UTC}, Time("k", time.Unix(0, 1000).In(time.UTC))},
  99. {"Time", Field{Key: "k", Type: zapcore.TimeType, Integer: math.MinInt64, Interface: time.UTC}, Time("k", time.Unix(0, math.MinInt64).In(time.UTC))},
  100. {"Time", Field{Key: "k", Type: zapcore.TimeType, Integer: math.MaxInt64, Interface: time.UTC}, Time("k", time.Unix(0, math.MaxInt64).In(time.UTC))},
  101. {"Time", Field{Key: "k", Type: zapcore.TimeFullType, Interface: time.Time{}}, Time("k", time.Time{})},
  102. {"Time", Field{Key: "k", Type: zapcore.TimeFullType, Interface: time.Unix(math.MaxInt64, 0)}, Time("k", time.Unix(math.MaxInt64, 0))},
  103. {"Uint", Field{Key: "k", Type: zapcore.Uint64Type, Integer: 1}, Uint("k", 1)},
  104. {"Uint64", Field{Key: "k", Type: zapcore.Uint64Type, Integer: 1}, Uint64("k", 1)},
  105. {"Uint32", Field{Key: "k", Type: zapcore.Uint32Type, Integer: 1}, Uint32("k", 1)},
  106. {"Uint16", Field{Key: "k", Type: zapcore.Uint16Type, Integer: 1}, Uint16("k", 1)},
  107. {"Uint8", Field{Key: "k", Type: zapcore.Uint8Type, Integer: 1}, Uint8("k", 1)},
  108. {"Uintptr", Field{Key: "k", Type: zapcore.UintptrType, Integer: 10}, Uintptr("k", 0xa)},
  109. {"Reflect", Field{Key: "k", Type: zapcore.ReflectType, Interface: ints}, Reflect("k", ints)},
  110. {"Reflect", Field{Key: "k", Type: zapcore.ReflectType}, Reflect("k", nil)},
  111. {"Stringer", Field{Key: "k", Type: zapcore.StringerType, Interface: addr}, Stringer("k", addr)},
  112. {"Object", Field{Key: "k", Type: zapcore.ObjectMarshalerType, Interface: name}, Object("k", name)},
  113. {"Any:ObjectMarshaler", Any("k", name), Object("k", name)},
  114. {"Any:ArrayMarshaler", Any("k", bools([]bool{true})), Array("k", bools([]bool{true}))},
  115. {"Any:Stringer", Any("k", addr), Stringer("k", addr)},
  116. {"Any:Bool", Any("k", true), Bool("k", true)},
  117. {"Any:Bools", Any("k", []bool{true}), Bools("k", []bool{true})},
  118. {"Any:Byte", Any("k", byte(1)), Uint8("k", 1)},
  119. {"Any:Bytes", Any("k", []byte{1}), Binary("k", []byte{1})},
  120. {"Any:Complex128", Any("k", 1+2i), Complex128("k", 1+2i)},
  121. {"Any:Complex128s", Any("k", []complex128{1 + 2i}), Complex128s("k", []complex128{1 + 2i})},
  122. {"Any:Complex64", Any("k", complex64(1+2i)), Complex64("k", 1+2i)},
  123. {"Any:Complex64s", Any("k", []complex64{1 + 2i}), Complex64s("k", []complex64{1 + 2i})},
  124. {"Any:Float64", Any("k", 3.14), Float64("k", 3.14)},
  125. {"Any:Float64s", Any("k", []float64{3.14}), Float64s("k", []float64{3.14})},
  126. {"Any:Float32", Any("k", float32(3.14)), Float32("k", 3.14)},
  127. {"Any:Float32s", Any("k", []float32{3.14}), Float32s("k", []float32{3.14})},
  128. {"Any:Int", Any("k", 1), Int("k", 1)},
  129. {"Any:Ints", Any("k", []int{1}), Ints("k", []int{1})},
  130. {"Any:Int64", Any("k", int64(1)), Int64("k", 1)},
  131. {"Any:Int64s", Any("k", []int64{1}), Int64s("k", []int64{1})},
  132. {"Any:Int32", Any("k", int32(1)), Int32("k", 1)},
  133. {"Any:Int32s", Any("k", []int32{1}), Int32s("k", []int32{1})},
  134. {"Any:Int16", Any("k", int16(1)), Int16("k", 1)},
  135. {"Any:Int16s", Any("k", []int16{1}), Int16s("k", []int16{1})},
  136. {"Any:Int8", Any("k", int8(1)), Int8("k", 1)},
  137. {"Any:Int8s", Any("k", []int8{1}), Int8s("k", []int8{1})},
  138. {"Any:Rune", Any("k", rune(1)), Int32("k", 1)},
  139. {"Any:Runes", Any("k", []rune{1}), Int32s("k", []int32{1})},
  140. {"Any:String", Any("k", "v"), String("k", "v")},
  141. {"Any:Strings", Any("k", []string{"v"}), Strings("k", []string{"v"})},
  142. {"Any:Uint", Any("k", uint(1)), Uint("k", 1)},
  143. {"Any:Uints", Any("k", []uint{1}), Uints("k", []uint{1})},
  144. {"Any:Uint64", Any("k", uint64(1)), Uint64("k", 1)},
  145. {"Any:Uint64s", Any("k", []uint64{1}), Uint64s("k", []uint64{1})},
  146. {"Any:Uint32", Any("k", uint32(1)), Uint32("k", 1)},
  147. {"Any:Uint32s", Any("k", []uint32{1}), Uint32s("k", []uint32{1})},
  148. {"Any:Uint16", Any("k", uint16(1)), Uint16("k", 1)},
  149. {"Any:Uint16s", Any("k", []uint16{1}), Uint16s("k", []uint16{1})},
  150. {"Any:Uint8", Any("k", uint8(1)), Uint8("k", 1)},
  151. {"Any:Uint8s", Any("k", []uint8{1}), Binary("k", []uint8{1})},
  152. {"Any:Uintptr", Any("k", uintptr(1)), Uintptr("k", 1)},
  153. {"Any:Uintptrs", Any("k", []uintptr{1}), Uintptrs("k", []uintptr{1})},
  154. {"Any:Time", Any("k", time.Unix(0, 0)), Time("k", time.Unix(0, 0))},
  155. {"Any:Times", Any("k", []time.Time{time.Unix(0, 0)}), Times("k", []time.Time{time.Unix(0, 0)})},
  156. {"Any:Duration", Any("k", time.Second), Duration("k", time.Second)},
  157. {"Any:Durations", Any("k", []time.Duration{time.Second}), Durations("k", []time.Duration{time.Second})},
  158. {"Any:Fallback", Any("k", struct{}{}), Reflect("k", struct{}{})},
  159. {"Ptr:Bool", Boolp("k", nil), nilField("k")},
  160. {"Ptr:Bool", Boolp("k", &boolVal), Bool("k", boolVal)},
  161. {"Any:PtrBool", Any("k", (*bool)(nil)), nilField("k")},
  162. {"Any:PtrBool", Any("k", &boolVal), Bool("k", boolVal)},
  163. {"Ptr:Complex128", Complex128p("k", nil), nilField("k")},
  164. {"Ptr:Complex128", Complex128p("k", &complex128Val), Complex128("k", complex128Val)},
  165. {"Any:PtrComplex128", Any("k", (*complex128)(nil)), nilField("k")},
  166. {"Any:PtrComplex128", Any("k", &complex128Val), Complex128("k", complex128Val)},
  167. {"Ptr:Complex64", Complex64p("k", nil), nilField("k")},
  168. {"Ptr:Complex64", Complex64p("k", &complex64Val), Complex64("k", complex64Val)},
  169. {"Any:PtrComplex64", Any("k", (*complex64)(nil)), nilField("k")},
  170. {"Any:PtrComplex64", Any("k", &complex64Val), Complex64("k", complex64Val)},
  171. {"Ptr:Duration", Durationp("k", nil), nilField("k")},
  172. {"Ptr:Duration", Durationp("k", &durationVal), Duration("k", durationVal)},
  173. {"Any:PtrDuration", Any("k", (*time.Duration)(nil)), nilField("k")},
  174. {"Any:PtrDuration", Any("k", &durationVal), Duration("k", durationVal)},
  175. {"Ptr:Float64", Float64p("k", nil), nilField("k")},
  176. {"Ptr:Float64", Float64p("k", &float64Val), Float64("k", float64Val)},
  177. {"Any:PtrFloat64", Any("k", (*float64)(nil)), nilField("k")},
  178. {"Any:PtrFloat64", Any("k", &float64Val), Float64("k", float64Val)},
  179. {"Ptr:Float32", Float32p("k", nil), nilField("k")},
  180. {"Ptr:Float32", Float32p("k", &float32Val), Float32("k", float32Val)},
  181. {"Any:PtrFloat32", Any("k", (*float32)(nil)), nilField("k")},
  182. {"Any:PtrFloat32", Any("k", &float32Val), Float32("k", float32Val)},
  183. {"Ptr:Int", Intp("k", nil), nilField("k")},
  184. {"Ptr:Int", Intp("k", &intVal), Int("k", intVal)},
  185. {"Any:PtrInt", Any("k", (*int)(nil)), nilField("k")},
  186. {"Any:PtrInt", Any("k", &intVal), Int("k", intVal)},
  187. {"Ptr:Int64", Int64p("k", nil), nilField("k")},
  188. {"Ptr:Int64", Int64p("k", &int64Val), Int64("k", int64Val)},
  189. {"Any:PtrInt64", Any("k", (*int64)(nil)), nilField("k")},
  190. {"Any:PtrInt64", Any("k", &int64Val), Int64("k", int64Val)},
  191. {"Ptr:Int32", Int32p("k", nil), nilField("k")},
  192. {"Ptr:Int32", Int32p("k", &int32Val), Int32("k", int32Val)},
  193. {"Any:PtrInt32", Any("k", (*int32)(nil)), nilField("k")},
  194. {"Any:PtrInt32", Any("k", &int32Val), Int32("k", int32Val)},
  195. {"Ptr:Int16", Int16p("k", nil), nilField("k")},
  196. {"Ptr:Int16", Int16p("k", &int16Val), Int16("k", int16Val)},
  197. {"Any:PtrInt16", Any("k", (*int16)(nil)), nilField("k")},
  198. {"Any:PtrInt16", Any("k", &int16Val), Int16("k", int16Val)},
  199. {"Ptr:Int8", Int8p("k", nil), nilField("k")},
  200. {"Ptr:Int8", Int8p("k", &int8Val), Int8("k", int8Val)},
  201. {"Any:PtrInt8", Any("k", (*int8)(nil)), nilField("k")},
  202. {"Any:PtrInt8", Any("k", &int8Val), Int8("k", int8Val)},
  203. {"Ptr:String", Stringp("k", nil), nilField("k")},
  204. {"Ptr:String", Stringp("k", &stringVal), String("k", stringVal)},
  205. {"Any:PtrString", Any("k", (*string)(nil)), nilField("k")},
  206. {"Any:PtrString", Any("k", &stringVal), String("k", stringVal)},
  207. {"Ptr:Time", Timep("k", nil), nilField("k")},
  208. {"Ptr:Time", Timep("k", &timeVal), Time("k", timeVal)},
  209. {"Any:PtrTime", Any("k", (*time.Time)(nil)), nilField("k")},
  210. {"Any:PtrTime", Any("k", &timeVal), Time("k", timeVal)},
  211. {"Ptr:Uint", Uintp("k", nil), nilField("k")},
  212. {"Ptr:Uint", Uintp("k", &uintVal), Uint("k", uintVal)},
  213. {"Any:PtrUint", Any("k", (*uint)(nil)), nilField("k")},
  214. {"Any:PtrUint", Any("k", &uintVal), Uint("k", uintVal)},
  215. {"Ptr:Uint64", Uint64p("k", nil), nilField("k")},
  216. {"Ptr:Uint64", Uint64p("k", &uint64Val), Uint64("k", uint64Val)},
  217. {"Any:PtrUint64", Any("k", (*uint64)(nil)), nilField("k")},
  218. {"Any:PtrUint64", Any("k", &uint64Val), Uint64("k", uint64Val)},
  219. {"Ptr:Uint32", Uint32p("k", nil), nilField("k")},
  220. {"Ptr:Uint32", Uint32p("k", &uint32Val), Uint32("k", uint32Val)},
  221. {"Any:PtrUint32", Any("k", (*uint32)(nil)), nilField("k")},
  222. {"Any:PtrUint32", Any("k", &uint32Val), Uint32("k", uint32Val)},
  223. {"Ptr:Uint16", Uint16p("k", nil), nilField("k")},
  224. {"Ptr:Uint16", Uint16p("k", &uint16Val), Uint16("k", uint16Val)},
  225. {"Any:PtrUint16", Any("k", (*uint16)(nil)), nilField("k")},
  226. {"Any:PtrUint16", Any("k", &uint16Val), Uint16("k", uint16Val)},
  227. {"Ptr:Uint8", Uint8p("k", nil), nilField("k")},
  228. {"Ptr:Uint8", Uint8p("k", &uint8Val), Uint8("k", uint8Val)},
  229. {"Any:PtrUint8", Any("k", (*uint8)(nil)), nilField("k")},
  230. {"Any:PtrUint8", Any("k", &uint8Val), Uint8("k", uint8Val)},
  231. {"Ptr:Uintptr", Uintptrp("k", nil), nilField("k")},
  232. {"Ptr:Uintptr", Uintptrp("k", &uintptrVal), Uintptr("k", uintptrVal)},
  233. {"Any:PtrUintptr", Any("k", (*uintptr)(nil)), nilField("k")},
  234. {"Any:PtrUintptr", Any("k", &uintptrVal), Uintptr("k", uintptrVal)},
  235. {"Namespace", Namespace("k"), Field{Key: "k", Type: zapcore.NamespaceType}},
  236. }
  237. for _, tt := range tests {
  238. if !assert.Equal(t, tt.expect, tt.field, "Unexpected output from convenience field constructor %s.", tt.name) {
  239. t.Logf("type expected: %T\nGot: %T", tt.expect.Interface, tt.field.Interface)
  240. }
  241. assertCanBeReused(t, tt.field)
  242. }
  243. }
  244. func TestStackField(t *testing.T) {
  245. f := Stack("stacktrace")
  246. assert.Equal(t, "stacktrace", f.Key, "Unexpected field key.")
  247. assert.Equal(t, zapcore.StringType, f.Type, "Unexpected field type.")
  248. assert.Equal(t, takeStacktrace(), f.String, "Unexpected stack trace")
  249. assertCanBeReused(t, f)
  250. }