| /* Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package lucy |
| |
| import "testing" |
| import "strings" |
| import "reflect" |
| import "git-wip-us.apache.org/repos/asf/lucy-clownfish.git/runtime/go/clownfish" |
| |
| func checkQuerySerialize(t *testing.T, query Query) { |
| folder := NewRAMFolder("") |
| outStream, _ := folder.OpenOut("foo") |
| query.serialize(outStream) |
| outStream.Close() |
| inStream, _ := folder.OpenIn("foo") |
| dupe := clownfish.GetClass(query).MakeObj().(Query).deserialize(inStream) |
| if !query.Equals(dupe) { |
| t.Errorf("Unsuccessful serialization round trip -- expected '%v', got '%v'", |
| query.ToString(), dupe.ToString()) |
| } |
| } |
| |
| func checkQueryDumpLoad(t *testing.T, query Query) { |
| dupe := clownfish.GetClass(query).MakeObj().(Query) |
| dupe = dupe.Load(query.Dump()).(Query) |
| if !query.Equals(dupe) { |
| t.Errorf("Unsuccessful Dump/Load round trip -- expected '%v', got '%v'", |
| query.ToString(), dupe.ToString()) |
| } |
| } |
| |
| func checkQueryEquals(t *testing.T, query Query) { |
| if !query.Equals(query) { |
| t.Error("Equals self") |
| } |
| if query.Equals("blah") { |
| t.Error("Equals against Go string") |
| } |
| } |
| |
| func checkQueryMakeCompiler(t *testing.T, query Query) { |
| index := createTestIndex("foo", "bar", "baz") |
| searcher, _ := OpenIndexSearcher(index) |
| compiler, err := query.MakeCompiler(searcher, 1.0, false) |
| if _, ok := compiler.(Compiler); !ok || err != nil { |
| t.Error("MakeCompiler for %v failed: %v", query, err) |
| } |
| } |
| |
| // Test whether ToString() yields a string which contains "foo". |
| func checkQueryToStringHasFoo(t *testing.T, query Query) { |
| if got := query.ToString(); !strings.Contains(got, "foo") { |
| t.Errorf("Unexpected stringification: '%v'", got) |
| } |
| } |
| |
| func TestTermQueryMisc(t *testing.T) { |
| query := NewTermQuery("content", "foo") |
| checkQuerySerialize(t, query) |
| checkQueryDumpLoad(t, query) |
| checkQueryEquals(t, query) |
| checkQueryMakeCompiler(t, query) |
| checkQueryToStringHasFoo(t, query) |
| } |
| |
| func TestTermQueryAccessors(t *testing.T) { |
| query := NewTermQuery("content", "foo") |
| if got := query.GetField(); got != "content" { |
| t.Errorf("Expected 'content', got '%v'", got) |
| } |
| if got := query.GetTerm().(string); got != "foo" { |
| t.Errorf("Expected 'foo', got '%v'", got) |
| } |
| } |
| |
| func TestTermCompilerMisc(t *testing.T) { |
| folder := createTestIndex("foo", "bar", "baz") |
| searcher, _ := OpenIndexSearcher(folder) |
| query := NewTermQuery("content", "foo") |
| compiler := NewTermCompiler(query, searcher, 1.0) |
| checkQuerySerialize(t, compiler) |
| checkQueryEquals(t, compiler) |
| checkQueryToStringHasFoo(t, compiler) |
| segReaders := searcher.GetReader().SegReaders() |
| matcher, err := compiler.MakeMatcher(segReaders[0].(SegReader), false) |
| if matcher == nil || err != nil { |
| t.Errorf("MakeMatcher: %v", err) |
| } |
| } |
| |
| func TestTermCompilerWeighting(t *testing.T) { |
| index := createTestIndex("foo", "bar", "baz") |
| searcher, _ := OpenIndexSearcher(index) |
| query := NewTermQuery("content", "foo") |
| compiler := NewTermCompiler(query, searcher, 1.0) |
| _ = compiler.SumOfSquaredWeights() |
| _ = compiler.GetWeight() |
| compiler.ApplyNormFactor(10.0) |
| } |
| |
| func TestPhraseQueryMisc(t *testing.T) { |
| terms := []interface{}{"foo", "bar"} |
| query := NewPhraseQuery("content", terms) |
| checkQuerySerialize(t, query) |
| checkQueryDumpLoad(t, query) |
| checkQueryEquals(t, query) |
| checkQueryMakeCompiler(t, query) |
| checkQueryToStringHasFoo(t, query) |
| } |
| |
| func TestPhraseQueryAccessors(t *testing.T) { |
| terms := []interface{}{"foo", "bar"} |
| query := NewPhraseQuery("content", terms) |
| if field := query.GetField(); field != "content" { |
| t.Errorf("Expected 'content', got '%v'", field) |
| } |
| if got := query.GetTerms(); !reflect.DeepEqual(terms, got) { |
| t.Errorf("Expected '%v', got '%v'", terms, got) |
| } |
| } |
| |
| func TestPhraseCompilerMisc(t *testing.T) { |
| folder := createTestIndex("foo", "bar", "baz") |
| searcher, _ := OpenIndexSearcher(folder) |
| terms := []interface{}{"foo", "bar"} |
| query := NewPhraseQuery("content", terms) |
| compiler := NewPhraseCompiler(query, searcher, 1.0) |
| checkQuerySerialize(t, compiler) |
| checkQueryEquals(t, compiler) |
| checkQueryToStringHasFoo(t, compiler) |
| } |
| |
| func TestPhraseCompilerWeighting(t *testing.T) { |
| index := createTestIndex("foo", "bar", "baz") |
| searcher, _ := OpenIndexSearcher(index) |
| terms := []interface{}{"foo", "bar"} |
| query := NewPhraseQuery("content", terms) |
| compiler := NewPhraseCompiler(query, searcher, 1.0) |
| _ = compiler.SumOfSquaredWeights() |
| _ = compiler.GetWeight() |
| compiler.ApplyNormFactor(10.0) |
| } |
| |
| func TestANDQueryBasics(t *testing.T) { |
| children := []Query{ |
| NewTermQuery("content", "foo"), |
| NewTermQuery("content", "bar"), |
| } |
| query := NewANDQuery(children) |
| checkQuerySerialize(t, query) |
| checkQueryDumpLoad(t, query) |
| checkQueryEquals(t, query) |
| checkQueryMakeCompiler(t, query) |
| checkQueryToStringHasFoo(t, query) |
| } |
| |
| func TestORQueryBasics(t *testing.T) { |
| children := []Query{ |
| NewTermQuery("content", "foo"), |
| NewTermQuery("content", "bar"), |
| } |
| query := NewORQuery(children) |
| checkQuerySerialize(t, query) |
| checkQueryDumpLoad(t, query) |
| checkQueryEquals(t, query) |
| checkQueryMakeCompiler(t, query) |
| checkQueryToStringHasFoo(t, query) |
| } |
| |
| func TestReqOptQueryBasics(t *testing.T) { |
| req := NewTermQuery("content", "foo") |
| opt := NewTermQuery("content", "bar") |
| query := NewRequiredOptionalQuery(req, opt) |
| checkQuerySerialize(t, query) |
| checkQueryDumpLoad(t, query) |
| checkQueryEquals(t, query) |
| checkQueryMakeCompiler(t, query) |
| checkQueryToStringHasFoo(t, query) |
| } |
| |
| func TestReqOptQueryAccessors(t *testing.T) { |
| req := NewTermQuery("content", "foo") |
| opt := NewTermQuery("content", "bar") |
| query := NewRequiredOptionalQuery(req, opt) |
| if query.GetRequiredQuery().TOPTR() != req.TOPTR() { |
| t.Errorf("GetRequiredQuery") |
| } |
| if query.GetOptionalQuery().TOPTR() != opt.TOPTR() { |
| t.Errorf("GetOptionalQuery") |
| } |
| } |
| |
| func TestNOTQueryBasics(t *testing.T) { |
| negated := NewTermQuery("content", "foo") |
| query := NewNOTQuery(negated) |
| checkQuerySerialize(t, query) |
| checkQueryDumpLoad(t, query) |
| checkQueryEquals(t, query) |
| checkQueryMakeCompiler(t, query) |
| checkQueryToStringHasFoo(t, query) |
| } |
| |
| func TestNOTQueryAccessors(t *testing.T) { |
| negated := NewTermQuery("content", "foo") |
| query := NewNOTQuery(negated) |
| if query.GetNegatedQuery().TOPTR() != negated.TOPTR() { |
| t.Errorf("GetNegatedQuery") |
| } |
| } |
| |
| func TestMatchAllQueryBasics(t *testing.T) { |
| query := NewMatchAllQuery() |
| checkQuerySerialize(t, query) |
| checkQueryDumpLoad(t, query) |
| checkQueryEquals(t, query) |
| checkQueryMakeCompiler(t, query) |
| } |
| |
| func TestNOMatchQueryBasics(t *testing.T) { |
| query := NewNoMatchQuery() |
| checkQuerySerialize(t, query) |
| checkQueryDumpLoad(t, query) |
| checkQueryEquals(t, query) |
| checkQueryMakeCompiler(t, query) |
| } |
| |
| func TestRangeQueryBasics(t *testing.T) { |
| query := NewRangeQuery("content", "fab", "foo", true, true) |
| checkQuerySerialize(t, query) |
| checkQueryDumpLoad(t, query) |
| checkQueryEquals(t, query) |
| checkQueryMakeCompiler(t, query) |
| checkQueryToStringHasFoo(t, query) |
| } |
| |
| func TestLeafQueryBasics(t *testing.T) { |
| query := NewLeafQuery("content", "foo") |
| checkQuerySerialize(t, query) |
| checkQueryDumpLoad(t, query) |
| checkQueryEquals(t, query) |
| checkQueryToStringHasFoo(t, query) |
| } |
| |
| func checkMatcher(t *testing.T, matcher Matcher, supportsScore bool) { |
| if got := matcher.Next(); got != 42 { |
| t.Error("Next: %d", got) |
| } |
| if got := matcher.GetDocID(); got != 42 { |
| t.Error("GetDocID: %d", got) |
| } |
| if supportsScore { |
| if score := matcher.Score(); score != 2 { |
| t.Error("Score: %f", score) |
| } |
| } |
| if got := matcher.Advance(50); got != 100 { |
| t.Error("Advance: %d", got) |
| } |
| if got := matcher.Next(); got != 0 { |
| t.Error("Next (iteration finished): %d", got) |
| } |
| if got := matcher.Error(); got != nil { |
| t.Error("Error after iteration finished: %v", got) |
| } |
| } |
| |
| func TestMockMatcherBasics(t *testing.T) { |
| matcher := newMockMatcher([]int32{42, 43, 100}, []float32{2,2,2}) |
| checkMatcher(t, matcher, true) |
| } |
| |
| func TestBitVecMatcherBasics(t *testing.T) { |
| bv := NewBitVector(0) |
| bv.Set(42) |
| bv.Set(43) |
| bv.Set(100) |
| matcher := NewBitVecMatcher(bv) |
| checkMatcher(t, matcher, false) |
| } |
| |
| func TestANDMatcherBasics(t *testing.T) { |
| a := newMockMatcher([]int32{42, 43, 99, 100}, []float32{1,1,1,1}) |
| b := newMockMatcher([]int32{1, 42, 43, 100}, []float32{1,1,1,1}) |
| matcher := NewANDMatcher([]Matcher{a, b}, nil) |
| checkMatcher(t, matcher, true) |
| } |
| |
| func TestORMatcherBasics(t *testing.T) { |
| a := newMockMatcher([]int32{42, 43}, nil) |
| b := newMockMatcher([]int32{42, 100}, nil) |
| matcher := NewORMatcher([]Matcher{a, b}) |
| checkMatcher(t, matcher, false) |
| } |
| |
| func TestORScorerBasics(t *testing.T) { |
| a := newMockMatcher([]int32{42, 43}, []float32{1,1}) |
| b := newMockMatcher([]int32{42, 100}, []float32{1,1}) |
| matcher := NewORScorer([]Matcher{a, b}, nil) |
| checkMatcher(t, matcher, true) |
| } |
| |
| func TestReqOptMatcherBasics(t *testing.T) { |
| req := newMockMatcher([]int32{42, 43, 100}, []float32{1,1,1}) |
| opt := newMockMatcher([]int32{1, 42, 99, 100}, []float32{1,1,1,1}) |
| matcher := NewRequiredOptionalMatcher(nil, req, opt) |
| checkMatcher(t, matcher, true) |
| } |
| |
| func TestNOTMatcherBasics(t *testing.T) { |
| a := newMockMatcher([]int32{1, 42, 43, 99, 100}, nil) |
| b := newMockMatcher([]int32{1, 99}, nil) |
| notB := NewNOTMatcher(b, 999) |
| matcher := NewANDMatcher([]Matcher{a, notB}, nil) |
| checkMatcher(t, matcher, false) |
| } |
| |
| func TestSeriesMatcherBasics(t *testing.T) { |
| a := newMockMatcher([]int32{42}, nil) |
| b := newMockMatcher([]int32{1, 4}, nil) |
| c := newMockMatcher([]int32{20}, nil) |
| matcher := NewSeriesMatcher([]Matcher{a, b, c}, []int32{0, 42, 80}) |
| checkMatcher(t, matcher, false) |
| } |
| |
| func TestMatchAllMatcherBasics(t *testing.T) { |
| matcher := NewMatchAllMatcher(1.5, 42) |
| matcher.Next() |
| if docID := matcher.Next(); docID != 2 { |
| t.Errorf("Unexpected return value for Next: %d", docID) |
| } |
| if docID := matcher.GetDocID(); docID != 2 { |
| t.Errorf("Unexpected return value for GetDocID: %d", docID) |
| } |
| if docID := matcher.Advance(42); docID != 42 { |
| t.Errorf("Advance returned %d", docID) |
| } |
| if score := matcher.Score(); score != 1.5 { |
| t.Errorf("Unexpected score: %f", score) |
| } |
| if matcher.Next() != 0 { |
| t.Error("Matcher should be exhausted") |
| } |
| } |
| |
| func TestNoMatchMatcherBasics(t *testing.T) { |
| matcher := NewNoMatchMatcher() |
| if matcher.Next() != 0 { |
| t.Error("Next should return false") |
| } |
| matcher = NewNoMatchMatcher() |
| if matcher.Advance(3) != 0 { |
| t.Error("Advance should return false") |
| } |
| } |
| |
| func TestRangeMatcherBasics(t *testing.T) { |
| index := createTestIndex("d", "c", "b", "a", "a", "a", "a") |
| ixReader, _ := OpenIndexReader(index, nil, nil) |
| segReaders := ixReader.SegReaders() |
| sortReader := segReaders[0].Fetch("Lucy::Index::SortReader").(SortReader) |
| sortCache, _ := sortReader.fetchSortCache("content") |
| matcher := NewRangeMatcher(0, 0, sortCache, segReaders[0].DocMax()) |
| if docID := matcher.Next(); docID != 4 { |
| t.Errorf("Next: %d", docID) |
| } |
| if docID := matcher.GetDocID(); docID != 4 { |
| t.Errorf("GetDocID: %d", docID) |
| } |
| if score := matcher.Score(); score != 0.0 { |
| t.Errorf("Score: %f", score) |
| } |
| if docID := matcher.Advance(7); docID != 7 { |
| t.Errorf("Advance: %d", docID) |
| } |
| if docID := matcher.Next(); docID != 0 { |
| t.Errorf("Matcher should be exhausted: %d", docID) |
| } |
| } |
| |
| func TestTopDocsBasics(t *testing.T) { |
| matchDocs := []MatchDoc{ |
| NewMatchDoc(42, 2.0, nil), |
| NewMatchDoc(100, 3.0, nil), |
| } |
| td := NewTopDocs(matchDocs, 50) |
| td.setTotalHits(20) |
| if totalHits := td.getTotalHits(); totalHits != 20 { |
| t.Errorf("Expected 20 total hits, got %d", totalHits) |
| } |
| td.SetMatchDocs(matchDocs) |
| fetched := td.GetMatchDocs() |
| if docID := fetched[0].getDocID(); docID != 42 { |
| t.Errorf("Set/Get MatchDocs expected 42, got %d", docID) |
| } |
| |
| folder := NewRAMFolder("") |
| outstream, _ := folder.OpenOut("foo") |
| td.serialize(outstream) |
| outstream.Close() |
| inStream, _ := folder.OpenIn("foo") |
| dupe := clownfish.GetClass(td).MakeObj().(TopDocs).deserialize(inStream) |
| if dupe.getTotalHits() != td.getTotalHits() { |
| t.Errorf("Failed round-trip serializetion of TopDocs") |
| } |
| } |
| |
| type simpleTestDoc struct { |
| Content string |
| } |
| |
| func TestHitsBasics(t *testing.T) { |
| index := createTestIndex("a", "b") |
| searcher, _ := OpenIndexSearcher(index) |
| topDocs, _ := searcher.topDocs(NewTermQuery("content", "a"), 10, nil) |
| hits := NewHits(searcher, topDocs, 0) |
| if got := hits.TotalHits(); got != topDocs.getTotalHits() { |
| t.Errorf("TotalHits is off: %d", got) |
| } |
| var doc simpleTestDoc |
| if !hits.Next(&doc) { |
| t.Error("Hits.Next") |
| } |
| if doc.Content != "a" { |
| t.Errorf("Bad doc content after Next: %s", doc.Content) |
| } |
| if hits.Next(&doc) { |
| t.Error("Hits iterator should be exhausted"); |
| } |
| if err := hits.Error(); err != nil { |
| t.Error("Hits.Error() not nil: %v", err) |
| } |
| } |
| |
| func TestHitsNext(t *testing.T) { |
| index := createTestIndex("a x", "a y", "a z", "b") |
| searcher, _ := OpenIndexSearcher(index) |
| hits, _ := searcher.Hits("a", 0, 10, nil) |
| docDoc := NewHitDoc(0, -1.0) |
| docStruct := &simpleTestDoc{} |
| docMap := make(map[string]interface{}) |
| if !hits.Next(docDoc) || !hits.Next(docStruct) || !hits.Next(docMap) { |
| t.Errorf("Hits.Next returned false: %v", hits.Error()) |
| } |
| if hits.Next(&simpleTestDoc{}) { |
| t.Error("Hits iterator should be exhausted"); |
| } |
| if docDoc.Extract("content").(string) != "a x" { |
| t.Error("Next with Doc object yielded bad data") |
| } |
| if docStruct.Content != "a y" { |
| t.Error("Next with struct yielded bad data") |
| } |
| if docMap["content"].(string) != "a z" { |
| t.Error("Next with map yielded bad data") |
| } |
| } |
| |
| func TestSortSpecBasics(t *testing.T) { |
| folder := NewRAMFolder("") |
| schema := NewSchema() |
| fieldType := NewFullTextType(NewStandardTokenizer()) |
| fieldType.SetSortable(true) |
| schema.SpecField("content", fieldType) |
| args := &OpenIndexerArgs{Index: folder, Schema: schema, Create: true} |
| indexer, err := OpenIndexer(args) |
| if err != nil { |
| panic(err) |
| } |
| for _, fieldVal := range []string{"a b", "a a"} { |
| indexer.AddDoc(&simpleTestDoc{fieldVal}) |
| } |
| indexer.Commit() |
| |
| rules := []SortRule{ |
| NewFieldSortRule("content", false), |
| } |
| sortSpec := NewSortSpec(rules) |
| searcher, _ := OpenIndexSearcher(folder) |
| hits, _ := searcher.Hits("a", 0, 1, sortSpec) |
| var doc simpleTestDoc |
| hits.Next(&doc) |
| if doc.Content != "a a" { |
| t.Error("Sort by field value") |
| } |
| |
| outstream, _ := folder.OpenOut("foo") |
| sortSpec.serialize(outstream) |
| outstream.Close() |
| inStream, _ := folder.OpenIn("foo") |
| dupe := clownfish.GetClass(sortSpec).MakeObj().(SortSpec).deserialize(inStream) |
| if len(dupe.GetRules()) != len(rules) { |
| t.Errorf("Failed round-trip serializetion of SortSpec") |
| } |
| } |
| |
| func TestHitQueueBasics(t *testing.T) { |
| hitQ := NewHitQueue(nil, nil, 1) |
| fortyTwo := NewMatchDoc(42, 1.0, nil) |
| fortyThree := NewMatchDoc(43, 1.0, nil) |
| if !hitQ.lessThan(fortyThree, fortyTwo) { |
| t.Error("lessThan") |
| } |
| if !hitQ.insert(fortyTwo) { |
| t.Error("insert") |
| } |
| if hitQ.getSize() != 1 { |
| t.Error("getSize") |
| } |
| if bumped := hitQ.jostle(fortyThree); bumped.(MatchDoc).getDocID() != 43 { |
| t.Error("jostle") |
| } |
| if peeked := hitQ.peek(); peeked.(MatchDoc).getDocID() != 42 { |
| t.Error("peek") |
| } |
| if popped := hitQ.pop(); popped.(MatchDoc).getDocID() != 42 { |
| t.Error("pop") |
| } |
| hitQ.insert(fortyTwo) |
| if got := hitQ.popAll(); got[0].(MatchDoc).getDocID() != 42 { |
| t.Error("popAll") |
| } |
| } |
| |
| func TestSpanBasics(t *testing.T) { |
| a := NewSpan(42, 1, 0.0) |
| b := NewSpan(42, 2, 0.0) |
| if !a.Equals(a) { |
| t.Error("Equals self") |
| } |
| if a.Equals(b) { |
| t.Error("Equals should return false for non-equal spans") |
| } |
| if got := a.CompareTo(b); got >= 0 { |
| t.Errorf("CompareTo returned %d", got) |
| } |
| a.SetOffset(21) |
| if got := a.GetOffset(); got != 21 { |
| t.Errorf("Set/Get offset: %d", got) |
| } |
| a.SetLength(10) |
| if got := a.GetLength(); got != 10 { |
| t.Errorf("Set/Get length: %d", got) |
| } |
| a.SetWeight(1.5) |
| if got := a.GetWeight(); got != 1.5 { |
| t.Errorf("Set/Get weight: %f", got) |
| } |
| } |
| |
| func TestBitCollectorBasics(t *testing.T) { |
| index := createTestIndex("a", "b", "c", "a") |
| searcher, _ := OpenIndexSearcher(index) |
| bitVec := NewBitVector(5) |
| collector := NewBitCollector(bitVec) |
| searcher.Collect(NewTermQuery("content", "a"), collector) |
| expected := []bool{false, true, false, false, true, false, false, false} |
| if got := bitVec.ToArray(); !reflect.DeepEqual(got,expected) { |
| t.Errorf("Unexpected result set: %v", got) |
| } |
| } |
| |
| func TestOffsetCollectorBasics(t *testing.T) { |
| index := createTestIndex("a", "b", "c") |
| searcher, _ := OpenIndexSearcher(index) |
| bitVec := NewBitVector(64) |
| bitColl := NewBitCollector(bitVec) |
| offsetColl := NewOffsetCollector(bitColl, 40) |
| searcher.Collect(NewTermQuery("content", "b"), offsetColl) |
| if got := bitVec.NextHit(0); got != 42 { |
| t.Errorf("Unexpected docID: %d", got) |
| } |
| } |
| |
| func TestSortCollectorBasics(t *testing.T) { |
| index := createTestIndex("a", "b", "c", "a") |
| searcher, _ := OpenIndexSearcher(index) |
| collector := NewSortCollector(nil, nil, 1) |
| searcher.Collect(NewTermQuery("content", "a"), collector) |
| if totalHits := collector.getTotalHits(); totalHits != 2 { |
| t.Errorf("Unexpected TotalHits: %d", totalHits) |
| } |
| matchDocs := collector.PopMatchDocs() |
| if docID := matchDocs[0].getDocID(); docID != 1 { |
| t.Errorf("Weird MatchDoc: %d", docID) |
| } |
| } |
| |
| func TestIndexSearcherMisc(t *testing.T) { |
| index := createTestIndex("a", "b", "c", "a a") |
| searcher, _ := OpenIndexSearcher(index) |
| if got := searcher.DocFreq("content", "a"); got != 2 { |
| t.Errorf("DocFreq expected 2, got %d", got) |
| } |
| if got := searcher.DocMax(); got != 4 { |
| t.Errorf("DocMax expected 4, got %d", got) |
| } |
| if _, ok := searcher.GetReader().(PolyReader); !ok { |
| t.Error("GetReader") |
| } |
| doc, err := searcher.FetchDoc(4) |
| if _, ok := doc.(Doc); !ok || err != nil { |
| t.Error("FetchDoc: %v", err) |
| } |
| docVec, err := searcher.fetchDocVec(4) |
| if _, ok := docVec.(DocVector); !ok || err != nil { |
| t.Error("FetchDocVec: %v", err) |
| } |
| } |
| |
| func TestIndexSearcherOpenClose(t *testing.T) { |
| if _, err := OpenIndexSearcher(NewRAMFolder("")); err == nil { |
| t.Error("Open non-existent index") |
| } |
| if _, err := OpenIndexSearcher(42); err == nil { |
| t.Error("Garbage 'index' argument") |
| } |
| index := createTestIndex("a", "b", "c") |
| searcher, _ := OpenIndexSearcher(index) |
| searcher.Close() |
| } |
| |
| func TestIndexSearcherHits(t *testing.T) { |
| index := createTestIndex("a", "b", "c", "a a") |
| searcher, _ := OpenIndexSearcher(index) |
| if got, _ := searcher.Hits("a", 0, 1, nil); got.TotalHits() != 2 { |
| t.Errorf("Hits() with query string: %d", got.TotalHits()) |
| } |
| termQuery := NewTermQuery("content", "a") |
| if got, _ := searcher.Hits(termQuery, 0, 1, nil); got.TotalHits() != 2 { |
| t.Errorf("Hits() with TermQuery object: %d", got.TotalHits()) |
| } |
| |
| if _, err := searcher.Hits(42, 0, 1, nil); err == nil { |
| t.Error("Garbage 'query' argument") |
| } |
| } |
| |
| func TestIndexSearcherTopDocs(t *testing.T) { |
| index := createTestIndex("a", "b") |
| searcher, _ := OpenIndexSearcher(index) |
| topDocs, err := searcher.topDocs(NewTermQuery("content", "b"), 10, nil) |
| if err != nil { |
| t.Errorf("topDocs: %v", err) |
| } |
| matchDocs := topDocs.GetMatchDocs() |
| if docID := matchDocs[0].getDocID(); docID != 2 { |
| t.Errorf("TopDocs expected 2, got %d", docID) |
| } |
| } |
| |
| func TestIndexSearcherReadDoc(t *testing.T) { |
| index := createTestIndex("a", "b") |
| searcher, _ := OpenIndexSearcher(index) |
| docDoc := NewHitDoc(0, -1.0) |
| docStruct := &simpleTestDoc{} |
| docMap := make(map[string]interface{}) |
| var err error |
| err = searcher.ReadDoc(2, docDoc) |
| if err != nil { |
| t.Errorf("ReadDoc failed with HitDoc: %v", err) |
| } |
| err = searcher.ReadDoc(2, docStruct) |
| if err != nil { |
| t.Errorf("ReadDoc failed with struct: %v", err) |
| } |
| err = searcher.ReadDoc(2, docMap) |
| if err != nil { |
| t.Errorf("ReadDoc failed with map: %v", err) |
| } |
| if docDoc.Extract("content").(string) != "b" { |
| t.Error("Next with Doc object yielded bad data") |
| } |
| if docStruct.Content != "b" { |
| t.Error("Next with struct yielded bad data") |
| } |
| if docMap["content"].(string) != "b" { |
| t.Error("Next with map yielded bad data") |
| } |
| } |
| |
| func TestMatchDocBasics(t *testing.T) { |
| matchDoc := NewMatchDoc(0, 1.0, nil) |
| matchDoc.setDocID(42) |
| if got := matchDoc.getDocID(); got != 42 { |
| t.Errorf("set/getDocID: %d", got) |
| } |
| matchDoc.setScore(1.5) |
| if got := matchDoc.getScore(); got != 1.5 { |
| t.Errorf("set/getScore: %f", got) |
| } |
| values := []interface{}{"foo", int64(42)} |
| matchDoc.setValues(values) |
| if got := matchDoc.getValues(); !reflect.DeepEqual(got, values) { |
| t.Error("get/setValues") |
| } |
| } |
| |
| func TestMatchDocSerialization(t *testing.T) { |
| values := []interface{}{"foo", int64(42)} |
| matchDoc := NewMatchDoc(100, 1.5, values) |
| folder := NewRAMFolder("") |
| outstream, _ := folder.OpenOut("foo") |
| matchDoc.serialize(outstream) |
| outstream.Close() |
| inStream, _ := folder.OpenIn("foo") |
| dupe := clownfish.GetClass(matchDoc).MakeObj().(MatchDoc).deserialize(inStream) |
| if got := dupe.getValues(); !reflect.DeepEqual(got, values) { |
| t.Errorf("Failed round-trip serializetion of MatchDoc") |
| } |
| } |
| |
| func TestQueryParserConstructors(t *testing.T) { |
| schema := createTestSchema() |
| qParser := NewQueryParser(schema, nil) |
| if _, ok := qParser.Parse("foo bar").(ORQuery); !ok { |
| t.Errorf("qParser boolop") |
| } |
| orParser := NewORParser(schema, nil) |
| if _, ok := orParser.Parse("foo bar").(ORQuery); !ok { |
| t.Errorf("orParser boolop") |
| } |
| andParser := NewANDParser(schema, nil) |
| if _, ok := andParser.Parse("foo bar").(ANDQuery); !ok { |
| t.Errorf("andParser boolop") |
| } |
| } |
| |
| func TestQueryParserFactories(t *testing.T) { |
| qParser := NewQueryParser(createTestSchema(), nil) |
| if _, ok := qParser.MakeTermQuery("content", "foo").(TermQuery); !ok { |
| t.Errorf("MakeTermQuery") |
| } |
| if _, ok := qParser.MakePhraseQuery("content", []interface{}{}).(PhraseQuery); !ok { |
| t.Errorf("MakePhraseQuery") |
| } |
| if _, ok := qParser.MakeORQuery([]Query{}).(ORQuery); !ok { |
| t.Errorf("MakeORQuery") |
| } |
| if _, ok := qParser.MakeANDQuery([]Query{}).(ANDQuery); !ok { |
| t.Errorf("MakeANDQuery") |
| } |
| if _, ok := qParser.MakeNOTQuery(NewTermQuery("content", "foo")).(NOTQuery); !ok { |
| t.Errorf("MakeNOTQuery") |
| } |
| req := NewTermQuery("content", "foo") |
| opt := NewTermQuery("content", "bar") |
| if _, ok := qParser.MakeReqOptQuery(req, opt).(RequiredOptionalQuery); !ok { |
| t.Errorf("MakeReqOptQuery") |
| } |
| } |
| |
| func TestQueryParserParsing(t *testing.T) { |
| qParser := NewQueryParser(createTestSchema(), nil) |
| if _, ok := qParser.Parse("foo").(Query); !ok { |
| t.Errorf("Parse") |
| } |
| if _, ok := qParser.Tree("foo").(Query); !ok { |
| t.Errorf("Tree") |
| } |
| if _, ok := qParser.Expand(NewTermQuery("content", "foo")).(Query); !ok { |
| t.Errorf("Expand") |
| } |
| if _, ok := qParser.ExpandLeaf(NewLeafQuery("content", "foo")).(Query); !ok { |
| t.Errorf("ExpandLeaf") |
| } |
| if _, ok := qParser.Prune(NewTermQuery("content", "foo")).(Query); !ok { |
| t.Errorf("Prune") |
| } |
| } |
| |
| func TestQueryParserAccessors(t *testing.T) { |
| qParser := NewQueryParser(createTestSchema(), nil) |
| if got := qParser.getAnalyzer(); got != nil { |
| t.Errorf("getAnalyzer") |
| } |
| if got := qParser.getSchema(); got == nil { |
| t.Errorf("getSchema") |
| } |
| if got := qParser.getFields(); !reflect.DeepEqual(got, []string{"content"}) { |
| t.Errorf("getFields") |
| } |
| if got := qParser.getDefaultBoolOp(); got != "OR" { |
| t.Errorf("getDefaultBoolOp") |
| } |
| qParser.SetHeedColons(true) |
| if !qParser.heedColons() { |
| t.Errorf("SetHeedColons/heedColons") |
| } |
| } |