You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucenenet.apache.org by ni...@apache.org on 2017/02/26 23:37:25 UTC
[37/72] [abbrv] [partial] lucenenet git commit: Lucene.Net.Tests:
Removed \core directory and put its contents in root directory
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/96822396/src/Lucene.Net.Tests/Index/TestDirectoryReader.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/Index/TestDirectoryReader.cs b/src/Lucene.Net.Tests/Index/TestDirectoryReader.cs
new file mode 100644
index 0000000..14fea69
--- /dev/null
+++ b/src/Lucene.Net.Tests/Index/TestDirectoryReader.cs
@@ -0,0 +1,1341 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Threading;
+using Lucene.Net.Documents;
+using Lucene.Net.Search;
+
+namespace Lucene.Net.Index
+{
+ using Attributes;
+ using Lucene.Net.Support;
+ using NUnit.Framework;
+ using IBits = Lucene.Net.Util.IBits;
+ using BytesRef = Lucene.Net.Util.BytesRef;
+ using Directory = Lucene.Net.Store.Directory;
+ using DocIdSetIterator = Lucene.Net.Search.DocIdSetIterator;
+ using Document = Documents.Document;
+ using Field = Field;
+ using FieldType = FieldType;
+ using Lucene41PostingsFormat = Lucene.Net.Codecs.Lucene41.Lucene41PostingsFormat;
+ using LuceneTestCase = Lucene.Net.Util.LuceneTestCase;
+
+ /*
+ * 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 MockAnalyzer = Lucene.Net.Analysis.MockAnalyzer;
+ using NoSuchDirectoryException = Lucene.Net.Store.NoSuchDirectoryException;
+ using StoredField = StoredField;
+ using StringField = StringField;
+ using TestUtil = Lucene.Net.Util.TestUtil;
+ using TextField = TextField;
+
+ [TestFixture]
+ public class TestDirectoryReader : LuceneTestCase
+ {
+ [Test]
+ public virtual void TestDocument()
+ {
+ SegmentReader[] readers = new SegmentReader[2];
+ Directory dir = NewDirectory();
+ Document doc1 = new Document();
+ Document doc2 = new Document();
+ DocHelper.SetupDoc(doc1);
+ DocHelper.SetupDoc(doc2);
+ DocHelper.WriteDoc(Random(), dir, doc1);
+ DocHelper.WriteDoc(Random(), dir, doc2);
+ DirectoryReader reader = DirectoryReader.Open(dir);
+ Assert.IsTrue(reader != null);
+ Assert.IsTrue(reader is StandardDirectoryReader);
+
+ Document newDoc1 = reader.Document(0);
+ Assert.IsTrue(newDoc1 != null);
+ Assert.IsTrue(DocHelper.NumFields(newDoc1) == DocHelper.NumFields(doc1) - DocHelper.Unstored.Count);
+ Document newDoc2 = reader.Document(1);
+ Assert.IsTrue(newDoc2 != null);
+ Assert.IsTrue(DocHelper.NumFields(newDoc2) == DocHelper.NumFields(doc2) - DocHelper.Unstored.Count);
+ Terms vector = reader.GetTermVectors(0).GetTerms(DocHelper.TEXT_FIELD_2_KEY);
+ Assert.IsNotNull(vector);
+
+ reader.Dispose();
+ if (readers[0] != null)
+ {
+ readers[0].Dispose();
+ }
+ if (readers[1] != null)
+ {
+ readers[1].Dispose();
+ }
+ dir.Dispose();
+ }
+
+ [Test]
+ public virtual void TestMultiTermDocs()
+ {
+ Directory ramDir1 = NewDirectory();
+ AddDoc(Random(), ramDir1, "test foo", true);
+ Directory ramDir2 = NewDirectory();
+ AddDoc(Random(), ramDir2, "test blah", true);
+ Directory ramDir3 = NewDirectory();
+ AddDoc(Random(), ramDir3, "test wow", true);
+
+ IndexReader[] readers1 = new IndexReader[] { DirectoryReader.Open(ramDir1), DirectoryReader.Open(ramDir3) };
+ IndexReader[] readers2 = new IndexReader[] { DirectoryReader.Open(ramDir1), DirectoryReader.Open(ramDir2), DirectoryReader.Open(ramDir3) };
+ MultiReader mr2 = new MultiReader(readers1);
+ MultiReader mr3 = new MultiReader(readers2);
+
+ // test mixing up TermDocs and TermEnums from different readers.
+ TermsEnum te2 = MultiFields.GetTerms(mr2, "body").GetIterator(null);
+ te2.SeekCeil(new BytesRef("wow"));
+ DocsEnum td = TestUtil.Docs(Random(), mr2, "body", te2.Term, MultiFields.GetLiveDocs(mr2), null, 0);
+
+ TermsEnum te3 = MultiFields.GetTerms(mr3, "body").GetIterator(null);
+ te3.SeekCeil(new BytesRef("wow"));
+ td = TestUtil.Docs(Random(), te3, MultiFields.GetLiveDocs(mr3), td, 0);
+
+ int ret = 0;
+
+ // this should blow up if we forget to check that the TermEnum is from the same
+ // reader as the TermDocs.
+ while (td.NextDoc() != DocIdSetIterator.NO_MORE_DOCS)
+ {
+ ret += td.DocID;
+ }
+
+ // really a dummy assert to ensure that we got some docs and to ensure that
+ // nothing is eliminated by hotspot
+ Assert.IsTrue(ret > 0);
+ readers1[0].Dispose();
+ readers1[1].Dispose();
+ readers2[0].Dispose();
+ readers2[1].Dispose();
+ readers2[2].Dispose();
+ ramDir1.Dispose();
+ ramDir2.Dispose();
+ ramDir3.Dispose();
+ }
+
+ private void AddDoc(Random random, Directory ramDir1, string s, bool create)
+ {
+ IndexWriter iw = new IndexWriter(ramDir1, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).SetOpenMode(create ? OpenMode.CREATE : OpenMode.APPEND));
+ Document doc = new Document();
+ doc.Add(NewTextField("body", s, Field.Store.NO));
+ iw.AddDocument(doc);
+ iw.Dispose();
+ }
+
+ [Test]
+ public virtual void TestIsCurrent()
+ {
+ Directory d = NewDirectory();
+ IndexWriter writer = new IndexWriter(d, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
+ AddDocumentWithFields(writer);
+ writer.Dispose();
+ // set up reader:
+ DirectoryReader reader = DirectoryReader.Open(d);
+ Assert.IsTrue(reader.IsCurrent);
+ // modify index by adding another document:
+ writer = new IndexWriter(d, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())).SetOpenMode(OpenMode.APPEND));
+ AddDocumentWithFields(writer);
+ writer.Dispose();
+ Assert.IsFalse(reader.IsCurrent);
+ // re-create index:
+ writer = new IndexWriter(d, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())).SetOpenMode(OpenMode.CREATE));
+ AddDocumentWithFields(writer);
+ writer.Dispose();
+ Assert.IsFalse(reader.IsCurrent);
+ reader.Dispose();
+ d.Dispose();
+ }
+
+ /// <summary>
+ /// Tests the IndexReader.getFieldNames implementation </summary>
+ /// <exception cref="Exception"> on error </exception>
+ [Test]
+ public virtual void TestGetFieldNames()
+ {
+ Directory d = NewDirectory();
+ // set up writer
+ IndexWriter writer = new IndexWriter(d, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
+
+ Document doc = new Document();
+
+ FieldType customType3 = new FieldType();
+ customType3.IsStored = true;
+
+ doc.Add(new StringField("keyword", "test1", Field.Store.YES));
+ doc.Add(new TextField("text", "test1", Field.Store.YES));
+ doc.Add(new Field("unindexed", "test1", customType3));
+ doc.Add(new TextField("unstored", "test1", Field.Store.NO));
+ writer.AddDocument(doc);
+
+ writer.Dispose();
+ // set up reader
+ DirectoryReader reader = DirectoryReader.Open(d);
+ FieldInfos fieldInfos = MultiFields.GetMergedFieldInfos(reader);
+ Assert.IsNotNull(fieldInfos.FieldInfo("keyword"));
+ Assert.IsNotNull(fieldInfos.FieldInfo("text"));
+ Assert.IsNotNull(fieldInfos.FieldInfo("unindexed"));
+ Assert.IsNotNull(fieldInfos.FieldInfo("unstored"));
+ reader.Dispose();
+ // add more documents
+ writer = new IndexWriter(d, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())).SetOpenMode(OpenMode.APPEND).SetMergePolicy(NewLogMergePolicy()));
+ // want to get some more segments here
+ int mergeFactor = ((LogMergePolicy)writer.Config.MergePolicy).MergeFactor;
+ for (int i = 0; i < 5 * mergeFactor; i++)
+ {
+ doc = new Document();
+ doc.Add(new StringField("keyword", "test1", Field.Store.YES));
+ doc.Add(new TextField("text", "test1", Field.Store.YES));
+ doc.Add(new Field("unindexed", "test1", customType3));
+ doc.Add(new TextField("unstored", "test1", Field.Store.NO));
+ writer.AddDocument(doc);
+ }
+ // new fields are in some different segments (we hope)
+ for (int i = 0; i < 5 * mergeFactor; i++)
+ {
+ doc = new Document();
+ doc.Add(new StringField("keyword2", "test1", Field.Store.YES));
+ doc.Add(new TextField("text2", "test1", Field.Store.YES));
+ doc.Add(new Field("unindexed2", "test1", customType3));
+ doc.Add(new TextField("unstored2", "test1", Field.Store.NO));
+ writer.AddDocument(doc);
+ }
+ // new termvector fields
+
+ FieldType customType5 = new FieldType(TextField.TYPE_STORED);
+ customType5.StoreTermVectors = true;
+ FieldType customType6 = new FieldType(TextField.TYPE_STORED);
+ customType6.StoreTermVectors = true;
+ customType6.StoreTermVectorOffsets = true;
+ FieldType customType7 = new FieldType(TextField.TYPE_STORED);
+ customType7.StoreTermVectors = true;
+ customType7.StoreTermVectorPositions = true;
+ FieldType customType8 = new FieldType(TextField.TYPE_STORED);
+ customType8.StoreTermVectors = true;
+ customType8.StoreTermVectorOffsets = true;
+ customType8.StoreTermVectorPositions = true;
+
+ for (int i = 0; i < 5 * mergeFactor; i++)
+ {
+ doc = new Document();
+ doc.Add(new TextField("tvnot", "tvnot", Field.Store.YES));
+ doc.Add(new Field("termvector", "termvector", customType5));
+ doc.Add(new Field("tvoffset", "tvoffset", customType6));
+ doc.Add(new Field("tvposition", "tvposition", customType7));
+ doc.Add(new Field("tvpositionoffset", "tvpositionoffset", customType8));
+ writer.AddDocument(doc);
+ }
+
+ writer.Dispose();
+
+ // verify fields again
+ reader = DirectoryReader.Open(d);
+ fieldInfos = MultiFields.GetMergedFieldInfos(reader);
+
+ ICollection<string> allFieldNames = new HashSet<string>();
+ ICollection<string> indexedFieldNames = new HashSet<string>();
+ ICollection<string> notIndexedFieldNames = new HashSet<string>();
+ ICollection<string> tvFieldNames = new HashSet<string>();
+
+ foreach (FieldInfo fieldInfo in fieldInfos)
+ {
+ string name = fieldInfo.Name;
+ allFieldNames.Add(name);
+ if (fieldInfo.IsIndexed)
+ {
+ indexedFieldNames.Add(name);
+ }
+ else
+ {
+ notIndexedFieldNames.Add(name);
+ }
+ if (fieldInfo.HasVectors)
+ {
+ tvFieldNames.Add(name);
+ }
+ }
+
+ Assert.IsTrue(allFieldNames.Contains("keyword"));
+ Assert.IsTrue(allFieldNames.Contains("text"));
+ Assert.IsTrue(allFieldNames.Contains("unindexed"));
+ Assert.IsTrue(allFieldNames.Contains("unstored"));
+ Assert.IsTrue(allFieldNames.Contains("keyword2"));
+ Assert.IsTrue(allFieldNames.Contains("text2"));
+ Assert.IsTrue(allFieldNames.Contains("unindexed2"));
+ Assert.IsTrue(allFieldNames.Contains("unstored2"));
+ Assert.IsTrue(allFieldNames.Contains("tvnot"));
+ Assert.IsTrue(allFieldNames.Contains("termvector"));
+ Assert.IsTrue(allFieldNames.Contains("tvposition"));
+ Assert.IsTrue(allFieldNames.Contains("tvoffset"));
+ Assert.IsTrue(allFieldNames.Contains("tvpositionoffset"));
+
+ // verify that only indexed fields were returned
+ Assert.AreEqual(11, indexedFieldNames.Count); // 6 original + the 5 termvector fields
+ Assert.IsTrue(indexedFieldNames.Contains("keyword"));
+ Assert.IsTrue(indexedFieldNames.Contains("text"));
+ Assert.IsTrue(indexedFieldNames.Contains("unstored"));
+ Assert.IsTrue(indexedFieldNames.Contains("keyword2"));
+ Assert.IsTrue(indexedFieldNames.Contains("text2"));
+ Assert.IsTrue(indexedFieldNames.Contains("unstored2"));
+ Assert.IsTrue(indexedFieldNames.Contains("tvnot"));
+ Assert.IsTrue(indexedFieldNames.Contains("termvector"));
+ Assert.IsTrue(indexedFieldNames.Contains("tvposition"));
+ Assert.IsTrue(indexedFieldNames.Contains("tvoffset"));
+ Assert.IsTrue(indexedFieldNames.Contains("tvpositionoffset"));
+
+ // verify that only unindexed fields were returned
+ Assert.AreEqual(2, notIndexedFieldNames.Count); // the following fields
+ Assert.IsTrue(notIndexedFieldNames.Contains("unindexed"));
+ Assert.IsTrue(notIndexedFieldNames.Contains("unindexed2"));
+
+ // verify index term vector fields
+ Assert.AreEqual(4, tvFieldNames.Count, tvFieldNames.ToString()); // 4 field has term vector only
+ Assert.IsTrue(tvFieldNames.Contains("termvector"));
+
+ reader.Dispose();
+ d.Dispose();
+ }
+
+#if !NETSTANDARD
+ // LUCENENET: There is no Timeout on NUnit for .NET Core.
+ [Timeout(40000)]
+#endif
+ [Test, HasTimeout]
+ public virtual void TestTermVectors()
+ {
+ Directory d = NewDirectory();
+ // set up writer
+ IndexWriter writer = new IndexWriter(d, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())).SetMergePolicy(NewLogMergePolicy()));
+ // want to get some more segments here
+ // new termvector fields
+ int mergeFactor = ((LogMergePolicy)writer.Config.MergePolicy).MergeFactor;
+ FieldType customType5 = new FieldType(TextField.TYPE_STORED);
+ customType5.StoreTermVectors = true;
+ FieldType customType6 = new FieldType(TextField.TYPE_STORED);
+ customType6.StoreTermVectors = true;
+ customType6.StoreTermVectorOffsets = true;
+ FieldType customType7 = new FieldType(TextField.TYPE_STORED);
+ customType7.StoreTermVectors = true;
+ customType7.StoreTermVectorPositions = true;
+ FieldType customType8 = new FieldType(TextField.TYPE_STORED);
+ customType8.StoreTermVectors = true;
+ customType8.StoreTermVectorOffsets = true;
+ customType8.StoreTermVectorPositions = true;
+ for (int i = 0; i < 5 * mergeFactor; i++)
+ {
+ Document doc = new Document();
+ doc.Add(new TextField("tvnot", "one two two three three three", Field.Store.YES));
+ doc.Add(new Field("termvector", "one two two three three three", customType5));
+ doc.Add(new Field("tvoffset", "one two two three three three", customType6));
+ doc.Add(new Field("tvposition", "one two two three three three", customType7));
+ doc.Add(new Field("tvpositionoffset", "one two two three three three", customType8));
+
+ writer.AddDocument(doc);
+ }
+ writer.Dispose();
+ d.Dispose();
+ }
+
+ internal virtual void AssertTermDocsCount(string msg, IndexReader reader, Term term, int expected)
+ {
+ DocsEnum tdocs = TestUtil.Docs(Random(), reader, term.Field, new BytesRef(term.Text()), MultiFields.GetLiveDocs(reader), null, 0);
+ int count = 0;
+ if (tdocs != null)
+ {
+ while (tdocs.NextDoc() != DocIdSetIterator.NO_MORE_DOCS)
+ {
+ count++;
+ }
+ }
+ Assert.AreEqual(expected, count, msg + ", count mismatch");
+ }
+
+ [Test]
+ public virtual void TestBinaryFields()
+ {
+ Directory dir = NewDirectory();
+ byte[] bin = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+
+ IndexWriter writer = new IndexWriter(dir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())).SetMergePolicy(NewLogMergePolicy()));
+
+ for (int i = 0; i < 10; i++)
+ {
+ AddDoc(writer, "document number " + (i + 1));
+ AddDocumentWithFields(writer);
+ AddDocumentWithDifferentFields(writer);
+ AddDocumentWithTermVectorFields(writer);
+ }
+ writer.Dispose();
+ writer = new IndexWriter(dir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())).SetOpenMode(OpenMode.APPEND).SetMergePolicy(NewLogMergePolicy()));
+ Document doc = new Document();
+ doc.Add(new StoredField("bin1", bin));
+ doc.Add(new TextField("junk", "junk text", Field.Store.NO));
+ writer.AddDocument(doc);
+ writer.Dispose();
+ DirectoryReader reader = DirectoryReader.Open(dir);
+ Document doc2 = reader.Document(reader.MaxDoc - 1);
+ IIndexableField[] fields = doc2.GetFields("bin1");
+ Assert.IsNotNull(fields);
+ Assert.AreEqual(1, fields.Length);
+ IIndexableField b1 = fields[0];
+ Assert.IsTrue(b1.GetBinaryValue() != null);
+ BytesRef bytesRef = b1.GetBinaryValue();
+ Assert.AreEqual(bin.Length, bytesRef.Length);
+ for (int i = 0; i < bin.Length; i++)
+ {
+ Assert.AreEqual(bin[i], bytesRef.Bytes[i + bytesRef.Offset]);
+ }
+ reader.Dispose();
+ // force merge
+
+ writer = new IndexWriter(dir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())).SetOpenMode(OpenMode.APPEND).SetMergePolicy(NewLogMergePolicy()));
+ writer.ForceMerge(1);
+ writer.Dispose();
+ reader = DirectoryReader.Open(dir);
+ doc2 = reader.Document(reader.MaxDoc - 1);
+ fields = doc2.GetFields("bin1");
+ Assert.IsNotNull(fields);
+ Assert.AreEqual(1, fields.Length);
+ b1 = fields[0];
+ Assert.IsTrue(b1.GetBinaryValue() != null);
+ bytesRef = b1.GetBinaryValue();
+ Assert.AreEqual(bin.Length, bytesRef.Length);
+ for (int i = 0; i < bin.Length; i++)
+ {
+ Assert.AreEqual(bin[i], bytesRef.Bytes[i + bytesRef.Offset]);
+ }
+ reader.Dispose();
+ dir.Dispose();
+ }
+
+ /* ??? public void testOpenEmptyDirectory() throws IOException{
+ String dirName = "test.empty";
+ File fileDirName = new File(dirName);
+ if (!fileDirName.exists()) {
+ fileDirName.mkdir();
+ }
+ try {
+ DirectoryReader.Open(fileDirName);
+ Assert.Fail("opening DirectoryReader on empty directory failed to produce FileNotFoundException/NoSuchFileException");
+ } catch (FileNotFoundException | NoSuchFileException e) {
+ // GOOD
+ }
+ rmDir(fileDirName);
+ }*/
+
+ [Test]
+ public virtual void TestFilesOpenClose()
+ {
+ // Create initial data set
+ DirectoryInfo dirFile = CreateTempDir("TestIndexReader.testFilesOpenClose");
+ Directory dir = NewFSDirectory(dirFile);
+ IndexWriter writer = new IndexWriter(dir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
+ AddDoc(writer, "test");
+ writer.Dispose();
+ dir.Dispose();
+
+ // Try to erase the data - this ensures that the writer closed all files
+ System.IO.Directory.Delete(dirFile.FullName, true);
+ dir = NewFSDirectory(dirFile);
+
+ // Now create the data set again, just as before
+ writer = new IndexWriter(dir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())).SetOpenMode(OpenMode.CREATE));
+ AddDoc(writer, "test");
+ writer.Dispose();
+ dir.Dispose();
+
+ // Now open existing directory and test that reader closes all files
+ dir = NewFSDirectory(dirFile);
+ DirectoryReader reader1 = DirectoryReader.Open(dir);
+ reader1.Dispose();
+ dir.Dispose();
+
+ // The following will fail if reader did not close
+ // all files
+ System.IO.Directory.Delete(dirFile.FullName, true);
+ }
+
+ [Test]
+ public virtual void TestOpenReaderAfterDelete()
+ {
+ DirectoryInfo dirFile = CreateTempDir("deletetest");
+ Directory dir = NewFSDirectory(dirFile);
+ try
+ {
+ DirectoryReader.Open(dir);
+ Assert.Fail("expected FileNotFoundException/NoSuchFileException");
+ }
+#pragma warning disable 168
+ catch (System.IO.FileNotFoundException /*| NoSuchFileException*/ e)
+#pragma warning restore 168
+ {
+ // expected
+ }
+
+ dirFile.Delete();
+
+ // Make sure we still get a CorruptIndexException (not NPE):
+ try
+ {
+ DirectoryReader.Open(dir);
+ Assert.Fail("expected FileNotFoundException/NoSuchFileException");
+ }
+#pragma warning disable 168
+ catch (System.IO.FileNotFoundException /*| NoSuchFileException*/ e)
+#pragma warning restore 168
+ {
+ // expected
+ }
+
+ dir.Dispose();
+ }
+
+ /// <summary>
+ /// LUCENENET specific
+ /// Is non-static because NewStringField, NewTextField, NewField methods
+ /// are no longer static.
+ /// </summary>
+ internal void AddDocumentWithFields(IndexWriter writer)
+ {
+ Document doc = new Document();
+
+ FieldType customType3 = new FieldType();
+ customType3.IsStored = true;
+ doc.Add(NewStringField("keyword", "test1", Field.Store.YES));
+ doc.Add(NewTextField("text", "test1", Field.Store.YES));
+ doc.Add(NewField("unindexed", "test1", customType3));
+ doc.Add(new TextField("unstored", "test1", Field.Store.NO));
+ writer.AddDocument(doc);
+ }
+
+ /// <summary>
+ /// LUCENENET specific
+ /// Is non-static because NewStringField, NewTextField, NewField methods
+ /// are no longer static.
+ /// </summary>
+ internal void AddDocumentWithDifferentFields(IndexWriter writer)
+ {
+ Document doc = new Document();
+
+ FieldType customType3 = new FieldType();
+ customType3.IsStored = true;
+ doc.Add(NewStringField("keyword2", "test1", Field.Store.YES));
+ doc.Add(NewTextField("text2", "test1", Field.Store.YES));
+ doc.Add(NewField("unindexed2", "test1", customType3));
+ doc.Add(new TextField("unstored2", "test1", Field.Store.NO));
+ writer.AddDocument(doc);
+ }
+
+ /// <summary>
+ /// LUCENENET specific
+ /// Is non-static because NewTextField, NewField methods are no longer
+ /// static.
+ /// </summary>
+ internal void AddDocumentWithTermVectorFields(IndexWriter writer)
+ {
+ Document doc = new Document();
+ FieldType customType5 = new FieldType(TextField.TYPE_STORED);
+ customType5.StoreTermVectors = true;
+ FieldType customType6 = new FieldType(TextField.TYPE_STORED);
+ customType6.StoreTermVectors = true;
+ customType6.StoreTermVectorOffsets = true;
+ FieldType customType7 = new FieldType(TextField.TYPE_STORED);
+ customType7.StoreTermVectors = true;
+ customType7.StoreTermVectorPositions = true;
+ FieldType customType8 = new FieldType(TextField.TYPE_STORED);
+ customType8.StoreTermVectors = true;
+ customType8.StoreTermVectorOffsets = true;
+ customType8.StoreTermVectorPositions = true;
+ doc.Add(NewTextField("tvnot", "tvnot", Field.Store.YES));
+ doc.Add(NewField("termvector", "termvector", customType5));
+ doc.Add(NewField("tvoffset", "tvoffset", customType6));
+ doc.Add(NewField("tvposition", "tvposition", customType7));
+ doc.Add(NewField("tvpositionoffset", "tvpositionoffset", customType8));
+
+ writer.AddDocument(doc);
+ }
+
+ /// <summary>
+ /// LUCENENET specific
+ /// Is non-static because NewTextField is no longer static.
+ /// </summary>
+ internal void AddDoc(IndexWriter writer, string value)
+ {
+ Document doc = new Document();
+ doc.Add(NewTextField("content", value, Field.Store.NO));
+ writer.AddDocument(doc);
+ }
+
+ // TODO: maybe this can reuse the logic of test dueling codecs?
+ public static void AssertIndexEquals(DirectoryReader index1, DirectoryReader index2)
+ {
+ Assert.AreEqual(index1.NumDocs, index2.NumDocs, "IndexReaders have different values for numDocs.");
+ Assert.AreEqual(index1.MaxDoc, index2.MaxDoc, "IndexReaders have different values for maxDoc.");
+ Assert.AreEqual(index1.HasDeletions, index2.HasDeletions, "Only one IndexReader has deletions.");
+ Assert.AreEqual(index1.Leaves.Count == 1, index2.Leaves.Count == 1, "Single segment test differs.");
+
+ // check field names
+ FieldInfos fieldInfos1 = MultiFields.GetMergedFieldInfos(index1);
+ FieldInfos fieldInfos2 = MultiFields.GetMergedFieldInfos(index2);
+ Assert.AreEqual(fieldInfos1.Count, fieldInfos2.Count, "IndexReaders have different numbers of fields.");
+ int numFields = fieldInfos1.Count;
+ for (int fieldID = 0; fieldID < numFields; fieldID++)
+ {
+ FieldInfo fieldInfo1 = fieldInfos1.FieldInfo(fieldID);
+ FieldInfo fieldInfo2 = fieldInfos2.FieldInfo(fieldID);
+ Assert.AreEqual(fieldInfo1.Name, fieldInfo2.Name, "Different field names.");
+ }
+
+ // check norms
+ foreach (FieldInfo fieldInfo in fieldInfos1)
+ {
+ string curField = fieldInfo.Name;
+ NumericDocValues norms1 = MultiDocValues.GetNormValues(index1, curField);
+ NumericDocValues norms2 = MultiDocValues.GetNormValues(index2, curField);
+ if (norms1 != null && norms2 != null)
+ {
+ // todo: generalize this (like TestDuelingCodecs assert)
+ for (int i = 0; i < index1.MaxDoc; i++)
+ {
+ Assert.AreEqual(norms1.Get(i), norms2.Get(i), "Norm different for doc " + i + " and field '" + curField + "'.");
+ }
+ }
+ else
+ {
+ Assert.IsNull(norms1);
+ Assert.IsNull(norms2);
+ }
+ }
+
+ // check deletions
+ IBits liveDocs1 = MultiFields.GetLiveDocs(index1);
+ IBits liveDocs2 = MultiFields.GetLiveDocs(index2);
+ for (int i = 0; i < index1.MaxDoc; i++)
+ {
+ Assert.AreEqual(liveDocs1 == null || !liveDocs1.Get(i), liveDocs2 == null || !liveDocs2.Get(i), "Doc " + i + " only deleted in one index.");
+ }
+
+ // check stored fields
+ for (int i = 0; i < index1.MaxDoc; i++)
+ {
+ if (liveDocs1 == null || liveDocs1.Get(i))
+ {
+ Document doc1 = index1.Document(i);
+ Document doc2 = index2.Document(i);
+ IList<IIndexableField> field1 = doc1.Fields;
+ IList<IIndexableField> field2 = doc2.Fields;
+ Assert.AreEqual(field1.Count, field2.Count, "Different numbers of fields for doc " + i + ".");
+ IEnumerator<IIndexableField> itField1 = field1.GetEnumerator();
+ IEnumerator<IIndexableField> itField2 = field2.GetEnumerator();
+ while (itField1.MoveNext())
+ {
+ Field curField1 = (Field)itField1.Current;
+ itField2.MoveNext();
+ Field curField2 = (Field)itField2.Current;
+ Assert.AreEqual(curField1.Name, curField2.Name, "Different fields names for doc " + i + ".");
+ Assert.AreEqual(curField1.GetStringValue(), curField2.GetStringValue(), "Different field values for doc " + i + ".");
+ }
+ }
+ }
+
+ // check dictionary and posting lists
+ Fields fields1 = MultiFields.GetFields(index1);
+ Fields fields2 = MultiFields.GetFields(index2);
+ IEnumerator<string> fenum2 = fields2.GetEnumerator();
+ IBits liveDocs = MultiFields.GetLiveDocs(index1);
+ foreach (string field1 in fields1)
+ {
+ fenum2.MoveNext();
+ Assert.AreEqual(field1, fenum2.Current, "Different fields");
+ Terms terms1 = fields1.GetTerms(field1);
+ if (terms1 == null)
+ {
+ Assert.IsNull(fields2.GetTerms(field1));
+ continue;
+ }
+ TermsEnum enum1 = terms1.GetIterator(null);
+
+ Terms terms2 = fields2.GetTerms(field1);
+ Assert.IsNotNull(terms2);
+ TermsEnum enum2 = terms2.GetIterator(null);
+
+ while (enum1.Next() != null)
+ {
+ Assert.AreEqual(enum1.Term, enum2.Next(), "Different terms");
+ DocsAndPositionsEnum tp1 = enum1.DocsAndPositions(liveDocs, null);
+ DocsAndPositionsEnum tp2 = enum2.DocsAndPositions(liveDocs, null);
+
+ while (tp1.NextDoc() != DocIdSetIterator.NO_MORE_DOCS)
+ {
+ Assert.IsTrue(tp2.NextDoc() != DocIdSetIterator.NO_MORE_DOCS);
+ Assert.AreEqual(tp1.DocID, tp2.DocID, "Different doc id in postinglist of term " + enum1.Term + ".");
+ Assert.AreEqual(tp1.Freq, tp2.Freq, "Different term frequence in postinglist of term " + enum1.Term + ".");
+ for (int i = 0; i < tp1.Freq; i++)
+ {
+ Assert.AreEqual(tp1.NextPosition(), tp2.NextPosition(), "Different positions in postinglist of term " + enum1.Term + ".");
+ }
+ }
+ }
+ }
+ Assert.IsFalse(fenum2.MoveNext());
+ }
+
+ [Test]
+ public virtual void TestGetIndexCommit()
+ {
+ Directory d = NewDirectory();
+
+ // set up writer
+ IndexWriter writer = new IndexWriter(d, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())).SetMaxBufferedDocs(2).SetMergePolicy(NewLogMergePolicy(10)));
+ for (int i = 0; i < 27; i++)
+ {
+ AddDocumentWithFields(writer);
+ }
+ writer.Dispose();
+
+ SegmentInfos sis = new SegmentInfos();
+ sis.Read(d);
+ DirectoryReader r = DirectoryReader.Open(d);
+ IndexCommit c = r.IndexCommit;
+
+ Assert.AreEqual(sis.GetSegmentsFileName(), c.SegmentsFileName);
+
+ Assert.IsTrue(c.Equals(r.IndexCommit));
+
+ // Change the index
+ writer = new IndexWriter(d, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())).SetOpenMode(OpenMode.APPEND).SetMaxBufferedDocs(2).SetMergePolicy(NewLogMergePolicy(10)));
+ for (int i = 0; i < 7; i++)
+ {
+ AddDocumentWithFields(writer);
+ }
+ writer.Dispose();
+
+ DirectoryReader r2 = DirectoryReader.OpenIfChanged(r);
+ Assert.IsNotNull(r2);
+ Assert.IsFalse(c.Equals(r2.IndexCommit));
+ Assert.IsFalse(r2.IndexCommit.SegmentCount == 1);
+ r2.Dispose();
+
+ writer = new IndexWriter(d, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())).SetOpenMode(OpenMode.APPEND));
+ writer.ForceMerge(1);
+ writer.Dispose();
+
+ r2 = DirectoryReader.OpenIfChanged(r);
+ Assert.IsNotNull(r2);
+ Assert.IsNull(DirectoryReader.OpenIfChanged(r2));
+ Assert.AreEqual(1, r2.IndexCommit.SegmentCount);
+
+ r.Dispose();
+ r2.Dispose();
+ d.Dispose();
+ }
+
+ internal Document CreateDocument(string id)
+ {
+ Document doc = new Document();
+ FieldType customType = new FieldType(TextField.TYPE_STORED);
+ customType.IsTokenized = false;
+ customType.OmitNorms = true;
+
+ doc.Add(NewField("id", id, customType));
+ return doc;
+ }
+
+ // LUCENE-1468 -- make sure on attempting to open an
+ // DirectoryReader on a non-existent directory, you get a
+ // good exception
+ [Test]
+ public virtual void TestNoDir()
+ {
+ DirectoryInfo tempDir = CreateTempDir("doesnotexist");
+ System.IO.Directory.Delete(tempDir.FullName, true);
+ Directory dir = NewFSDirectory(tempDir);
+ try
+ {
+ DirectoryReader.Open(dir);
+ Assert.Fail("did not hit expected exception");
+ }
+#pragma warning disable 168
+ catch (NoSuchDirectoryException nsde)
+#pragma warning restore 168
+ {
+ // expected
+ }
+ dir.Dispose();
+ }
+
+ // LUCENE-1509
+ [Test]
+ public virtual void TestNoDupCommitFileNames()
+ {
+ Directory dir = NewDirectory();
+
+ IndexWriter writer = new IndexWriter(dir, (IndexWriterConfig)NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())).SetMaxBufferedDocs(2));
+ writer.AddDocument(CreateDocument("a"));
+ writer.AddDocument(CreateDocument("a"));
+ writer.AddDocument(CreateDocument("a"));
+ writer.Dispose();
+
+ ICollection<IndexCommit> commits = DirectoryReader.ListCommits(dir);
+ foreach (IndexCommit commit in commits)
+ {
+ ICollection<string> files = commit.FileNames;
+ HashSet<string> seen = new HashSet<string>();
+ foreach (String fileName in files)
+ {
+ Assert.IsTrue(!seen.Contains(fileName), "file " + fileName + " was duplicated");
+ seen.Add(fileName);
+ }
+ }
+
+ dir.Dispose();
+ }
+
+ // LUCENE-1579: Ensure that on a reopened reader, that any
+ // shared segments reuse the doc values arrays in
+ // FieldCache
+ [Test]
+ public virtual void TestFieldCacheReuseAfterReopen()
+ {
+ Directory dir = NewDirectory();
+ IndexWriter writer = new IndexWriter(dir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())).SetMergePolicy(NewLogMergePolicy(10)));
+ Document doc = new Document();
+ doc.Add(NewStringField("number", "17", Field.Store.NO));
+ writer.AddDocument(doc);
+ writer.Commit();
+
+ // Open reader1
+ DirectoryReader r = DirectoryReader.Open(dir);
+ AtomicReader r1 = GetOnlySegmentReader(r);
+ FieldCache.Int32s ints = FieldCache.DEFAULT.GetInt32s(r1, "number", false);
+ Assert.AreEqual(17, ints.Get(0));
+
+ // Add new segment
+ writer.AddDocument(doc);
+ writer.Commit();
+
+ // Reopen reader1 --> reader2
+ DirectoryReader r2 = DirectoryReader.OpenIfChanged(r);
+ Assert.IsNotNull(r2);
+ r.Dispose();
+ AtomicReader sub0 = (AtomicReader)r2.Leaves[0].Reader;
+ FieldCache.Int32s ints2 = FieldCache.DEFAULT.GetInt32s(sub0, "number", false);
+ r2.Dispose();
+ Assert.IsTrue(ints == ints2);
+
+ writer.Dispose();
+ dir.Dispose();
+ }
+
+ // LUCENE-1586: getUniqueTermCount
+ [Test]
+ public virtual void TestUniqueTermCount()
+ {
+ Directory dir = NewDirectory();
+ IndexWriter writer = new IndexWriter(dir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
+ Document doc = new Document();
+ doc.Add(NewTextField("field", "a b c d e f g h i j k l m n o p q r s t u v w x y z", Field.Store.NO));
+ doc.Add(NewTextField("number", "0 1 2 3 4 5 6 7 8 9", Field.Store.NO));
+ writer.AddDocument(doc);
+ writer.AddDocument(doc);
+ writer.Commit();
+
+ DirectoryReader r = DirectoryReader.Open(dir);
+ AtomicReader r1 = GetOnlySegmentReader(r);
+#pragma warning disable 612, 618
+ Assert.AreEqual(36, r1.Fields.UniqueTermCount);
+#pragma warning restore 612, 618
+ writer.AddDocument(doc);
+ writer.Commit();
+ DirectoryReader r2 = DirectoryReader.OpenIfChanged(r);
+ Assert.IsNotNull(r2);
+ r.Dispose();
+
+ foreach (AtomicReaderContext s in r2.Leaves)
+ {
+#pragma warning disable 612, 618
+ Assert.AreEqual(36, ((AtomicReader)s.Reader).Fields.UniqueTermCount);
+#pragma warning restore 612, 618
+ }
+ r2.Dispose();
+ writer.Dispose();
+ dir.Dispose();
+ }
+
+ // LUCENE-1609: don't load terms index
+ [Test]
+ public virtual void TestNoTermsIndex()
+ {
+ Directory dir = NewDirectory();
+ IndexWriter writer = new IndexWriter(dir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())).SetCodec(TestUtil.AlwaysPostingsFormat(new Lucene41PostingsFormat())));
+ Document doc = new Document();
+ doc.Add(NewTextField("field", "a b c d e f g h i j k l m n o p q r s t u v w x y z", Field.Store.NO));
+ doc.Add(NewTextField("number", "0 1 2 3 4 5 6 7 8 9", Field.Store.NO));
+ writer.AddDocument(doc);
+ writer.AddDocument(doc);
+ writer.Dispose();
+
+ DirectoryReader r = DirectoryReader.Open(dir, -1);
+ try
+ {
+ r.DocFreq(new Term("field", "f"));
+ Assert.Fail("did not hit expected exception");
+ }
+#pragma warning disable 168
+ catch (InvalidOperationException ise)
+#pragma warning restore 168
+ {
+ // expected
+ }
+
+ Assert.AreEqual(-1, ((SegmentReader)r.Leaves[0].Reader).TermInfosIndexDivisor);
+ writer = new IndexWriter(dir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())).SetCodec(TestUtil.AlwaysPostingsFormat(new Lucene41PostingsFormat())).SetMergePolicy(NewLogMergePolicy(10)));
+ writer.AddDocument(doc);
+ writer.Dispose();
+
+ // LUCENE-1718: ensure re-open carries over no terms index:
+ DirectoryReader r2 = DirectoryReader.OpenIfChanged(r);
+ Assert.IsNotNull(r2);
+ Assert.IsNull(DirectoryReader.OpenIfChanged(r2));
+ r.Dispose();
+ IList<AtomicReaderContext> leaves = r2.Leaves;
+ Assert.AreEqual(2, leaves.Count);
+ foreach (AtomicReaderContext ctx in leaves)
+ {
+ try
+ {
+ ctx.Reader.DocFreq(new Term("field", "f"));
+ Assert.Fail("did not hit expected exception");
+ }
+#pragma warning disable 168
+ catch (InvalidOperationException ise)
+#pragma warning restore 168
+ {
+ // expected
+ }
+ }
+ r2.Dispose();
+ dir.Dispose();
+ }
+
+ // LUCENE-2046
+ [Test]
+ public virtual void TestPrepareCommitIsCurrent()
+ {
+ Directory dir = NewDirectory();
+ IndexWriter writer = new IndexWriter(dir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
+ writer.Commit();
+ Document doc = new Document();
+ writer.AddDocument(doc);
+ DirectoryReader r = DirectoryReader.Open(dir);
+ Assert.IsTrue(r.IsCurrent);
+ writer.AddDocument(doc);
+ writer.PrepareCommit();
+ Assert.IsTrue(r.IsCurrent);
+ DirectoryReader r2 = DirectoryReader.OpenIfChanged(r);
+ Assert.IsNull(r2);
+ writer.Commit();
+ Assert.IsFalse(r.IsCurrent);
+ writer.Dispose();
+ r.Dispose();
+ dir.Dispose();
+ }
+
+ // LUCENE-2753
+ [Test]
+ public virtual void TestListCommits()
+ {
+ Directory dir = NewDirectory();
+ IndexWriter writer = new IndexWriter(dir, NewIndexWriterConfig(TEST_VERSION_CURRENT, null).SetIndexDeletionPolicy(new SnapshotDeletionPolicy(new KeepOnlyLastCommitDeletionPolicy())));
+ SnapshotDeletionPolicy sdp = (SnapshotDeletionPolicy)writer.Config.IndexDeletionPolicy;
+ writer.AddDocument(new Document());
+ writer.Commit();
+ sdp.Snapshot();
+ writer.AddDocument(new Document());
+ writer.Commit();
+ sdp.Snapshot();
+ writer.AddDocument(new Document());
+ writer.Commit();
+ sdp.Snapshot();
+ writer.Dispose();
+ long currentGen = 0;
+ foreach (IndexCommit ic in DirectoryReader.ListCommits(dir))
+ {
+ Assert.IsTrue(currentGen < ic.Generation, "currentGen=" + currentGen + " commitGen=" + ic.Generation);
+ currentGen = ic.Generation;
+ }
+ dir.Dispose();
+ }
+
+ // Make sure totalTermFreq works correctly in the terms
+ // dict cache
+ [Test]
+ public virtual void TestTotalTermFreqCached()
+ {
+ Directory dir = NewDirectory();
+ IndexWriter writer = new IndexWriter(dir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
+ Document d = new Document();
+ d.Add(NewTextField("f", "a a b", Field.Store.NO));
+ writer.AddDocument(d);
+ DirectoryReader r = writer.Reader;
+ writer.Dispose();
+ try
+ {
+ // Make sure codec impls totalTermFreq (eg PreFlex doesn't)
+ Assume.That(r.TotalTermFreq(new Term("f", new BytesRef("b"))) != -1);
+ Assert.AreEqual(1, r.TotalTermFreq(new Term("f", new BytesRef("b"))));
+ Assert.AreEqual(2, r.TotalTermFreq(new Term("f", new BytesRef("a"))));
+ Assert.AreEqual(1, r.TotalTermFreq(new Term("f", new BytesRef("b"))));
+ }
+ finally
+ {
+ r.Dispose();
+ dir.Dispose();
+ }
+ }
+
+ [Test]
+ public virtual void TestGetSumDocFreq()
+ {
+ Directory dir = NewDirectory();
+ IndexWriter writer = new IndexWriter(dir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
+ Document d = new Document();
+ d.Add(NewTextField("f", "a", Field.Store.NO));
+ writer.AddDocument(d);
+ d = new Document();
+ d.Add(NewTextField("f", "b", Field.Store.NO));
+ writer.AddDocument(d);
+ DirectoryReader r = writer.Reader;
+ writer.Dispose();
+ try
+ {
+ // Make sure codec impls getSumDocFreq (eg PreFlex doesn't)
+ Assume.That(r.GetSumDocFreq("f") != -1);
+ Assert.AreEqual(2, r.GetSumDocFreq("f"));
+ }
+ finally
+ {
+ r.Dispose();
+ dir.Dispose();
+ }
+ }
+
+ [Test]
+ public virtual void TestGetDocCount()
+ {
+ Directory dir = NewDirectory();
+ IndexWriter writer = new IndexWriter(dir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
+ Document d = new Document();
+ d.Add(NewTextField("f", "a", Field.Store.NO));
+ writer.AddDocument(d);
+ d = new Document();
+ d.Add(NewTextField("f", "a", Field.Store.NO));
+ writer.AddDocument(d);
+ DirectoryReader r = writer.Reader;
+ writer.Dispose();
+ try
+ {
+ // Make sure codec impls getSumDocFreq (eg PreFlex doesn't)
+ Assume.That(r.GetDocCount("f") != -1);
+ Assert.AreEqual(2, r.GetDocCount("f"));
+ }
+ finally
+ {
+ r.Dispose();
+ dir.Dispose();
+ }
+ }
+
+ [Test]
+ public virtual void TestGetSumTotalTermFreq()
+ {
+ Directory dir = NewDirectory();
+ IndexWriter writer = new IndexWriter(dir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
+ Document d = new Document();
+ d.Add(NewTextField("f", "a b b", Field.Store.NO));
+ writer.AddDocument(d);
+ d = new Document();
+ d.Add(NewTextField("f", "a a b", Field.Store.NO));
+ writer.AddDocument(d);
+ DirectoryReader r = writer.Reader;
+ writer.Dispose();
+ try
+ {
+ // Make sure codec impls getSumDocFreq (eg PreFlex doesn't)
+ Assume.That(r.GetSumTotalTermFreq("f") != -1);
+ Assert.AreEqual(6, r.GetSumTotalTermFreq("f"));
+ }
+ finally
+ {
+ r.Dispose();
+ dir.Dispose();
+ }
+ }
+
+ // LUCENE-2474
+ [Test]
+ public virtual void TestReaderFinishedListener()
+ {
+ Directory dir = NewDirectory();
+ IndexWriter writer = new IndexWriter(dir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())).SetMergePolicy(NewLogMergePolicy()));
+ ((LogMergePolicy)writer.Config.MergePolicy).MergeFactor = 3;
+ writer.AddDocument(new Document());
+ writer.Commit();
+ writer.AddDocument(new Document());
+ writer.Commit();
+ DirectoryReader reader = writer.Reader;
+ int[] closeCount = new int[1];
+ IndexReader.IReaderClosedListener listener = new ReaderClosedListenerAnonymousInnerClassHelper(this, reader, closeCount);
+
+ reader.AddReaderClosedListener(listener);
+
+ reader.Dispose();
+
+ // Close the top reader, its the only one that should be closed
+ Assert.AreEqual(1, closeCount[0]);
+ writer.Dispose();
+
+ DirectoryReader reader2 = DirectoryReader.Open(dir);
+ reader2.AddReaderClosedListener(listener);
+
+ closeCount[0] = 0;
+ reader2.Dispose();
+ Assert.AreEqual(1, closeCount[0]);
+ dir.Dispose();
+ }
+
+ private class ReaderClosedListenerAnonymousInnerClassHelper : IndexReader.IReaderClosedListener
+ {
+ private readonly TestDirectoryReader OuterInstance;
+
+ private DirectoryReader Reader;
+ private int[] CloseCount;
+
+ public ReaderClosedListenerAnonymousInnerClassHelper(TestDirectoryReader outerInstance, DirectoryReader reader, int[] closeCount)
+ {
+ this.OuterInstance = outerInstance;
+ this.Reader = reader;
+ this.CloseCount = closeCount;
+ }
+
+ public void OnClose(IndexReader reader)
+ {
+ CloseCount[0]++;
+ }
+ }
+
+ [Test]
+ public virtual void TestOOBDocID()
+ {
+ Directory dir = NewDirectory();
+ IndexWriter writer = new IndexWriter(dir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
+ writer.AddDocument(new Document());
+ DirectoryReader r = writer.Reader;
+ writer.Dispose();
+ r.Document(0);
+ try
+ {
+ r.Document(1);
+ Assert.Fail("did not hit exception");
+ }
+#pragma warning disable 168
+ catch (System.ArgumentException iae)
+#pragma warning restore 168
+ {
+ // expected
+ }
+ r.Dispose();
+ dir.Dispose();
+ }
+
+ [Test]
+ public virtual void TestTryIncRef()
+ {
+ Directory dir = NewDirectory();
+ IndexWriter writer = new IndexWriter(dir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
+ writer.AddDocument(new Document());
+ writer.Commit();
+ DirectoryReader r = DirectoryReader.Open(dir);
+ Assert.IsTrue(r.TryIncRef());
+ r.DecRef();
+ r.Dispose();
+ Assert.IsFalse(r.TryIncRef());
+ writer.Dispose();
+ dir.Dispose();
+ }
+
+ [Test]
+ public virtual void TestStressTryIncRef()
+ {
+ Directory dir = NewDirectory();
+ IndexWriter writer = new IndexWriter(dir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
+ writer.AddDocument(new Document());
+ writer.Commit();
+ DirectoryReader r = DirectoryReader.Open(dir);
+ int numThreads = AtLeast(2);
+
+ IncThread[] threads = new IncThread[numThreads];
+ for (int i = 0; i < threads.Length; i++)
+ {
+ threads[i] = new IncThread(r, Random());
+ threads[i].Start();
+ }
+ Thread.Sleep(100);
+
+ Assert.IsTrue(r.TryIncRef());
+ r.DecRef();
+ r.Dispose();
+
+ for (int i = 0; i < threads.Length; i++)
+ {
+ threads[i].Join();
+ Assert.IsNull(threads[i].Failed);
+ }
+ Assert.IsFalse(r.TryIncRef());
+ writer.Dispose();
+ dir.Dispose();
+ }
+
+ internal class IncThread : ThreadClass
+ {
+ internal readonly IndexReader ToInc;
+ internal readonly Random Random;
+ internal Exception Failed;
+
+ internal IncThread(IndexReader toInc, Random random)
+ {
+ this.ToInc = toInc;
+ this.Random = random;
+ }
+
+ public override void Run()
+ {
+ try
+ {
+ while (ToInc.TryIncRef())
+ {
+ Assert.IsFalse(ToInc.HasDeletions);
+ ToInc.DecRef();
+ }
+ Assert.IsFalse(ToInc.TryIncRef());
+ }
+ catch (Exception e)
+ {
+ Failed = e;
+ }
+ }
+ }
+
+ [Test]
+ public virtual void TestLoadCertainFields()
+ {
+ Directory dir = NewDirectory();
+ RandomIndexWriter writer = new RandomIndexWriter(Random(), dir, Similarity, TimeZone);
+ Document doc = new Document();
+ doc.Add(NewStringField("field1", "foobar", Field.Store.YES));
+ doc.Add(NewStringField("field2", "foobaz", Field.Store.YES));
+ writer.AddDocument(doc);
+ DirectoryReader r = writer.Reader;
+ writer.Dispose();
+ HashSet<string> fieldsToLoad = new HashSet<string>();
+ Assert.AreEqual(0, r.Document(0, fieldsToLoad).Fields.Count);
+ fieldsToLoad.Add("field1");
+ Document doc2 = r.Document(0, fieldsToLoad);
+ Assert.AreEqual(1, doc2.Fields.Count);
+ Assert.AreEqual("foobar", doc2.Get("field1"));
+ r.Dispose();
+ dir.Dispose();
+ }
+
+ /// @deprecated just to ensure IndexReader static methods work
+ [Obsolete("just to ensure IndexReader static methods work")]
+ [Test]
+ public virtual void TestBackwards()
+ {
+ Directory dir = NewDirectory();
+ IndexWriter writer = new IndexWriter(dir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())).SetCodec(TestUtil.AlwaysPostingsFormat(new Lucene41PostingsFormat())));
+ Document doc = new Document();
+ doc.Add(NewTextField("field", "a b c d e f g h i j k l m n o p q r s t u v w x y z", Field.Store.NO));
+ doc.Add(NewTextField("number", "0 1 2 3 4 5 6 7 8 9", Field.Store.NO));
+ writer.AddDocument(doc);
+
+ // open(IndexWriter, boolean)
+ DirectoryReader r = IndexReader.Open(writer, true);
+ Assert.AreEqual(1, r.DocFreq(new Term("field", "f")));
+ r.Dispose();
+ writer.AddDocument(doc);
+ writer.Dispose();
+
+ // open(Directory)
+ r = IndexReader.Open(dir);
+ Assert.AreEqual(2, r.DocFreq(new Term("field", "f")));
+ r.Dispose();
+
+ // open(IndexCommit)
+ IList<IndexCommit> commits = DirectoryReader.ListCommits(dir);
+ Assert.AreEqual(1, commits.Count);
+ r = IndexReader.Open(commits[0]);
+ Assert.AreEqual(2, r.DocFreq(new Term("field", "f")));
+ r.Dispose();
+
+ // open(Directory, int)
+ r = IndexReader.Open(dir, -1);
+ try
+ {
+ r.DocFreq(new Term("field", "f"));
+ Assert.Fail("did not hit expected exception");
+ }
+#pragma warning disable 168
+ catch (InvalidOperationException ise)
+#pragma warning restore 168
+ {
+ // expected
+ }
+ Assert.AreEqual(-1, ((SegmentReader)r.Leaves[0].Reader).TermInfosIndexDivisor);
+ r.Dispose();
+
+ // open(IndexCommit, int)
+ r = IndexReader.Open(commits[0], -1);
+ try
+ {
+ r.DocFreq(new Term("field", "f"));
+ Assert.Fail("did not hit expected exception");
+ }
+#pragma warning disable 168
+ catch (InvalidOperationException ise)
+#pragma warning restore 168
+ {
+ // expected
+ }
+ Assert.AreEqual(-1, ((SegmentReader)r.Leaves[0].Reader).TermInfosIndexDivisor);
+ r.Dispose();
+ dir.Dispose();
+ }
+
+ [Test]
+ public virtual void TestIndexExistsOnNonExistentDirectory()
+ {
+ DirectoryInfo tempDir = CreateTempDir("testIndexExistsOnNonExistentDirectory");
+ tempDir.Delete();
+ Directory dir = NewFSDirectory(tempDir);
+ Console.WriteLine("dir=" + dir);
+ Assert.IsFalse(DirectoryReader.IndexExists(dir));
+ dir.Dispose();
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/96822396/src/Lucene.Net.Tests/Index/TestDirectoryReaderReopen.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/Index/TestDirectoryReaderReopen.cs b/src/Lucene.Net.Tests/Index/TestDirectoryReaderReopen.cs
new file mode 100644
index 0000000..bb52f58
--- /dev/null
+++ b/src/Lucene.Net.Tests/Index/TestDirectoryReaderReopen.cs
@@ -0,0 +1,785 @@
+using Lucene.Net.Documents;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading;
+
+namespace Lucene.Net.Index
+{
+ using Lucene.Net.Support;
+ using NUnit.Framework;
+ using Directory = Lucene.Net.Store.Directory;
+ using Document = Documents.Document;
+ using Field = Field;
+ using FieldType = FieldType;
+ using IndexSearcher = Lucene.Net.Search.IndexSearcher;
+ using LuceneTestCase = Lucene.Net.Util.LuceneTestCase;
+
+ /*
+ * 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 MockAnalyzer = Lucene.Net.Analysis.MockAnalyzer;
+ using ScoreDoc = Lucene.Net.Search.ScoreDoc;
+ using TermQuery = Lucene.Net.Search.TermQuery;
+ using TestUtil = Lucene.Net.Util.TestUtil;
+ using TextField = TextField;
+
+ [TestFixture]
+ public class TestDirectoryReaderReopen : LuceneTestCase
+ {
+ [Test]
+ public virtual void TestReopen_Mem()
+ {
+ Directory dir1 = NewDirectory();
+
+ CreateIndex(Random(), dir1, false);
+ PerformDefaultTests(new TestReopenAnonymousInnerClassHelper(this, dir1));
+ dir1.Dispose();
+
+ Directory dir2 = NewDirectory();
+
+ CreateIndex(Random(), dir2, true);
+ PerformDefaultTests(new TestReopenAnonymousInnerClassHelper2(this, dir2));
+ dir2.Dispose();
+ }
+
+ private class TestReopenAnonymousInnerClassHelper : TestReopen
+ {
+ private readonly TestDirectoryReaderReopen OuterInstance;
+
+ private Directory Dir1;
+
+ public TestReopenAnonymousInnerClassHelper(TestDirectoryReaderReopen outerInstance, Directory dir1)
+ {
+ this.OuterInstance = outerInstance;
+ this.Dir1 = dir1;
+ }
+
+ protected internal override void ModifyIndex(int i)
+ {
+ TestDirectoryReaderReopen.ModifyIndex(i, Dir1);
+ }
+
+ protected internal override DirectoryReader OpenReader()
+ {
+ return DirectoryReader.Open(Dir1);
+ }
+ }
+
+ private class TestReopenAnonymousInnerClassHelper2 : TestReopen
+ {
+ private readonly TestDirectoryReaderReopen OuterInstance;
+
+ private Directory Dir2;
+
+ public TestReopenAnonymousInnerClassHelper2(TestDirectoryReaderReopen outerInstance, Directory dir2)
+ {
+ this.OuterInstance = outerInstance;
+ this.Dir2 = dir2;
+ }
+
+ protected internal override void ModifyIndex(int i)
+ {
+ TestDirectoryReaderReopen.ModifyIndex(i, Dir2);
+ }
+
+ protected internal override DirectoryReader OpenReader()
+ {
+ return DirectoryReader.Open(Dir2);
+ }
+ }
+
+ // LUCENE-1228: IndexWriter.Commit() does not update the index version
+ // populate an index in iterations.
+ // at the end of every iteration, commit the index and reopen/recreate the reader.
+ // in each iteration verify the work of previous iteration.
+ // try this once with reopen once recreate, on both RAMDir and FSDir.
+ [Test]
+ public virtual void TestCommitReopen()
+ {
+ Directory dir = NewDirectory();
+ DoTestReopenWithCommit(Random(), dir, true);
+ dir.Dispose();
+ }
+
+ [Test]
+ public virtual void TestCommitRecreate()
+ {
+ Directory dir = NewDirectory();
+ DoTestReopenWithCommit(Random(), dir, false);
+ dir.Dispose();
+ }
+
+ private void DoTestReopenWithCommit(Random random, Directory dir, bool withReopen)
+ {
+ IndexWriter iwriter = new IndexWriter(dir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(random)).SetOpenMode(OpenMode.CREATE).SetMergeScheduler(new SerialMergeScheduler()).SetMergePolicy(NewLogMergePolicy()));
+ iwriter.Commit();
+ DirectoryReader reader = DirectoryReader.Open(dir);
+ try
+ {
+ int M = 3;
+ FieldType customType = new FieldType(TextField.TYPE_STORED);
+ customType.IsTokenized = false;
+ FieldType customType2 = new FieldType(TextField.TYPE_STORED);
+ customType2.IsTokenized = false;
+ customType2.OmitNorms = true;
+ FieldType customType3 = new FieldType();
+ customType3.IsStored = true;
+ for (int i = 0; i < 4; i++)
+ {
+ for (int j = 0; j < M; j++)
+ {
+ Document doc = new Document();
+ doc.Add(NewField("id", i + "_" + j, customType));
+ doc.Add(NewField("id2", i + "_" + j, customType2));
+ doc.Add(NewField("id3", i + "_" + j, customType3));
+ iwriter.AddDocument(doc);
+ if (i > 0)
+ {
+ int k = i - 1;
+ int n = j + k * M;
+ Document prevItereationDoc = reader.Document(n);
+ Assert.IsNotNull(prevItereationDoc);
+ string id = prevItereationDoc.Get("id");
+ Assert.AreEqual(k + "_" + j, id);
+ }
+ }
+ iwriter.Commit();
+ if (withReopen)
+ {
+ // reopen
+ DirectoryReader r2 = DirectoryReader.OpenIfChanged(reader);
+ if (r2 != null)
+ {
+ reader.Dispose();
+ reader = r2;
+ }
+ }
+ else
+ {
+ // recreate
+ reader.Dispose();
+ reader = DirectoryReader.Open(dir);
+ }
+ }
+ }
+ finally
+ {
+ iwriter.Dispose();
+ reader.Dispose();
+ }
+ }
+
+ private void PerformDefaultTests(TestReopen test)
+ {
+ DirectoryReader index1 = test.OpenReader();
+ DirectoryReader index2 = test.OpenReader();
+
+ TestDirectoryReader.AssertIndexEquals(index1, index2);
+
+ // verify that reopen() does not return a new reader instance
+ // in case the index has no changes
+ ReaderCouple couple = RefreshReader(index2, false);
+ Assert.IsTrue(couple.RefreshedReader == index2);
+
+ couple = RefreshReader(index2, test, 0, true);
+ index1.Dispose();
+ index1 = couple.NewReader;
+
+ DirectoryReader index2_refreshed = couple.RefreshedReader;
+ index2.Dispose();
+
+ // test if refreshed reader and newly opened reader return equal results
+ TestDirectoryReader.AssertIndexEquals(index1, index2_refreshed);
+
+ index2_refreshed.Dispose();
+ AssertReaderClosed(index2, true);
+ AssertReaderClosed(index2_refreshed, true);
+
+ index2 = test.OpenReader();
+
+ for (int i = 1; i < 4; i++)
+ {
+ index1.Dispose();
+ couple = RefreshReader(index2, test, i, true);
+ // refresh DirectoryReader
+ index2.Dispose();
+
+ index2 = couple.RefreshedReader;
+ index1 = couple.NewReader;
+ TestDirectoryReader.AssertIndexEquals(index1, index2);
+ }
+
+ index1.Dispose();
+ index2.Dispose();
+ AssertReaderClosed(index1, true);
+ AssertReaderClosed(index2, true);
+ }
+
+ [Test]
+ public virtual void TestThreadSafety()
+ {
+ Directory dir = NewDirectory();
+ // NOTE: this also controls the number of threads!
+ int n = TestUtil.NextInt(Random(), 20, 40);
+ IndexWriter writer = new IndexWriter(dir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
+ for (int i = 0; i < n; i++)
+ {
+ writer.AddDocument(CreateDocument(i, 3));
+ }
+ writer.ForceMerge(1);
+ writer.Dispose();
+
+ TestReopen test = new TestReopenAnonymousInnerClassHelper3(this, dir, n);
+
+ IList<ReaderCouple> readers = new SynchronizedList<ReaderCouple>();
+ DirectoryReader firstReader = DirectoryReader.Open(dir);
+ DirectoryReader reader = firstReader;
+
+ ReaderThread[] threads = new ReaderThread[n];
+ ISet<DirectoryReader> readersToClose = new ConcurrentHashSet<DirectoryReader>(new HashSet<DirectoryReader>());
+
+ for (int i = 0; i < n; i++)
+ {
+ if (i % 2 == 0)
+ {
+ DirectoryReader refreshed = DirectoryReader.OpenIfChanged(reader);
+ if (refreshed != null)
+ {
+ readersToClose.Add(reader);
+ reader = refreshed;
+ }
+ }
+ DirectoryReader r = reader;
+
+ int index = i;
+
+ ReaderThreadTask task;
+
+ if (i < 4 || (i >= 10 && i < 14) || i > 18)
+ {
+ task = new ReaderThreadTaskAnonymousInnerClassHelper(this, test, readers, readersToClose, r, index);
+ }
+ else
+ {
+ task = new ReaderThreadTaskAnonymousInnerClassHelper2(this, readers);
+ }
+
+ threads[i] = new ReaderThread(task);
+ threads[i].Start();
+ }
+
+ lock (this)
+ {
+ Monitor.Wait(this, TimeSpan.FromMilliseconds(1000));
+ }
+
+ for (int i = 0; i < n; i++)
+ {
+ if (threads[i] != null)
+ {
+ threads[i].StopThread();
+ }
+ }
+
+ for (int i = 0; i < n; i++)
+ {
+ if (threads[i] != null)
+ {
+ threads[i].Join();
+ if (threads[i].Error != null)
+ {
+ string msg = "Error occurred in thread " + threads[i].Name + ":\n" + threads[i].Error.Message;
+ Assert.Fail(msg);
+ }
+ }
+ }
+
+ foreach (DirectoryReader readerToClose in readersToClose)
+ {
+ readerToClose.Dispose();
+ }
+
+ firstReader.Dispose();
+ reader.Dispose();
+
+ foreach (DirectoryReader readerToClose in readersToClose)
+ {
+ AssertReaderClosed(readerToClose, true);
+ }
+
+ AssertReaderClosed(reader, true);
+ AssertReaderClosed(firstReader, true);
+
+ dir.Dispose();
+ }
+
+ private class TestReopenAnonymousInnerClassHelper3 : TestReopen
+ {
+ private readonly TestDirectoryReaderReopen OuterInstance;
+
+ private Directory Dir;
+ private int n;
+
+ public TestReopenAnonymousInnerClassHelper3(TestDirectoryReaderReopen outerInstance, Directory dir, int n)
+ {
+ this.OuterInstance = outerInstance;
+ this.Dir = dir;
+ this.n = n;
+ }
+
+ protected internal override void ModifyIndex(int i)
+ {
+ IndexWriter modifier = new IndexWriter(Dir, new IndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
+ modifier.AddDocument(CreateDocument(n + i, 6));
+ modifier.Dispose();
+ }
+
+ protected internal override DirectoryReader OpenReader()
+ {
+ return DirectoryReader.Open(Dir);
+ }
+ }
+
+ private class ReaderThreadTaskAnonymousInnerClassHelper : ReaderThreadTask
+ {
+ private readonly TestDirectoryReaderReopen OuterInstance;
+
+ private Lucene.Net.Index.TestDirectoryReaderReopen.TestReopen Test;
+ private IList<ReaderCouple> Readers;
+ private ISet<DirectoryReader> ReadersToClose;
+ private DirectoryReader r;
+ private int Index;
+
+ public ReaderThreadTaskAnonymousInnerClassHelper(TestDirectoryReaderReopen outerInstance, Lucene.Net.Index.TestDirectoryReaderReopen.TestReopen test, IList<ReaderCouple> readers, ISet<DirectoryReader> readersToClose, DirectoryReader r, int index)
+ {
+ this.OuterInstance = outerInstance;
+ this.Test = test;
+ this.Readers = readers;
+ this.ReadersToClose = readersToClose;
+ this.r = r;
+ this.Index = index;
+ }
+
+ public override void Run()
+ {
+ Random rnd = LuceneTestCase.Random();
+ while (!Stopped)
+ {
+ if (Index % 2 == 0)
+ {
+ // refresh reader synchronized
+ ReaderCouple c = (OuterInstance.RefreshReader(r, Test, Index, true));
+ ReadersToClose.Add(c.NewReader);
+ ReadersToClose.Add(c.RefreshedReader);
+ Readers.Add(c);
+ // prevent too many readers
+ break;
+ }
+ else
+ {
+ // not synchronized
+ DirectoryReader refreshed = DirectoryReader.OpenIfChanged(r);
+ if (refreshed == null)
+ {
+ refreshed = r;
+ }
+
+ IndexSearcher searcher = OuterInstance.NewSearcher(refreshed);
+ ScoreDoc[] hits = searcher.Search(new TermQuery(new Term("field1", "a" + rnd.Next(refreshed.MaxDoc))), null, 1000).ScoreDocs;
+ if (hits.Length > 0)
+ {
+ searcher.Doc(hits[0].Doc);
+ }
+ if (refreshed != r)
+ {
+ refreshed.Dispose();
+ }
+ }
+ lock (this)
+ {
+ Monitor.Wait(this, TimeSpan.FromMilliseconds(TestUtil.NextInt(Random(), 1, 100)));
+ }
+ }
+ }
+ }
+
+ private class ReaderThreadTaskAnonymousInnerClassHelper2 : ReaderThreadTask
+ {
+ private readonly TestDirectoryReaderReopen OuterInstance;
+
+ private IList<ReaderCouple> Readers;
+
+ public ReaderThreadTaskAnonymousInnerClassHelper2(TestDirectoryReaderReopen outerInstance, IList<ReaderCouple> readers)
+ {
+ this.OuterInstance = outerInstance;
+ this.Readers = readers;
+ }
+
+ public override void Run()
+ {
+ Random rnd = LuceneTestCase.Random();
+ while (!Stopped)
+ {
+ int numReaders = Readers.Count;
+ if (numReaders > 0)
+ {
+ ReaderCouple c = Readers[rnd.Next(numReaders)];
+ TestDirectoryReader.AssertIndexEquals(c.NewReader, c.RefreshedReader);
+ }
+
+ lock (this)
+ {
+ Monitor.Wait(this, TimeSpan.FromMilliseconds(TestUtil.NextInt(Random(), 1, 100)));
+ }
+ }
+ }
+ }
+
+ internal class ReaderCouple
+ {
+ internal ReaderCouple(DirectoryReader r1, DirectoryReader r2)
+ {
+ NewReader = r1;
+ RefreshedReader = r2;
+ }
+
+ internal DirectoryReader NewReader;
+ internal DirectoryReader RefreshedReader;
+ }
+
+ internal abstract class ReaderThreadTask
+ {
+ protected internal volatile bool Stopped;
+
+ public virtual void Stop()
+ {
+ this.Stopped = true;
+ }
+
+ public abstract void Run();
+ }
+
+ private class ReaderThread : ThreadClass
+ {
+ internal ReaderThreadTask Task;
+ internal Exception Error;
+
+ internal ReaderThread(ReaderThreadTask task)
+ {
+ this.Task = task;
+ }
+
+ public virtual void StopThread()
+ {
+ this.Task.Stop();
+ }
+
+ public override void Run()
+ {
+ try
+ {
+ this.Task.Run();
+ }
+ catch (Exception r)
+ {
+ Console.WriteLine(r.StackTrace);
+ this.Error = r;
+ }
+ }
+ }
+
+ private object CreateReaderMutex = new object();
+
+ private ReaderCouple RefreshReader(DirectoryReader reader, bool hasChanges)
+ {
+ return RefreshReader(reader, null, -1, hasChanges);
+ }
+
+ internal virtual ReaderCouple RefreshReader(DirectoryReader reader, TestReopen test, int modify, bool hasChanges)
+ {
+ lock (CreateReaderMutex)
+ {
+ DirectoryReader r = null;
+ if (test != null)
+ {
+ test.ModifyIndex(modify);
+ r = test.OpenReader();
+ }
+
+ DirectoryReader refreshed = null;
+ try
+ {
+ refreshed = DirectoryReader.OpenIfChanged(reader);
+ if (refreshed == null)
+ {
+ refreshed = reader;
+ }
+ }
+ finally
+ {
+ if (refreshed == null && r != null)
+ {
+ // Hit exception -- close opened reader
+ r.Dispose();
+ }
+ }
+
+ if (hasChanges)
+ {
+ if (refreshed == reader)
+ {
+ Assert.Fail("No new DirectoryReader instance created during refresh.");
+ }
+ }
+ else
+ {
+ if (refreshed != reader)
+ {
+ Assert.Fail("New DirectoryReader instance created during refresh even though index had no changes.");
+ }
+ }
+
+ return new ReaderCouple(r, refreshed);
+ }
+ }
+
+ /// <summary>
+ /// LUCENENET specific
+ /// Is non-static because NewIndexWriterConfig is no longer static.
+ /// </summary>
+ public void CreateIndex(Random random, Directory dir, bool multiSegment)
+ {
+ IndexWriter.Unlock(dir);
+ IndexWriter w = new IndexWriter(dir, NewIndexWriterConfig(random, TEST_VERSION_CURRENT, new MockAnalyzer(random)).SetMergePolicy(new LogDocMergePolicy()));
+
+ for (int i = 0; i < 100; i++)
+ {
+ w.AddDocument(CreateDocument(i, 4));
+ if (multiSegment && (i % 10) == 0)
+ {
+ w.Commit();
+ }
+ }
+
+ if (!multiSegment)
+ {
+ w.ForceMerge(1);
+ }
+
+ w.Dispose();
+
+ DirectoryReader r = DirectoryReader.Open(dir);
+ if (multiSegment)
+ {
+ Assert.IsTrue(r.Leaves.Count > 1);
+ }
+ else
+ {
+ Assert.IsTrue(r.Leaves.Count == 1);
+ }
+ r.Dispose();
+ }
+
+ public static Document CreateDocument(int n, int numFields)
+ {
+ StringBuilder sb = new StringBuilder();
+ Document doc = new Document();
+ sb.Append("a");
+ sb.Append(n);
+ FieldType customType2 = new FieldType(TextField.TYPE_STORED);
+ customType2.IsTokenized = false;
+ customType2.OmitNorms = true;
+ FieldType customType3 = new FieldType();
+ customType3.IsStored = true;
+ doc.Add(new TextField("field1", sb.ToString(), Field.Store.YES));
+ doc.Add(new Field("fielda", sb.ToString(), customType2));
+ doc.Add(new Field("fieldb", sb.ToString(), customType3));
+ sb.Append(" b");
+ sb.Append(n);
+ for (int i = 1; i < numFields; i++)
+ {
+ doc.Add(new TextField("field" + (i + 1), sb.ToString(), Field.Store.YES));
+ }
+ return doc;
+ }
+
+ internal static void ModifyIndex(int i, Directory dir)
+ {
+ switch (i)
+ {
+ case 0:
+ {
+ if (VERBOSE)
+ {
+ Console.WriteLine("TEST: modify index");
+ }
+ IndexWriter w = new IndexWriter(dir, new IndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
+ w.DeleteDocuments(new Term("field2", "a11"));
+ w.DeleteDocuments(new Term("field2", "b30"));
+ w.Dispose();
+ break;
+ }
+ case 1:
+ {
+ IndexWriter w = new IndexWriter(dir, new IndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
+ w.ForceMerge(1);
+ w.Dispose();
+ break;
+ }
+ case 2:
+ {
+ IndexWriter w = new IndexWriter(dir, new IndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
+ w.AddDocument(CreateDocument(101, 4));
+ w.ForceMerge(1);
+ w.AddDocument(CreateDocument(102, 4));
+ w.AddDocument(CreateDocument(103, 4));
+ w.Dispose();
+ break;
+ }
+ case 3:
+ {
+ IndexWriter w = new IndexWriter(dir, new IndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
+ w.AddDocument(CreateDocument(101, 4));
+ w.Dispose();
+ break;
+ }
+ }
+ }
+
+ internal static void AssertReaderClosed(IndexReader reader, bool checkSubReaders)
+ {
+ Assert.AreEqual(0, reader.RefCount);
+
+ if (checkSubReaders && reader is CompositeReader)
+ {
+ // we cannot use reader context here, as reader is
+ // already closed and calling getTopReaderContext() throws AlreadyClosed!
+ IList<IndexReader> subReaders = ((CompositeReader)reader).GetSequentialSubReaders();
+ foreach (IndexReader r in subReaders)
+ {
+ AssertReaderClosed(r, checkSubReaders);
+ }
+ }
+ }
+
+ internal abstract class TestReopen
+ {
+ protected internal abstract DirectoryReader OpenReader();
+
+ protected internal abstract void ModifyIndex(int i);
+ }
+
+ internal class KeepAllCommits : IndexDeletionPolicy
+ {
+ public override void OnInit<T>(IList<T> commits)
+ {
+ }
+
+ public override void OnCommit<T>(IList<T> commits)
+ {
+ }
+ }
+
+ [Test]
+ public virtual void TestReopenOnCommit()
+ {
+ Directory dir = NewDirectory();
+ IndexWriter writer = new IndexWriter(dir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())).SetIndexDeletionPolicy(new KeepAllCommits()).SetMaxBufferedDocs(-1).SetMergePolicy(NewLogMergePolicy(10)));
+ for (int i = 0; i < 4; i++)
+ {
+ Document doc = new Document();
+ doc.Add(NewStringField("id", "" + i, Field.Store.NO));
+ writer.AddDocument(doc);
+ IDictionary<string, string> data = new Dictionary<string, string>();
+ data["index"] = i + "";
+ writer.CommitData = data;
+ writer.Commit();
+ }
+ for (int i = 0; i < 4; i++)
+ {
+ writer.DeleteDocuments(new Term("id", "" + i));
+ IDictionary<string, string> data = new Dictionary<string, string>();
+ data["index"] = (4 + i) + "";
+ writer.CommitData = data;
+ writer.Commit();
+ }
+ writer.Dispose();
+
+ DirectoryReader r = DirectoryReader.Open(dir);
+ Assert.AreEqual(0, r.NumDocs);
+
+ ICollection<IndexCommit> commits = DirectoryReader.ListCommits(dir);
+ foreach (IndexCommit commit in commits)
+ {
+ DirectoryReader r2 = DirectoryReader.OpenIfChanged(r, commit);
+ Assert.IsNotNull(r2);
+ Assert.IsTrue(r2 != r);
+
+ IDictionary<string, string> s = commit.UserData;
+ int v;
+ if (s.Count == 0)
+ {
+ // First commit created by IW
+ v = -1;
+ }
+ else
+ {
+ v = Convert.ToInt32(s["index"]);
+ }
+ if (v < 4)
+ {
+ Assert.AreEqual(1 + v, r2.NumDocs);
+ }
+ else
+ {
+ Assert.AreEqual(7 - v, r2.NumDocs);
+ }
+ r.Dispose();
+ r = r2;
+ }
+ r.Dispose();
+ dir.Dispose();
+ }
+
+ [Test]
+ public virtual void TestOpenIfChangedNRTToCommit()
+ {
+ Directory dir = NewDirectory();
+
+ // Can't use RIW because it randomly commits:
+ IndexWriter w = new IndexWriter(dir, NewIndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random())));
+ Document doc = new Document();
+ doc.Add(NewStringField("field", "value", Field.Store.NO));
+ w.AddDocument(doc);
+ w.Commit();
+ IList<IndexCommit> commits = DirectoryReader.ListCommits(dir);
+ Assert.AreEqual(1, commits.Count);
+ w.AddDocument(doc);
+ DirectoryReader r = DirectoryReader.Open(w, true);
+
+ Assert.AreEqual(2, r.NumDocs);
+ IndexReader r2 = DirectoryReader.OpenIfChanged(r, commits[0]);
+ Assert.IsNotNull(r2);
+ r.Dispose();
+ Assert.AreEqual(1, r2.NumDocs);
+ w.Dispose();
+ r2.Dispose();
+ dir.Dispose();
+ }
+ }
+}
\ No newline at end of file