struct_test.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  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. wantErr: true,
  59. },
  60. {
  61. desc: "Ignore unsettable field",
  62. fields: []Field{
  63. {Name: "meaning", Value: float64(42)},
  64. },
  65. want: &struct{ meaning float64 }{}, // field not populated.
  66. wantErr: true,
  67. },
  68. {
  69. desc: "Error on missing facet",
  70. meta: &DocumentMetadata{Facets: []Facet{
  71. {Name: "Set", Value: Atom("yes")},
  72. {Name: "Missing", Value: Atom("no")},
  73. }},
  74. want: &struct {
  75. Set Atom `search:",facet"`
  76. }{Atom("yes")},
  77. wantErr: true,
  78. },
  79. {
  80. desc: "Error on unsettable facet",
  81. meta: &DocumentMetadata{Facets: []Facet{
  82. {Name: "Set", Value: Atom("yes")},
  83. {Name: "unset", Value: Atom("no")},
  84. }},
  85. want: &struct {
  86. Set Atom `search:",facet"`
  87. }{Atom("yes")},
  88. wantErr: true,
  89. },
  90. {
  91. desc: "Error setting ignored field",
  92. fields: []Field{
  93. {Name: "Set", Value: "yes"},
  94. {Name: "Ignored", Value: "no"},
  95. },
  96. want: &struct {
  97. Set string
  98. Ignored string `search:"-"`
  99. }{Set: "yes"},
  100. wantErr: true,
  101. },
  102. {
  103. desc: "Error setting ignored facet",
  104. meta: &DocumentMetadata{Facets: []Facet{
  105. {Name: "Set", Value: Atom("yes")},
  106. {Name: "Ignored", Value: Atom("no")},
  107. }},
  108. want: &struct {
  109. Set Atom `search:",facet"`
  110. Ignored Atom `search:"-,facet"`
  111. }{Set: Atom("yes")},
  112. wantErr: true,
  113. },
  114. }
  115. for _, tt := range testCases {
  116. // Make a pointer to an empty version of what want points to.
  117. dst := reflect.New(reflect.TypeOf(tt.want).Elem()).Interface()
  118. err := loadStructWithMeta(dst, tt.fields, tt.meta)
  119. if err != nil != tt.wantErr {
  120. t.Errorf("%s: got err %v; want err %t", tt.desc, err, tt.wantErr)
  121. continue
  122. }
  123. if !reflect.DeepEqual(dst, tt.want) {
  124. t.Errorf("%s: doesn't match\ngot: %v\nwant: %v", tt.desc, dst, tt.want)
  125. }
  126. }
  127. }
  128. func TestSavingStruct(t *testing.T) {
  129. testCases := []struct {
  130. desc string
  131. doc interface{}
  132. wantFields []Field
  133. wantFacets []Facet
  134. }{
  135. {
  136. desc: "Basic struct",
  137. doc: &struct {
  138. Name string
  139. Legs float64
  140. }{"Gopher", 4},
  141. wantFields: []Field{
  142. {Name: "Name", Value: "Gopher"},
  143. {Name: "Legs", Value: float64(4)},
  144. },
  145. },
  146. {
  147. desc: "Struct with tags",
  148. doc: &struct {
  149. Name string
  150. Info string `search:"about"`
  151. Legs float64 `search:",facet"`
  152. Fuzz Atom `search:"Fur,facet"`
  153. }{"Gopher", "Likes slide rules.", 4, Atom("furry")},
  154. wantFields: []Field{
  155. {Name: "Name", Value: "Gopher"},
  156. {Name: "about", Value: "Likes slide rules."},
  157. },
  158. wantFacets: []Facet{
  159. {Name: "Legs", Value: float64(4)},
  160. {Name: "Fur", Value: Atom("furry")},
  161. },
  162. },
  163. {
  164. desc: "Ignore unexported struct fields",
  165. doc: &struct {
  166. Name string
  167. info string
  168. Legs float64 `search:",facet"`
  169. fuzz Atom `search:",facet"`
  170. }{"Gopher", "Likes slide rules.", 4, Atom("furry")},
  171. wantFields: []Field{
  172. {Name: "Name", Value: "Gopher"},
  173. },
  174. wantFacets: []Facet{
  175. {Name: "Legs", Value: float64(4)},
  176. },
  177. },
  178. {
  179. desc: "Ignore fields marked -",
  180. doc: &struct {
  181. Name string
  182. Info string `search:"-"`
  183. Legs float64 `search:",facet"`
  184. Fuzz Atom `search:"-,facet"`
  185. }{"Gopher", "Likes slide rules.", 4, Atom("furry")},
  186. wantFields: []Field{
  187. {Name: "Name", Value: "Gopher"},
  188. },
  189. wantFacets: []Facet{
  190. {Name: "Legs", Value: float64(4)},
  191. },
  192. },
  193. }
  194. for _, tt := range testCases {
  195. fields, meta, err := saveStructWithMeta(tt.doc)
  196. if err != nil {
  197. t.Errorf("%s: got err %v; want nil", tt.desc, err)
  198. continue
  199. }
  200. if !reflect.DeepEqual(fields, tt.wantFields) {
  201. t.Errorf("%s: fields don't match\ngot: %v\nwant: %v", tt.desc, fields, tt.wantFields)
  202. }
  203. if facets := meta.Facets; !reflect.DeepEqual(facets, tt.wantFacets) {
  204. t.Errorf("%s: facets don't match\ngot: %v\nwant: %v", tt.desc, facets, tt.wantFacets)
  205. }
  206. }
  207. }