blob: e83df9c78597716a4be119a84385c1d843eab49d [file] [log] [blame]
using J2N.Runtime.CompilerServices;
using Lucene.Net.Index;
using Lucene.Net.Index.Extensions;
using Lucene.Net.Util;
using NUnit.Framework;
using RandomizedTesting.Generators;
using System;
using System.Collections.Generic;
using Assert = Lucene.Net.TestFramework.Assert;
using JCG = J2N.Collections.Generic;
namespace Lucene.Net.Codecs.Lucene40
{
/*
* 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.
*/
using AtomicReader = Lucene.Net.Index.AtomicReader;
using AtomicReaderContext = Lucene.Net.Index.AtomicReaderContext;
using BytesRef = Lucene.Net.Util.BytesRef;
using Directory = Lucene.Net.Store.Directory;
using DirectoryReader = Lucene.Net.Index.DirectoryReader;
using DocsEnum = Lucene.Net.Index.DocsEnum;
using IBits = Lucene.Net.Util.IBits;
using IndexWriter = Lucene.Net.Index.IndexWriter;
using IOUtils = Lucene.Net.Util.IOUtils;
using LineFileDocs = Lucene.Net.Util.LineFileDocs;
using LuceneTestCase = Lucene.Net.Util.LuceneTestCase;
using MatchNoBits = Lucene.Net.Util.Bits.MatchNoBits;
using MockAnalyzer = Lucene.Net.Analysis.MockAnalyzer;
using RandomIndexWriter = Lucene.Net.Index.RandomIndexWriter;
using Terms = Lucene.Net.Index.Terms;
using TermsEnum = Lucene.Net.Index.TermsEnum;
using TestUtil = Lucene.Net.Util.TestUtil;
// TODO: really this should be in BaseTestPF or somewhere else? useful test!
// LUCENENET specific - Specify to unzip the line file docs
[UseTempLineDocsFile]
public class TestReuseDocsEnum : LuceneTestCase
{
[OneTimeSetUp]
public override void OneTimeSetUp()
{
base.OneTimeSetUp();
OldFormatImpersonationIsActive = true; // explicitly instantiates ancient codec
}
[Test]
public virtual void TestReuseDocsEnumNoReuse()
{
Directory dir = NewDirectory();
Codec cp = TestUtil.AlwaysPostingsFormat(new Lucene40RWPostingsFormat());
RandomIndexWriter writer = new RandomIndexWriter(Random, dir,
NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random)).SetCodec(cp));
int numdocs = AtLeast(20);
CreateRandomIndex(numdocs, writer, Random);
writer.Commit();
DirectoryReader open = DirectoryReader.Open(dir);
foreach (AtomicReaderContext ctx in open.Leaves)
{
AtomicReader indexReader = (AtomicReader)ctx.Reader;
Terms terms = indexReader.GetTerms("body");
TermsEnum iterator = terms.GetEnumerator();
IDictionary<DocsEnum, bool> enums = new JCG.Dictionary<DocsEnum, bool>(IdentityEqualityComparer<DocsEnum>.Default);
MatchNoBits bits = new MatchNoBits(indexReader.MaxDoc);
while (iterator.MoveNext())
{
DocsEnum docs = iterator.Docs(Random.NextBoolean() ? bits : new MatchNoBits(indexReader.MaxDoc), null, Random.NextBoolean() ? DocsFlags.FREQS : DocsFlags.NONE);
enums[docs] = true;
}
Assert.AreEqual(terms.Count, enums.Count);
}
IOUtils.Dispose(writer, open, dir);
}
// tests for reuse only if bits are the same either null or the same instance
[Test]
public virtual void TestReuseDocsEnumSameBitsOrNull()
{
Directory dir = NewDirectory();
Codec cp = TestUtil.AlwaysPostingsFormat(new Lucene40RWPostingsFormat());
RandomIndexWriter writer = new RandomIndexWriter(Random, dir,
NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random)).SetCodec(cp));
int numdocs = AtLeast(20);
CreateRandomIndex(numdocs, writer, Random);
writer.Commit();
DirectoryReader open = DirectoryReader.Open(dir);
foreach (AtomicReaderContext ctx in open.Leaves)
{
Terms terms = ((AtomicReader)ctx.Reader).GetTerms("body");
TermsEnum iterator = terms.GetEnumerator();
IDictionary<DocsEnum, bool> enums = new JCG.Dictionary<DocsEnum, bool>(IdentityEqualityComparer<DocsEnum>.Default);
MatchNoBits bits = new MatchNoBits(open.MaxDoc);
DocsEnum docs = null;
while (iterator.MoveNext())
{
docs = iterator.Docs(bits, docs, Random.NextBoolean() ? DocsFlags.FREQS : DocsFlags.NONE);
enums[docs] = true;
}
Assert.AreEqual(1, enums.Count);
enums.Clear();
iterator = terms.GetEnumerator();
docs = null;
while (iterator.MoveNext())
{
docs = iterator.Docs(new MatchNoBits(open.MaxDoc), docs, Random.NextBoolean() ? DocsFlags.FREQS : DocsFlags.NONE);
enums[docs] = true;
}
Assert.AreEqual(terms.Count, enums.Count);
enums.Clear();
iterator = terms.GetEnumerator();
docs = null;
while (iterator.MoveNext())
{
docs = iterator.Docs(null, docs, Random.NextBoolean() ? DocsFlags.FREQS : DocsFlags.NONE);
enums[docs] = true;
}
Assert.AreEqual(1, enums.Count);
}
IOUtils.Dispose(writer, open, dir);
}
// make sure we never reuse from another reader even if it is the same field & codec etc
[Test]
public virtual void TestReuseDocsEnumDifferentReader()
{
Directory dir = NewDirectory();
Codec cp = TestUtil.AlwaysPostingsFormat(new Lucene40RWPostingsFormat());
MockAnalyzer analyzer = new MockAnalyzer(Random);
analyzer.MaxTokenLength = TestUtil.NextInt32(Random, 1, IndexWriter.MAX_TERM_LENGTH);
RandomIndexWriter writer = new RandomIndexWriter(Random, dir, NewIndexWriterConfig(TEST_VERSION_CURRENT, analyzer).SetCodec(cp));
int numdocs = AtLeast(20);
CreateRandomIndex(numdocs, writer, Random);
writer.Commit();
DirectoryReader firstReader = DirectoryReader.Open(dir);
DirectoryReader secondReader = DirectoryReader.Open(dir);
IList<AtomicReaderContext> leaves = firstReader.Leaves;
IList<AtomicReaderContext> leaves2 = secondReader.Leaves;
foreach (AtomicReaderContext ctx in leaves)
{
Terms terms = ((AtomicReader)ctx.Reader).GetTerms("body");
TermsEnum iterator = terms.GetEnumerator();
IDictionary<DocsEnum, bool> enums = new JCG.Dictionary<DocsEnum, bool>(IdentityEqualityComparer<DocsEnum>.Default);
MatchNoBits bits = new MatchNoBits(firstReader.MaxDoc);
iterator = terms.GetEnumerator();
DocsEnum docs = null;
BytesRef term = null;
while (iterator.MoveNext())
{
term = iterator.Term;
docs = iterator.Docs(null, RandomDocsEnum("body", term, leaves2, bits), Random.NextBoolean() ? DocsFlags.FREQS : DocsFlags.NONE);
enums[docs] = true;
}
Assert.AreEqual(terms.Count, enums.Count);
iterator = terms.GetEnumerator();
enums.Clear();
docs = null;
while (iterator.MoveNext())
{
term = iterator.Term;
docs = iterator.Docs(bits, RandomDocsEnum("body", term, leaves2, bits), Random.NextBoolean() ? DocsFlags.FREQS : DocsFlags.NONE);
enums[docs] = true;
}
Assert.AreEqual(terms.Count, enums.Count);
}
IOUtils.Dispose(writer, firstReader, secondReader, dir);
}
// LUCENENET specific - made static
public static DocsEnum RandomDocsEnum(string field, BytesRef term, IList<AtomicReaderContext> readers, IBits bits)
{
if (Random.Next(10) == 0)
{
return null;
}
AtomicReader indexReader = (AtomicReader)readers[Random.Next(readers.Count)].Reader;
Terms terms = indexReader.GetTerms(field);
if (terms is null)
{
return null;
}
TermsEnum iterator = terms.GetEnumerator();
if (iterator.SeekExact(term))
{
return iterator.Docs(bits, null, Random.NextBoolean() ? DocsFlags.FREQS : DocsFlags.NONE);
}
return null;
}
/// <summary>
/// populates a writer with random stuff. this must be fully reproducable with
/// the seed!
/// </summary>
public static void CreateRandomIndex(int numdocs, RandomIndexWriter writer, Random random)
{
LineFileDocs lineFileDocs = new LineFileDocs(random);
for (int i = 0; i < numdocs; i++)
{
writer.AddDocument(lineFileDocs.NextDoc());
}
lineFileDocs.Dispose();
}
}
}