blob: 0049ee4afd4979d6845046504669976e5661bf5d [file] [log] [blame]
/* 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 "os"
import "reflect"
import "git-wip-us.apache.org/repos/asf/lucy-clownfish.git/runtime/go/clownfish"
func TestIndexerAddDoc(t *testing.T) {
schema := createTestSchema()
index := NewRAMFolder("")
indexer, _ := OpenIndexer(&OpenIndexerArgs{
Create: true,
Index: index,
Schema: schema,
})
indexer.AddDoc(&testDoc{Content: "foo"})
indexer.AddDoc(map[string]interface{}{"content": "foo"})
doc := NewDoc(0)
doc.Store("content", "foo")
indexer.AddDoc(doc)
indexer.Commit()
searcher, _ := OpenIndexSearcher(index)
if got := searcher.DocFreq("content", "foo"); got != 3 {
t.Errorf("Didn't index all docs -- DocMax: %d", got)
}
}
func TestIndexerAddIndex(t *testing.T) {
var err error
origIndex := "_test_go_indexer_add_index"
defer os.RemoveAll(origIndex)
schema := createTestSchema()
indexer, err := OpenIndexer(&OpenIndexerArgs{
Create: true,
Index: origIndex,
Schema: schema,
})
if err != nil {
t.Errorf("OpenIndexer: %v", err)
return
}
err = indexer.AddDoc(&testDoc{Content: "foo"})
if err != nil {
t.Errorf("AddDoc: %v", err)
}
err = indexer.Commit()
if err != nil {
t.Errorf("Commit FS index: %v", err)
}
indexer, _ = OpenIndexer(&OpenIndexerArgs{
Create: true,
Index: NewRAMFolder(""),
Schema: schema,
})
err = indexer.AddIndex(origIndex)
if err != nil {
t.Errorf("AddIndex: %v", err)
}
err = indexer.Commit()
if err != nil {
t.Errorf("AddIndex: %v", err)
}
}
func TestIndexerDeletions(t *testing.T) {
index := createTestIndex("foo", "bar", "baz", "gazi")
indexer, _ := OpenIndexer(&OpenIndexerArgs{Index: index})
err := indexer.DeleteByTerm("content", "foo")
if err != nil {
t.Errorf("DeleteByTerm: %v", err)
}
indexer.DeleteByQuery(NewTermQuery("content", "bar"))
if err != nil {
t.Errorf("DeleteByQuery: %v", err)
}
indexer.DeleteByDocID(3)
if err != nil {
t.Errorf("DeleteByDocID: %v", err)
}
err = indexer.Commit()
if err != nil {
t.Errorf("Commit: %v", err)
}
searcher, _ := OpenIndexSearcher(index)
if count := searcher.GetReader().DocCount(); count != 1 {
t.Errorf("Some deletions didn't go through (count=%d)", count)
}
}
func TestIndexerMisc(t *testing.T) {
var err error
index := createTestIndex("foo", "bar", "baz")
indexer, _ := OpenIndexer(&OpenIndexerArgs{Index: index})
if _, ok := indexer.GetSchema().(Schema); !ok {
t.Errorf("GetSchema")
}
if _, ok := indexer.getStockDoc().(Doc); !ok {
t.Errorf("getStockDoc")
}
if _, ok := indexer.getSegWriter().(SegWriter); !ok {
t.Errorf("getSegWriter")
}
indexer.AddDoc(&testDoc{Content: "gazi"})
indexer.Optimize()
err = indexer.PrepareCommit()
if err != nil {
t.Errorf("PrepareCommit: %v", err)
}
err = indexer.Commit()
if err != nil {
t.Errorf("Commit: %v", err)
}
}
func TestBackgroundMergerMisc(t *testing.T) {
var err error
index := createTestIndex("foo", "bar", "baz")
merger, _ := OpenBackgroundMerger(index, nil)
merger.Optimize()
err = merger.PrepareCommit()
if err != nil {
t.Errorf("PrepareCommit: %v", err)
}
err = merger.Commit()
if err != nil {
t.Errorf("Commit: %v", err)
}
}
func TestIndexManagerAccessors(t *testing.T) {
host := "dev.example.com"
manager := NewIndexManager(host, nil)
if got := manager.GetHost(); got != host {
t.Errorf("GetHost: %v", got)
}
folder := NewRAMFolder("")
manager.SetFolder(folder)
if got := manager.GetFolder(); !reflect.DeepEqual(folder, got) {
t.Errorf("SetFolder/GetFolder")
}
manager.SetWriteLockTimeout(72)
if got := manager.GetWriteLockTimeout(); got != 72 {
t.Errorf("set/GetWriteLockTimeout: %d", got)
}
manager.SetWriteLockInterval(42)
if got := manager.GetWriteLockInterval(); got != 42 {
t.Errorf("set/GetWriteLockInterval: %d", got)
}
manager.setMergeLockTimeout(73)
if got := manager.getMergeLockTimeout(); got != 73 {
t.Errorf("set/getMergeLockTimeout: %d", got)
}
manager.setMergeLockInterval(43)
if got := manager.getMergeLockInterval(); got != 43 {
t.Errorf("set/getMergeLockInterval: %d", got)
}
manager.setDeletionLockTimeout(71)
if got := manager.getDeletionLockTimeout(); got != 71 {
t.Errorf("set/getDeletionLockTimeout: %d", got)
}
manager.setDeletionLockInterval(41)
if got := manager.getDeletionLockInterval(); got != 41 {
t.Errorf("set/getDeletionLockInterval: %d", got)
}
}
func TestIndexManagerLocks(t *testing.T) {
manager := NewIndexManager("", nil)
manager.SetFolder(NewRAMFolder(""))
if _, ok := manager.MakeWriteLock().(Lock); !ok {
t.Errorf("MakeWriteLock")
}
if _, ok := manager.makeMergeLock().(Lock); !ok {
t.Errorf("makeMergeLock")
}
if _, ok := manager.makeDeletionLock().(Lock); !ok {
t.Errorf("makeDeletionLock")
}
snapFile := "snapshot_4a.json"
if _, ok := manager.makeSnapshotReadLock(snapFile).(SharedLock); !ok {
t.Errorf("makeDeletionLock")
}
}
func TestIndexManagerMergeData(t *testing.T) {
var err error
manager := NewIndexManager("", nil)
manager.SetFolder(NewRAMFolder(""))
err = manager.WriteMergeData(42)
if err != nil {
t.Errorf("WriteMergeData: %v", err)
}
mergeData, err := manager.ReadMergeData()
if err != nil {
t.Errorf("ReadMergeData: %v", err)
}
if got, ok := mergeData["cutoff"].(string); !ok || got != "42" {
t.Errorf("ReadMergeData: %v", got)
}
err = manager.RemoveMergeData()
if err != nil {
t.Errorf("RemoveMergeData: %v", err)
}
}
func TestIndexManagerMisc(t *testing.T) {
manager := NewIndexManager("", nil)
snapshot := NewSnapshot()
snapshot.AddEntry("seg_4")
snapshot.AddEntry("seg_5")
if got := manager.highestSegNum(snapshot); got != 5 {
t.Errorf("highestSegNum: %d", got)
}
}
func TestIndexManagerRecycle(t *testing.T) {
index := createTestIndex("foo", "bar", "baz")
manager := NewIndexManager("", nil)
manager.SetFolder(index)
indexer, _ := OpenIndexer(&OpenIndexerArgs{Index: index})
searcher, _ := OpenIndexSearcher(index)
reader := searcher.GetReader().(PolyReader)
delWriter := indexer.getSegWriter().getDelWriter()
segReaders, err := manager.Recycle(reader, delWriter, 0, true)
if err != nil || len(segReaders) != 1 {
t.Errorf("Recycle: (%d SegReaders) %v", len(segReaders), err)
}
}
func TestTermInfoMisc(t *testing.T) {
tinfo := NewTermInfo(1000)
if got := tinfo.GetDocFreq(); got != 1000 {
t.Errorf("GetDocFreq: %d", got)
}
tinfo.SetDocFreq(1001)
if got := tinfo.GetDocFreq(); got != 1001 {
t.Errorf("Set/GetDocFreq: %d", got)
}
tinfo.SetLexFilePos(1002)
if got := tinfo.GetLexFilePos(); got != 1002 {
t.Errorf("Set/GetLexFilePos: %d", got)
}
tinfo.SetPostFilePos(1003)
if got := tinfo.GetPostFilePos(); got != 1003 {
t.Errorf("Set/GetPostFilePos: %d", got)
}
tinfo.SetSkipFilePos(1002)
if got := tinfo.GetSkipFilePos(); got != 1002 {
t.Errorf("Set/GetSkipFilePos: %d", got)
}
other := NewTermInfo(42)
other.Mimic(tinfo)
if got := other.GetDocFreq(); got != tinfo.GetDocFreq() {
t.Errorf("Mimic: (%d != %d)", got, tinfo.GetDocFreq())
}
other = tinfo.Clone().(TermInfo)
if got := other.GetDocFreq(); got != tinfo.GetDocFreq() {
t.Errorf("Clone: (%d != %d)", got, tinfo.GetDocFreq())
}
tinfo.reset()
if got := tinfo.GetDocFreq(); got != 0 {
t.Errorf("Reset: expected 0, got %d", got)
}
}
func TestBitVecDelDocsMisc(t *testing.T) {
folder := NewRAMFolder("")
out, _ := folder.OpenOut("bits")
out.WriteU32(0xDEADBEEF)
out.Close()
bv := NewBitVecDelDocs(folder, "bits")
if !bv.Get(31) {
t.Errorf("Get returned false")
}
}
func TestTermVectorMisc(t *testing.T) {
positions := []int32{0, 3}
startOffsets := []int32{0, 20}
endOffsets := []int32{2, 22}
tv := NewTermVector("content", "red yellow green red blue", positions, startOffsets, endOffsets)
if got := tv.GetPositions(); !reflect.DeepEqual(got, positions) {
t.Errorf("GetPositions: %v", got)
}
if got := tv.GetStartOffsets(); !reflect.DeepEqual(got, startOffsets) {
t.Errorf("GetStartOffsets: %v", got)
}
if got := tv.GetEndOffsets(); !reflect.DeepEqual(got, endOffsets) {
t.Errorf("GetEndOffsets: %v", got)
}
folder := NewRAMFolder("")
out, _ := folder.OpenOut("dump")
tv.serialize(out)
out.Close()
in, _ := folder.OpenIn("dump")
dupe := clownfish.GetClass(tv).MakeObj().(TermVector).deserialize(in)
if !tv.Equals(dupe) {
t.Errorf("Unsuccessful serialization round trip")
}
}
func TestDocVectorMisc(t *testing.T) {
schema := NewSchema()
spec := NewFullTextType(NewStandardTokenizer())
spec.SetHighlightable(true)
schema.SpecField("content", spec)
folder := NewRAMFolder("")
indexer, _ := OpenIndexer(&OpenIndexerArgs{Index: folder, Schema: schema, Create: true})
indexer.AddDoc(&testDoc{Content: "foo bar baz"})
indexer.Commit()
searcher, _ := OpenIndexSearcher(folder)
dv, _ := searcher.fetchDocVec(1)
fieldBuf := dv.fieldBuf("content");
if fieldBuf == nil {
t.Errorf("fieldBuf returned nil")
}
dv.addFieldBuf("content", fieldBuf)
if got := dv.termVector("content", "bar"); got == nil {
t.Errorf("termVector returned nil")
}
out, _ := folder.OpenOut("dump")
dv.serialize(out)
out.Close()
in, _ := folder.OpenIn("dump")
dupe := clownfish.GetClass(dv).MakeObj().(DocVector).deserialize(in)
in.Close()
if _, ok := dupe.(DocVector); !ok {
t.Errorf("serialize/deserialize")
}
}
func TestSnapshotMisc(t *testing.T) {
var err error
snapshot := NewSnapshot()
snapshot.AddEntry("foo")
snapshot.AddEntry("bar")
snapshot.DeleteEntry("bar")
if got := snapshot.NumEntries(); got != 1 {
t.Errorf("Add/DeleteEntry, NumEntries: %d", got)
}
if got := snapshot.List(); !reflect.DeepEqual(got, []string{"foo"}) {
t.Errorf("List: %v", got)
}
folder := NewRAMFolder("")
err = snapshot.WriteFile(folder, "")
if err != nil {
t.Errorf("WriteFile: %v", err)
}
other := NewSnapshot()
_, err = other.ReadFile(folder, "")
if err != nil {
t.Errorf("ReadFile: %v", err)
}
path := "snapshot_4.json"
snapshot.SetPath(path)
if got := snapshot.GetPath(); got != path {
t.Errorf("SetPath/GetPath: %v", path)
}
}
func TestSortCacheMisc(t *testing.T) {
var err error
schema := NewSchema()
spec := NewFullTextType(NewStandardTokenizer())
spec.SetSortable(true)
schema.SpecField("content", spec)
folder := NewRAMFolder("")
indexer, _ := OpenIndexer(&OpenIndexerArgs{Index: folder, Schema: schema, Create: true})
indexer.AddDoc(&testDoc{Content: "foo"})
indexer.AddDoc(&testDoc{Content: "bar"})
indexer.AddDoc(&testDoc{Content: "baz"})
indexer.AddDoc(make(map[string]interface{}))
indexer.Commit()
ixReader, _ := OpenIndexReader(folder, nil, nil)
segReaders := ixReader.SegReaders()
sortReader := segReaders[0].Fetch("Lucy::Index::SortReader").(SortReader)
sortCache, _ := sortReader.fetchSortCache("content")
if card := sortCache.GetCardinality(); card != 4 {
t.Errorf("GetCardinality: %d", card)
}
if width := sortCache.GetOrdWidth(); width != 2 {
t.Errorf("GetOrdWidth: %d", width)
}
lowest, err := sortCache.Value(0)
if _, ok := lowest.(string); err != nil || !ok || lowest != "bar" {
t.Errorf("Value: %v", err)
}
if ord, err := sortCache.Ordinal(1); err != nil || ord != 2 { // "foo" is ordinal 2
t.Errorf("Ordinal: %d, %v", ord, err)
}
if nullOrd := sortCache.GetNullOrd(); nullOrd != 3 {
t.Errorf("GetNullOrd: %d", nullOrd)
}
if ord, err := sortCache.Find("foo"); err != nil || ord != 2 {
t.Errorf("Find: %d, %v", ord, err)
}
if sortCache.getNativeOrds() {
t.Errorf("recent index shouldn't have native ords")
}
}
func TestSimilarityMisc(t *testing.T) {
sim := NewSimilarity()
if _, ok := sim.makePosting().(Posting); !ok {
t.Errorf("makePosting")
}
if got := sim.tF(4.0); got != 2.0 {
t.Errorf("tF: %f", got)
}
if got := sim.iDF(40, 1000); got <= 0 {
t.Errorf("iDF: %f", got)
}
if got := sim.coord(3, 4); got <= 0 {
t.Errorf("coord: %f", got)
}
if got := sim.LengthNorm(4); got != 0.5 {
t.Errorf("LengthNorm: %f", got)
}
if got := sim.queryNorm(4); got != 0.5 {
t.Errorf("queryNorm: %f", got)
}
if got := sim.encodeNorm(sim.decodeNorm(42)); got != 42 {
t.Errorf("encode/decodeNorm: %d", got)
}
}
func TestSimilarityRoundTrip(t *testing.T) {
sim := NewSimilarity()
dupe := sim.load(sim.dump())
if !sim.Equals(dupe) {
t.Errorf("Dump/Load round-trip")
}
folder := NewRAMFolder("")
out, _ := folder.OpenOut("dump")
sim.serialize(out)
out.Close()
in, _ := folder.OpenIn("dump")
dupe = clownfish.GetClass(sim).MakeObj().(Similarity).deserialize(in)
if !sim.Equals(dupe) {
t.Errorf("serialize/deserialize round-trip")
}
}
func TestSegmentMisc(t *testing.T) {
var err error
seg := NewSegment(4)
if name := seg.GetName(); name != "seg_4" {
t.Errorf("GetName: %s", name)
}
if num := seg.GetNumber(); num != 4 {
t.Errorf("GetNumber: %d", num)
}
if num := seg.AddField("field1"); num != 1 {
t.Errorf("AddField: %d", num)
}
if field := seg.FieldName(1); field != "field1" {
t.Errorf("FieldName: %v", field)
}
if num := seg.FieldNum("field1"); num != 1 {
t.Errorf("FieldNum: %d", num)
}
metadata := map[string]interface{}{
"foo": "1",
"bar": "2",
}
seg.StoreMetadata("mycomponent", metadata)
if got := seg.FetchMetadata("mycomponent"); !reflect.DeepEqual(got, metadata) {
t.Errorf("Store/FetchMetadata: %v", got)
}
if got := seg.getMetadata(); got["mycomponent"] == nil {
t.Errorf("%v", got)
}
seg.SetCount(42)
seg.incrementCount(5)
if got := seg.GetCount(); got != 47 {
t.Errorf("SetCount/GetCount: %d", got)
}
folder := NewRAMFolder("")
folder.MkDir("seg_4")
err = seg.WriteFile(folder)
if err != nil {
t.Errorf("WriteFile: %v", err)
}
dupe := NewSegment(4)
dupe.ReadFile(folder)
if err != nil {
t.Errorf("WriteFile: %v", err)
}
other := NewSegment(5)
if got := seg.CompareTo(other); got >= 0 {
t.Errorf("CompareTo (seg 4 vs seg 5): %d", got)
}
}
func TestFilePurgerMisc(t *testing.T) {
folder := NewRAMFolder("")
oldSnapshot := NewSnapshot()
oldSnapshot.AddEntry("foo")
out, _ := folder.OpenOut("foo")
out.Close()
oldSnapshot.WriteFile(folder, "")
snapshot := NewSnapshot()
snapshot.WriteFile(folder, "")
purger := NewFilePurger(folder, snapshot, nil)
purger.purge()
if folder.exists("foo") {
t.Errorf("Failed to purge file")
}
}
func TestInvEntryMisc(t *testing.T) {
entry := NewInverterEntry(nil, "content", 1)
other := NewInverterEntry(nil, "title", 2)
if got := entry.CompareTo(other); got >= 0 {
t.Errorf("CompareTo compares field numbers: %d", got)
}
}
func TestInverterMisc(t *testing.T) {
schema := NewSchema()
spec := NewFullTextType(NewStandardTokenizer())
schema.SpecField("title", spec)
schema.SpecField("content", spec)
seg := NewSegment(4)
seg.AddField("title")
seg.AddField("content")
inverter := NewInverter(schema, seg)
inverter.SetBoost(2.0)
if got := inverter.GetBoost(); got != 2.0 {
t.Errorf("Set/GetBoost: %f", got)
}
if got := inverter.GetDoc(); got != nil {
t.Errorf("GetDoc should return nil when not yet set")
}
inverter.Clear()
doc := NewDoc(42)
doc.Store("title", "Foo")
doc.Store("content", "foo foo foo foo foo")
inverter.SetDoc(doc)
if docID := inverter.GetDoc().GetDocID(); docID != 42 {
t.Errorf("Set/GetDoc: %d", docID)
}
inverter.Clear()
// Can't test AddField.
// inverter.AddField(entry)
inverter.InvertDoc(doc)
numFields := inverter.Iterate()
if numFields != 2 {
t.Errorf("Iterate: %d", numFields)
}
fieldNum := inverter.Next()
if fieldNum != 1 {
t.Errorf("Next: %d", fieldNum)
}
if got := inverter.GetFieldName(); got != "title" {
t.Errorf("GetFieldName during first iter: %s", got)
}
if got := inverter.GetValue(); got != "Foo" {
t.Errorf("GetValue during first iter: %v", got)
}
if got, ok := inverter.GetType().(FullTextType); !ok {
t.Errorf("GetType: %T", got)
}
if got, ok := inverter.GetAnalyzer().(StandardTokenizer); !ok {
t.Errorf("GetType: %T", got)
}
if got, ok := inverter.GetSimilarity().(Similarity); !ok {
t.Errorf("GetSimilarity: %T", got)
}
if got, ok := inverter.GetInversion().(Inversion); !ok {
t.Errorf("GetInversion: %T", got)
}
if nextFieldNum := inverter.Next(); nextFieldNum != 2 {
t.Errorf("Next second iter: %d", nextFieldNum)
}
if done := inverter.Next(); done != 0 {
t.Errorf("Next should return 0 when exhausted: %d", done)
}
if got := inverter.GetFieldName(); got != "" {
t.Errorf("GetFieldName after iterator exhausted: %s", got)
}
if got := inverter.GetValue(); got != nil {
t.Errorf("GetValue after iterator exhausted: %v", got)
}
if got := inverter.GetType(); got != nil {
t.Errorf("GetType after iterator exhausted: %v", got)
}
if got := inverter.GetAnalyzer(); got != nil {
t.Errorf("GetAnalyzer after iterator exhausted: %v", got)
}
if got := inverter.GetSimilarity(); got != nil {
t.Errorf("GetSimilarity after iterator exhausted: %v", got)
}
if got := inverter.GetInversion(); got != nil {
t.Errorf("GetInversion after iterator exhausted: %v", got)
}
}
// Use SegLexicon to air out the Lexicon interface.
func TestLexiconBasics(t *testing.T) {
folder := createTestIndex("a", "b", "c")
ixReader, _ := OpenIndexReader(folder, nil, nil)
segReaders := ixReader.SegReaders()
lexReader := segReaders[0].Fetch("Lucy::Index::LexiconReader").(LexiconReader)
segLex, _ := lexReader.Lexicon("content", nil)
if field := segLex.getField(); field != "content" {
t.Errorf("getField: %s", field)
}
segLex.Next()
if got := segLex.GetTerm(); got != "a" {
t.Errorf("GetTerm: %v", got)
}
if docFreq := segLex.docFreq(); docFreq != 1 {
t.Errorf("docFreq: %d", docFreq)
}
if !segLex.Next() || !segLex.Next() {
t.Errorf("Iterate")
}
if segLex.Next() {
t.Errorf("Iteration should be finished")
}
segLex.Seek("b")
if got := segLex.GetTerm(); got != "b" {
t.Errorf("Seek: %v", got)
}
segLex.Reset()
if !segLex.Next() {
t.Errorf("Next after Reset")
}
}
func TestPostingListBasics(t *testing.T) {
folder := createTestIndex("c", "b b b", "a", "b",)
ixReader, _ := OpenIndexReader(folder, nil, nil)
segReaders := ixReader.SegReaders()
pListReader := segReaders[0].Fetch("Lucy::Index::PostingListReader").(PostingListReader)
pList, _ := pListReader.PostingList("content", nil)
pList.Seek("b")
if docFreq := pList.GetDocFreq(); docFreq != 2 {
t.Errorf("GetDocFreq: %d", docFreq)
}
if got := pList.Next(); got != 2 {
t.Errorf("Next: %d", got)
}
if docID := pList.GetDocID(); docID != 2 {
t.Errorf("GetDocID: %d", docID)
}
if got := pList.Next(); got != 4 {
t.Errorf("Next (second iter): %d", got)
}
if got := pList.Next(); got != 0 {
t.Error("Next (done): %d", got)
}
}
func TestPostingBasics(t *testing.T) {
sim := NewSimilarity()
posting := NewMatchPosting(sim)
posting.SetDocID(42)
if got := posting.GetDocID(); got != 42 {
t.Errorf("Set/GetDocID: %d", got)
}
posting.Reset()
if got := posting.getFreq(); got != 0 {
t.Errorf("getFreq: %d", got)
}
}
// This function runs Close(), so the reader becomes unusable afterwards.
func runDataReaderCommon(t *testing.T, reader DataReader, runAggregator bool) {
if runAggregator {
got, err := reader.Aggregator([]DataReader{}, []int32{})
if got == nil || err != nil {
t.Errorf("Aggregator: %#v, %v", got, err)
}
}
if got := reader.GetSchema(); false {
t.Errorf("GetSchema: %v", got)
}
if got := reader.GetFolder(); false {
t.Errorf("GetFolder: %v", got)
}
if got := reader.GetSnapshot(); false {
t.Errorf("GetSnapshot: %v", got)
}
if got := reader.GetSegments(); false {
t.Errorf("GetSegments: %#v", got)
}
if got := reader.GetSegment(); false {
t.Errorf("GetSegment: %#v", got)
}
if got := reader.GetSegTick(); false {
t.Errorf("GetSegTick: %d", got)
}
if err := reader.Close(); err != nil {
t.Errorf("Close: %v", err)
}
}
func TestIndexReaderMisc(t *testing.T) {
folder := createTestIndex("a", "b", "c")
reader, _ := OpenIndexReader(folder, nil, nil)
if segReaders := reader.SegReaders(); len(segReaders) != 1 {
t.Errorf("SegReaders: %#v", segReaders)
}
if offsets := reader.Offsets(); offsets[0] != 0 {
t.Errorf("Offsets: %#v", offsets)
}
if got, err := reader.Obtain("Lucy::Index::DocReader"); got == nil || err != nil {
t.Errorf("Obtain should succeed for DocReader: %#v, %v", got, err)
}
if got, err := reader.Obtain("Nope"); got != nil || err == nil {
t.Errorf("Obtain should fail for non-existent API name: %v", err)
}
if got := reader.Fetch("Lucy::Index::DocReader"); got == nil {
t.Errorf("Fetch should succeed for DocReader")
}
if got := reader.Fetch("Nope"); got != nil {
t.Errorf("Fetch should return nil for non-existent API name: %v", got)
}
if got := reader.DocMax(); got != 3 {
t.Errorf("DocMax: %d", got);
}
if got := reader.DocCount(); got != 3 {
t.Errorf("DocCount: %d", got);
}
if got := reader.DelCount(); got != 0 {
t.Errorf("DelCount: %d", got);
}
runDataReaderCommon(t, reader, false)
}
func TestIndexReaderOpen(t *testing.T) {
folder := createTestIndex("a", "b", "c")
if got, err := OpenIndexReader(folder, nil, nil); got == nil || err != nil {
t.Errorf("nil Snapshot and IndexManager: %v", err)
}
snapshot := NewSnapshot()
snapshot.ReadFile(folder, "")
if got, err := OpenIndexReader(folder, snapshot, nil); got == nil || err != nil {
t.Errorf("With Snapshot: %v", err)
}
manager := NewIndexManager("", nil)
manager.SetFolder(folder)
if got, err := OpenIndexReader(folder, nil, manager); got == nil || err != nil {
t.Errorf("With IndexManager: %v", err)
}
if got, err := OpenIndexReader("no-index-here", nil, nil); got != nil || err == nil {
t.Errorf("Non-existent index path")
}
}
func TestDefaultDocReaderMisc(t *testing.T) {
folder := createTestIndex("a", "b", "c")
ixReader, _ := OpenIndexReader(folder, nil, nil)
segReaders := ixReader.SegReaders()
reader := segReaders[0].Fetch("Lucy::Index::DocReader").(DefaultDocReader)
doc := make(map[string]interface{})
if err := reader.ReadDoc(2, doc); err != nil {
t.Errorf("ReadDoc: %v", err)
}
runDataReaderCommon(t, reader, true)
}
func TestPolyDocReaderMisc(t *testing.T) {
folder := createTestIndex("a", "b", "c")
ixReader, _ := OpenIndexReader(folder, nil, nil)
reader := ixReader.Fetch("Lucy::Index::DocReader").(PolyDocReader)
doc := make(map[string]interface{})
if err := reader.ReadDoc(2, doc); err != nil {
t.Errorf("ReadDoc: %v", err)
}
runDataReaderCommon(t, reader, true)
}
func TestLexReaderMisc(t *testing.T) {
folder := createTestIndex("a", "b", "c")
ixReader, _ := OpenIndexReader(folder, nil, nil)
segReaders := ixReader.SegReaders()
lexReader := segReaders[0].Fetch("Lucy::Index::LexiconReader").(LexiconReader)
if got, err := lexReader.Lexicon("content", nil); got == nil || err != nil {
t.Errorf("Lexicon should succeed: %v", err)
}
if got, err := lexReader.Lexicon("content", "foo"); got == nil || err != nil {
t.Errorf("Lexicon with term should succeed: %v", err)
}
if got, err := lexReader.Lexicon("nope", nil); got != nil || err != nil {
t.Errorf("Lexicon for non-field should return nil: %v", err)
}
if got, err := lexReader.DocFreq("content", "b"); got != 1 || err != nil {
t.Errorf("DocFreq: %d, %v", got, err)
}
if got, err := lexReader.DocFreq("content", "nope"); got != 0 || err != nil {
t.Errorf("DocFreq should be 0: %d, %v", got, err)
}
if got, err := lexReader.fetchTermInfo("content", "a"); got == nil || err != nil {
t.Errorf("fetchTermInfo should succeed: %v", err)
}
if got, err := lexReader.fetchTermInfo("content", "nope"); got != nil || err != nil {
t.Errorf("fetchTermInfo with non-existent term should return nil: %v", err)
}
runDataReaderCommon(t, lexReader, false)
}
func TestPostingListReaderMisc(t *testing.T) {
folder := createTestIndex("a", "b", "c")
ixReader, _ := OpenIndexReader(folder, nil, nil)
segReaders := ixReader.SegReaders()
pListReader := segReaders[0].Fetch("Lucy::Index::PostingListReader").(PostingListReader)
if got, err := pListReader.PostingList("content", nil); got == nil || err != nil {
t.Errorf("PostingList should succeed: %v", err)
}
if got, err := pListReader.PostingList("content", "foo"); got == nil || err != nil {
t.Errorf("PostingList with term should succeed: %v", err)
}
if got, err := pListReader.PostingList("nope", nil); got != nil || err != nil {
t.Errorf("PostingList for non-field should return nil: %v", err)
}
runDataReaderCommon(t, pListReader, false)
}
func TestHighlightReaderMisc(t *testing.T) {
folder := createTestIndex("a", "b", "c")
ixReader, _ := OpenIndexReader(folder, nil, nil)
segReaders := ixReader.SegReaders()
reader := segReaders[0].Fetch("Lucy::Index::HighlightReader").(HighlightReader)
if got, err := reader.FetchDocVec(2); got == nil || err != nil {
t.Errorf("FetchDocVec: %v", err)
}
if got, err := reader.FetchDocVec(4); got != nil || err == nil {
t.Errorf("FetchDocVec catch error: %#v", got)
}
runDataReaderCommon(t, reader, true)
}
func TestDeletionsReaderMisc(t *testing.T) {
folder := createTestIndex("a", "b", "c")
ixReader, _ := OpenIndexReader(folder, nil, nil)
segReaders := ixReader.SegReaders()
delReader := segReaders[0].Fetch("Lucy::Index::DeletionsReader").(DeletionsReader)
if count := delReader.delCount(); count != 0 {
t.Errorf("delCount: %d", count);
}
if matcher := delReader.iterator(); matcher == nil {
t.Errorf("iterator: %#v", matcher)
}
runDataReaderCommon(t, delReader, true)
}
func TestSortReaderMisc(t *testing.T) {
folder := createTestIndex("a", "b", "c")
ixReader, _ := OpenIndexReader(folder, nil, nil)
segReaders := ixReader.SegReaders()
sortReader := segReaders[0].Fetch("Lucy::Index::SortReader").(SortReader)
if got, err := sortReader.fetchSortCache("content"); got == nil || err != nil {
t.Errorf("fetchSortCache should succeed: %v", err)
}
if got, err := sortReader.fetchSortCache("nope"); got != nil || err != nil {
t.Errorf("fetchSortCache for non-field should return nil: %v", err)
}
runDataReaderCommon(t, sortReader, false)
}
func runDataWriterCommon(t *testing.T, api string) {
abcIndex := createTestIndex("a", "b", "c")
indexer, _ := OpenIndexer(&OpenIndexerArgs{Index: abcIndex})
dataWriter := indexer.getSegWriter().Fetch(api).(DataWriter)
if got := dataWriter.GetSnapshot(); false {
t.Errorf("GetSnapshot: %v", got)
}
if got := dataWriter.GetSegment(); false {
t.Errorf("GetSegment: %#v", got)
}
if got := dataWriter.GetPolyReader(); false {
t.Errorf("GetPolyReader: %#v", got)
}
if got := dataWriter.GetSchema(); false {
t.Errorf("GetSchema: %v", got)
}
if got := dataWriter.GetFolder(); false {
t.Errorf("GetFolder: %v", got)
}
doc := NewDoc(1)
doc.Store("content", "three blind mice")
inverter := NewInverter(dataWriter.GetSchema(), dataWriter.GetSegment())
inverter.SetDoc(doc)
inverter.InvertDoc(doc)
if err := dataWriter.addInvertedDoc(inverter, 1); err != nil {
t.Errorf("addInvertedDoc: %v", err)
}
segReaders := indexer.getSegWriter().GetPolyReader().SegReaders()
abcSegReader := segReaders[0]
if err := dataWriter.MergeSegment(abcSegReader, []int32{0, 2, 0, 3}); err != nil {
t.Errorf("MergeSegment: %v", err)
}
// TODO
//if err := dataWriter.DeleteSegment(fooSegReader); err != nil {
// t.Errorf("DeleteSegment: %v", err)
//}
xyzIndex := createTestIndex("x", "y", "z")
xyzReader, _ := OpenIndexReader(xyzIndex, nil, nil)
xyzSegReaders := xyzReader.SegReaders()
if err := dataWriter.AddSegment(xyzSegReaders[0], []int32{0, 4, 5, 6}); err != nil {
t.Errorf("AddSegment: %v", err)
}
if err := dataWriter.Finish(); err != nil {
t.Errorf("Finish: %v", err)
}
}
// TODO
//func TestSortWriterMisc(t *testing.T) {
// runDataWriterCommon(t, "Lucy::Index::SortWriter")
//}
func TestDeletionsWriterMisc(t *testing.T) {
index := createTestIndex("a", "b", "c")
indexer, _ := OpenIndexer(&OpenIndexerArgs{Index: index})
delWriter := indexer.getSegWriter().Fetch("Lucy::Index::DeletionsWriter").(DeletionsWriter)
if delWriter.Updated() {
t.Errorf("Not yet updated")
}
if err := delWriter.DeleteByTerm("content", "a"); err != nil {
t.Errorf("DeleteByTerm: %v", err)
}
if err := delWriter.DeleteByQuery(NewTermQuery("content", "b")); err != nil {
t.Errorf("DeleteByQuery: %v", err)
}
if err := delWriter.deleteByDocID(3); err != nil {
t.Errorf("deleteByDocID: %v", err)
}
if !delWriter.Updated() {
t.Errorf("Now we're updated")
}
if got := delWriter.SegDelCount("seg_1"); got != 3 {
t.Errorf("SegDelCount: %d", got)
}
segReaders := delWriter.GetPolyReader().SegReaders()
if dels, err := delWriter.segDeletions(segReaders[0]); dels == nil || err != nil {
t.Errorf("segDeletions: %v", err)
}
}
func TestSegWriterMisc(t *testing.T) {
index := createTestIndex("a", "b", "c")
ixReader, _ := OpenIndexReader(index, nil, nil)
polyReader := ixReader.(PolyReader)
schema := polyReader.GetSchema()
segment := NewSegment(2)
snapshot := polyReader.GetSnapshot()
segWriter := NewSegWriter(schema, snapshot, segment, polyReader)
if err := segWriter.PrepSegDir(); err != nil {
t.Errorf("PrepSegDir: %v", err)
}
doc := NewDoc(1)
if err := segWriter.AddDoc(doc, 1.0); err != nil {
t.Errorf("AddDoc: %v", err)
}
}