| // Copyright 2015 Google Inc. All rights reserved. |
| // Use of this source code is governed by the Apache 2.0 |
| // license that can be found in the LICENSE file. |
| |
| package search |
| |
| import ( |
| "reflect" |
| "testing" |
| ) |
| |
| func TestLoadingStruct(t *testing.T) { |
| testCases := []struct { |
| desc string |
| fields []Field |
| meta *DocumentMetadata |
| want interface{} |
| wantErr bool |
| }{ |
| { |
| desc: "Basic struct", |
| fields: []Field{ |
| {Name: "Name", Value: "Gopher"}, |
| {Name: "Legs", Value: float64(4)}, |
| }, |
| want: &struct { |
| Name string |
| Legs float64 |
| }{"Gopher", 4}, |
| }, |
| { |
| desc: "Struct with tags", |
| fields: []Field{ |
| {Name: "Name", Value: "Gopher"}, |
| {Name: "about", Value: "Likes slide rules."}, |
| }, |
| meta: &DocumentMetadata{Facets: []Facet{ |
| {Name: "Legs", Value: float64(4)}, |
| {Name: "Fur", Value: Atom("furry")}, |
| }}, |
| want: &struct { |
| Name string |
| Info string `search:"about"` |
| Legs float64 `search:",facet"` |
| Fuzz Atom `search:"Fur,facet"` |
| }{"Gopher", "Likes slide rules.", 4, Atom("furry")}, |
| }, |
| { |
| desc: "Bad field from tag", |
| want: &struct { |
| AlphaBeta string `search:"αβ"` |
| }{}, |
| wantErr: true, |
| }, |
| { |
| desc: "Ignore missing field", |
| fields: []Field{ |
| {Name: "Meaning", Value: float64(42)}, |
| }, |
| want: &struct{}{}, |
| wantErr: true, |
| }, |
| { |
| desc: "Ignore unsettable field", |
| fields: []Field{ |
| {Name: "meaning", Value: float64(42)}, |
| }, |
| want: &struct{ meaning float64 }{}, // field not populated. |
| wantErr: true, |
| }, |
| { |
| desc: "Error on missing facet", |
| meta: &DocumentMetadata{Facets: []Facet{ |
| {Name: "Set", Value: Atom("yes")}, |
| {Name: "Missing", Value: Atom("no")}, |
| }}, |
| want: &struct { |
| Set Atom `search:",facet"` |
| }{Atom("yes")}, |
| wantErr: true, |
| }, |
| { |
| desc: "Error on unsettable facet", |
| meta: &DocumentMetadata{Facets: []Facet{ |
| {Name: "Set", Value: Atom("yes")}, |
| {Name: "unset", Value: Atom("no")}, |
| }}, |
| want: &struct { |
| Set Atom `search:",facet"` |
| }{Atom("yes")}, |
| wantErr: true, |
| }, |
| { |
| desc: "Error setting ignored field", |
| fields: []Field{ |
| {Name: "Set", Value: "yes"}, |
| {Name: "Ignored", Value: "no"}, |
| }, |
| want: &struct { |
| Set string |
| Ignored string `search:"-"` |
| }{Set: "yes"}, |
| wantErr: true, |
| }, |
| { |
| desc: "Error setting ignored facet", |
| meta: &DocumentMetadata{Facets: []Facet{ |
| {Name: "Set", Value: Atom("yes")}, |
| {Name: "Ignored", Value: Atom("no")}, |
| }}, |
| want: &struct { |
| Set Atom `search:",facet"` |
| Ignored Atom `search:"-,facet"` |
| }{Set: Atom("yes")}, |
| wantErr: true, |
| }, |
| } |
| |
| for _, tt := range testCases { |
| // Make a pointer to an empty version of what want points to. |
| dst := reflect.New(reflect.TypeOf(tt.want).Elem()).Interface() |
| err := loadStructWithMeta(dst, tt.fields, tt.meta) |
| if err != nil != tt.wantErr { |
| t.Errorf("%s: got err %v; want err %t", tt.desc, err, tt.wantErr) |
| continue |
| } |
| if !reflect.DeepEqual(dst, tt.want) { |
| t.Errorf("%s: doesn't match\ngot: %v\nwant: %v", tt.desc, dst, tt.want) |
| } |
| } |
| } |
| |
| func TestSavingStruct(t *testing.T) { |
| testCases := []struct { |
| desc string |
| doc interface{} |
| wantFields []Field |
| wantFacets []Facet |
| }{ |
| { |
| desc: "Basic struct", |
| doc: &struct { |
| Name string |
| Legs float64 |
| }{"Gopher", 4}, |
| wantFields: []Field{ |
| {Name: "Name", Value: "Gopher"}, |
| {Name: "Legs", Value: float64(4)}, |
| }, |
| }, |
| { |
| desc: "Struct with tags", |
| doc: &struct { |
| Name string |
| Info string `search:"about"` |
| Legs float64 `search:",facet"` |
| Fuzz Atom `search:"Fur,facet"` |
| }{"Gopher", "Likes slide rules.", 4, Atom("furry")}, |
| wantFields: []Field{ |
| {Name: "Name", Value: "Gopher"}, |
| {Name: "about", Value: "Likes slide rules."}, |
| }, |
| wantFacets: []Facet{ |
| {Name: "Legs", Value: float64(4)}, |
| {Name: "Fur", Value: Atom("furry")}, |
| }, |
| }, |
| { |
| desc: "Ignore unexported struct fields", |
| doc: &struct { |
| Name string |
| info string |
| Legs float64 `search:",facet"` |
| fuzz Atom `search:",facet"` |
| }{"Gopher", "Likes slide rules.", 4, Atom("furry")}, |
| wantFields: []Field{ |
| {Name: "Name", Value: "Gopher"}, |
| }, |
| wantFacets: []Facet{ |
| {Name: "Legs", Value: float64(4)}, |
| }, |
| }, |
| { |
| desc: "Ignore fields marked -", |
| doc: &struct { |
| Name string |
| Info string `search:"-"` |
| Legs float64 `search:",facet"` |
| Fuzz Atom `search:"-,facet"` |
| }{"Gopher", "Likes slide rules.", 4, Atom("furry")}, |
| wantFields: []Field{ |
| {Name: "Name", Value: "Gopher"}, |
| }, |
| wantFacets: []Facet{ |
| {Name: "Legs", Value: float64(4)}, |
| }, |
| }, |
| } |
| |
| for _, tt := range testCases { |
| fields, meta, err := saveStructWithMeta(tt.doc) |
| if err != nil { |
| t.Errorf("%s: got err %v; want nil", tt.desc, err) |
| continue |
| } |
| if !reflect.DeepEqual(fields, tt.wantFields) { |
| t.Errorf("%s: fields don't match\ngot: %v\nwant: %v", tt.desc, fields, tt.wantFields) |
| } |
| if facets := meta.Facets; !reflect.DeepEqual(facets, tt.wantFacets) { |
| t.Errorf("%s: facets don't match\ngot: %v\nwant: %v", tt.desc, facets, tt.wantFacets) |
| } |
| } |
| } |