set_test.go 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. // Copyright The OpenTelemetry Authors
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package attribute_test
  15. import (
  16. "reflect"
  17. "regexp"
  18. "testing"
  19. "github.com/stretchr/testify/assert"
  20. "github.com/stretchr/testify/require"
  21. "go.opentelemetry.io/otel/attribute"
  22. )
  23. type testCase struct {
  24. kvs []attribute.KeyValue
  25. keyRe *regexp.Regexp
  26. encoding string
  27. fullEnc string
  28. }
  29. func expect(enc string, kvs ...attribute.KeyValue) testCase {
  30. return testCase{
  31. kvs: kvs,
  32. encoding: enc,
  33. }
  34. }
  35. func expectFiltered(enc, filter, fullEnc string, kvs ...attribute.KeyValue) testCase {
  36. return testCase{
  37. kvs: kvs,
  38. keyRe: regexp.MustCompile(filter),
  39. encoding: enc,
  40. fullEnc: fullEnc,
  41. }
  42. }
  43. func TestSetDedup(t *testing.T) {
  44. cases := []testCase{
  45. expect("A=B", attribute.String("A", "2"), attribute.String("A", "B")),
  46. expect("A=B", attribute.String("A", "2"), attribute.Int("A", 1), attribute.String("A", "B")),
  47. expect("A=B", attribute.String("A", "B"), attribute.String("A", "C"), attribute.String("A", "D"), attribute.String("A", "B")),
  48. expect("A=B,C=D", attribute.String("A", "1"), attribute.String("C", "D"), attribute.String("A", "B")),
  49. expect("A=B,C=D", attribute.String("A", "2"), attribute.String("A", "B"), attribute.String("C", "D")),
  50. expect("A=B,C=D", attribute.Float64("C", 1.2), attribute.String("A", "2"), attribute.String("A", "B"), attribute.String("C", "D")),
  51. expect("A=B,C=D", attribute.String("C", "D"), attribute.String("A", "B"), attribute.String("A", "C"), attribute.String("A", "D"), attribute.String("A", "B")),
  52. expect("A=B,C=D", attribute.String("A", "B"), attribute.String("C", "D"), attribute.String("A", "C"), attribute.String("A", "D"), attribute.String("A", "B")),
  53. expect("A=B,C=D", attribute.String("A", "B"), attribute.String("A", "C"), attribute.String("A", "D"), attribute.String("A", "B"), attribute.String("C", "D")),
  54. }
  55. enc := attribute.DefaultEncoder()
  56. s2d := map[string][]attribute.Distinct{}
  57. d2s := map[attribute.Distinct][]string{}
  58. for _, tc := range cases {
  59. cpy := make([]attribute.KeyValue, len(tc.kvs))
  60. copy(cpy, tc.kvs)
  61. sl := attribute.NewSet(cpy...)
  62. // Ensure that the input was reordered but no elements went missing.
  63. require.ElementsMatch(t, tc.kvs, cpy)
  64. str := sl.Encoded(enc)
  65. equ := sl.Equivalent()
  66. s2d[str] = append(s2d[str], equ)
  67. d2s[equ] = append(d2s[equ], str)
  68. require.Equal(t, tc.encoding, str)
  69. }
  70. for s, d := range s2d {
  71. // No other Distinct values are equal to this.
  72. for s2, d2 := range s2d {
  73. if s2 == s {
  74. continue
  75. }
  76. for _, elt := range d {
  77. for _, otherDistinct := range d2 {
  78. require.NotEqual(t, otherDistinct, elt)
  79. }
  80. }
  81. }
  82. for _, strings := range d2s {
  83. if strings[0] == s {
  84. continue
  85. }
  86. for _, otherString := range strings {
  87. require.NotEqual(t, otherString, s)
  88. }
  89. }
  90. }
  91. for d, s := range d2s {
  92. // No other Distinct values are equal to this.
  93. for d2, s2 := range d2s {
  94. if d2 == d {
  95. continue
  96. }
  97. for _, elt := range s {
  98. for _, otherDistinct := range s2 {
  99. require.NotEqual(t, otherDistinct, elt)
  100. }
  101. }
  102. }
  103. for _, distincts := range s2d {
  104. if distincts[0] == d {
  105. continue
  106. }
  107. for _, otherDistinct := range distincts {
  108. require.NotEqual(t, otherDistinct, d)
  109. }
  110. }
  111. }
  112. }
  113. func TestUniqueness(t *testing.T) {
  114. short := []attribute.KeyValue{
  115. attribute.String("A", "0"),
  116. attribute.String("B", "2"),
  117. attribute.String("A", "1"),
  118. }
  119. long := []attribute.KeyValue{
  120. attribute.String("B", "2"),
  121. attribute.String("C", "5"),
  122. attribute.String("B", "2"),
  123. attribute.String("C", "1"),
  124. attribute.String("A", "4"),
  125. attribute.String("C", "3"),
  126. attribute.String("A", "1"),
  127. }
  128. cases := []testCase{
  129. expectFiltered("A=1", "^A$", "B=2", short...),
  130. expectFiltered("B=2", "^B$", "A=1", short...),
  131. expectFiltered("A=1,B=2", "^A|B$", "", short...),
  132. expectFiltered("", "^C", "A=1,B=2", short...),
  133. expectFiltered("A=1,C=3", "A|C", "B=2", long...),
  134. expectFiltered("B=2,C=3", "C|B", "A=1", long...),
  135. expectFiltered("C=3", "C", "A=1,B=2", long...),
  136. expectFiltered("", "D", "A=1,B=2,C=3", long...),
  137. }
  138. enc := attribute.DefaultEncoder()
  139. for _, tc := range cases {
  140. cpy := make([]attribute.KeyValue, len(tc.kvs))
  141. copy(cpy, tc.kvs)
  142. distinct, uniq := attribute.NewSetWithFiltered(cpy, func(attr attribute.KeyValue) bool {
  143. return tc.keyRe.MatchString(string(attr.Key))
  144. })
  145. full := attribute.NewSet(uniq...)
  146. require.Equal(t, tc.encoding, distinct.Encoded(enc))
  147. require.Equal(t, tc.fullEnc, full.Encoded(enc))
  148. }
  149. }
  150. func TestLookup(t *testing.T) {
  151. set := attribute.NewSet(attribute.Int("C", 3), attribute.Int("A", 1), attribute.Int("B", 2))
  152. value, has := set.Value("C")
  153. require.True(t, has)
  154. require.Equal(t, int64(3), value.AsInt64())
  155. value, has = set.Value("B")
  156. require.True(t, has)
  157. require.Equal(t, int64(2), value.AsInt64())
  158. value, has = set.Value("A")
  159. require.True(t, has)
  160. require.Equal(t, int64(1), value.AsInt64())
  161. _, has = set.Value("D")
  162. require.False(t, has)
  163. }
  164. func TestZeroSetExportedMethodsNoPanic(t *testing.T) {
  165. rType := reflect.TypeOf((*attribute.Set)(nil))
  166. rVal := reflect.ValueOf(&attribute.Set{})
  167. for n := 0; n < rType.NumMethod(); n++ {
  168. mType := rType.Method(n)
  169. if !mType.IsExported() {
  170. t.Logf("ignoring unexported %s", mType.Name)
  171. continue
  172. }
  173. t.Run(mType.Name, func(t *testing.T) {
  174. m := rVal.MethodByName(mType.Name)
  175. if !m.IsValid() {
  176. t.Errorf("unknown method: %s", mType.Name)
  177. }
  178. assert.NotPanics(t, func() { _ = m.Call(args(mType)) })
  179. })
  180. }
  181. }
  182. func args(m reflect.Method) []reflect.Value {
  183. numIn := m.Type.NumIn() - 1 // Do not include the receiver arg.
  184. if numIn <= 0 {
  185. return nil
  186. }
  187. if m.Type.IsVariadic() {
  188. numIn--
  189. }
  190. out := make([]reflect.Value, numIn)
  191. for i := range out {
  192. aType := m.Type.In(i + 1) // Skip receiver arg.
  193. out[i] = reflect.New(aType).Elem()
  194. }
  195. return out
  196. }