struct_test.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. // Copyright 2015 Google Inc. All rights reserved.
  2. // Use of this source code is governed by the Apache 2.0
  3. // license that can be found in the LICENSE file.
  4. package search
  5. import (
  6. "reflect"
  7. "testing"
  8. )
  9. func TestLoadingStruct(t *testing.T) {
  10. testCases := []struct {
  11. desc string
  12. fields []Field
  13. meta *DocumentMetadata
  14. want interface{}
  15. wantErr bool
  16. }{
  17. {
  18. desc: "Basic struct",
  19. fields: []Field{
  20. {Name: "Name", Value: "Gopher"},
  21. {Name: "Legs", Value: float64(4)},
  22. },
  23. want: &struct {
  24. Name string
  25. Legs float64
  26. }{"Gopher", 4},
  27. },
  28. {
  29. desc: "Struct with tags",
  30. fields: []Field{
  31. {Name: "Name", Value: "Gopher"},
  32. {Name: "about", Value: "Likes slide rules."},
  33. },
  34. meta: &DocumentMetadata{Facets: []Facet{
  35. {Name: "Legs", Value: float64(4)},
  36. {Name: "Fur", Value: Atom("furry")},
  37. }},
  38. want: &struct {
  39. Name string
  40. Info string `search:"about"`
  41. Legs float64 `search:",facet"`
  42. Fuzz Atom `search:"Fur,facet"`
  43. }{"Gopher", "Likes slide rules.", 4, Atom("furry")},
  44. },
  45. {
  46. desc: "Bad field from tag",
  47. want: &struct {
  48. AlphaBeta string `search:"αβ"`
  49. }{},
  50. wantErr: true,
  51. },
  52. {
  53. desc: "Ignore missing field",
  54. fields: []Field{
  55. {Name: "Meaning", Value: float64(42)},
  56. },
  57. want: &struct{}{},
  58. },
  59. {
  60. desc: "Ignore unsettable field",
  61. fields: []Field{
  62. {Name: "meaning", Value: float64(42)},
  63. },
  64. want: &struct{ meaning float64 }{}, // field not populated.
  65. },
  66. {
  67. desc: "Error on missing facet",
  68. meta: &DocumentMetadata{Facets: []Facet{
  69. {Name: "Set", Value: Atom("yes")},
  70. {Name: "Missing", Value: Atom("no")},
  71. }},
  72. want: &struct {
  73. Set Atom `search:",facet"`
  74. }{Atom("yes")},
  75. wantErr: true,
  76. },
  77. {
  78. desc: "Error on unsettable facet",
  79. meta: &DocumentMetadata{Facets: []Facet{
  80. {Name: "Set", Value: Atom("yes")},
  81. {Name: "unset", Value: Atom("no")},
  82. }},
  83. want: &struct {
  84. Set Atom `search:",facet"`
  85. }{Atom("yes")},
  86. wantErr: true,
  87. },
  88. }
  89. for _, tt := range testCases {
  90. // Make a pointer to an empty version of what want points to.
  91. dst := reflect.New(reflect.TypeOf(tt.want).Elem()).Interface()
  92. err := loadStructWithMeta(dst, tt.fields, tt.meta)
  93. if err != nil != tt.wantErr {
  94. t.Errorf("%s: got err %v; want err %t", tt.desc, err, tt.wantErr)
  95. continue
  96. }
  97. if !reflect.DeepEqual(dst, tt.want) {
  98. t.Errorf("%s: doesn't match\ngot: %v\nwant: %v", tt.desc, dst, tt.want)
  99. }
  100. }
  101. }
  102. func TestSavingStruct(t *testing.T) {
  103. testCases := []struct {
  104. desc string
  105. doc interface{}
  106. wantFields []Field
  107. wantFacets []Facet
  108. }{
  109. {
  110. desc: "Basic struct",
  111. doc: &struct {
  112. Name string
  113. Legs float64
  114. }{"Gopher", 4},
  115. wantFields: []Field{
  116. {Name: "Name", Value: "Gopher"},
  117. {Name: "Legs", Value: float64(4)},
  118. },
  119. },
  120. {
  121. desc: "Struct with tags",
  122. doc: &struct {
  123. Name string
  124. Info string `search:"about"`
  125. Legs float64 `search:",facet"`
  126. Fuzz Atom `search:"Fur,facet"`
  127. }{"Gopher", "Likes slide rules.", 4, Atom("furry")},
  128. wantFields: []Field{
  129. {Name: "Name", Value: "Gopher"},
  130. {Name: "about", Value: "Likes slide rules."},
  131. },
  132. wantFacets: []Facet{
  133. {Name: "Legs", Value: float64(4)},
  134. {Name: "Fur", Value: Atom("furry")},
  135. },
  136. },
  137. {
  138. desc: "Ignore unexported struct fields",
  139. doc: &struct {
  140. Name string
  141. info string
  142. Legs float64 `search:",facet"`
  143. fuzz Atom `search:",facet"`
  144. }{"Gopher", "Likes slide rules.", 4, Atom("furry")},
  145. wantFields: []Field{
  146. {Name: "Name", Value: "Gopher"},
  147. },
  148. wantFacets: []Facet{
  149. {Name: "Legs", Value: float64(4)},
  150. },
  151. },
  152. }
  153. for _, tt := range testCases {
  154. fields, meta, err := saveStructWithMeta(tt.doc)
  155. if err != nil {
  156. t.Errorf("%s: got err %v; want nil", tt.desc, err)
  157. continue
  158. }
  159. if !reflect.DeepEqual(fields, tt.wantFields) {
  160. t.Errorf("%s: fields don't match\ngot: %v\nwant: %v", tt.desc, fields, tt.wantFields)
  161. }
  162. if facets := meta.Facets; !reflect.DeepEqual(facets, tt.wantFacets) {
  163. t.Errorf("%s: facets don't match\ngot: %v\nwant: %v", tt.desc, facets, tt.wantFacets)
  164. }
  165. }
  166. }