metadata_test.go 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. /*
  2. *
  3. * Copyright 2014 gRPC authors.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. package metadata
  19. import (
  20. "context"
  21. "reflect"
  22. "strconv"
  23. "testing"
  24. )
  25. func TestPairsMD(t *testing.T) {
  26. for _, test := range []struct {
  27. // input
  28. kv []string
  29. // output
  30. md MD
  31. }{
  32. {[]string{}, MD{}},
  33. {[]string{"k1", "v1", "k1", "v2"}, MD{"k1": []string{"v1", "v2"}}},
  34. } {
  35. md := Pairs(test.kv...)
  36. if !reflect.DeepEqual(md, test.md) {
  37. t.Fatalf("Pairs(%v) = %v, want %v", test.kv, md, test.md)
  38. }
  39. }
  40. }
  41. func TestCopy(t *testing.T) {
  42. const key, val = "key", "val"
  43. orig := Pairs(key, val)
  44. cpy := orig.Copy()
  45. if !reflect.DeepEqual(orig, cpy) {
  46. t.Errorf("copied value not equal to the original, got %v, want %v", cpy, orig)
  47. }
  48. orig[key][0] = "foo"
  49. if v := cpy[key][0]; v != val {
  50. t.Errorf("change in original should not affect copy, got %q, want %q", v, val)
  51. }
  52. }
  53. func TestJoin(t *testing.T) {
  54. for _, test := range []struct {
  55. mds []MD
  56. want MD
  57. }{
  58. {[]MD{}, MD{}},
  59. {[]MD{Pairs("foo", "bar")}, Pairs("foo", "bar")},
  60. {[]MD{Pairs("foo", "bar"), Pairs("foo", "baz")}, Pairs("foo", "bar", "foo", "baz")},
  61. {[]MD{Pairs("foo", "bar"), Pairs("foo", "baz"), Pairs("zip", "zap")}, Pairs("foo", "bar", "foo", "baz", "zip", "zap")},
  62. } {
  63. md := Join(test.mds...)
  64. if !reflect.DeepEqual(md, test.want) {
  65. t.Errorf("context's metadata is %v, want %v", md, test.want)
  66. }
  67. }
  68. }
  69. func TestGet(t *testing.T) {
  70. for _, test := range []struct {
  71. md MD
  72. key string
  73. wantVals []string
  74. }{
  75. {md: Pairs("My-Optional-Header", "42"), key: "My-Optional-Header", wantVals: []string{"42"}},
  76. {md: Pairs("Header", "42", "Header", "43", "Header", "44", "other", "1"), key: "HEADER", wantVals: []string{"42", "43", "44"}},
  77. {md: Pairs("HEADER", "10"), key: "HEADER", wantVals: []string{"10"}},
  78. } {
  79. vals := test.md.Get(test.key)
  80. if !reflect.DeepEqual(vals, test.wantVals) {
  81. t.Errorf("value of metadata %v is %v, want %v", test.key, vals, test.wantVals)
  82. }
  83. }
  84. }
  85. func TestSet(t *testing.T) {
  86. for _, test := range []struct {
  87. md MD
  88. setKey string
  89. setVals []string
  90. want MD
  91. }{
  92. {
  93. md: Pairs("My-Optional-Header", "42", "other-key", "999"),
  94. setKey: "Other-Key",
  95. setVals: []string{"1"},
  96. want: Pairs("my-optional-header", "42", "other-key", "1"),
  97. },
  98. {
  99. md: Pairs("My-Optional-Header", "42"),
  100. setKey: "Other-Key",
  101. setVals: []string{"1", "2", "3"},
  102. want: Pairs("my-optional-header", "42", "other-key", "1", "other-key", "2", "other-key", "3"),
  103. },
  104. {
  105. md: Pairs("My-Optional-Header", "42"),
  106. setKey: "Other-Key",
  107. setVals: []string{},
  108. want: Pairs("my-optional-header", "42"),
  109. },
  110. } {
  111. test.md.Set(test.setKey, test.setVals...)
  112. if !reflect.DeepEqual(test.md, test.want) {
  113. t.Errorf("value of metadata is %v, want %v", test.md, test.want)
  114. }
  115. }
  116. }
  117. func TestAppend(t *testing.T) {
  118. for _, test := range []struct {
  119. md MD
  120. appendKey string
  121. appendVals []string
  122. want MD
  123. }{
  124. {
  125. md: Pairs("My-Optional-Header", "42"),
  126. appendKey: "Other-Key",
  127. appendVals: []string{"1"},
  128. want: Pairs("my-optional-header", "42", "other-key", "1"),
  129. },
  130. {
  131. md: Pairs("My-Optional-Header", "42"),
  132. appendKey: "my-OptIoNal-HeAder",
  133. appendVals: []string{"1", "2", "3"},
  134. want: Pairs("my-optional-header", "42", "my-optional-header", "1",
  135. "my-optional-header", "2", "my-optional-header", "3"),
  136. },
  137. {
  138. md: Pairs("My-Optional-Header", "42"),
  139. appendKey: "my-OptIoNal-HeAder",
  140. appendVals: []string{},
  141. want: Pairs("my-optional-header", "42"),
  142. },
  143. } {
  144. test.md.Append(test.appendKey, test.appendVals...)
  145. if !reflect.DeepEqual(test.md, test.want) {
  146. t.Errorf("value of metadata is %v, want %v", test.md, test.want)
  147. }
  148. }
  149. }
  150. func TestAppendToOutgoingContext(t *testing.T) {
  151. // Pre-existing metadata
  152. ctx := NewOutgoingContext(context.Background(), Pairs("k1", "v1", "k2", "v2"))
  153. ctx = AppendToOutgoingContext(ctx, "k1", "v3")
  154. ctx = AppendToOutgoingContext(ctx, "k1", "v4")
  155. md, ok := FromOutgoingContext(ctx)
  156. if !ok {
  157. t.Errorf("Expected MD to exist in ctx, but got none")
  158. }
  159. want := Pairs("k1", "v1", "k1", "v3", "k1", "v4", "k2", "v2")
  160. if !reflect.DeepEqual(md, want) {
  161. t.Errorf("context's metadata is %v, want %v", md, want)
  162. }
  163. // No existing metadata
  164. ctx = AppendToOutgoingContext(context.Background(), "k1", "v1")
  165. md, ok = FromOutgoingContext(ctx)
  166. if !ok {
  167. t.Errorf("Expected MD to exist in ctx, but got none")
  168. }
  169. want = Pairs("k1", "v1")
  170. if !reflect.DeepEqual(md, want) {
  171. t.Errorf("context's metadata is %v, want %v", md, want)
  172. }
  173. }
  174. func TestAppendToOutgoingContext_Repeated(t *testing.T) {
  175. ctx := context.Background()
  176. for i := 0; i < 100; i = i + 2 {
  177. ctx1 := AppendToOutgoingContext(ctx, "k", strconv.Itoa(i))
  178. ctx2 := AppendToOutgoingContext(ctx, "k", strconv.Itoa(i+1))
  179. md1, _ := FromOutgoingContext(ctx1)
  180. md2, _ := FromOutgoingContext(ctx2)
  181. if reflect.DeepEqual(md1, md2) {
  182. t.Fatalf("md1, md2 = %v, %v; should not be equal", md1, md2)
  183. }
  184. ctx = ctx1
  185. }
  186. }
  187. func TestAppendToOutgoingContext_FromKVSlice(t *testing.T) {
  188. const k, v = "a", "b"
  189. kv := []string{k, v}
  190. ctx := AppendToOutgoingContext(context.Background(), kv...)
  191. md, _ := FromOutgoingContext(ctx)
  192. if md[k][0] != v {
  193. t.Fatalf("md[%q] = %q; want %q", k, md[k], v)
  194. }
  195. kv[1] = "xxx"
  196. md, _ = FromOutgoingContext(ctx)
  197. if md[k][0] != v {
  198. t.Fatalf("md[%q] = %q; want %q", k, md[k], v)
  199. }
  200. }
  201. // Old/slow approach to adding metadata to context
  202. func Benchmark_AddingMetadata_ContextManipulationApproach(b *testing.B) {
  203. // TODO: Add in N=1-100 tests once Go1.6 support is removed.
  204. const num = 10
  205. for n := 0; n < b.N; n++ {
  206. ctx := context.Background()
  207. for i := 0; i < num; i++ {
  208. md, _ := FromOutgoingContext(ctx)
  209. NewOutgoingContext(ctx, Join(Pairs("k1", "v1", "k2", "v2"), md))
  210. }
  211. }
  212. }
  213. // Newer/faster approach to adding metadata to context
  214. func BenchmarkAppendToOutgoingContext(b *testing.B) {
  215. const num = 10
  216. for n := 0; n < b.N; n++ {
  217. ctx := context.Background()
  218. for i := 0; i < num; i++ {
  219. ctx = AppendToOutgoingContext(ctx, "k1", "v1", "k2", "v2")
  220. }
  221. }
  222. }
  223. func BenchmarkFromOutgoingContext(b *testing.B) {
  224. ctx := context.Background()
  225. ctx = NewOutgoingContext(ctx, MD{"k3": {"v3", "v4"}})
  226. ctx = AppendToOutgoingContext(ctx, "k1", "v1", "k2", "v2")
  227. for n := 0; n < b.N; n++ {
  228. FromOutgoingContext(ctx)
  229. }
  230. }