value_test.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. // Copyright 2018 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package protoreflect
  5. import (
  6. "bytes"
  7. "math"
  8. "reflect"
  9. "testing"
  10. )
  11. func TestValue(t *testing.T) {
  12. fakeMessage := new(struct{ Message })
  13. fakeVector := new(struct{ Vector })
  14. fakeMap := new(struct{ Map })
  15. tests := []struct {
  16. in Value
  17. want interface{}
  18. }{
  19. {in: Null},
  20. {in: Value{}},
  21. {in: ValueOf(nil)},
  22. {in: ValueOf(true), want: true},
  23. {in: ValueOf(int32(math.MaxInt32)), want: int32(math.MaxInt32)},
  24. {in: ValueOf(int64(math.MaxInt64)), want: int64(math.MaxInt64)},
  25. {in: ValueOf(uint32(math.MaxUint32)), want: uint32(math.MaxUint32)},
  26. {in: ValueOf(uint64(math.MaxUint64)), want: uint64(math.MaxUint64)},
  27. {in: ValueOf(float32(math.MaxFloat32)), want: float32(math.MaxFloat32)},
  28. {in: ValueOf(float64(math.MaxFloat64)), want: float64(math.MaxFloat64)},
  29. {in: ValueOf(string("hello")), want: string("hello")},
  30. {in: ValueOf([]byte("hello")), want: []byte("hello")},
  31. {in: ValueOf(fakeMessage), want: fakeMessage},
  32. {in: ValueOf(fakeVector), want: fakeVector},
  33. {in: ValueOf(fakeMap), want: fakeMap},
  34. }
  35. for _, tt := range tests {
  36. got := tt.in.Interface()
  37. if !reflect.DeepEqual(got, tt.want) {
  38. t.Errorf("Value(%v).Interface() = %v, want %v", tt.in, got, tt.want)
  39. }
  40. if got := tt.in.IsNull(); got != (tt.want == nil) {
  41. t.Errorf("Value(%v).IsNull() = %v, want %v", tt.in, got, tt.want == nil)
  42. }
  43. switch want := tt.want.(type) {
  44. case int32:
  45. if got := tt.in.Int(); got != int64(want) {
  46. t.Errorf("Value(%v).Int() = %v, want %v", tt.in, got, tt.want)
  47. }
  48. case int64:
  49. if got := tt.in.Int(); got != int64(want) {
  50. t.Errorf("Value(%v).Int() = %v, want %v", tt.in, got, tt.want)
  51. }
  52. case uint32:
  53. if got := tt.in.Uint(); got != uint64(want) {
  54. t.Errorf("Value(%v).Uint() = %v, want %v", tt.in, got, tt.want)
  55. }
  56. case uint64:
  57. if got := tt.in.Uint(); got != uint64(want) {
  58. t.Errorf("Value(%v).Uint() = %v, want %v", tt.in, got, tt.want)
  59. }
  60. case float32:
  61. if got := tt.in.Float(); got != float64(want) {
  62. t.Errorf("Value(%v).Float() = %v, want %v", tt.in, got, tt.want)
  63. }
  64. case float64:
  65. if got := tt.in.Float(); got != float64(want) {
  66. t.Errorf("Value(%v).Float() = %v, want %v", tt.in, got, tt.want)
  67. }
  68. case string:
  69. if got := tt.in.String(); got != string(want) {
  70. t.Errorf("Value(%v).String() = %v, want %v", tt.in, got, tt.want)
  71. }
  72. case []byte:
  73. if got := tt.in.Bytes(); !bytes.Equal(got, want) {
  74. t.Errorf("Value(%v).Bytes() = %v, want %v", tt.in, got, tt.want)
  75. }
  76. case EnumNumber:
  77. if got := tt.in.Enum(); got != want {
  78. t.Errorf("Value(%v).Enum() = %v, want %v", tt.in, got, tt.want)
  79. }
  80. case Message:
  81. if got := tt.in.Message(); got != want {
  82. t.Errorf("Value(%v).Message() = %v, want %v", tt.in, got, tt.want)
  83. }
  84. case Map:
  85. if got := tt.in.Map(); got != want {
  86. t.Errorf("Value(%v).Map() = %v, want %v", tt.in, got, tt.want)
  87. }
  88. case Vector:
  89. if got := tt.in.Vector(); got != want {
  90. t.Errorf("Value(%v).Vector() = %v, want %v", tt.in, got, tt.want)
  91. }
  92. }
  93. }
  94. }
  95. func BenchmarkValue(b *testing.B) {
  96. const testdata = "The quick brown fox jumped over the lazy dog."
  97. var sink1 string
  98. var sink2 Value
  99. var sink3 interface{}
  100. // Baseline measures the time to store a string into a native variable.
  101. b.Run("Baseline", func(b *testing.B) {
  102. b.ReportAllocs()
  103. for i := 0; i < b.N; i++ {
  104. sink1 = testdata[:len(testdata)%(i+1)]
  105. }
  106. })
  107. // Inline measures the time to store a string into a Value,
  108. // assuming that the compiler could inline the ValueOf function call.
  109. b.Run("Inline", func(b *testing.B) {
  110. b.ReportAllocs()
  111. for i := 0; i < b.N; i++ {
  112. sink2 = valueOfString(testdata[:len(testdata)%(i+1)])
  113. }
  114. })
  115. // Value measures the time to store a string into a Value using the general
  116. // ValueOf function call. This should be identical to Inline.
  117. //
  118. // NOTE: As of Go1.11, this is not as efficient as Inline due to the lack
  119. // of some compiler optimizations:
  120. // https://golang.org/issue/22310
  121. // https://golang.org/issue/25189
  122. b.Run("Value", func(b *testing.B) {
  123. b.ReportAllocs()
  124. for i := 0; i < b.N; i++ {
  125. sink2 = ValueOf(string(testdata[:len(testdata)%(i+1)]))
  126. }
  127. })
  128. // Interface measures the time to store a string into an interface.
  129. b.Run("Interface", func(b *testing.B) {
  130. b.ReportAllocs()
  131. for i := 0; i < b.N; i++ {
  132. sink3 = string(testdata[:len(testdata)%(i+1)])
  133. }
  134. })
  135. _, _, _ = sink1, sink2, sink3
  136. }