// 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) } } }