| /* |
| * 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 System; |
| using System.Threading; |
| using Lucene.Net.Analysis.Tokenattributes; |
| using Lucene.Net.Support; |
| using NUnit.Framework; |
| |
| using Analyzer = Lucene.Net.Analysis.Analyzer; |
| using CachingTokenFilter = Lucene.Net.Analysis.CachingTokenFilter; |
| using SimpleAnalyzer = Lucene.Net.Analysis.SimpleAnalyzer; |
| using StopAnalyzer = Lucene.Net.Analysis.StopAnalyzer; |
| using TeeSinkTokenFilter = Lucene.Net.Analysis.TeeSinkTokenFilter; |
| using TokenFilter = Lucene.Net.Analysis.TokenFilter; |
| using TokenStream = Lucene.Net.Analysis.TokenStream; |
| using WhitespaceAnalyzer = Lucene.Net.Analysis.WhitespaceAnalyzer; |
| using WhitespaceTokenizer = Lucene.Net.Analysis.WhitespaceTokenizer; |
| using StandardAnalyzer = Lucene.Net.Analysis.Standard.StandardAnalyzer; |
| using StandardTokenizer = Lucene.Net.Analysis.Standard.StandardTokenizer; |
| using Document = Lucene.Net.Documents.Document; |
| using Field = Lucene.Net.Documents.Field; |
| using AlreadyClosedException = Lucene.Net.Store.AlreadyClosedException; |
| using Directory = Lucene.Net.Store.Directory; |
| using FSDirectory = Lucene.Net.Store.FSDirectory; |
| using IndexInput = Lucene.Net.Store.IndexInput; |
| using IndexOutput = Lucene.Net.Store.IndexOutput; |
| using Lock = Lucene.Net.Store.Lock; |
| using LockFactory = Lucene.Net.Store.LockFactory; |
| using MockRAMDirectory = Lucene.Net.Store.MockRAMDirectory; |
| using RAMDirectory = Lucene.Net.Store.RAMDirectory; |
| using SingleInstanceLockFactory = Lucene.Net.Store.SingleInstanceLockFactory; |
| using UnicodeUtil = Lucene.Net.Util.UnicodeUtil; |
| using BaseTokenStreamTestCase = Lucene.Net.Test.Analysis.BaseTokenStreamTestCase; |
| using IndexSearcher = Lucene.Net.Search.IndexSearcher; |
| using PhraseQuery = Lucene.Net.Search.PhraseQuery; |
| using Query = Lucene.Net.Search.Query; |
| using ScoreDoc = Lucene.Net.Search.ScoreDoc; |
| using TermQuery = Lucene.Net.Search.TermQuery; |
| using SpanTermQuery = Lucene.Net.Search.Spans.SpanTermQuery; |
| using _TestUtil = Lucene.Net.Util._TestUtil; |
| using System.Collections.Generic; |
| |
| namespace Lucene.Net.Index |
| { |
| [TestFixture] |
| public class TestIndexWriter : Test.Analysis.BaseTokenStreamTestCase |
| { |
| //public TestIndexWriter(System.String name) |
| // : base(name) |
| //{ |
| //} |
| |
| public class MyRAMDirectory : RAMDirectory |
| { |
| private void InitBlock(TestIndexWriter enclosingInstance) |
| { |
| this.enclosingInstance = enclosingInstance; |
| } |
| private TestIndexWriter enclosingInstance; |
| public TestIndexWriter Enclosing_Instance |
| { |
| get |
| { |
| return enclosingInstance; |
| } |
| |
| } |
| private LockFactory myLockFactory; |
| internal MyRAMDirectory(TestIndexWriter enclosingInstance) |
| { |
| InitBlock(enclosingInstance); |
| interalLockFactory = null; |
| myLockFactory = new SingleInstanceLockFactory(); |
| } |
| public override Lock MakeLock(System.String name) |
| { |
| return myLockFactory.MakeLock(name); |
| } |
| } |
| private class AnonymousClassAnalyzer : Analyzer |
| { |
| public AnonymousClassAnalyzer(TestIndexWriter enclosingInstance) |
| { |
| InitBlock(enclosingInstance); |
| } |
| private class AnonymousClassTokenFilter : TokenFilter |
| { |
| public AnonymousClassTokenFilter(AnonymousClassAnalyzer enclosingInstance, StandardTokenizer standardTokenizer) |
| : base(standardTokenizer) |
| { |
| InitBlock(enclosingInstance); |
| } |
| private void InitBlock(AnonymousClassAnalyzer enclosingInstance) |
| { |
| this.enclosingInstance = enclosingInstance; |
| } |
| private AnonymousClassAnalyzer enclosingInstance; |
| public AnonymousClassAnalyzer Enclosing_Instance |
| { |
| get |
| { |
| return enclosingInstance; |
| } |
| |
| } |
| private int count = 0; |
| |
| public override bool IncrementToken() |
| { |
| if (count++ == 5) |
| { |
| throw new System.IO.IOException(); |
| } |
| return input.IncrementToken(); |
| } |
| } |
| private void InitBlock(TestIndexWriter enclosingInstance) |
| { |
| this.enclosingInstance = enclosingInstance; |
| } |
| private TestIndexWriter enclosingInstance; |
| public TestIndexWriter Enclosing_Instance |
| { |
| get |
| { |
| return enclosingInstance; |
| } |
| |
| } |
| |
| public override /*virtual*/ TokenStream TokenStream(System.String fieldName, System.IO.TextReader reader) |
| { |
| return new AnonymousClassTokenFilter(this, new StandardTokenizer(Util.Version.LUCENE_CURRENT, reader)); |
| } |
| } |
| private class AnonymousClassAnalyzer1 : Analyzer |
| { |
| public AnonymousClassAnalyzer1(TestIndexWriter enclosingInstance) |
| { |
| InitBlock(enclosingInstance); |
| } |
| private void InitBlock(TestIndexWriter enclosingInstance) |
| { |
| this.enclosingInstance = enclosingInstance; |
| } |
| private TestIndexWriter enclosingInstance; |
| public TestIndexWriter Enclosing_Instance |
| { |
| get |
| { |
| return enclosingInstance; |
| } |
| |
| } |
| public override /*virtual*/ TokenStream TokenStream(System.String fieldName, System.IO.TextReader reader) |
| { |
| return new CrashingFilter(this.enclosingInstance, fieldName, new WhitespaceTokenizer(reader)); |
| } |
| } |
| private class AnonymousClassAnalyzer2 : Analyzer |
| { |
| public AnonymousClassAnalyzer2(TestIndexWriter enclosingInstance) |
| { |
| InitBlock(enclosingInstance); |
| } |
| private void InitBlock(TestIndexWriter enclosingInstance) |
| { |
| this.enclosingInstance = enclosingInstance; |
| } |
| private TestIndexWriter enclosingInstance; |
| public TestIndexWriter Enclosing_Instance |
| { |
| get |
| { |
| return enclosingInstance; |
| } |
| |
| } |
| public override /*virtual*/ TokenStream TokenStream(System.String fieldName, System.IO.TextReader reader) |
| { |
| return new CrashingFilter(this.enclosingInstance, fieldName, new WhitespaceTokenizer(reader)); |
| } |
| } |
| private class AnonymousClassThread : ThreadClass |
| { |
| public AnonymousClassThread(int NUM_ITER, IndexWriter writer, int finalI, TestIndexWriter enclosingInstance) |
| { |
| InitBlock(NUM_ITER, writer, finalI, enclosingInstance); |
| } |
| private void InitBlock(int NUM_ITER, IndexWriter writer, int finalI, TestIndexWriter enclosingInstance) |
| { |
| this.NUM_ITER = NUM_ITER; |
| this.writer = writer; |
| this.finalI = finalI; |
| this.enclosingInstance = enclosingInstance; |
| } |
| private int NUM_ITER; |
| private IndexWriter writer; |
| private int finalI; |
| private TestIndexWriter enclosingInstance; |
| public TestIndexWriter Enclosing_Instance |
| { |
| get |
| { |
| return enclosingInstance; |
| } |
| |
| } |
| override public void Run() |
| { |
| try |
| { |
| for (int iter = 0; iter < NUM_ITER; iter++) |
| { |
| Document doc = new Document(); |
| doc.Add(new Field("contents", "here are some contents", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS)); |
| writer.AddDocument(doc); |
| writer.AddDocument(doc); |
| doc.Add(new Field("crash", "this should crash after 4 terms", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS)); |
| doc.Add(new Field("other", "this will not get indexed", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS)); |
| |
| Assert.Throws<System.IO.IOException>(() => writer.AddDocument(doc), "did not hit expected exception"); |
| |
| if (0 == finalI) |
| { |
| doc = new Document(); |
| doc.Add(new Field("contents", "here are some contents", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS)); |
| writer.AddDocument(doc); |
| writer.AddDocument(doc); |
| } |
| } |
| } |
| catch (System.Exception t) |
| { |
| lock (this) |
| { |
| System.Console.Out.WriteLine(ThreadClass.Current().Name + ": ERROR: hit unexpected exception"); |
| System.Console.Out.WriteLine(t.StackTrace); |
| } |
| Assert.Fail(); |
| } |
| } |
| } |
| private class AnonymousClassThread1 : ThreadClass |
| { |
| public AnonymousClassThread1(IndexWriter finalWriter, Document doc, System.Collections.ArrayList failure, TestIndexWriter enclosingInstance) |
| { |
| InitBlock(finalWriter, doc, failure, enclosingInstance); |
| } |
| private void InitBlock(IndexWriter finalWriter, Document doc, System.Collections.ArrayList failure, TestIndexWriter enclosingInstance) |
| { |
| this.finalWriter = finalWriter; |
| this.doc = doc; |
| this.failure = failure; |
| this.enclosingInstance = enclosingInstance; |
| } |
| private IndexWriter finalWriter; |
| private Document doc; |
| private System.Collections.ArrayList failure; |
| private TestIndexWriter enclosingInstance; |
| public TestIndexWriter Enclosing_Instance |
| { |
| get |
| { |
| return enclosingInstance; |
| } |
| |
| } |
| override public void Run() |
| { |
| bool done = false; |
| while (!done) |
| { |
| for (int i = 0; i < 100; i++) |
| { |
| try |
| { |
| finalWriter.AddDocument(doc); |
| } |
| catch (AlreadyClosedException) |
| { |
| done = true; |
| break; |
| } |
| catch (System.NullReferenceException) |
| { |
| done = true; |
| break; |
| } |
| catch (System.Exception e) |
| { |
| System.Console.Out.WriteLine(e.StackTrace); |
| failure.Add(e); |
| done = true; |
| break; |
| } |
| } |
| System.Threading.Thread.Sleep(0); |
| } |
| } |
| } |
| private class AnonymousClassAnalyzer3 : Analyzer |
| { |
| public AnonymousClassAnalyzer3(TestIndexWriter enclosingInstance) |
| { |
| InitBlock(enclosingInstance); |
| } |
| private void InitBlock(TestIndexWriter enclosingInstance) |
| { |
| this.enclosingInstance = enclosingInstance; |
| } |
| private TestIndexWriter enclosingInstance; |
| public TestIndexWriter Enclosing_Instance |
| { |
| get |
| { |
| return enclosingInstance; |
| } |
| |
| } |
| public override /*virtual*/ TokenStream TokenStream(System.String fieldName, System.IO.TextReader reader) |
| { |
| return new CrashingFilter(this.enclosingInstance, fieldName, new WhitespaceTokenizer(reader)); |
| } |
| } |
| private class AnonymousClassTokenStream : TokenStream |
| { |
| public AnonymousClassTokenStream(TestIndexWriter enclosingInstance) |
| { |
| InitBlock(enclosingInstance); |
| } |
| private void InitBlock(TestIndexWriter enclosingInstance) |
| { |
| this.enclosingInstance = enclosingInstance; |
| this.termAtt = this.AddAttribute<ITermAttribute>(); |
| this.posIncrAtt = this.AddAttribute<IPositionIncrementAttribute>(); |
| } |
| private TestIndexWriter enclosingInstance; |
| public TestIndexWriter Enclosing_Instance |
| { |
| get |
| { |
| return enclosingInstance; |
| } |
| |
| } |
| internal ITermAttribute termAtt; |
| internal IPositionIncrementAttribute posIncrAtt; |
| |
| internal System.Collections.IEnumerator tokens = new System.Collections.ArrayList(new System.String[] { "a", "b", "c" }).GetEnumerator(); |
| internal bool first = true; |
| |
| public override bool IncrementToken() |
| { |
| if (!tokens.MoveNext()) |
| return false; |
| ClearAttributes(); |
| termAtt.SetTermBuffer((System.String)tokens.Current); |
| posIncrAtt.PositionIncrement = first ? 0 : 1; |
| first = false; |
| return true; |
| } |
| |
| protected override void Dispose(bool disposing) |
| { |
| // Do nothing |
| } |
| } |
| private class AnonymousClassIndexWriter : IndexWriter |
| { |
| public AnonymousClassIndexWriter(System.Collections.IList thrown, TestIndexWriter enclosingInstance, MockRAMDirectory mockRAMDir, StandardAnalyzer standardAnalyzer) |
| : base(mockRAMDir, standardAnalyzer, MaxFieldLength.UNLIMITED) |
| { |
| InitBlock(thrown, enclosingInstance); |
| } |
| private void InitBlock(System.Collections.IList thrown, TestIndexWriter enclosingInstance) |
| { |
| this.thrown = thrown; |
| this.enclosingInstance = enclosingInstance; |
| } |
| private System.Collections.IList thrown; |
| private TestIndexWriter enclosingInstance; |
| public TestIndexWriter Enclosing_Instance |
| { |
| get |
| { |
| return enclosingInstance; |
| } |
| |
| } |
| public override void Message(System.String message) |
| { |
| if (message.StartsWith("now flush at close") && 0 == thrown.Count) |
| { |
| thrown.Add(null); |
| throw new System.OutOfMemoryException("fake OOME at " + message); |
| } |
| } |
| } |
| |
| [Test] |
| public virtual void TestDocCount() |
| { |
| Directory dir = new RAMDirectory(); |
| |
| IndexWriter writer = null; |
| IndexReader reader = null; |
| int i; |
| |
| IndexWriter.DefaultWriteLockTimeout = 2000; |
| Assert.AreEqual(2000, IndexWriter.DefaultWriteLockTimeout); |
| |
| writer = new IndexWriter(dir, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.LIMITED); |
| |
| IndexWriter.DefaultWriteLockTimeout = 1000; |
| |
| // add 100 documents |
| for (i = 0; i < 100; i++) |
| { |
| AddDoc(writer); |
| } |
| Assert.AreEqual(100, writer.MaxDoc()); |
| writer.Close(); |
| |
| // delete 40 documents |
| reader = IndexReader.Open(dir, false); |
| for (i = 0; i < 40; i++) |
| { |
| reader.DeleteDocument(i); |
| } |
| reader.Close(); |
| |
| // test doc count before segments are merged/index is optimized |
| writer = new IndexWriter(dir, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.LIMITED); |
| Assert.AreEqual(100, writer.MaxDoc()); |
| writer.Close(); |
| |
| reader = IndexReader.Open(dir, true); |
| Assert.AreEqual(100, reader.MaxDoc); |
| Assert.AreEqual(60, reader.NumDocs()); |
| reader.Close(); |
| |
| // optimize the index and check that the new doc count is correct |
| writer = new IndexWriter(dir, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.UNLIMITED); |
| Assert.AreEqual(100, writer.MaxDoc()); |
| Assert.AreEqual(60, writer.NumDocs()); |
| writer.Optimize(); |
| Assert.AreEqual(60, writer.MaxDoc()); |
| Assert.AreEqual(60, writer.NumDocs()); |
| writer.Close(); |
| |
| // check that the index reader gives the same numbers. |
| reader = IndexReader.Open(dir, true); |
| Assert.AreEqual(60, reader.MaxDoc); |
| Assert.AreEqual(60, reader.NumDocs()); |
| reader.Close(); |
| |
| // make sure opening a new index for create over |
| // this existing one works correctly: |
| writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED); |
| Assert.AreEqual(0, writer.MaxDoc()); |
| Assert.AreEqual(0, writer.NumDocs()); |
| writer.Close(); |
| } |
| |
| private static void AddDoc(IndexWriter writer) |
| { |
| Document doc = new Document(); |
| doc.Add(new Field("content", "aaa", Field.Store.NO, Field.Index.ANALYZED)); |
| writer.AddDocument(doc); |
| } |
| |
| private void AddDocWithIndex(IndexWriter writer, int index) |
| { |
| Document doc = new Document(); |
| doc.Add(new Field("content", "aaa " + index, Field.Store.YES, Field.Index.ANALYZED)); |
| doc.Add(new Field("id", "" + index, Field.Store.YES, Field.Index.ANALYZED)); |
| writer.AddDocument(doc); |
| } |
| |
| /* |
| Test: make sure when we run out of disk space or hit |
| random IOExceptions in any of the AddIndexesNoOptimize(*) calls |
| that 1) index is not corrupt (searcher can open/search |
| it) and 2) transactional semantics are followed: |
| either all or none of the incoming documents were in |
| fact added. |
| */ |
| [Test] |
| public virtual void TestAddIndexOnDiskFull() |
| { |
| int START_COUNT = 57; |
| int NUM_DIR = 50; |
| int END_COUNT = START_COUNT + NUM_DIR * 25; |
| |
| bool debug = false; |
| |
| // Build up a bunch of dirs that have indexes which we |
| // will then merge together by calling AddIndexesNoOptimize(*): |
| Directory[] dirs = new Directory[NUM_DIR]; |
| long inputDiskUsage = 0; |
| for (int i = 0; i < NUM_DIR; i++) |
| { |
| dirs[i] = new RAMDirectory(); |
| IndexWriter writer = new IndexWriter(dirs[i], new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED); |
| for (int j = 0; j < 25; j++) |
| { |
| AddDocWithIndex(writer, 25 * i + j); |
| } |
| writer.Close(); |
| System.String[] files = dirs[i].ListAll(); |
| for (int j = 0; j < files.Length; j++) |
| { |
| inputDiskUsage += dirs[i].FileLength(files[j]); |
| } |
| } |
| |
| // Now, build a starting index that has START_COUNT docs. We |
| // will then try to AddIndexesNoOptimize into a copy of this: |
| RAMDirectory startDir = new RAMDirectory(); |
| IndexWriter writer2 = new IndexWriter(startDir, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED); |
| for (int j = 0; j < START_COUNT; j++) |
| { |
| AddDocWithIndex(writer2, j); |
| } |
| writer2.Close(); |
| |
| // Make sure starting index seems to be working properly: |
| Term searchTerm = new Term("content", "aaa"); |
| IndexReader reader = IndexReader.Open(startDir, true); |
| Assert.AreEqual(57, reader.DocFreq(searchTerm), "first docFreq"); |
| |
| IndexSearcher searcher = new IndexSearcher(reader); |
| ScoreDoc[] hits = searcher.Search(new TermQuery(searchTerm), null, 1000).ScoreDocs; |
| Assert.AreEqual(57, hits.Length, "first number of hits"); |
| searcher.Close(); |
| reader.Close(); |
| |
| // Iterate with larger and larger amounts of free |
| // disk space. With little free disk space, |
| // AddIndexesNoOptimize will certainly run out of space & |
| // fail. Verify that when this happens, index is |
| // not corrupt and index in fact has added no |
| // documents. Then, we increase disk space by 2000 |
| // bytes each iteration. At some point there is |
| // enough free disk space and AddIndexesNoOptimize should |
| // succeed and index should show all documents were |
| // added. |
| |
| // String[] files = startDir.listAll(); |
| long diskUsage = startDir.SizeInBytes(); |
| |
| long startDiskUsage = 0; |
| System.String[] files2 = startDir.ListAll(); |
| for (int i = 0; i < files2.Length; i++) |
| { |
| startDiskUsage += startDir.FileLength(files2[i]); |
| } |
| |
| for (int iter = 0; iter < 3; iter++) |
| { |
| |
| if (debug) |
| System.Console.Out.WriteLine("TEST: iter=" + iter); |
| |
| // Start with 100 bytes more than we are currently using: |
| long diskFree = diskUsage + 100; |
| |
| int method = iter; |
| |
| bool success = false; |
| bool done = false; |
| |
| System.String methodName; |
| if (0 == method) |
| { |
| methodName = "addIndexes(Directory[]) + optimize()"; |
| } |
| else if (1 == method) |
| { |
| methodName = "addIndexes(IndexReader[])"; |
| } |
| else |
| { |
| methodName = "addIndexesNoOptimize(Directory[])"; |
| } |
| |
| while (!done) |
| { |
| |
| // Make a new dir that will enforce disk usage: |
| MockRAMDirectory dir = new MockRAMDirectory(startDir); |
| writer2 = new IndexWriter(dir, new WhitespaceAnalyzer(), false, IndexWriter.MaxFieldLength.UNLIMITED); |
| System.IO.IOException err = null; |
| |
| MergeScheduler ms = writer2.MergeScheduler; |
| for (int x = 0; x < 2; x++) |
| { |
| if (ms is ConcurrentMergeScheduler) |
| // This test intentionally produces exceptions |
| // in the threads that CMS launches; we don't |
| // want to pollute test output with these. |
| if (0 == x) |
| ((ConcurrentMergeScheduler)ms).SetSuppressExceptions(); |
| else |
| ((ConcurrentMergeScheduler)ms).ClearSuppressExceptions(); |
| |
| // Two loops: first time, limit disk space & |
| // throw random IOExceptions; second time, no |
| // disk space limit: |
| |
| double rate = 0.05; |
| double diskRatio = ((double)diskFree) / diskUsage; |
| long thisDiskFree; |
| |
| System.String testName = null; |
| |
| if (0 == x) |
| { |
| thisDiskFree = diskFree; |
| if (diskRatio >= 2.0) |
| { |
| rate /= 2; |
| } |
| if (diskRatio >= 4.0) |
| { |
| rate /= 2; |
| } |
| if (diskRatio >= 6.0) |
| { |
| rate = 0.0; |
| } |
| if (debug) |
| testName = "disk full test " + methodName + " with disk full at " + diskFree + " bytes"; |
| } |
| else |
| { |
| thisDiskFree = 0; |
| rate = 0.0; |
| if (debug) |
| testName = "disk full test " + methodName + " with unlimited disk space"; |
| } |
| |
| if (debug) |
| System.Console.Out.WriteLine("\ncycle: " + testName); |
| |
| dir.SetMaxSizeInBytes(thisDiskFree); |
| dir.SetRandomIOExceptionRate(rate, diskFree); |
| |
| try |
| { |
| |
| if (0 == method) |
| { |
| writer2.AddIndexesNoOptimize(dirs); |
| writer2.Optimize(); |
| } |
| else if (1 == method) |
| { |
| IndexReader[] readers = new IndexReader[dirs.Length]; |
| for (int i = 0; i < dirs.Length; i++) |
| { |
| readers[i] = IndexReader.Open(dirs[i], true); |
| } |
| try |
| { |
| writer2.AddIndexes(readers); |
| } |
| finally |
| { |
| for (int i = 0; i < dirs.Length; i++) |
| { |
| readers[i].Close(); |
| } |
| } |
| } |
| else |
| { |
| writer2.AddIndexesNoOptimize(dirs); |
| } |
| |
| success = true; |
| if (debug) |
| { |
| System.Console.Out.WriteLine(" success!"); |
| } |
| |
| if (0 == x) |
| { |
| done = true; |
| } |
| } |
| catch (System.IO.IOException e) |
| { |
| success = false; |
| err = e; |
| if (debug) |
| { |
| System.Console.Out.WriteLine(" hit IOException: " + e); |
| System.Console.Out.WriteLine(e.StackTrace); |
| } |
| |
| if (1 == x) |
| { |
| System.Console.Out.WriteLine(e.StackTrace); |
| Assert.Fail(methodName + " hit IOException after disk space was freed up"); |
| } |
| } |
| |
| // Make sure all threads from |
| // ConcurrentMergeScheduler are done |
| _TestUtil.SyncConcurrentMerges(writer2); |
| |
| if (debug) |
| { |
| System.Console.Out.WriteLine(" now test readers"); |
| } |
| |
| // Finally, verify index is not corrupt, and, if |
| // we succeeded, we see all docs added, and if we |
| // failed, we see either all docs or no docs added |
| // (transactional semantics): |
| try |
| { |
| reader = IndexReader.Open(dir, true); |
| } |
| catch (System.IO.IOException e) |
| { |
| System.Console.Out.WriteLine(e.StackTrace); |
| Assert.Fail(testName + ": exception when creating IndexReader: " + e); |
| } |
| int result = reader.DocFreq(searchTerm); |
| if (success) |
| { |
| if (result != START_COUNT) |
| { |
| Assert.Fail(testName + ": method did not throw exception but docFreq('aaa') is " + result + " instead of expected " + START_COUNT); |
| } |
| } |
| else |
| { |
| // On hitting exception we still may have added |
| // all docs: |
| if (result != START_COUNT && result != END_COUNT) |
| { |
| System.Console.Out.WriteLine(err.StackTrace); |
| Assert.Fail(testName + ": method did throw exception but docFreq('aaa') is " + result + " instead of expected " + START_COUNT + " or " + END_COUNT); |
| } |
| } |
| |
| searcher = new IndexSearcher(reader); |
| try |
| { |
| hits = searcher.Search(new TermQuery(searchTerm), null, END_COUNT).ScoreDocs; |
| } |
| catch (System.IO.IOException e) |
| { |
| System.Console.Out.WriteLine(e.StackTrace); |
| Assert.Fail(testName + ": exception when searching: " + e); |
| } |
| int result2 = hits.Length; |
| if (success) |
| { |
| if (result2 != result) |
| { |
| Assert.Fail(testName + ": method did not throw exception but hits.length for search on term 'aaa' is " + result2 + " instead of expected " + result); |
| } |
| } |
| else |
| { |
| // On hitting exception we still may have added |
| // all docs: |
| if (result2 != result) |
| { |
| System.Console.Out.WriteLine(err.StackTrace); |
| Assert.Fail(testName + ": method did throw exception but hits.length for search on term 'aaa' is " + result2 + " instead of expected " + result); |
| } |
| } |
| |
| searcher.Close(); |
| reader.Close(); |
| if (debug) |
| { |
| System.Console.Out.WriteLine(" count is " + result); |
| } |
| |
| if (done || result == END_COUNT) |
| { |
| break; |
| } |
| } |
| |
| if (debug) |
| { |
| System.Console.Out.WriteLine(" start disk = " + startDiskUsage + "; input disk = " + inputDiskUsage + "; max used = " + dir.GetMaxUsedSizeInBytes()); |
| } |
| |
| if (done) |
| { |
| // Javadocs state that temp free Directory space |
| // required is at most 3X total input size of |
| // indices so let's make sure: |
| Assert.IsTrue((dir.GetMaxUsedSizeInBytes() - startDiskUsage) < 3 * (startDiskUsage + inputDiskUsage), "max free Directory space required exceeded 1X the total input index sizes during " + methodName + ": max temp usage = " + (dir.GetMaxUsedSizeInBytes() - startDiskUsage) + " bytes; " + "starting disk usage = " + startDiskUsage + " bytes; " + "input index disk usage = " + inputDiskUsage + " bytes"); |
| } |
| |
| // Make sure we don't hit disk full during close below: |
| dir.SetMaxSizeInBytes(0); |
| dir.SetRandomIOExceptionRate(0.0, 0); |
| |
| writer2.Close(); |
| |
| // Wait for all BG threads to finish else |
| // dir.close() will throw IOException because |
| // there are still open files |
| _TestUtil.SyncConcurrentMerges(ms); |
| |
| dir.Close(); |
| |
| // Try again with 2000 more bytes of free space: |
| diskFree += 2000; |
| } |
| } |
| |
| startDir.Close(); |
| } |
| |
| /* |
| * Make sure IndexWriter cleans up on hitting a disk |
| * full exception in addDocument. |
| */ |
| [Test] |
| public virtual void TestAddDocumentOnDiskFull() |
| { |
| |
| bool debug = false; |
| |
| for (int pass = 0; pass < 2; pass++) |
| { |
| if (debug) |
| System.Console.Out.WriteLine("TEST: pass=" + pass); |
| bool doAbort = pass == 1; |
| long diskFree = 200; |
| while (true) |
| { |
| if (debug) |
| System.Console.Out.WriteLine("TEST: cycle: diskFree=" + diskFree); |
| MockRAMDirectory dir = new MockRAMDirectory(); |
| dir.SetMaxSizeInBytes(diskFree); |
| IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.UNLIMITED); |
| |
| MergeScheduler ms = writer.MergeScheduler; |
| if (ms is ConcurrentMergeScheduler) |
| // This test intentionally produces exceptions |
| // in the threads that CMS launches; we don't |
| // want to pollute test output with these. |
| ((ConcurrentMergeScheduler)ms).SetSuppressExceptions(); |
| |
| bool hitError = false; |
| try |
| { |
| for (int i = 0; i < 200; i++) |
| { |
| AddDoc(writer); |
| } |
| } |
| catch (System.IO.IOException e) |
| { |
| if (debug) |
| { |
| System.Console.Out.WriteLine("TEST: exception on addDoc"); |
| System.Console.Out.WriteLine(e.StackTrace); |
| } |
| hitError = true; |
| } |
| |
| if (hitError) |
| { |
| if (doAbort) |
| { |
| writer.Rollback(); |
| } |
| else |
| { |
| try |
| { |
| writer.Close(); |
| } |
| catch (System.IO.IOException e) |
| { |
| if (debug) |
| { |
| System.Console.Out.WriteLine("TEST: exception on close"); |
| System.Console.Out.WriteLine(e.StackTrace); |
| } |
| dir.SetMaxSizeInBytes(0); |
| writer.Close(); |
| } |
| } |
| |
| _TestUtil.SyncConcurrentMerges(ms); |
| |
| AssertNoUnreferencedFiles(dir, "after disk full during addDocument"); |
| |
| // Make sure reader can open the index: |
| IndexReader.Open(dir, true).Close(); |
| |
| dir.Close(); |
| |
| // Now try again w/ more space: |
| diskFree += 500; |
| } |
| else |
| { |
| _TestUtil.SyncConcurrentMerges(writer); |
| dir.Close(); |
| break; |
| } |
| } |
| } |
| } |
| |
| public static void AssertNoUnreferencedFiles(Directory dir, System.String message) |
| { |
| System.String[] startFiles = dir.ListAll(); |
| SegmentInfos infos = new SegmentInfos(); |
| infos.Read(dir); |
| new IndexFileDeleter(dir, new KeepOnlyLastCommitDeletionPolicy(), infos, null, null, null); |
| System.String[] endFiles = dir.ListAll(); |
| |
| System.Array.Sort(startFiles); |
| System.Array.Sort(endFiles); |
| |
| if (!CollectionsHelper.Equals(startFiles, endFiles)) |
| { |
| Assert.Fail(message + ": before delete:\n " + ArrayToString(startFiles) + "\n after delete:\n " + ArrayToString(endFiles)); |
| } |
| } |
| |
| /// <summary> Make sure we skip wicked long terms.</summary> |
| [Test] |
| public virtual void TestWickedLongTerm() |
| { |
| RAMDirectory dir = new RAMDirectory(); |
| IndexWriter writer = new IndexWriter(dir, new StandardAnalyzer(Util.Version.LUCENE_CURRENT), true, IndexWriter.MaxFieldLength.LIMITED); |
| |
| char[] chars = new char[DocumentsWriter.CHAR_BLOCK_SIZE_ForNUnit - 1]; |
| CollectionsHelper.Fill(chars, 'x'); |
| Document doc = new Document(); |
| System.String bigTerm = new System.String(chars); |
| |
| // Max length term is 16383, so this contents produces |
| // a too-long term: |
| System.String contents = "abc xyz x" + bigTerm + " another term"; |
| doc.Add(new Field("content", contents, Field.Store.NO, Field.Index.ANALYZED)); |
| writer.AddDocument(doc); |
| |
| // Make sure we can add another normal document |
| doc = new Document(); |
| doc.Add(new Field("content", "abc bbb ccc", Field.Store.NO, Field.Index.ANALYZED)); |
| writer.AddDocument(doc); |
| writer.Close(); |
| |
| IndexReader reader = IndexReader.Open(dir, true); |
| |
| // Make sure all terms < max size were indexed |
| Assert.AreEqual(2, reader.DocFreq(new Term("content", "abc"))); |
| Assert.AreEqual(1, reader.DocFreq(new Term("content", "bbb"))); |
| Assert.AreEqual(1, reader.DocFreq(new Term("content", "term"))); |
| Assert.AreEqual(1, reader.DocFreq(new Term("content", "another"))); |
| |
| // Make sure position is still incremented when |
| // massive term is skipped: |
| TermPositions tps = reader.TermPositions(new Term("content", "another")); |
| Assert.IsTrue(tps.Next()); |
| Assert.AreEqual(1, tps.Freq); |
| Assert.AreEqual(3, tps.NextPosition()); |
| |
| // Make sure the doc that has the massive term is in |
| // the index: |
| Assert.AreEqual(2, reader.NumDocs(), "document with wicked long term should is not in the index!"); |
| |
| reader.Close(); |
| |
| // Make sure we can add a document with exactly the |
| // maximum length term, and search on that term: |
| doc = new Document(); |
| doc.Add(new Field("content", bigTerm, Field.Store.NO, Field.Index.ANALYZED)); |
| StandardAnalyzer sa = new StandardAnalyzer(Util.Version.LUCENE_CURRENT); |
| sa.MaxTokenLength = 100000; |
| writer = new IndexWriter(dir, sa, IndexWriter.MaxFieldLength.LIMITED); |
| writer.AddDocument(doc); |
| writer.Close(); |
| reader = IndexReader.Open(dir, true); |
| Assert.AreEqual(1, reader.DocFreq(new Term("content", bigTerm))); |
| reader.Close(); |
| |
| dir.Close(); |
| } |
| |
| [Test] |
| public virtual void TestOptimizeMaxNumSegments() |
| { |
| MockRAMDirectory dir = new MockRAMDirectory(); |
| |
| Document doc = new Document(); |
| doc.Add(new Field("content", "aaa", Field.Store.YES, Field.Index.ANALYZED)); |
| |
| for (int numDocs = 38; numDocs < 500; numDocs += 38) |
| { |
| IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED); |
| LogDocMergePolicy ldmp = new LogDocMergePolicy(writer); |
| ldmp.MinMergeDocs = 1; |
| writer.SetMergePolicy(ldmp); |
| writer.MergeFactor = 5; |
| writer.SetMaxBufferedDocs(2); |
| for (int j = 0; j < numDocs; j++) |
| writer.AddDocument(doc); |
| writer.Close(); |
| |
| SegmentInfos sis = new SegmentInfos(); |
| sis.Read(dir); |
| int segCount = sis.Count; |
| |
| writer = new IndexWriter(dir, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.LIMITED); |
| writer.SetMergePolicy(ldmp); |
| writer.MergeFactor = 5; |
| writer.Optimize(3); |
| writer.Close(); |
| |
| sis = new SegmentInfos(); |
| sis.Read(dir); |
| int optSegCount = sis.Count; |
| |
| if (segCount < 3) |
| Assert.AreEqual(segCount, optSegCount); |
| else |
| Assert.AreEqual(3, optSegCount); |
| } |
| } |
| |
| [Test] |
| public virtual void TestOptimizeMaxNumSegments2() |
| { |
| MockRAMDirectory dir = new MockRAMDirectory(); |
| |
| Document doc = new Document(); |
| doc.Add(new Field("content", "aaa", Field.Store.YES, Field.Index.ANALYZED)); |
| |
| IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED); |
| LogDocMergePolicy ldmp = new LogDocMergePolicy(writer); |
| ldmp.MinMergeDocs = 1; |
| writer.SetMergePolicy(ldmp); |
| writer.MergeFactor = 4; |
| writer.SetMaxBufferedDocs(2); |
| |
| for (int iter = 0; iter < 10; iter++) |
| { |
| for (int i = 0; i < 19; i++) |
| writer.AddDocument(doc); |
| |
| writer.Commit(); |
| writer.WaitForMerges(); |
| writer.Commit(); |
| |
| SegmentInfos sis = new SegmentInfos(); |
| sis.Read(dir); |
| |
| int segCount = sis.Count; |
| |
| writer.Optimize(7); |
| writer.Commit(); |
| |
| sis = new SegmentInfos(); |
| ((ConcurrentMergeScheduler)writer.MergeScheduler).Sync(); |
| sis.Read(dir); |
| int optSegCount = sis.Count; |
| |
| if (segCount < 7) |
| Assert.AreEqual(segCount, optSegCount); |
| else |
| Assert.AreEqual(7, optSegCount); |
| } |
| } |
| |
| /// <summary> Make sure optimize doesn't use any more than 1X |
| /// starting index size as its temporary free space |
| /// required. |
| /// </summary> |
| [Test] |
| public virtual void TestOptimizeTempSpaceUsage() |
| { |
| |
| MockRAMDirectory dir = new MockRAMDirectory(); |
| IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED); |
| for (int j = 0; j < 500; j++) |
| { |
| AddDocWithIndex(writer, j); |
| } |
| |
| // force one extra segment w/ different doc store so |
| // we see the doc stores get merged |
| writer.Commit(); |
| AddDocWithIndex(writer, 500); |
| |
| writer.Close(); |
| |
| long startDiskUsage = 0; |
| System.String[] files = dir.ListAll(); |
| for (int i = 0; i < files.Length; i++) |
| { |
| startDiskUsage += dir.FileLength(files[i]); |
| } |
| |
| dir.ResetMaxUsedSizeInBytes(); |
| writer = new IndexWriter(dir, new WhitespaceAnalyzer(), false, IndexWriter.MaxFieldLength.LIMITED); |
| writer.Optimize(); |
| writer.Close(); |
| long maxDiskUsage = dir.GetMaxUsedSizeInBytes(); |
| |
| Assert.IsTrue(maxDiskUsage <= 4 * startDiskUsage, "optimized used too much temporary space: starting usage was " + startDiskUsage + " bytes; max temp usage was " + maxDiskUsage + " but should have been " + (4 * startDiskUsage) + " (= 4X starting usage)"); |
| dir.Close(); |
| } |
| |
| internal static System.String ArrayToString(System.String[] l) |
| { |
| System.String s = ""; |
| for (int i = 0; i < l.Length; i++) |
| { |
| if (i > 0) |
| { |
| s += "\n "; |
| } |
| s += l[i]; |
| } |
| return s; |
| } |
| |
| // Make sure we can open an index for create even when a |
| // reader holds it open (this fails pre lock-less |
| // commits on windows): |
| [Test] |
| public virtual void TestCreateWithReader() |
| { |
| System.IO.DirectoryInfo indexDir = _TestUtil.GetTempDir("lucenetestindexwriter"); |
| |
| try |
| { |
| Directory dir = FSDirectory.Open(indexDir); |
| |
| // add one document & close writer |
| IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED); |
| AddDoc(writer); |
| writer.Close(); |
| |
| // now open reader: |
| IndexReader reader = IndexReader.Open(dir, true); |
| Assert.AreEqual(reader.NumDocs(), 1, "should be one document"); |
| |
| // now open index for create: |
| writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED); |
| Assert.AreEqual(writer.MaxDoc(), 0, "should be zero documents"); |
| AddDoc(writer); |
| writer.Close(); |
| |
| Assert.AreEqual(reader.NumDocs(), 1, "should be one document"); |
| IndexReader reader2 = IndexReader.Open(dir, true); |
| Assert.AreEqual(reader2.NumDocs(), 1, "should be one document"); |
| reader.Close(); |
| reader2.Close(); |
| } |
| finally |
| { |
| RmDir(indexDir); |
| } |
| } |
| |
| // Simulate a writer that crashed while writing segments |
| // file: make sure we can still open the index (ie, |
| // gracefully fallback to the previous segments file), |
| // and that we can add to the index: |
| [Test] |
| public virtual void TestSimulatedCrashedWriter() |
| { |
| Directory dir = new RAMDirectory(); |
| |
| IndexWriter writer = null; |
| |
| writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED); |
| |
| // add 100 documents |
| for (int i = 0; i < 100; i++) |
| { |
| AddDoc(writer); |
| } |
| |
| // close |
| writer.Close(); |
| |
| long gen = SegmentInfos.GetCurrentSegmentGeneration(dir); |
| Assert.IsTrue(gen > 1, "segment generation should be > 1 but got " + gen); |
| |
| // Make the next segments file, with last byte |
| // missing, to simulate a writer that crashed while |
| // writing segments file: |
| System.String fileNameIn = SegmentInfos.GetCurrentSegmentFileName(dir); |
| System.String fileNameOut = IndexFileNames.FileNameFromGeneration(IndexFileNames.SEGMENTS, "", 1 + gen); |
| IndexInput in_Renamed = dir.OpenInput(fileNameIn); |
| IndexOutput out_Renamed = dir.CreateOutput(fileNameOut); |
| long length = in_Renamed.Length(); |
| for (int i = 0; i < length - 1; i++) |
| { |
| out_Renamed.WriteByte(in_Renamed.ReadByte()); |
| } |
| in_Renamed.Close(); |
| out_Renamed.Close(); |
| |
| IndexReader reader = null; |
| Assert.DoesNotThrow(() => reader = IndexReader.Open(dir, true), "reader failed to open on a crashed index"); |
| reader.Close(); |
| |
| Assert.DoesNotThrow(() => writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true, |
| IndexWriter.MaxFieldLength.LIMITED), |
| "writer failed to open on a crashed index"); |
| |
| |
| // add 100 documents |
| for (int i = 0; i < 100; i++) |
| { |
| AddDoc(writer); |
| } |
| |
| // close |
| writer.Close(); |
| } |
| |
| // Simulate a corrupt index by removing last byte of |
| // latest segments file and make sure we get an |
| // IOException trying to open the index: |
| [Test] |
| public virtual void TestSimulatedCorruptIndex1() |
| { |
| Directory dir = new RAMDirectory(); |
| |
| IndexWriter writer = null; |
| |
| writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED); |
| |
| // add 100 documents |
| for (int i = 0; i < 100; i++) |
| { |
| AddDoc(writer); |
| } |
| |
| // close |
| writer.Close(); |
| |
| long gen = SegmentInfos.GetCurrentSegmentGeneration(dir); |
| Assert.IsTrue(gen > 1, "segment generation should be > 1 but got " + gen); |
| |
| System.String fileNameIn = SegmentInfos.GetCurrentSegmentFileName(dir); |
| System.String fileNameOut = IndexFileNames.FileNameFromGeneration(IndexFileNames.SEGMENTS, "", 1 + gen); |
| IndexInput in_Renamed = dir.OpenInput(fileNameIn); |
| IndexOutput out_Renamed = dir.CreateOutput(fileNameOut); |
| long length = in_Renamed.Length(); |
| for (int i = 0; i < length - 1; i++) |
| { |
| out_Renamed.WriteByte(in_Renamed.ReadByte()); |
| } |
| in_Renamed.Close(); |
| out_Renamed.Close(); |
| dir.DeleteFile(fileNameIn); |
| |
| IndexReader reader; |
| Assert.Throws<System.IO.IOException>(() => reader = IndexReader.Open(dir, true), "reader did not hit IOException on opening a corrupt index"); |
| } |
| |
| [Test] |
| public virtual void TestChangesAfterClose() |
| { |
| Directory dir = new RAMDirectory(); |
| |
| IndexWriter writer = null; |
| |
| writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED); |
| AddDoc(writer); |
| |
| // close |
| writer.Close(); |
| |
| Assert.Throws<AlreadyClosedException>(() => AddDoc(writer), "did not hit AlreadyClosedException"); |
| } |
| |
| |
| // Simulate a corrupt index by removing one of the cfs |
| // files and make sure we get an IOException trying to |
| // open the index: |
| [Test] |
| public virtual void TestSimulatedCorruptIndex2() |
| { |
| Directory dir = new RAMDirectory(); |
| |
| IndexWriter writer = null; |
| |
| writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED); |
| |
| // add 100 documents |
| for (int i = 0; i < 100; i++) |
| { |
| AddDoc(writer); |
| } |
| |
| // close |
| writer.Close(); |
| |
| long gen = SegmentInfos.GetCurrentSegmentGeneration(dir); |
| Assert.IsTrue(gen > 1, "segment generation should be > 1 but got " + gen); |
| |
| System.String[] files = dir.ListAll(); |
| for (int i = 0; i < files.Length; i++) |
| { |
| if (files[i].EndsWith(".cfs")) |
| { |
| dir.DeleteFile(files[i]); |
| break; |
| } |
| } |
| |
| Assert.Throws<System.IO.FileNotFoundException>(() => IndexReader.Open(dir, true), |
| "reader did not hit IOException on opening a corrupt index"); |
| } |
| |
| /* |
| * Simple test for "commit on close": open writer then |
| * add a bunch of docs, making sure reader does not |
| * see these docs until writer is closed. |
| */ |
| [Test] |
| public virtual void TestCommitOnClose() |
| { |
| Directory dir = new RAMDirectory(); |
| IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED); |
| for (int i = 0; i < 14; i++) |
| { |
| AddDoc(writer); |
| } |
| writer.Close(); |
| |
| Term searchTerm = new Term("content", "aaa"); |
| IndexSearcher searcher = new IndexSearcher(dir, false); |
| ScoreDoc[] hits = searcher.Search(new TermQuery(searchTerm), null, 1000).ScoreDocs; |
| Assert.AreEqual(14, hits.Length, "first number of hits"); |
| searcher.Close(); |
| |
| IndexReader reader = IndexReader.Open(dir, true); |
| |
| writer = new IndexWriter(dir, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.LIMITED); |
| for (int i = 0; i < 3; i++) |
| { |
| for (int j = 0; j < 11; j++) |
| { |
| AddDoc(writer); |
| } |
| searcher = new IndexSearcher(dir, true); |
| hits = searcher.Search(new TermQuery(searchTerm), null, 1000).ScoreDocs; |
| Assert.AreEqual(14, hits.Length, "reader incorrectly sees changes from writer"); |
| searcher.Close(); |
| Assert.IsTrue(reader.IsCurrent(), "reader should have still been current"); |
| } |
| |
| // Now, close the writer: |
| writer.Close(); |
| Assert.IsFalse(reader.IsCurrent(), "reader should not be current now"); |
| |
| searcher = new IndexSearcher(dir, false); |
| hits = searcher.Search(new TermQuery(searchTerm), null, 1000).ScoreDocs; |
| Assert.AreEqual(47, hits.Length, "reader did not see changes after writer was closed"); |
| searcher.Close(); |
| } |
| |
| /* |
| * Simple test for "commit on close": open writer then |
| * add a bunch of docs, making sure reader does not |
| * see them until writer has closed. Then instead of |
| * closing the writer, call abort and verify reader sees |
| * nothing was added. Then verify we can open the index |
| * and add docs to it. |
| */ |
| [Test] |
| public virtual void TestCommitOnCloseAbort() |
| { |
| MockRAMDirectory dir = new MockRAMDirectory(); |
| IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED); |
| writer.SetMaxBufferedDocs(10); |
| for (int i = 0; i < 14; i++) |
| { |
| AddDoc(writer); |
| } |
| writer.Close(); |
| |
| Term searchTerm = new Term("content", "aaa"); |
| IndexSearcher searcher = new IndexSearcher(dir, false); |
| ScoreDoc[] hits = searcher.Search(new TermQuery(searchTerm), null, 1000).ScoreDocs; |
| Assert.AreEqual(14, hits.Length, "first number of hits"); |
| searcher.Close(); |
| |
| writer = new IndexWriter(dir, new WhitespaceAnalyzer(), false, IndexWriter.MaxFieldLength.LIMITED); |
| writer.SetMaxBufferedDocs(10); |
| for (int j = 0; j < 17; j++) |
| { |
| AddDoc(writer); |
| } |
| // Delete all docs: |
| writer.DeleteDocuments(searchTerm); |
| |
| searcher = new IndexSearcher(dir, false); |
| hits = searcher.Search(new TermQuery(searchTerm), null, 1000).ScoreDocs; |
| Assert.AreEqual(14, hits.Length, "reader incorrectly sees changes from writer"); |
| searcher.Close(); |
| |
| // Now, close the writer: |
| writer.Rollback(); |
| |
| AssertNoUnreferencedFiles(dir, "unreferenced files remain after Rollback()"); |
| |
| searcher = new IndexSearcher(dir, false); |
| hits = searcher.Search(new TermQuery(searchTerm), null, 1000).ScoreDocs; |
| Assert.AreEqual(14, hits.Length, "saw changes after writer.abort"); |
| searcher.Close(); |
| |
| // Now make sure we can re-open the index, add docs, |
| // and all is good: |
| writer = new IndexWriter(dir, new WhitespaceAnalyzer(), false, IndexWriter.MaxFieldLength.LIMITED); |
| writer.SetMaxBufferedDocs(10); |
| |
| // On abort, writer in fact may write to the same |
| // segments_N file: |
| dir.SetPreventDoubleWrite(false); |
| |
| for (int i = 0; i < 12; i++) |
| { |
| for (int j = 0; j < 17; j++) |
| { |
| AddDoc(writer); |
| } |
| searcher = new IndexSearcher(dir, false); |
| hits = searcher.Search(new TermQuery(searchTerm), null, 1000).ScoreDocs; |
| Assert.AreEqual(14, hits.Length, "reader incorrectly sees changes from writer"); |
| searcher.Close(); |
| } |
| |
| writer.Close(); |
| searcher = new IndexSearcher(dir, false); |
| hits = searcher.Search(new TermQuery(searchTerm), null, 1000).ScoreDocs; |
| Assert.AreEqual(218, hits.Length, "didn't see changes after close"); |
| searcher.Close(); |
| |
| dir.Close(); |
| } |
| |
| /* |
| * Verify that a writer with "commit on close" indeed |
| * cleans up the temp segments created after opening |
| * that are not referenced by the starting segments |
| * file. We check this by using MockRAMDirectory to |
| * measure max temp disk space used. |
| */ |
| [Test] |
| public virtual void TestCommitOnCloseDiskUsage() |
| { |
| MockRAMDirectory dir = new MockRAMDirectory(); |
| IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED); |
| for (int j = 0; j < 30; j++) |
| { |
| AddDocWithIndex(writer, j); |
| } |
| writer.Close(); |
| dir.ResetMaxUsedSizeInBytes(); |
| |
| long startDiskUsage = dir.GetMaxUsedSizeInBytes(); |
| writer = new IndexWriter(dir, new WhitespaceAnalyzer(), false, IndexWriter.MaxFieldLength.LIMITED); |
| writer.SetMaxBufferedDocs(10); |
| writer.SetMergeScheduler(new SerialMergeScheduler()); |
| for (int j = 0; j < 1470; j++) |
| { |
| AddDocWithIndex(writer, j); |
| } |
| long midDiskUsage = dir.GetMaxUsedSizeInBytes(); |
| dir.ResetMaxUsedSizeInBytes(); |
| writer.Optimize(); |
| writer.Close(); |
| |
| IndexReader.Open(dir, true).Close(); |
| |
| long endDiskUsage = dir.GetMaxUsedSizeInBytes(); |
| |
| // Ending index is 50X as large as starting index; due |
| // to 3X disk usage normally we allow 150X max |
| // transient usage. If something is wrong w/ deleter |
| // and it doesn't delete intermediate segments then it |
| // will exceed this 105X: |
| // System.out.println("start " + startDiskUsage + "; mid " + midDiskUsage + ";end " + endDiskUsage); |
| Assert.IsTrue(midDiskUsage < 150 * startDiskUsage, "writer used too much space while adding documents: mid=" + midDiskUsage + " start=" + startDiskUsage + " end=" + endDiskUsage); |
| Assert.IsTrue(endDiskUsage < 150 * startDiskUsage, "writer used too much space after close: endDiskUsage=" + endDiskUsage + " startDiskUsage=" + startDiskUsage); |
| } |
| |
| |
| /* |
| * Verify that calling optimize when writer is open for |
| * "commit on close" works correctly both for Rollback() |
| * and close(). |
| */ |
| [Test] |
| public virtual void TestCommitOnCloseOptimize() |
| { |
| RAMDirectory dir = new RAMDirectory(); |
| IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED); |
| writer.SetMaxBufferedDocs(10); |
| for (int j = 0; j < 17; j++) |
| { |
| AddDocWithIndex(writer, j); |
| } |
| writer.Close(); |
| |
| writer = new IndexWriter(dir, new WhitespaceAnalyzer(), false, IndexWriter.MaxFieldLength.LIMITED); |
| writer.Optimize(); |
| |
| // Open a reader before closing (commiting) the writer: |
| IndexReader reader = IndexReader.Open(dir, true); |
| |
| // Reader should see index as unoptimized at this |
| // point: |
| Assert.IsFalse(reader.IsOptimized(), "Reader incorrectly sees that the index is optimized"); |
| reader.Close(); |
| |
| // Abort the writer: |
| writer.Rollback(); |
| AssertNoUnreferencedFiles(dir, "aborted writer after optimize"); |
| |
| // Open a reader after aborting writer: |
| reader = IndexReader.Open(dir, true); |
| |
| // Reader should still see index as unoptimized: |
| Assert.IsFalse(reader.IsOptimized(), "Reader incorrectly sees that the index is optimized"); |
| reader.Close(); |
| |
| writer = new IndexWriter(dir, new WhitespaceAnalyzer(), false, IndexWriter.MaxFieldLength.LIMITED); |
| writer.Optimize(); |
| writer.Close(); |
| AssertNoUnreferencedFiles(dir, "aborted writer after optimize"); |
| |
| // Open a reader after aborting writer: |
| reader = IndexReader.Open(dir, true); |
| |
| // Reader should still see index as unoptimized: |
| Assert.IsTrue(reader.IsOptimized(), "Reader incorrectly sees that the index is unoptimized"); |
| reader.Close(); |
| } |
| |
| [Test] |
| public virtual void TestIndexNoDocuments() |
| { |
| RAMDirectory dir = new RAMDirectory(); |
| IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED); |
| writer.Commit(); |
| writer.Close(); |
| |
| IndexReader reader = IndexReader.Open(dir, true); |
| Assert.AreEqual(0, reader.MaxDoc); |
| Assert.AreEqual(0, reader.NumDocs()); |
| reader.Close(); |
| |
| writer = new IndexWriter(dir, new WhitespaceAnalyzer(), false, IndexWriter.MaxFieldLength.LIMITED); |
| writer.Commit(); |
| writer.Close(); |
| |
| reader = IndexReader.Open(dir, true); |
| Assert.AreEqual(0, reader.MaxDoc); |
| Assert.AreEqual(0, reader.NumDocs()); |
| reader.Close(); |
| } |
| |
| [Test] |
| public virtual void TestManyFields() |
| { |
| RAMDirectory dir = new RAMDirectory(); |
| IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED); |
| writer.SetMaxBufferedDocs(10); |
| for (int j = 0; j < 100; j++) |
| { |
| Document doc = new Document(); |
| doc.Add(new Field("a" + j, "aaa" + j, Field.Store.YES, Field.Index.ANALYZED)); |
| doc.Add(new Field("b" + j, "aaa" + j, Field.Store.YES, Field.Index.ANALYZED)); |
| doc.Add(new Field("c" + j, "aaa" + j, Field.Store.YES, Field.Index.ANALYZED)); |
| doc.Add(new Field("d" + j, "aaa", Field.Store.YES, Field.Index.ANALYZED)); |
| doc.Add(new Field("e" + j, "aaa", Field.Store.YES, Field.Index.ANALYZED)); |
| doc.Add(new Field("f" + j, "aaa", Field.Store.YES, Field.Index.ANALYZED)); |
| writer.AddDocument(doc); |
| } |
| writer.Close(); |
| |
| IndexReader reader = IndexReader.Open(dir, true); |
| Assert.AreEqual(100, reader.MaxDoc); |
| Assert.AreEqual(100, reader.NumDocs()); |
| for (int j = 0; j < 100; j++) |
| { |
| Assert.AreEqual(1, reader.DocFreq(new Term("a" + j, "aaa" + j))); |
| Assert.AreEqual(1, reader.DocFreq(new Term("b" + j, "aaa" + j))); |
| Assert.AreEqual(1, reader.DocFreq(new Term("c" + j, "aaa" + j))); |
| Assert.AreEqual(1, reader.DocFreq(new Term("d" + j, "aaa"))); |
| Assert.AreEqual(1, reader.DocFreq(new Term("e" + j, "aaa"))); |
| Assert.AreEqual(1, reader.DocFreq(new Term("f" + j, "aaa"))); |
| } |
| reader.Close(); |
| dir.Close(); |
| } |
| |
| [Test] |
| public virtual void TestSmallRAMBuffer() |
| { |
| RAMDirectory dir = new RAMDirectory(); |
| IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED); |
| writer.SetRAMBufferSizeMB(0.000001); |
| int lastNumFile = dir.ListAll().Length; |
| for (int j = 0; j < 9; j++) |
| { |
| Document doc = new Document(); |
| doc.Add(new Field("field", "aaa" + j, Field.Store.YES, Field.Index.ANALYZED)); |
| writer.AddDocument(doc); |
| int numFile = dir.ListAll().Length; |
| // Verify that with a tiny RAM buffer we see new |
| // segment after every doc |
| Assert.IsTrue(numFile > lastNumFile); |
| lastNumFile = numFile; |
| } |
| writer.Close(); |
| dir.Close(); |
| } |
| |
| // Make sure it's OK to change RAM buffer size and |
| // maxBufferedDocs in a write session |
| [Test] |
| public virtual void TestChangingRAMBuffer() |
| { |
| RAMDirectory dir = new RAMDirectory(); |
| IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED); |
| writer.SetMaxBufferedDocs(10); |
| writer.SetRAMBufferSizeMB(IndexWriter.DISABLE_AUTO_FLUSH); |
| |
| int lastFlushCount = -1; |
| for (int j = 1; j < 52; j++) |
| { |
| Document doc = new Document(); |
| doc.Add(new Field("field", "aaa" + j, Field.Store.YES, Field.Index.ANALYZED)); |
| writer.AddDocument(doc); |
| _TestUtil.SyncConcurrentMerges(writer); |
| int flushCount = writer.GetFlushCount(); |
| if (j == 1) |
| lastFlushCount = flushCount; |
| else if (j < 10) |
| // No new files should be created |
| Assert.AreEqual(flushCount, lastFlushCount); |
| else if (10 == j) |
| { |
| Assert.IsTrue(flushCount > lastFlushCount); |
| lastFlushCount = flushCount; |
| writer.SetRAMBufferSizeMB(0.000001); |
| writer.SetMaxBufferedDocs(IndexWriter.DISABLE_AUTO_FLUSH); |
| } |
| else if (j < 20) |
| { |
| Assert.IsTrue(flushCount > lastFlushCount); |
| lastFlushCount = flushCount; |
| } |
| else if (20 == j) |
| { |
| writer.SetRAMBufferSizeMB(16); |
| writer.SetMaxBufferedDocs(IndexWriter.DISABLE_AUTO_FLUSH); |
| lastFlushCount = flushCount; |
| } |
| else if (j < 30) |
| { |
| Assert.AreEqual(flushCount, lastFlushCount); |
| } |
| else if (30 == j) |
| { |
| writer.SetRAMBufferSizeMB(0.000001); |
| writer.SetMaxBufferedDocs(IndexWriter.DISABLE_AUTO_FLUSH); |
| } |
| else if (j < 40) |
| { |
| Assert.IsTrue(flushCount > lastFlushCount); |
| lastFlushCount = flushCount; |
| } |
| else if (40 == j) |
| { |
| writer.SetMaxBufferedDocs(10); |
| writer.SetRAMBufferSizeMB(IndexWriter.DISABLE_AUTO_FLUSH); |
| lastFlushCount = flushCount; |
| } |
| else if (j < 50) |
| { |
| Assert.AreEqual(flushCount, lastFlushCount); |
| writer.SetMaxBufferedDocs(10); |
| writer.SetRAMBufferSizeMB(IndexWriter.DISABLE_AUTO_FLUSH); |
| } |
| else if (50 == j) |
| { |
| Assert.IsTrue(flushCount > lastFlushCount); |
| } |
| } |
| writer.Close(); |
| dir.Close(); |
| } |
| |
| [Test] |
| public virtual void TestChangingRAMBuffer2() |
| { |
| RAMDirectory dir = new RAMDirectory(); |
| IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED); |
| writer.SetMaxBufferedDocs(10); |
| writer.SetMaxBufferedDeleteTerms(10); |
| writer.SetRAMBufferSizeMB(IndexWriter.DISABLE_AUTO_FLUSH); |
| |
| for (int j = 1; j < 52; j++) |
| { |
| Document doc = new Document(); |
| doc.Add(new Field("field", "aaa" + j, Field.Store.YES, Field.Index.ANALYZED)); |
| writer.AddDocument(doc); |
| } |
| |
| int lastFlushCount = -1; |
| for (int j = 1; j < 52; j++) |
| { |
| writer.DeleteDocuments(new Term("field", "aaa" + j)); |
| _TestUtil.SyncConcurrentMerges(writer); |
| int flushCount = writer.GetFlushCount(); |
| if (j == 1) |
| lastFlushCount = flushCount; |
| else if (j < 10) |
| { |
| // No new files should be created |
| Assert.AreEqual(flushCount, lastFlushCount); |
| } |
| else if (10 == j) |
| { |
| Assert.IsTrue(flushCount > lastFlushCount); |
| lastFlushCount = flushCount; |
| writer.SetRAMBufferSizeMB(0.000001); |
| writer.SetMaxBufferedDeleteTerms(1); |
| } |
| else if (j < 20) |
| { |
| Assert.IsTrue(flushCount > lastFlushCount); |
| lastFlushCount = flushCount; |
| } |
| else if (20 == j) |
| { |
| writer.SetRAMBufferSizeMB(16); |
| writer.SetMaxBufferedDeleteTerms(IndexWriter.DISABLE_AUTO_FLUSH); |
| lastFlushCount = flushCount; |
| } |
| else if (j < 30) |
| { |
| Assert.AreEqual(flushCount, lastFlushCount); |
| } |
| else if (30 == j) |
| { |
| writer.SetRAMBufferSizeMB(0.000001); |
| writer.SetMaxBufferedDeleteTerms(IndexWriter.DISABLE_AUTO_FLUSH); |
| writer.SetMaxBufferedDeleteTerms(1); |
| } |
| else if (j < 40) |
| { |
| Assert.IsTrue(flushCount > lastFlushCount); |
| lastFlushCount = flushCount; |
| } |
| else if (40 == j) |
| { |
| writer.SetMaxBufferedDeleteTerms(10); |
| writer.SetRAMBufferSizeMB(IndexWriter.DISABLE_AUTO_FLUSH); |
| lastFlushCount = flushCount; |
| } |
| else if (j < 50) |
| { |
| Assert.AreEqual(flushCount, lastFlushCount); |
| writer.SetMaxBufferedDeleteTerms(10); |
| writer.SetRAMBufferSizeMB(IndexWriter.DISABLE_AUTO_FLUSH); |
| } |
| else if (50 == j) |
| { |
| Assert.IsTrue(flushCount > lastFlushCount); |
| } |
| } |
| writer.Close(); |
| dir.Close(); |
| } |
| |
| [Test] |
| public virtual void TestDiverseDocs() |
| { |
| RAMDirectory dir = new RAMDirectory(); |
| IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED); |
| writer.SetRAMBufferSizeMB(0.5); |
| System.Random rand = NewRandom(); |
| for (int i = 0; i < 3; i++) |
| { |
| // First, docs where every term is unique (heavy on |
| // Posting instances) |
| for (int j = 0; j < 100; j++) |
| { |
| Document doc = new Document(); |
| for (int k = 0; k < 100; k++) |
| { |
| doc.Add(new Field("field", System.Convert.ToString(rand.Next()), Field.Store.YES, Field.Index.ANALYZED)); |
| } |
| writer.AddDocument(doc); |
| } |
| |
| // Next, many single term docs where only one term |
| // occurs (heavy on byte blocks) |
| for (int j = 0; j < 100; j++) |
| { |
| Document doc = new Document(); |
| doc.Add(new Field("field", "aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa", Field.Store.YES, Field.Index.ANALYZED)); |
| writer.AddDocument(doc); |
| } |
| |
| // Next, many single term docs where only one term |
| // occurs but the terms are very long (heavy on |
| // char[] arrays) |
| for (int j = 0; j < 100; j++) |
| { |
| System.Text.StringBuilder b = new System.Text.StringBuilder(); |
| System.String x = System.Convert.ToString(j) + "."; |
| for (int k = 0; k < 1000; k++) |
| b.Append(x); |
| System.String longTerm = b.ToString(); |
| |
| Document doc = new Document(); |
| doc.Add(new Field("field", longTerm, Field.Store.YES, Field.Index.ANALYZED)); |
| writer.AddDocument(doc); |
| } |
| } |
| writer.Close(); |
| |
| IndexSearcher searcher = new IndexSearcher(dir, false); |
| ScoreDoc[] hits = searcher.Search(new TermQuery(new Term("field", "aaa")), null, 1000).ScoreDocs; |
| Assert.AreEqual(300, hits.Length); |
| searcher.Close(); |
| |
| dir.Close(); |
| } |
| |
| [Test] |
| public virtual void TestEnablingNorms() |
| { |
| RAMDirectory dir = new RAMDirectory(); |
| IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED); |
| writer.SetMaxBufferedDocs(10); |
| // Enable norms for only 1 doc, pre flush |
| for (int j = 0; j < 10; j++) |
| { |
| Document doc = new Document(); |
| Field f = new Field("field", "aaa", Field.Store.YES, Field.Index.ANALYZED); |
| if (j != 8) |
| { |
| f.OmitNorms = true; |
| } |
| doc.Add(f); |
| writer.AddDocument(doc); |
| } |
| writer.Close(); |
| |
| Term searchTerm = new Term("field", "aaa"); |
| |
| IndexSearcher searcher = new IndexSearcher(dir, false); |
| ScoreDoc[] hits = searcher.Search(new TermQuery(searchTerm), null, 1000).ScoreDocs; |
| Assert.AreEqual(10, hits.Length); |
| searcher.Close(); |
| |
| writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED); |
| writer.SetMaxBufferedDocs(10); |
| // Enable norms for only 1 doc, post flush |
| for (int j = 0; j < 27; j++) |
| { |
| Document doc = new Document(); |
| Field f = new Field("field", "aaa", Field.Store.YES, Field.Index.ANALYZED); |
| if (j != 26) |
| { |
| f.OmitNorms = true; |
| } |
| doc.Add(f); |
| writer.AddDocument(doc); |
| } |
| writer.Close(); |
| searcher = new IndexSearcher(dir, false); |
| hits = searcher.Search(new TermQuery(searchTerm), null, 1000).ScoreDocs; |
| Assert.AreEqual(27, hits.Length); |
| searcher.Close(); |
| |
| IndexReader reader = IndexReader.Open(dir, true); |
| reader.Close(); |
| |
| dir.Close(); |
| } |
| |
| [Test] |
| public virtual void TestHighFreqTerm() |
| { |
| RAMDirectory dir = new RAMDirectory(); |
| IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true, new IndexWriter.MaxFieldLength(100000000)); |
| writer.SetRAMBufferSizeMB(0.01); |
| // Massive doc that has 128 K a's |
| System.Text.StringBuilder b = new System.Text.StringBuilder(1024 * 1024); |
| for (int i = 0; i < 4096; i++) |
| { |
| b.Append(" a a a a a a a a"); |
| b.Append(" a a a a a a a a"); |
| b.Append(" a a a a a a a a"); |
| b.Append(" a a a a a a a a"); |
| } |
| Document doc = new Document(); |
| doc.Add(new Field("field", b.ToString(), Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS)); |
| writer.AddDocument(doc); |
| writer.Close(); |
| |
| IndexReader reader = IndexReader.Open(dir, true); |
| Assert.AreEqual(1, reader.MaxDoc); |
| Assert.AreEqual(1, reader.NumDocs()); |
| Term t = new Term("field", "a"); |
| Assert.AreEqual(1, reader.DocFreq(t)); |
| TermDocs td = reader.TermDocs(t); |
| td.Next(); |
| Assert.AreEqual(128 * 1024, td.Freq); |
| reader.Close(); |
| dir.Close(); |
| } |
| |
| // Make sure that a Directory implementation that does |
| // not use LockFactory at all (ie overrides makeLock and |
| // implements its own private locking) works OK. This |
| // was raised on java-dev as loss of backwards |
| // compatibility. |
| [Test] |
| public virtual void TestNullLockFactory() |
| { |
| |
| |
| Directory dir = new MyRAMDirectory(this); |
| IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED); |
| for (int i = 0; i < 100; i++) |
| { |
| AddDoc(writer); |
| } |
| writer.Close(); |
| Term searchTerm = new Term("content", "aaa"); |
| IndexSearcher searcher = new IndexSearcher(dir, false); |
| ScoreDoc[] hits = searcher.Search(new TermQuery(searchTerm), null, 1000).ScoreDocs; |
| Assert.AreEqual(100, hits.Length, "did not get right number of hits"); |
| writer.Close(); |
| |
| writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED); |
| writer.Close(); |
| |
| dir.Close(); |
| } |
| |
| [Test] |
| public virtual void TestFlushWithNoMerging() |
| { |
| Directory dir = new RAMDirectory(); |
| IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED); |
| writer.SetMaxBufferedDocs(2); |
| Document doc = new Document(); |
| doc.Add(new Field("field", "aaa", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS)); |
| for (int i = 0; i < 19; i++) |
| writer.AddDocument(doc); |
| writer.Flush(false, true, true); |
| writer.Close(); |
| SegmentInfos sis = new SegmentInfos(); |
| sis.Read(dir); |
| // Since we flushed w/o allowing merging we should now |
| // have 10 segments |
| // {{}} assert sis.size() == 10; |
| } |
| |
| // Make sure we can flush segment w/ norms, then add |
| // empty doc (no norms) and flush |
| [Test] |
| public virtual void TestEmptyDocAfterFlushingRealDoc() |
| { |
| Directory dir = new RAMDirectory(); |
| IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED); |
| Document doc = new Document(); |
| doc.Add(new Field("field", "aaa", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS)); |
| writer.AddDocument(doc); |
| writer.Commit(); |
| writer.AddDocument(new Document()); |
| writer.Close(); |
| _TestUtil.CheckIndex(dir); |
| IndexReader reader = IndexReader.Open(dir, true); |
| Assert.AreEqual(2, reader.NumDocs()); |
| } |
| |
| // Test calling optimize(false) whereby optimize is kicked |
| // off but we don't wait for it to finish (but |
| // writer.close()) does wait |
| [Test] |
| public virtual void TestBackgroundOptimize() |
| { |
| |
| Directory dir = new MockRAMDirectory(); |
| for (int pass = 0; pass < 2; pass++) |
| { |
| IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED); |
| writer.SetMergeScheduler(new ConcurrentMergeScheduler()); |
| Document doc = new Document(); |
| doc.Add(new Field("field", "aaa", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS)); |
| writer.SetMaxBufferedDocs(2); |
| writer.MergeFactor = 101; |
| for (int i = 0; i < 200; i++) |
| writer.AddDocument(doc); |
| writer.Optimize(false); |
| |
| if (0 == pass) |
| { |
| writer.Close(); |
| IndexReader reader = IndexReader.Open(dir, false); |
| Assert.IsTrue(reader.IsOptimized()); |
| reader.Close(); |
| } |
| else |
| { |
| // Get another segment to flush so we can verify it is |
| // NOT included in the optimization |
| writer.AddDocument(doc); |
| writer.AddDocument(doc); |
| writer.Close(); |
| |
| IndexReader reader = IndexReader.Open(dir, true); |
| Assert.IsTrue(!reader.IsOptimized()); |
| reader.Close(); |
| |
| SegmentInfos infos = new SegmentInfos(); |
| infos.Read(dir); |
| Assert.AreEqual(2, infos.Count); |
| } |
| } |
| |
| dir.Close(); |
| } |
| |
| // TODO: Could be less complicated. |
| private void RmDir(System.IO.DirectoryInfo dir) |
| { |
| System.IO.FileInfo[] files = FileSupport.GetFiles(dir); |
| if (files != null) |
| { |
| for (int i = 0; i < files.Length; i++) |
| { |
| bool tmpBool; |
| if (System.IO.File.Exists(files[i].FullName)) |
| { |
| System.IO.File.Delete(files[i].FullName); |
| tmpBool = true; |
| } |
| else if (System.IO.Directory.Exists(files[i].FullName)) |
| { |
| System.IO.Directory.Delete(files[i].FullName); |
| tmpBool = true; |
| } |
| else |
| tmpBool = false; |
| bool generatedAux = tmpBool; |
| } |
| } |
| bool tmpBool2; |
| if (System.IO.File.Exists(dir.FullName)) |
| { |
| System.IO.File.Delete(dir.FullName); |
| tmpBool2 = true; |
| } |
| else if (System.IO.Directory.Exists(dir.FullName)) |
| { |
| System.IO.Directory.Delete(dir.FullName); |
| tmpBool2 = true; |
| } |
| else |
| tmpBool2 = false; |
| bool generatedAux2 = tmpBool2; |
| } |
| |
| /// <summary> Test that no NullPointerException will be raised, |
| /// when adding one document with a single, empty field |
| /// and term vectors enabled. |
| /// </summary> |
| /// <throws> IOException </throws> |
| /// <summary> |
| /// </summary> |
| [Test] |
| public virtual void TestBadSegment() |
| { |
| MockRAMDirectory dir = new MockRAMDirectory(); |
| IndexWriter ir = new IndexWriter(dir, new StandardAnalyzer(Util.Version.LUCENE_CURRENT), true, IndexWriter.MaxFieldLength.LIMITED); |
| |
| Document document = new Document(); |
| document.Add(new Field("tvtest", "", Field.Store.NO, Field.Index.ANALYZED, Field.TermVector.YES)); |
| ir.AddDocument(document); |
| ir.Close(); |
| dir.Close(); |
| } |
| |
| // LUCENE-1008 |
| [Test] |
| public virtual void TestNoTermVectorAfterTermVector() |
| { |
| MockRAMDirectory dir = new MockRAMDirectory(); |
| IndexWriter iw = new IndexWriter(dir, new StandardAnalyzer(Util.Version.LUCENE_CURRENT), true, IndexWriter.MaxFieldLength.LIMITED); |
| Document document = new Document(); |
| document.Add(new Field("tvtest", "a b c", Field.Store.NO, Field.Index.ANALYZED, Field.TermVector.YES)); |
| iw.AddDocument(document); |
| document = new Document(); |
| document.Add(new Field("tvtest", "x y z", Field.Store.NO, Field.Index.ANALYZED, Field.TermVector.NO)); |
| iw.AddDocument(document); |
| // Make first segment |
| iw.Commit(); |
| |
| document.Add(new Field("tvtest", "a b c", Field.Store.NO, Field.Index.ANALYZED, Field.TermVector.YES)); |
| iw.AddDocument(document); |
| // Make 2nd segment |
| iw.Commit(); |
| |
| iw.Optimize(); |
| iw.Close(); |
| dir.Close(); |
| } |
| |
| // LUCENE-1010 |
| [Test] |
| public virtual void TestNoTermVectorAfterTermVectorMerge() |
| { |
| MockRAMDirectory dir = new MockRAMDirectory(); |
| IndexWriter iw = new IndexWriter(dir, new StandardAnalyzer(Util.Version.LUCENE_CURRENT), true, IndexWriter.MaxFieldLength.LIMITED); |
| Document document = new Document(); |
| document.Add(new Field("tvtest", "a b c", Field.Store.NO, Field.Index.ANALYZED, Field.TermVector.YES)); |
| iw.AddDocument(document); |
| iw.Commit(); |
| |
| document = new Document(); |
| document.Add(new Field("tvtest", "x y z", Field.Store.NO, Field.Index.ANALYZED, Field.TermVector.NO)); |
| iw.AddDocument(document); |
| // Make first segment |
| iw.Commit(); |
| |
| iw.Optimize(); |
| |
| document.Add(new Field("tvtest", "a b c", Field.Store.NO, Field.Index.ANALYZED, Field.TermVector.YES)); |
| iw.AddDocument(document); |
| // Make 2nd segment |
| iw.Commit(); |
| iw.Optimize(); |
| |
| iw.Close(); |
| dir.Close(); |
| } |
| |
| // LUCENE-1036 |
| [Test] |
| public virtual void TestMaxThreadPriority() |
| { |
| int pri = (System.Int32)ThreadClass.Current().Priority; |
| try |
| { |
| MockRAMDirectory dir = new MockRAMDirectory(); |
| IndexWriter iw = new IndexWriter(dir, new StandardAnalyzer(Util.Version.LUCENE_CURRENT), true, IndexWriter.MaxFieldLength.LIMITED); |
| Document document = new Document(); |
| document.Add(new Field("tvtest", "a b c", Field.Store.NO, Field.Index.ANALYZED, Field.TermVector.YES)); |
| iw.SetMaxBufferedDocs(2); |
| iw.MergeFactor = 2; |
| ThreadClass.Current().Priority = (System.Threading.ThreadPriority)System.Threading.ThreadPriority.Highest; |
| for (int i = 0; i < 4; i++) |
| iw.AddDocument(document); |
| iw.Close(); |
| } |
| finally |
| { |
| ThreadClass.Current().Priority = (System.Threading.ThreadPriority)pri; |
| } |
| } |
| |
| // Just intercepts all merges & verifies that we are never |
| // merging a segment with >= 20 (maxMergeDocs) docs |
| private class MyMergeScheduler : MergeScheduler |
| { |
| public MyMergeScheduler(TestIndexWriter enclosingInstance) |
| { |
| InitBlock(enclosingInstance); |
| } |
| private void InitBlock(TestIndexWriter enclosingInstance) |
| { |
| this.enclosingInstance = enclosingInstance; |
| } |
| private TestIndexWriter enclosingInstance; |
| public TestIndexWriter Enclosing_Instance |
| { |
| get |
| { |
| return enclosingInstance; |
| } |
| |
| } |
| public override /*virtual*/ void Merge(IndexWriter writer) |
| { |
| lock (this) |
| { |
| |
| while (true) |
| { |
| MergePolicy.OneMerge merge = writer.GetNextMerge(); |
| if (merge == null) |
| break; |
| for (int i = 0; i < merge.segments_ForNUnit.Count; i++) |
| ; // {{}} assert merge.segments.Info(i).docCount < 20; |
| writer.Merge_ForNUnit(merge); |
| } |
| } |
| } |
| protected override void Dispose(bool disposing) |
| { |
| // Do nothing |
| } |
| |
| } |
| |
| // LUCENE-1013 |
| [Test] |
| public virtual void TestSetMaxMergeDocs() |
| { |
| MockRAMDirectory dir = new MockRAMDirectory(); |
| IndexWriter iw = new IndexWriter(dir, new StandardAnalyzer(Util.Version.LUCENE_CURRENT), true, IndexWriter.MaxFieldLength.LIMITED); |
| iw.SetMergeScheduler(new MyMergeScheduler(this)); |
| iw.MaxMergeDocs = 20; |
| iw.SetMaxBufferedDocs(2); |
| iw.MergeFactor = 2; |
| Document document = new Document(); |
| document.Add(new Field("tvtest", "a b c", Field.Store.NO, Field.Index.ANALYZED, Field.TermVector.YES)); |
| for (int i = 0; i < 177; i++) |
| iw.AddDocument(document); |
| iw.Close(); |
| } |
| |
| // LUCENE-1072 |
| [Test] |
| public virtual void TestExceptionFromTokenStream() |
| { |
| RAMDirectory dir = new MockRAMDirectory(); |
| IndexWriter writer = new IndexWriter(dir, new AnonymousClassAnalyzer(this), true, IndexWriter.MaxFieldLength.LIMITED); |
| |
| Document doc = new Document(); |
| System.String contents = "aa bb cc dd ee ff gg hh ii jj kk"; |
| doc.Add(new Field("content", contents, Field.Store.NO, Field.Index.ANALYZED)); |
| |
| Assert.Throws<System.IO.IOException>(() => writer.AddDocument(doc), "did not hit expected exception"); |
| |
| // Make sure we can add another normal document |
| doc = new Document(); |
| doc.Add(new Field("content", "aa bb cc dd", Field.Store.NO, Field.Index.ANALYZED)); |
| writer.AddDocument(doc); |
| |
| // Make sure we can add another normal document |
| doc = new Document(); |
| doc.Add(new Field("content", "aa bb cc dd", Field.Store.NO, Field.Index.ANALYZED)); |
| writer.AddDocument(doc); |
| |
| writer.Close(); |
| IndexReader reader = IndexReader.Open(dir, true); |
| Term t = new Term("content", "aa"); |
| Assert.AreEqual(reader.DocFreq(t), 3); |
| |
| // Make sure the doc that hit the exception was marked |
| // as deleted: |
| TermDocs tdocs = reader.TermDocs(t); |
| int count = 0; |
| while (tdocs.Next()) |
| { |
| count++; |
| } |
| Assert.AreEqual(2, count); |
| |
| Assert.AreEqual(reader.DocFreq(new Term("content", "gg")), 0); |
| reader.Close(); |
| dir.Close(); |
| } |
| |
| private class FailOnlyOnFlush : MockRAMDirectory.Failure |
| { |
| internal new bool doFail = false; |
| internal int count; |
| |
| public override void SetDoFail() |
| { |
| this.doFail = true; |
| } |
| public override void ClearDoFail() |
| { |
| this.doFail = false; |
| } |
| |
| public override void Eval(MockRAMDirectory dir) |
| { |
| if (doFail) |
| { |
| System.Diagnostics.StackTrace trace = new System.Diagnostics.StackTrace(); |
| bool sawAppend = false; |
| bool sawFlush = false; |
| for (int i = 0; i < trace.FrameCount; i++) |
| { |
| System.Diagnostics.StackFrame sf = trace.GetFrame(i); |
| string className = sf.GetMethod().DeclaringType.Namespace + "." + sf.GetMethod().DeclaringType.Name; |
| if ("Lucene.Net.Index.FreqProxTermsWriter".Equals(className) && "AppendPostings".Equals(sf.GetMethod().Name)) |
| sawAppend = true; |
| if ("DoFlush".Equals(sf.GetMethod().Name)) |
| sawFlush = true; |
| } |
| |
| if (sawAppend && sawFlush && count++ >= 30) |
| { |
| doFail = false; |
| throw new System.IO.IOException("now failing during flush"); |
| } |
| } |
| } |
| } |
| |
| // LUCENE-1072: make sure an errant exception on flushing |
| // one segment only takes out those docs in that one flush |
| [Test] |
| public virtual void TestDocumentsWriterAbort() |
| { |
| MockRAMDirectory dir = new MockRAMDirectory(); |
| FailOnlyOnFlush failure = new FailOnlyOnFlush(); |
| failure.SetDoFail(); |
| dir.FailOn(failure); |
| |
| IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.LIMITED); |
| writer.SetMaxBufferedDocs(2); |
| Document doc = new Document(); |
| System.String contents = "aa bb cc dd ee ff gg hh ii jj kk"; |
| doc.Add(new Field("content", contents, Field.Store.NO, Field.Index.ANALYZED)); |
| bool hitError = false; |
| for (int i = 0; i < 200; i++) |
| { |
| try |
| { |
| writer.AddDocument(doc); |
| } |
| catch (System.IO.IOException ioe) |
| { |
| // only one flush should fail: |
| Assert.IsFalse(hitError); |
| hitError = true; |
| } |
| } |
| Assert.IsTrue(hitError); |
| writer.Close(); |
| IndexReader reader = IndexReader.Open(dir, true); |
| Assert.AreEqual(198, reader.DocFreq(new Term("content", "aa"))); |
| reader.Close(); |
| } |
| |
| private class CrashingFilter : TokenFilter |
| { |
| private void InitBlock(TestIndexWriter enclosingInstance) |
| { |
| this.enclosingInstance = enclosingInstance; |
| } |
| private TestIndexWriter enclosingInstance; |
| public TestIndexWriter Enclosing_Instance |
| { |
| get |
| { |
| return enclosingInstance; |
| } |
| |
| } |
| internal System.String fieldName; |
| internal int count; |
| |
| public CrashingFilter(TestIndexWriter enclosingInstance, System.String fieldName, TokenStream input) |
| : base(input) |
| { |
| InitBlock(enclosingInstance); |
| this.fieldName = fieldName; |
| } |
| |
| public override bool IncrementToken() |
| { |
| if (this.fieldName.Equals("crash") && count++ >= 4) |
| throw new System.IO.IOException("I'm experiencing problems"); |
| return input.IncrementToken(); |
| } |
| |
| public override void Reset() |
| { |
| base.Reset(); |
| count = 0; |
| } |
| } |
| |
| [Test] |
| public virtual void TestDocumentsWriterExceptions() |
| { |
| Analyzer analyzer = new AnonymousClassAnalyzer1(this); |
| |
| for (int i = 0; i < 2; i++) |
| { |
| MockRAMDirectory dir = new MockRAMDirectory(); |
| IndexWriter writer = new IndexWriter(dir, analyzer, IndexWriter.MaxFieldLength.LIMITED); |
| //writer.setInfoStream(System.out); |
| Document doc = new Document(); |
| doc.Add(new Field("contents", "here are some contents", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS)); |
| writer.AddDocument(doc); |
| writer.AddDocument(doc); |
| doc.Add(new Field("crash", "this should crash after 4 terms", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS)); |
| doc.Add(new Field("other", "this will not get indexed", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS)); |
| |
| Assert.Throws<System.IO.IOException>(() => writer.AddDocument(doc), "did not hit expected exception"); |
| |
| if (0 == i) |
| { |
| doc = new Document(); |
| doc.Add(new Field("contents", "here are some contents", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS)); |
| writer.AddDocument(doc); |
| writer.AddDocument(doc); |
| } |
| writer.Close(); |
| |
| IndexReader reader = IndexReader.Open(dir, true); |
| int expected = 3 + (1 - i) * 2; |
| Assert.AreEqual(expected, reader.DocFreq(new Term("contents", "here"))); |
| Assert.AreEqual(expected, reader.MaxDoc); |
| int numDel = 0; |
| for (int j = 0; j < reader.MaxDoc; j++) |
| { |
| if (reader.IsDeleted(j)) |
| numDel++; |
| else |
| { |
| reader.Document(j); |
| reader.GetTermFreqVectors(j); |
| } |
| } |
| reader.Close(); |
| |
| Assert.AreEqual(1, numDel); |
| |
| writer = new IndexWriter(dir, analyzer, IndexWriter.MaxFieldLength.LIMITED); |
| writer.SetMaxBufferedDocs(10); |
| doc = new Document(); |
| doc.Add(new Field("contents", "here are some contents", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS)); |
| for (int j = 0; j < 17; j++) |
| writer.AddDocument(doc); |
| writer.Optimize(); |
| writer.Close(); |
| |
| reader = IndexReader.Open(dir, true); |
| expected = 19 + (1 - i) * 2; |
| Assert.AreEqual(expected, reader.DocFreq(new Term("contents", "here"))); |
| Assert.AreEqual(expected, reader.MaxDoc); |
| numDel = 0; |
| for (int j = 0; j < reader.MaxDoc; j++) |
| { |
| if (reader.IsDeleted(j)) |
| numDel++; |
| else |
| { |
| reader.Document(j); |
| reader.GetTermFreqVectors(j); |
| } |
| } |
| reader.Close(); |
| Assert.AreEqual(0, numDel); |
| |
| dir.Close(); |
| } |
| } |
| |
| [Test] |
| public virtual void TestDocumentsWriterExceptionThreads() |
| { |
| Analyzer analyzer = new AnonymousClassAnalyzer2(this); |
| |
| int NUM_THREAD = 3; |
| int NUM_ITER = 100; |
| |
| for (int i = 0; i < 2; i++) |
| { |
| MockRAMDirectory dir = new MockRAMDirectory(); |
| |
| { |
| IndexWriter writer = new IndexWriter(dir, analyzer, IndexWriter.MaxFieldLength.LIMITED); |
| |
| int finalI = i; |
| |
| ThreadClass[] threads = new ThreadClass[NUM_THREAD]; |
| for (int t = 0; t < NUM_THREAD; t++) |
| { |
| threads[t] = new AnonymousClassThread(NUM_ITER, writer, finalI, this); |
| threads[t].Start(); |
| } |
| |
| for (int t = 0; t < NUM_THREAD; t++) |
| threads[t].Join(); |
| |
| writer.Close(); |
| } |
| |
| IndexReader reader = IndexReader.Open(dir, true); |
| int expected = (3 + (1 - i) * 2) * NUM_THREAD * NUM_ITER; |
| Assert.AreEqual(expected, reader.DocFreq(new Term("contents", "here"))); |
| Assert.AreEqual(expected, reader.MaxDoc); |
| int numDel = 0; |
| for (int j = 0; j < reader.MaxDoc; j++) |
| { |
| if (reader.IsDeleted(j)) |
| numDel++; |
| else |
| { |
| reader.Document(j); |
| reader.GetTermFreqVectors(j); |
| } |
| } |
| reader.Close(); |
| |
| Assert.AreEqual(NUM_THREAD * NUM_ITER, numDel); |
| |
| IndexWriter writer2 = new IndexWriter(dir, analyzer, IndexWriter.MaxFieldLength.LIMITED); |
| writer2.SetMaxBufferedDocs(10); |
| Document doc = new Document(); |
| doc.Add(new Field("contents", "here are some contents", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS)); |
| for (int j = 0; j < 17; j++) |
| writer2.AddDocument(doc); |
| writer2.Optimize(); |
| writer2.Close(); |
| |
| reader = IndexReader.Open(dir, true); |
| expected += 17 - NUM_THREAD * NUM_ITER; |
| Assert.AreEqual(expected, reader.DocFreq(new Term("contents", "here"))); |
| Assert.AreEqual(expected, reader.MaxDoc); |
| numDel = 0; |
| for (int j = 0; j < reader.MaxDoc; j++) |
| { |
| if (reader.IsDeleted(j)) |
| numDel++; |
| else |
| { |
| reader.Document(j); |
| reader.GetTermFreqVectors(j); |
| } |
| } |
| reader.Close(); |
| Assert.AreEqual(0, numDel); |
| |
| dir.Close(); |
| } |
| } |
| |
| [Test] |
| public virtual void TestVariableSchema() |
| { |
| MockRAMDirectory dir = new MockRAMDirectory(); |
| int delID = 0; |
| for (int i = 0; i < 20; i++) |
| { |
| IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.LIMITED); |
| writer.SetMaxBufferedDocs(2); |
| writer.MergeFactor = 2; |
| writer.UseCompoundFile = false; |
| Document doc = new Document(); |
| System.String contents = "aa bb cc dd ee ff gg hh ii jj kk"; |
| |
| if (i == 7) |
| { |
| // Add empty docs here |
| doc.Add(new Field("content3", "", Field.Store.NO, Field.Index.ANALYZED)); |
| } |
| else |
| { |
| Field.Store storeVal; |
| if (i % 2 == 0) |
| { |
| doc.Add(new Field("content4", contents, Field.Store.YES, Field.Index.ANALYZED)); |
| storeVal = Field.Store.YES; |
| } |
| else |
| storeVal = Field.Store.NO; |
| doc.Add(new Field("content1", contents, storeVal, Field.Index.ANALYZED)); |
| doc.Add(new Field("content3", "", Field.Store.YES, Field.Index.ANALYZED)); |
| doc.Add(new Field("content5", "", storeVal, Field.Index.ANALYZED)); |
| } |
| |
| for (int j = 0; j < 4; j++) |
| writer.AddDocument(doc); |
| |
| writer.Close(); |
| IndexReader reader = IndexReader.Open(dir, false); |
| reader.DeleteDocument(delID++); |
| reader.Close(); |
| |
| if (0 == i % 4) |
| { |
| writer = new IndexWriter(dir, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.LIMITED); |
| writer.UseCompoundFile = false; |
| writer.Optimize(); |
| writer.Close(); |
| } |
| } |
| } |
| |
| [Test] |
| public virtual void TestNoWaitClose() |
| { |
| RAMDirectory directory = new MockRAMDirectory(); |
| |
| Document doc = new Document(); |
| Field idField = new Field("id", "", Field.Store.YES, Field.Index.NOT_ANALYZED); |
| doc.Add(idField); |
| |
| for (int pass = 0; pass < 2; pass++) |
| { |
| IndexWriter writer = new IndexWriter(directory, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.UNLIMITED); |
| |
| //System.out.println("TEST: pass=" + pass + " cms=" + (pass >= 2)); |
| for (int iter = 0; iter < 10; iter++) |
| { |
| //System.out.println("TEST: iter=" + iter); |
| MergeScheduler ms; |
| if (pass == 1) |
| ms = new ConcurrentMergeScheduler(); |
| else |
| ms = new SerialMergeScheduler(); |
| |
| writer.SetMergeScheduler(ms); |
| writer.SetMaxBufferedDocs(2); |
| writer.MergeFactor = 100; |
| |
| for (int j = 0; j < 199; j++) |
| { |
| idField.SetValue(System.Convert.ToString(iter * 201 + j)); |
| writer.AddDocument(doc); |
| } |
| |
| int delID = iter * 199; |
| for (int j = 0; j < 20; j++) |
| { |
| writer.DeleteDocuments(new Term("id", System.Convert.ToString(delID))); |
| delID += 5; |
| } |
| |
| // Force a bunch of merge threads to kick off so we |
| // stress out aborting them on close: |
| writer.MergeFactor = 2; |
| |
| IndexWriter finalWriter = writer; |
| System.Collections.ArrayList failure = new System.Collections.ArrayList(); |
| ThreadClass t1 = new AnonymousClassThread1(finalWriter, doc, failure, this); |
| |
| if (failure.Count > 0) |
| { |
| throw (System.Exception)failure[0]; |
| } |
| |
| t1.Start(); |
| |
| writer.Close(false); |
| t1.Join(); |
| |
| // Make sure reader can read |
| IndexReader reader = IndexReader.Open(directory, true); |
| reader.Close(); |
| |
| // Reopen |
| writer = new IndexWriter(directory, new WhitespaceAnalyzer(), false, IndexWriter.MaxFieldLength.UNLIMITED); |
| } |
| writer.Close(); |
| } |
| |
| directory.Close(); |
| } |
| |
| // Used by test cases below |
| private class IndexerThread : ThreadClass |
| { |
| private void InitBlock(TestIndexWriter enclosingInstance) |
| { |
| this.enclosingInstance = enclosingInstance; |
| } |
| private TestIndexWriter enclosingInstance; |
| public TestIndexWriter Enclosing_Instance |
| { |
| get |
| { |
| return enclosingInstance; |
| } |
| |
| } |
| |
| internal bool diskFull; |
| internal System.Exception error; |
| internal AlreadyClosedException ace; |
| internal IndexWriter writer; |
| internal bool noErrors; |
| internal volatile int addCount; |
| |
| public IndexerThread(TestIndexWriter enclosingInstance, IndexWriter writer, bool noErrors) |
| { |
| InitBlock(enclosingInstance); |
| this.writer = writer; |
| this.noErrors = noErrors; |
| } |
| |
| override public void Run() |
| { |
| |
| Document doc = new Document(); |
| doc.Add(new Field("field", "aaa bbb ccc ddd eee fff ggg hhh iii jjj", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS)); |
| |
| int idUpto = 0; |
| int fullCount = 0; |
| long stopTime = (DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) + 500; |
| |
| while ((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) < stopTime) |
| { |
| try |
| { |
| writer.UpdateDocument(new Term("id", "" + (idUpto++)), doc); |
| addCount++; |
| } |
| catch (System.IO.IOException ioe) |
| { |
| //System.out.println(Thread.currentThread().getName() + ": hit exc"); |
| //ioe.printStackTrace(System.out); |
| if (ioe.Message.StartsWith("fake disk full at") || ioe.Message.Equals("now failing on purpose")) |
| { |
| diskFull = true; |
| //try |
| //{ |
| System.Threading.Thread.Sleep(new System.TimeSpan((System.Int64)10000 * 1)); |
| //} |
| //catch (System.Threading.ThreadInterruptedException ie) |
| //{ |
| // throw; |
| //} |
| if (fullCount++ >= 5) |
| break; |
| } |
| else |
| { |
| if (noErrors) |
| { |
| System.Console.Out.WriteLine(ThreadClass.Current().Name + ": ERROR: unexpected IOException:"); |
| System.Console.Out.WriteLine(ioe.StackTrace); |
| error = ioe; |
| } |
| break; |
| } |
| } |
| catch (System.Exception t) |
| { |
| //t.printStackTrace(System.out); |
| if (noErrors) |
| { |
| System.Console.Out.WriteLine(ThreadClass.Current().Name + ": ERROR: unexpected Throwable:"); |
| System.Console.Out.WriteLine(t.StackTrace); |
| error = t; |
| } |
| break; |
| } |
| } |
| } |
| } |
| |
| // LUCENE-1130: make sure we can close() even while |
| // threads are trying to add documents. Strictly |
| // speaking, this isn't valid us of Lucene's APIs, but we |
| // still want to be robust to this case: |
| [Test] |
| public virtual void TestCloseWithThreads() |
| { |
| int NUM_THREADS = 3; |
| |
| for (int iter = 0; iter < 20; iter++) |
| { |
| MockRAMDirectory dir = new MockRAMDirectory(); |
| IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.LIMITED); |
| ConcurrentMergeScheduler cms = new ConcurrentMergeScheduler(); |
| |
| // We expect AlreadyClosedException |
| cms.SetSuppressExceptions(); |
| |
| writer.SetMergeScheduler(cms); |
| writer.SetMaxBufferedDocs(10); |
| writer.MergeFactor = 4; |
| |
| IndexerThread[] threads = new IndexerThread[NUM_THREADS]; |
| |
| for (int i = 0; i < NUM_THREADS; i++) |
| threads[i] = new IndexerThread(this, writer, false); |
| |
| for (int i = 0; i < NUM_THREADS; i++) |
| threads[i].Start(); |
| |
| bool done = false; |
| while (!done) |
| { |
| System.Threading.Thread.Sleep(new System.TimeSpan((System.Int64)10000 * 100)); |
| for (int i = 0; i < NUM_THREADS; i++) |
| // only stop when at least one thread has added a doc |
| if (threads[i].addCount > 0) |
| { |
| done = true; |
| break; |
| } |
| } |
| |
| writer.Close(false); |
| |
| // Make sure threads that are adding docs are not hung: |
| for (int i = 0; i < NUM_THREADS; i++) |
| { |
| // Without fix for LUCENE-1130: one of the |
| // threads will hang |
| threads[i].Join(); |
| if (threads[i].IsAlive) |
| Assert.Fail("thread seems to be hung"); |
| } |
| |
| // Quick test to make sure index is not corrupt: |
| IndexReader reader = IndexReader.Open(dir, true); |
| TermDocs tdocs = reader.TermDocs(new Term("field", "aaa")); |
| int count = 0; |
| while (tdocs.Next()) |
| { |
| count++; |
| } |
| Assert.IsTrue(count > 0); |
| reader.Close(); |
| |
| dir.Close(); |
| } |
| } |
| |
| // LUCENE-1130: make sure immeidate disk full on creating |
| // an IndexWriter (hit during DW.ThreadState.init()) is |
| // OK: |
| [Test] |
| public virtual void TestImmediateDiskFull() |
| { |
| MockRAMDirectory dir = new MockRAMDirectory(); |
| IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.LIMITED); |
| dir.SetMaxSizeInBytes(dir.GetRecomputedActualSizeInBytes()); |
| writer.SetMaxBufferedDocs(2); |
| Document doc = new Document(); |
| doc.Add(new Field("field", "aaa bbb ccc ddd eee fff ggg hhh iii jjj", Field.Store.YES, Field.Index.ANALYZED, |
| Field.TermVector.WITH_POSITIONS_OFFSETS)); |
| |
| Assert.Throws<System.IO.IOException>(() => writer.AddDocument(doc), "did not hit disk full"); |
| |
| // Without fix for LUCENE-1130: this call will hang: |
| Assert.Throws<System.IO.IOException>(() => writer.AddDocument(doc), "did not hit disk full"); |
| Assert.Throws<System.IO.IOException>(() => writer.Close(false), "did not hit disk full"); |
| } |
| |
| // LUCENE-1130: make sure immediate disk full on creating |
| // an IndexWriter (hit during DW.ThreadState.init()), with |
| // multiple threads, is OK: |
| [Test] |
| public virtual void TestImmediateDiskFullWithThreads() |
| { |
| |
| int NUM_THREADS = 3; |
| |
| for (int iter = 0; iter < 10; iter++) |
| { |
| MockRAMDirectory dir = new MockRAMDirectory(); |
| IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.UNLIMITED); |
| ConcurrentMergeScheduler cms = new ConcurrentMergeScheduler(); |
| // We expect disk full exceptions in the merge threads |
| cms.SetSuppressExceptions(); |
| writer.SetMergeScheduler(cms); |
| writer.SetMaxBufferedDocs(2); |
| writer.MergeFactor = 4; |
| dir.SetMaxSizeInBytes(4 * 1024 + 20 * iter); |
| |
| IndexerThread[] threads = new IndexerThread[NUM_THREADS]; |
| |
| for (int i = 0; i < NUM_THREADS; i++) |
| threads[i] = new IndexerThread(this, writer, true); |
| |
| for (int i = 0; i < NUM_THREADS; i++) |
| threads[i].Start(); |
| |
| for (int i = 0; i < NUM_THREADS; i++) |
| { |
| // Without fix for LUCENE-1130: one of the |
| // threads will hang |
| threads[i].Join(); |
| Assert.IsTrue(threads[i].error == null, "hit unexpected Throwable"); |
| } |
| |
| try |
| { |
| writer.Close(false); |
| } |
| catch (System.IO.IOException ioe) |
| { |
| } |
| |
| dir.Close(); |
| } |
| } |
| |
| // Throws IOException during FieldsWriter.flushDocument and during DocumentsWriter.abort |
| private class FailOnlyOnAbortOrFlush : MockRAMDirectory.Failure |
| { |
| private bool onlyOnce; |
| public FailOnlyOnAbortOrFlush(bool onlyOnce) |
| { |
| this.onlyOnce = onlyOnce; |
| } |
| public override void Eval(MockRAMDirectory dir) |
| { |
| if (doFail) |
| { |
| System.Diagnostics.StackTrace trace = new System.Diagnostics.StackTrace(); |
| for (int i = 0; i < trace.FrameCount; i++) |
| { |
| System.Diagnostics.StackFrame sf = trace.GetFrame(i); |
| if ("Abort".Equals(sf.GetMethod().Name) || "FlushDocument".Equals(sf.GetMethod().Name)) |
| { |
| if (onlyOnce) |
| doFail = false; |
| //System.out.println(Thread.currentThread().getName() + ": now fail"); |
| //new Throwable().printStackTrace(System.out); |
| throw new System.IO.IOException("now failing on purpose"); |
| } |
| } |
| } |
| } |
| } |
| |
| // Runs test, with one thread, using the specific failure |
| // to trigger an IOException |
| public virtual void _testSingleThreadFailure(MockRAMDirectory.Failure failure) |
| { |
| MockRAMDirectory dir = new MockRAMDirectory(); |
| |
| IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.UNLIMITED); |
| writer.SetMaxBufferedDocs(2); |
| Document doc = new Document(); |
| doc.Add(new Field("field", "aaa bbb ccc ddd eee fff ggg hhh iii jjj", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS)); |
| |
| for (int i = 0; i < 6; i++) |
| writer.AddDocument(doc); |
| |
| dir.FailOn(failure); |
| failure.SetDoFail(); |
| |
| Assert.Throws<System.IO.IOException>(() => |
| { |
| writer.AddDocument(doc); |
| writer.AddDocument(doc); |
| writer.Commit(); |
| }, "did not hit exception"); |
| |
| failure.ClearDoFail(); |
| writer.AddDocument(doc); |
| writer.Close(false); |
| } |
| |
| // Runs test, with multiple threads, using the specific |
| // failure to trigger an IOException |
| public virtual void _testMultipleThreadsFailure(MockRAMDirectory.Failure failure) |
| { |
| |
| int NUM_THREADS = 3; |
| |
| for (int iter = 0; iter < 5; iter++) |
| { |
| MockRAMDirectory dir = new MockRAMDirectory(); |
| IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.LIMITED); |
| ConcurrentMergeScheduler cms = new ConcurrentMergeScheduler(); |
| // We expect disk full exceptions in the merge threads |
| cms.SetSuppressExceptions(); |
| writer.SetMergeScheduler(cms); |
| writer.SetMaxBufferedDocs(2); |
| writer.MergeFactor = 4; |
| |
| IndexerThread[] threads = new IndexerThread[NUM_THREADS]; |
| |
| for (int i = 0; i < NUM_THREADS; i++) |
| threads[i] = new IndexerThread(this, writer, true); |
| |
| for (int i = 0; i < NUM_THREADS; i++) |
| threads[i].Start(); |
| |
| System.Threading.Thread.Sleep(new System.TimeSpan((System.Int64)10000 * 10)); |
| |
| dir.FailOn(failure); |
| failure.SetDoFail(); |
| |
| for (int i = 0; i < NUM_THREADS; i++) |
| { |
| threads[i].Join(); |
| Assert.IsTrue(threads[i].error == null, "hit unexpected Throwable"); |
| } |
| |
| bool success = false; |
| try |
| { |
| writer.Close(false); |
| success = true; |
| } |
| catch (System.IO.IOException ioe) |
| { |
| failure.ClearDoFail(); |
| writer.Close(false); |
| } |
| |
| if (success) |
| { |
| IndexReader reader = IndexReader.Open(dir, true); |
| for (int j = 0; j < reader.MaxDoc; j++) |
| { |
| if (!reader.IsDeleted(j)) |
| { |
| reader.Document(j); |
| reader.GetTermFreqVectors(j); |
| } |
| } |
| reader.Close(); |
| } |
| |
| dir.Close(); |
| } |
| } |
| |
| // LUCENE-1130: make sure initial IOException, and then 2nd |
| // IOException during Rollback(), is OK: |
| [Test] |
| public virtual void TestIOExceptionDuringAbort() |
| { |
| _testSingleThreadFailure(new FailOnlyOnAbortOrFlush(false)); |
| } |
| |
| // LUCENE-1130: make sure initial IOException, and then 2nd |
| // IOException during Rollback(), is OK: |
| [Test] |
| public virtual void TestIOExceptionDuringAbortOnlyOnce() |
| { |
| _testSingleThreadFailure(new FailOnlyOnAbortOrFlush(true)); |
| } |
| |
| // LUCENE-1130: make sure initial IOException, and then 2nd |
| // IOException during Rollback(), with multiple threads, is OK: |
| [Test] |
| public virtual void TestIOExceptionDuringAbortWithThreads() |
| { |
| _testMultipleThreadsFailure(new FailOnlyOnAbortOrFlush(false)); |
| } |
| |
| // LUCENE-1130: make sure initial IOException, and then 2nd |
| // IOException during Rollback(), with multiple threads, is OK: |
| [Test] |
| public virtual void TestIOExceptionDuringAbortWithThreadsOnlyOnce() |
| { |
| _testMultipleThreadsFailure(new FailOnlyOnAbortOrFlush(true)); |
| } |
| |
| // Throws IOException during DocumentsWriter.closeDocStore |
| private class FailOnlyInCloseDocStore : MockRAMDirectory.Failure |
| { |
| private bool onlyOnce; |
| public FailOnlyInCloseDocStore(bool onlyOnce) |
| { |
| this.onlyOnce = onlyOnce; |
| } |
| public override void Eval(MockRAMDirectory dir) |
| { |
| if (doFail) |
| { |
| System.Diagnostics.StackTrace trace = new System.Diagnostics.StackTrace(); |
| for (int i = 0; i < trace.FrameCount; i++) |
| { |
| System.Diagnostics.StackFrame sf = trace.GetFrame(i); |
| if ("CloseDocStore".Equals(sf.GetMethod().Name)) |
| { |
| if (onlyOnce) |
| doFail = false; |
| throw new System.IO.IOException("now failing on purpose"); |
| } |
| } |
| } |
| } |
| } |
| |
| // LUCENE-1130: test IOException in closeDocStore |
| [Test] |
| public virtual void TestIOExceptionDuringCloseDocStore() |
| { |
| _testSingleThreadFailure(new FailOnlyInCloseDocStore(false)); |
| } |
| |
| // LUCENE-1130: test IOException in closeDocStore |
| [Test] |
| public virtual void TestIOExceptionDuringCloseDocStoreOnlyOnce() |
| { |
| _testSingleThreadFailure(new FailOnlyInCloseDocStore(true)); |
| } |
| |
| // LUCENE-1130: test IOException in closeDocStore, with threads |
| [Test] |
| public virtual void TestIOExceptionDuringCloseDocStoreWithThreads() |
| { |
| _testMultipleThreadsFailure(new FailOnlyInCloseDocStore(false)); |
| } |
| |
| // LUCENE-1130: test IOException in closeDocStore, with threads |
| [Test] |
| public virtual void TestIOExceptionDuringCloseDocStoreWithThreadsOnlyOnce() |
| { |
| _testMultipleThreadsFailure(new FailOnlyInCloseDocStore(true)); |
| } |
| |
| // Throws IOException during DocumentsWriter.writeSegment |
| private class FailOnlyInWriteSegment : MockRAMDirectory.Failure |
| { |
| private bool onlyOnce; |
| public FailOnlyInWriteSegment(bool onlyOnce) |
| { |
| this.onlyOnce = onlyOnce; |
| } |
| public override void Eval(MockRAMDirectory dir) |
| { |
| if (doFail) |
| { |
| System.Diagnostics.StackTrace trace = new System.Diagnostics.StackTrace(); |
| for (int i = 0; i < trace.FrameCount; i++) |
| { |
| System.Diagnostics.StackFrame sf = trace.GetFrame(i); |
| string className = sf.GetMethod().DeclaringType.Namespace + "." + sf.GetMethod().DeclaringType.Name; |
| if ("Flush".Equals(sf.GetMethod().Name) && "Lucene.Net.Index.DocFieldProcessor".Equals(className)) |
| { |
| if (onlyOnce) |
| doFail = false; |
| throw new System.IO.IOException("now failing on purpose"); |
| } |
| } |
| } |
| } |
| } |
| |
| // LUCENE-1130: test IOException in writeSegment |
| [Test] |
| public virtual void TestIOExceptionDuringWriteSegment() |
| { |
| _testSingleThreadFailure(new FailOnlyInWriteSegment(false)); |
| } |
| |
| // LUCENE-1130: test IOException in writeSegment |
| [Test] |
| public virtual void TestIOExceptionDuringWriteSegmentOnlyOnce() |
| { |
| _testSingleThreadFailure(new FailOnlyInWriteSegment(true)); |
| } |
| |
| // LUCENE-1130: test IOException in writeSegment, with threads |
| [Test] |
| public virtual void TestIOExceptionDuringWriteSegmentWithThreads() |
| { |
| _testMultipleThreadsFailure(new FailOnlyInWriteSegment(false)); |
| } |
| |
| // LUCENE-1130: test IOException in writeSegment, with threads |
| [Test] |
| public virtual void TestIOExceptionDuringWriteSegmentWithThreadsOnlyOnce() |
| { |
| _testMultipleThreadsFailure(new FailOnlyInWriteSegment(true)); |
| } |
| |
| // LUCENE-1084: test unlimited field length |
| [Test] |
| public virtual void TestUnlimitedMaxFieldLength() |
| { |
| Directory dir = new MockRAMDirectory(); |
| |
| IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.UNLIMITED); |
| |
| Document doc = new Document(); |
| System.Text.StringBuilder b = new System.Text.StringBuilder(); |
| for (int i = 0; i < 10000; i++) |
| b.Append(" a"); |
| b.Append(" x"); |
| doc.Add(new Field("field", b.ToString(), Field.Store.NO, Field.Index.ANALYZED)); |
| writer.AddDocument(doc); |
| writer.Close(); |
| |
| IndexReader reader = IndexReader.Open(dir, true); |
| Term t = new Term("field", "x"); |
| Assert.AreEqual(1, reader.DocFreq(t)); |
| reader.Close(); |
| dir.Close(); |
| } |
| |
| // LUCENE-1044: Simulate checksum error in segments_N |
| [Test] |
| public virtual void TestSegmentsChecksumError() |
| { |
| Directory dir = new MockRAMDirectory(); |
| |
| IndexWriter writer = null; |
| |
| writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED); |
| |
| // add 100 documents |
| for (int i = 0; i < 100; i++) |
| { |
| AddDoc(writer); |
| } |
| |
| // close |
| writer.Close(); |
| |
| long gen = SegmentInfos.GetCurrentSegmentGeneration(dir); |
| Assert.IsTrue(gen > 1, "segment generation should be > 1 but got " + gen); |
| |
| System.String segmentsFileName = SegmentInfos.GetCurrentSegmentFileName(dir); |
| IndexInput in_Renamed = dir.OpenInput(segmentsFileName); |
| IndexOutput out_Renamed = dir.CreateOutput(IndexFileNames.FileNameFromGeneration(IndexFileNames.SEGMENTS, "", 1 + gen)); |
| out_Renamed.CopyBytes(in_Renamed, in_Renamed.Length() - 1); |
| byte b = in_Renamed.ReadByte(); |
| out_Renamed.WriteByte((byte)(1 + b)); |
| out_Renamed.Close(); |
| in_Renamed.Close(); |
| |
| IndexReader reader = null; |
| try |
| { |
| reader = IndexReader.Open(dir, true); |
| } |
| catch (System.IO.IOException e) |
| { |
| System.Console.Out.WriteLine(e.StackTrace); |
| Assert.Fail("segmentInfos failed to retry fallback to correct segments_N file"); |
| } |
| reader.Close(); |
| } |
| |
| // LUCENE-1044: test writer.commit() when ac=false |
| [Test] |
| public virtual void TestForceCommit() |
| { |
| Directory dir = new MockRAMDirectory(); |
| |
| IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.LIMITED); |
| writer.SetMaxBufferedDocs(2); |
| writer.MergeFactor = 5; |
| |
| for (int i = 0; i < 23; i++) |
| AddDoc(writer); |
| |
| IndexReader reader = IndexReader.Open(dir, true); |
| Assert.AreEqual(0, reader.NumDocs()); |
| writer.Commit(); |
| IndexReader reader2 = reader.Reopen(); |
| Assert.AreEqual(0, reader.NumDocs()); |
| Assert.AreEqual(23, reader2.NumDocs()); |
| reader.Close(); |
| |
| for (int i = 0; i < 17; i++) |
| AddDoc(writer); |
| Assert.AreEqual(23, reader2.NumDocs()); |
| reader2.Close(); |
| reader = IndexReader.Open(dir, true); |
| Assert.AreEqual(23, reader.NumDocs()); |
| reader.Close(); |
| writer.Commit(); |
| |
| reader = IndexReader.Open(dir, true); |
| Assert.AreEqual(40, reader.NumDocs()); |
| reader.Close(); |
| writer.Close(); |
| dir.Close(); |
| } |
| |
| // Throws IOException during MockRAMDirectory.sync |
| private class FailOnlyInSync : MockRAMDirectory.Failure |
| { |
| internal bool didFail; |
| public override void Eval(MockRAMDirectory dir) |
| { |
| if (doFail) |
| { |
| System.Diagnostics.StackTrace trace = new System.Diagnostics.StackTrace(); |
| for (int i = 0; i < trace.FrameCount; i++) |
| { |
| System.Diagnostics.StackFrame sf = trace.GetFrame(i); |
| string className = sf.GetMethod().DeclaringType.Namespace + "." + sf.GetMethod().DeclaringType.Name; |
| if (doFail && "Lucene.Net.Store.MockRAMDirectory".Equals(className) && "Sync".Equals(sf.GetMethod().Name)) |
| { |
| didFail = true; |
| throw new System.IO.IOException("now failing on purpose during sync"); |
| } |
| } |
| } |
| } |
| } |
| |
| // LUCENE-1044: test exception during sync |
| [Test] |
| public virtual void TestExceptionDuringSync() |
| { |
| MockRAMDirectory dir = new MockRAMDirectory(); |
| FailOnlyInSync failure = new FailOnlyInSync(); |
| dir.FailOn(failure); |
| |
| IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.UNLIMITED); |
| failure.SetDoFail(); |
| |
| ConcurrentMergeScheduler cms = new ConcurrentMergeScheduler(); |
| writer.SetMergeScheduler(cms); |
| writer.SetMaxBufferedDocs(2); |
| writer.MergeFactor = 5; |
| |
| for (int i = 0; i < 23; i++) |
| { |
| AddDoc(writer); |
| if ((i - 1) % 2 == 0) |
| { |
| try |
| { |
| writer.Commit(); |
| } |
| catch (System.IO.IOException ioe) |
| { |
| //expected |
| } |
| } |
| } |
| |
| cms.Sync(); |
| Assert.IsTrue(failure.didFail); |
| failure.ClearDoFail(); |
| writer.Close(); |
| |
| IndexReader reader = IndexReader.Open(dir, true); |
| Assert.AreEqual(23, reader.NumDocs()); |
| reader.Close(); |
| dir.Close(); |
| } |
| |
| // LUCENE-1168 |
| [Test] |
| public virtual void TestTermVectorCorruption() |
| { |
| |
| Directory dir = new MockRAMDirectory(); |
| for (int iter = 0; iter < 4; iter++) |
| { |
| bool autoCommit = 1 == iter / 2; |
| IndexWriter writer = new IndexWriter(dir, new StandardAnalyzer(Util.Version.LUCENE_CURRENT), |
| IndexWriter.MaxFieldLength.UNLIMITED); |
| writer.SetMaxBufferedDocs(2); |
| writer.SetRAMBufferSizeMB(IndexWriter.DISABLE_AUTO_FLUSH); |
| writer.SetMergeScheduler(new SerialMergeScheduler()); |
| writer.SetMergePolicy(new LogDocMergePolicy(writer)); |
| |
| Document document = new Document(); |
| |
| Field storedField = new Field("stored", "stored", Field.Store.YES, Field.Index.NO); |
| document.Add(storedField); |
| writer.AddDocument(document); |
| writer.AddDocument(document); |
| |
| document = new Document(); |
| document.Add(storedField); |
| Field termVectorField = new Field("termVector", "termVector", Field.Store.NO, Field.Index.NOT_ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS); |
| |
| document.Add(termVectorField); |
| writer.AddDocument(document); |
| writer.Optimize(); |
| writer.Close(); |
| |
| IndexReader reader = IndexReader.Open(dir, true); |
| for (int i = 0; i < reader.NumDocs(); i++) |
| { |
| reader.Document(i); |
| reader.GetTermFreqVectors(i); |
| } |
| reader.Close(); |
| |
| writer = new IndexWriter(dir, new StandardAnalyzer(Util.Version.LUCENE_CURRENT), IndexWriter.MaxFieldLength.UNLIMITED); |
| writer.SetMaxBufferedDocs(2); |
| writer.SetRAMBufferSizeMB(IndexWriter.DISABLE_AUTO_FLUSH); |
| writer.SetMergeScheduler(new SerialMergeScheduler()); |
| writer.SetMergePolicy(new LogDocMergePolicy(writer)); |
| |
| Directory[] indexDirs = new Directory[] { new MockRAMDirectory(dir) }; |
| writer.AddIndexesNoOptimize(indexDirs); |
| writer.Optimize(); |
| writer.Close(); |
| } |
| dir.Close(); |
| } |
| |
| // LUCENE-1168 |
| [Test] |
| public virtual void TestTermVectorCorruption2() |
| { |
| Directory dir = new MockRAMDirectory(); |
| for (int iter = 0; iter < 2; iter++) |
| { |
| IndexWriter writer = new IndexWriter(dir, new StandardAnalyzer(Util.Version.LUCENE_CURRENT), IndexWriter.MaxFieldLength.UNLIMITED); |
| writer.SetMaxBufferedDocs(2); |
| writer.SetRAMBufferSizeMB(IndexWriter.DISABLE_AUTO_FLUSH); |
| writer.SetMergeScheduler(new SerialMergeScheduler()); |
| writer.SetMergePolicy(new LogDocMergePolicy(writer)); |
| |
| Document document = new Document(); |
| |
| Field storedField = new Field("stored", "stored", Field.Store.YES, Field.Index.NO); |
| document.Add(storedField); |
| writer.AddDocument(document); |
| writer.AddDocument(document); |
| |
| document = new Document(); |
| document.Add(storedField); |
| Field termVectorField = new Field("termVector", "termVector", Field.Store.NO, Field.Index.NOT_ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS); |
| document.Add(termVectorField); |
| writer.AddDocument(document); |
| writer.Optimize(); |
| writer.Close(); |
| |
| IndexReader reader = IndexReader.Open(dir, true); |
| Assert.IsTrue(reader.GetTermFreqVectors(0) == null); |
| Assert.IsTrue(reader.GetTermFreqVectors(1) == null); |
| Assert.IsTrue(reader.GetTermFreqVectors(2) != null); |
| reader.Close(); |
| } |
| dir.Close(); |
| } |
| |
| // LUCENE-1168 |
| [Test] |
| public virtual void TestTermVectorCorruption3() |
| { |
| Directory dir = new MockRAMDirectory(); |
| IndexWriter writer = new IndexWriter(dir, new StandardAnalyzer(Util.Version.LUCENE_CURRENT), IndexWriter.MaxFieldLength.LIMITED); |
| writer.SetMaxBufferedDocs(2); |
| writer.SetRAMBufferSizeMB(IndexWriter.DISABLE_AUTO_FLUSH); |
| writer.SetMergeScheduler(new SerialMergeScheduler()); |
| writer.SetMergePolicy(new LogDocMergePolicy(writer)); |
| |
| Document document = new Document(); |
| |
| document = new Document(); |
| Field storedField = new Field("stored", "stored", Field.Store.YES, Field.Index.NO); |
| document.Add(storedField); |
| Field termVectorField = new Field("termVector", "termVector", Field.Store.NO, Field.Index.NOT_ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS); |
| document.Add(termVectorField); |
| for (int i = 0; i < 10; i++) |
| writer.AddDocument(document); |
| writer.Close(); |
| |
| writer = new IndexWriter(dir, new StandardAnalyzer(Util.Version.LUCENE_CURRENT), IndexWriter.MaxFieldLength.LIMITED); |
| writer.SetMaxBufferedDocs(2); |
| writer.SetRAMBufferSizeMB(IndexWriter.DISABLE_AUTO_FLUSH); |
| writer.SetMergeScheduler(new SerialMergeScheduler()); |
| writer.SetMergePolicy(new LogDocMergePolicy(writer)); |
| for (int i = 0; i < 6; i++) |
| writer.AddDocument(document); |
| |
| writer.Optimize(); |
| writer.Close(); |
| |
| IndexReader reader = IndexReader.Open(dir, true); |
| for (int i = 0; i < 10; i++) |
| { |
| reader.GetTermFreqVectors(i); |
| reader.Document(i); |
| } |
| reader.Close(); |
| dir.Close(); |
| } |
| |
| // LUCENE-1084: test user-specified field length |
| [Test] |
| public virtual void TestUserSpecifiedMaxFieldLength() |
| { |
| Directory dir = new MockRAMDirectory(); |
| |
| IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), new IndexWriter.MaxFieldLength(100000)); |
| |
| Document doc = new Document(); |
| System.Text.StringBuilder b = new System.Text.StringBuilder(); |
| for (int i = 0; i < 10000; i++) |
| b.Append(" a"); |
| b.Append(" x"); |
| doc.Add(new Field("field", b.ToString(), Field.Store.NO, Field.Index.ANALYZED)); |
| writer.AddDocument(doc); |
| writer.Close(); |
| |
| IndexReader reader = IndexReader.Open(dir, true); |
| Term t = new Term("field", "x"); |
| Assert.AreEqual(1, reader.DocFreq(t)); |
| reader.Close(); |
| dir.Close(); |
| } |
| |
| // LUCENE-325: test expungeDeletes, when 2 singular merges |
| // are required |
| [Test] |
| public virtual void TestExpungeDeletes() |
| { |
| Directory dir = new MockRAMDirectory(); |
| IndexWriter writer = new IndexWriter(dir, new StandardAnalyzer(Util.Version.LUCENE_CURRENT), IndexWriter.MaxFieldLength.LIMITED); |
| writer.SetMaxBufferedDocs(2); |
| writer.SetRAMBufferSizeMB(IndexWriter.DISABLE_AUTO_FLUSH); |
| |
| Document document = new Document(); |
| |
| document = new Document(); |
| Field storedField = new Field("stored", "stored", Field.Store.YES, Field.Index.NO); |
| document.Add(storedField); |
| Field termVectorField = new Field("termVector", "termVector", Field.Store.NO, Field.Index.NOT_ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS); |
| document.Add(termVectorField); |
| for (int i = 0; i < 10; i++) |
| writer.AddDocument(document); |
| writer.Close(); |
| |
| IndexReader ir = IndexReader.Open(dir, false); |
| Assert.AreEqual(10, ir.MaxDoc); |
| Assert.AreEqual(10, ir.NumDocs()); |
| ir.DeleteDocument(0); |
| ir.DeleteDocument(7); |
| Assert.AreEqual(8, ir.NumDocs()); |
| ir.Close(); |
| |
| writer = new IndexWriter(dir, new StandardAnalyzer(Util.Version.LUCENE_CURRENT), IndexWriter.MaxFieldLength.LIMITED); |
| Assert.AreEqual(8, writer.NumDocs()); |
| Assert.AreEqual(10, writer.MaxDoc()); |
| writer.ExpungeDeletes(); |
| Assert.AreEqual(8, writer.NumDocs()); |
| writer.Close(); |
| ir = IndexReader.Open(dir, true); |
| Assert.AreEqual(8, ir.MaxDoc); |
| Assert.AreEqual(8, ir.NumDocs()); |
| ir.Close(); |
| dir.Close(); |
| } |
| |
| // LUCENE-325: test expungeDeletes, when many adjacent merges are required |
| [Test] |
| public virtual void TestExpungeDeletes2() |
| { |
| Directory dir = new MockRAMDirectory(); |
| IndexWriter writer = new IndexWriter(dir, new StandardAnalyzer(Util.Version.LUCENE_CURRENT), IndexWriter.MaxFieldLength.LIMITED); |
| writer.SetMaxBufferedDocs(2); |
| writer.MergeFactor = 50; |
| writer.SetRAMBufferSizeMB(IndexWriter.DISABLE_AUTO_FLUSH); |
| |
| Document document = new Document(); |
| |
| document = new Document(); |
| Field storedField = new Field("stored", "stored", Field.Store.YES, Field.Index.NO); |
| document.Add(storedField); |
| Field termVectorField = new Field("termVector", "termVector", Field.Store.NO, Field.Index.NOT_ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS); |
| document.Add(termVectorField); |
| for (int i = 0; i < 98; i++) |
| writer.AddDocument(document); |
| writer.Close(); |
| |
| IndexReader ir = IndexReader.Open(dir, false); |
| Assert.AreEqual(98, ir.MaxDoc); |
| Assert.AreEqual(98, ir.NumDocs()); |
| for (int i = 0; i < 98; i += 2) |
| ir.DeleteDocument(i); |
| Assert.AreEqual(49, ir.NumDocs()); |
| ir.Close(); |
| |
| writer = new IndexWriter(dir, new StandardAnalyzer(Util.Version.LUCENE_CURRENT), IndexWriter.MaxFieldLength.LIMITED); |
| writer.MergeFactor = 3; |
| Assert.AreEqual(49, writer.NumDocs()); |
| writer.ExpungeDeletes(); |
| writer.Close(); |
| ir = IndexReader.Open(dir, true); |
| Assert.AreEqual(49, ir.MaxDoc); |
| Assert.AreEqual(49, ir.NumDocs()); |
| ir.Close(); |
| dir.Close(); |
| } |
| |
| // LUCENE-325: test expungeDeletes without waiting, when |
| // many adjacent merges are required |
| [Test] |
| public virtual void TestExpungeDeletes3() |
| { |
| Directory dir = new MockRAMDirectory(); |
| IndexWriter writer = new IndexWriter(dir, new StandardAnalyzer(Util.Version.LUCENE_CURRENT), IndexWriter.MaxFieldLength.LIMITED); |
| writer.SetMaxBufferedDocs(2); |
| writer.MergeFactor = 50; |
| writer.SetRAMBufferSizeMB(IndexWriter.DISABLE_AUTO_FLUSH); |
| |
| Document document = new Document(); |
| |
| document = new Document(); |
| Field storedField = new Field("stored", "stored", Field.Store.YES, Field.Index.NO); |
| document.Add(storedField); |
| Field termVectorField = new Field("termVector", "termVector", Field.Store.NO, Field.Index.NOT_ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS); |
| document.Add(termVectorField); |
| for (int i = 0; i < 98; i++) |
| writer.AddDocument(document); |
| writer.Close(); |
| |
| IndexReader ir = IndexReader.Open(dir, false); |
| Assert.AreEqual(98, ir.MaxDoc); |
| Assert.AreEqual(98, ir.NumDocs()); |
| for (int i = 0; i < 98; i += 2) |
| ir.DeleteDocument(i); |
| Assert.AreEqual(49, ir.NumDocs()); |
| ir.Close(); |
| |
| writer = new IndexWriter(dir, new StandardAnalyzer(Util.Version.LUCENE_CURRENT), IndexWriter.MaxFieldLength.LIMITED); |
| // Force many merges to happen |
| writer.MergeFactor = 3; |
| writer.ExpungeDeletes(false); |
| writer.Close(); |
| ir = IndexReader.Open(dir, true); |
| Assert.AreEqual(49, ir.MaxDoc); |
| Assert.AreEqual(49, ir.NumDocs()); |
| ir.Close(); |
| dir.Close(); |
| } |
| |
| // LUCENE-1179 |
| [Test] |
| public virtual void TestEmptyFieldName() |
| { |
| MockRAMDirectory dir = new MockRAMDirectory(); |
| IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.UNLIMITED); |
| Document doc = new Document(); |
| doc.Add(new Field("", "a b c", Field.Store.NO, Field.Index.ANALYZED)); |
| writer.AddDocument(doc); |
| writer.Close(); |
| } |
| |
| // LUCENE-1198 |
| public class MockIndexWriter : IndexWriter |
| { |
| private void InitBlock(TestIndexWriter enclosingInstance) |
| { |
| this.enclosingInstance = enclosingInstance; |
| } |
| private TestIndexWriter enclosingInstance; |
| public TestIndexWriter Enclosing_Instance |
| { |
| get |
| { |
| return enclosingInstance; |
| } |
| |
| } |
| |
| public MockIndexWriter(TestIndexWriter enclosingInstance, Directory dir, Analyzer a, bool create, MaxFieldLength mfl) |
| : base(dir, a, create, mfl) |
| { |
| InitBlock(enclosingInstance); |
| } |
| |
| internal bool doFail; |
| |
| public override bool TestPoint(System.String name) |
| { |
| if (doFail && name.Equals("DocumentsWriter.ThreadState.init start")) |
| throw new System.SystemException("intentionally failing"); |
| return true; |
| } |
| } |
| |
| [Test] |
| public virtual void TestExceptionDocumentsWriterInit() |
| { |
| MockRAMDirectory dir = new MockRAMDirectory(); |
| MockIndexWriter w = new MockIndexWriter(this, dir, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.UNLIMITED); |
| Document doc = new Document(); |
| doc.Add(new Field("field", "a field", Field.Store.YES, Field.Index.ANALYZED)); |
| w.AddDocument(doc); |
| w.doFail = true; |
| try |
| { |
| w.AddDocument(doc); |
| |
| if (BuildType.Debug) |
| Assert.Fail("did not hit exception"); |
| else |
| Assert.Ignore("This test is not executed in release mode"); |
| } |
| catch (System.SystemException re) |
| { |
| // expected |
| } |
| w.Close(); |
| _TestUtil.CheckIndex(dir); |
| dir.Close(); |
| } |
| |
| // LUCENE-1208 |
| [Test] |
| public virtual void TestExceptionJustBeforeFlush() |
| { |
| MockRAMDirectory dir = new MockRAMDirectory(); |
| MockIndexWriter w = new MockIndexWriter(this, dir, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.UNLIMITED); |
| w.SetMaxBufferedDocs(2); |
| Document doc = new Document(); |
| doc.Add(new Field("field", "a field", Field.Store.YES, Field.Index.ANALYZED)); |
| w.AddDocument(doc); |
| |
| Analyzer analyzer = new AnonymousClassAnalyzer3(this); |
| |
| Document crashDoc = new Document(); |
| crashDoc.Add(new Field("crash", "do it on token 4", Field.Store.YES, Field.Index.ANALYZED)); |
| |
| Assert.Throws<System.IO.IOException>(() => w.AddDocument(crashDoc, analyzer), |
| "did not hit expected exception"); |
| |
| w.AddDocument(doc); |
| w.Close(); |
| dir.Close(); |
| } |
| |
| public class MockIndexWriter2 : IndexWriter |
| { |
| private void InitBlock(TestIndexWriter enclosingInstance) |
| { |
| this.enclosingInstance = enclosingInstance; |
| } |
| private TestIndexWriter enclosingInstance; |
| public TestIndexWriter Enclosing_Instance |
| { |
| get |
| { |
| return enclosingInstance; |
| } |
| |
| } |
| |
| public MockIndexWriter2(TestIndexWriter enclosingInstance, Directory dir, Analyzer a, bool create, MaxFieldLength mfl) |
| : base(dir, a, create, mfl) |
| { |
| InitBlock(enclosingInstance); |
| } |
| |
| internal bool doFail; |
| internal bool failed; |
| |
| public override bool TestPoint(System.String name) |
| { |
| if (doFail && name.Equals("startMergeInit")) |
| { |
| failed = true; |
| throw new System.SystemException("intentionally failing"); |
| } |
| return true; |
| } |
| } |
| |
| // LUCENE-1210 |
| [Test] |
| public virtual void TestExceptionOnMergeInit() |
| { |
| MockRAMDirectory dir = new MockRAMDirectory(); |
| MockIndexWriter2 w = new MockIndexWriter2(this, dir, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.UNLIMITED); |
| w.SetMaxBufferedDocs(2); |
| w.MergeFactor = 2; |
| w.doFail = true; |
| w.SetMergeScheduler(new ConcurrentMergeScheduler()); |
| Document doc = new Document(); |
| doc.Add(new Field("field", "a field", Field.Store.YES, Field.Index.ANALYZED)); |
| for (int i = 0; i < 10; i++) |
| try |
| { |
| w.AddDocument(doc); |
| } |
| catch (System.SystemException re) |
| { |
| break; |
| } |
| |
| ((ConcurrentMergeScheduler)w.MergeScheduler).Sync(); |
| if (BuildType.Debug) |
| Assert.IsTrue(w.failed); |
| else |
| Assert.Ignore("This test is not executed in release mode"); |
| w.Close(); |
| dir.Close(); |
| } |
| |
| public class MockIndexWriter3 : IndexWriter |
| { |
| private void InitBlock(TestIndexWriter enclosingInstance) |
| { |
| this.enclosingInstance = enclosingInstance; |
| } |
| private TestIndexWriter enclosingInstance; |
| public TestIndexWriter Enclosing_Instance |
| { |
| get |
| { |
| return enclosingInstance; |
| } |
| |
| } |
| |
| public MockIndexWriter3(TestIndexWriter enclosingInstance, Directory dir, Analyzer a, bool create, IndexWriter.MaxFieldLength mfl) |
| : base(dir, a, create, mfl) |
| { |
| InitBlock(enclosingInstance); |
| } |
| |
| public bool afterWasCalled; |
| public bool beforeWasCalled; |
| |
| protected override void DoAfterFlush() |
| { |
| afterWasCalled = true; |
| } |
| |
| protected override void DoBeforeFlush() |
| { |
| beforeWasCalled = true; |
| } |
| } |
| |
| // LUCENE-1222 |
| [Test] |
| public virtual void TestDoBeforeAfterFlush() |
| { |
| MockRAMDirectory dir = new MockRAMDirectory(); |
| MockIndexWriter3 w = new MockIndexWriter3(this, dir, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED); |
| Document doc = new Document(); |
| doc.Add(new Field("field", "a field", Field.Store.YES, Field.Index.ANALYZED)); |
| w.AddDocument(doc); |
| w.Commit(); |
| Assert.IsTrue(w.beforeWasCalled); |
| Assert.IsTrue(w.afterWasCalled); |
| w.beforeWasCalled = false; |
| w.afterWasCalled = false; |
| w.DeleteDocuments(new Term("field", "field")); |
| w.Commit(); |
| Assert.IsTrue(w.beforeWasCalled); |
| Assert.IsTrue(w.afterWasCalled); |
| w.Close(); |
| |
| IndexReader ir = IndexReader.Open(dir, true); |
| Assert.AreEqual(1, ir.MaxDoc); |
| Assert.AreEqual(0, ir.NumDocs()); |
| ir.Close(); |
| |
| dir.Close(); |
| } |
| |
| private class FailOnlyInCommit : MockRAMDirectory.Failure |
| { |
| |
| internal bool fail1, fail2; |
| |
| public override void Eval(MockRAMDirectory dir) |
| { |
| System.Diagnostics.StackTrace trace = new System.Diagnostics.StackTrace(); |
| bool isCommit = false; |
| bool isDelete = false; |
| for (int i = 0; i < trace.FrameCount; i++) |
| { |
| System.Diagnostics.StackFrame sf = trace.GetFrame(i); |
| string className = sf.GetMethod().DeclaringType.Namespace + "." + sf.GetMethod().DeclaringType.Name; |
| // NOTE: Added "Write" to the method name comparisons for TestExceptionDuringCommit to pass. |
| // In release mode, the JITer inlines PrepareCommit, and it wasn't getting caught by this check. |
| // Write seems to get the expected behavior, though. The other alternative, to disable inlining |
| // on that function, which would be specifically for testing only; hurting release performance - cc |
| if ("Lucene.Net.Index.SegmentInfos".Equals(className) && ("Write".Equals(sf.GetMethod().Name) || "PrepareCommit".Equals(sf.GetMethod().Name))) |
| isCommit = true; |
| if ("Lucene.Net.Store.MockRAMDirectory".Equals(className) && "DeleteFile".Equals(sf.GetMethod().Name)) |
| isDelete = true; |
| if ("Lucene.Net.Index.SegmentInfos".Equals(className)) |
| Console.WriteLine(sf.GetMethod().Name); |
| } |
| |
| if (isCommit) |
| { |
| if (!isDelete) |
| { |
| fail1 = true; |
| throw new System.SystemException("now fail first"); |
| } |
| else |
| { |
| fail2 = true; |
| throw new System.IO.IOException("now fail during delete"); |
| } |
| } |
| } |
| } |
| |
| // LUCENE-1214 |
| [Test] |
| public virtual void TestExceptionsDuringCommit() |
| { |
| MockRAMDirectory dir = new MockRAMDirectory(); |
| FailOnlyInCommit failure = new FailOnlyInCommit(); |
| IndexWriter w = new IndexWriter(dir, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.UNLIMITED); |
| Document doc = new Document(); |
| doc.Add(new Field("field", "a field", Field.Store.YES, Field.Index.ANALYZED)); |
| w.AddDocument(doc); |
| dir.FailOn(failure); |
| |
| Assert.Throws<SystemException>(w.Close, "expected only RuntimeException"); |
| |
| Assert.IsTrue(failure.fail1 && failure.fail2); |
| w.Rollback(); |
| dir.Close(); |
| } |
| |
| internal System.String[] utf8Data = new System.String[] { "ab\udc17cd", "ab\ufffdcd", "\udc17abcd", "\ufffdabcd", "\udc17", "\ufffd", "ab\udc17\udc17cd", "ab\ufffd\ufffdcd", "\udc17\udc17abcd", "\ufffd\ufffdabcd", "\udc17\udc17", "\ufffd\ufffd", "ab\ud917cd", "ab\ufffdcd", "\ud917abcd", "\ufffdabcd", "\ud917", "\ufffd", "ab\ud917\ud917cd", "ab\ufffd\ufffdcd", "\ud917\ud917abcd", "\ufffd\ufffdabcd", "\ud917\ud917", "\ufffd\ufffd", "ab\udc17\ud917cd", "ab\ufffd\ufffdcd", "\udc17\ud917abcd", "\ufffd\ufffdabcd", "\udc17\ud917", "\ufffd\ufffd", "ab\udc17\ud917\udc17\ud917cd", "ab\ufffd\ud917\udc17\ufffdcd", "\udc17\ud917\udc17\ud917abcd", "\ufffd\ud917\udc17\ufffdabcd", "\udc17\ud917\udc17\ud917", "\ufffd\ud917\udc17\ufffd" }; |
| |
| // LUCENE-510 |
| [Test] |
| public virtual void TestInvalidUTF16() |
| { |
| MockRAMDirectory dir = new MockRAMDirectory(); |
| IndexWriter w = new IndexWriter(dir, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.UNLIMITED); |
| Document doc = new Document(); |
| |
| int count = utf8Data.Length / 2; |
| for (int i = 0; i < count; i++) |
| doc.Add(new Field("f" + i, utf8Data[2 * i], Field.Store.YES, Field.Index.ANALYZED)); |
| w.AddDocument(doc); |
| w.Close(); |
| |
| IndexReader ir = IndexReader.Open(dir, true); |
| Document doc2 = ir.Document(0); |
| for (int i = 0; i < count; i++) |
| { |
| Assert.AreEqual(1, ir.DocFreq(new Term("f" + i, utf8Data[2 * i + 1])), "field " + i + " was not indexed correctly"); |
| Assert.AreEqual(utf8Data[2 * i + 1], doc2.GetField("f" + i).StringValue, "field " + i + " is incorrect"); |
| } |
| ir.Close(); |
| dir.Close(); |
| } |
| |
| // LUCENE-510 |
| [Test] |
| public virtual void TestAllUnicodeChars() |
| { |
| |
| UnicodeUtil.UTF8Result utf8 = new UnicodeUtil.UTF8Result(); |
| UnicodeUtil.UTF16Result utf16 = new UnicodeUtil.UTF16Result(); |
| char[] chars = new char[2]; |
| for (int ch = 0; ch < 0x0010FFFF; ch++) |
| { |
| |
| if (ch == 0xd800) |
| // Skip invalid code points |
| ch = 0xe000; |
| |
| int len = 0; |
| if (ch <= 0xffff) |
| { |
| chars[len++] = (char)ch; |
| } |
| else |
| { |
| chars[len++] = (char)(((ch - 0x0010000) >> 10) + UnicodeUtil.UNI_SUR_HIGH_START); |
| chars[len++] = (char)(((ch - 0x0010000) & 0x3FFL) + UnicodeUtil.UNI_SUR_LOW_START); |
| } |
| |
| UnicodeUtil.UTF16toUTF8(chars, 0, len, utf8); |
| |
| System.String s1 = new System.String(chars, 0, len); |
| System.String s2 = System.Text.Encoding.UTF8.GetString(utf8.result, 0, utf8.length); |
| Assert.AreEqual(s1, s2, "codepoint " + ch); |
| |
| UnicodeUtil.UTF8toUTF16(utf8.result, 0, utf8.length, utf16); |
| Assert.AreEqual(s1, new String(utf16.result, 0, utf16.length), "codepoint " + ch); |
| |
| byte[] b = System.Text.Encoding.GetEncoding("UTF-8").GetBytes(s1); |
| Assert.AreEqual(utf8.length, b.Length); |
| for (int j = 0; j < utf8.length; j++) |
| Assert.AreEqual(utf8.result[j], b[j]); |
| } |
| } |
| |
| internal System.Random r; |
| |
| private int NextInt(int lim) |
| { |
| return r.Next(lim); |
| } |
| |
| private int NextInt(int start, int end) |
| { |
| return start + NextInt(end - start); |
| } |
| |
| private bool FillUnicode(char[] buffer, char[] expected, int offset, int count) |
| { |
| int len = offset + count; |
| bool hasIllegal = false; |
| |
| if (offset > 0 && buffer[offset] >= 0xdc00 && buffer[offset] < 0xe000) |
| // Don't start in the middle of a valid surrogate pair |
| offset--; |
| |
| for (int i = offset; i < len; i++) |
| { |
| int t = NextInt(6); |
| if (0 == t && i < len - 1) |
| { |
| // Make a surrogate pair |
| // High surrogate |
| expected[i] = buffer[i++] = (char)NextInt(0xd800, 0xdc00); |
| // Low surrogate |
| expected[i] = buffer[i] = (char)NextInt(0xdc00, 0xe000); |
| } |
| else if (t <= 1) |
| expected[i] = buffer[i] = (char)NextInt(0x80); |
| else if (2 == t) |
| expected[i] = buffer[i] = (char)NextInt(0x80, 0x800); |
| else if (3 == t) |
| expected[i] = buffer[i] = (char)NextInt(0x800, 0xd800); |
| else if (4 == t) |
| expected[i] = buffer[i] = (char)NextInt(0xe000, 0xffff); |
| else if (5 == t && i < len - 1) |
| { |
| // Illegal unpaired surrogate |
| if (NextInt(10) == 7) |
| { |
| if (r.NextDouble() > 0.5) |
| buffer[i] = (char)NextInt(0xd800, 0xdc00); |
| else |
| buffer[i] = (char)NextInt(0xdc00, 0xe000); |
| expected[i++] = (char)(0xfffd); |
| expected[i] = buffer[i] = (char)NextInt(0x800, 0xd800); |
| hasIllegal = true; |
| } |
| else |
| expected[i] = buffer[i] = (char)NextInt(0x800, 0xd800); |
| } |
| else |
| { |
| expected[i] = buffer[i] = ' '; |
| } |
| } |
| |
| return hasIllegal; |
| } |
| |
| // LUCENE-510 |
| [Test] |
| public virtual void TestRandomUnicodeStrings() |
| { |
| r = NewRandom(); |
| |
| char[] buffer = new char[20]; |
| char[] expected = new char[20]; |
| |
| UnicodeUtil.UTF8Result utf8 = new UnicodeUtil.UTF8Result(); |
| UnicodeUtil.UTF16Result utf16 = new UnicodeUtil.UTF16Result(); |
| |
| for (int iter = 0; iter < 100000; iter++) |
| { |
| bool hasIllegal = FillUnicode(buffer, expected, 0, 20); |
| |
| UnicodeUtil.UTF16toUTF8(buffer, 0, 20, utf8); |
| if (!hasIllegal) |
| { |
| byte[] b = System.Text.Encoding.GetEncoding("UTF-8").GetBytes(new System.String(buffer, 0, 20)); |
| Assert.AreEqual(b.Length, utf8.length); |
| for (int i = 0; i < b.Length; i++) |
| Assert.AreEqual(b[i], utf8.result[i]); |
| } |
| |
| UnicodeUtil.UTF8toUTF16(utf8.result, 0, utf8.length, utf16); |
| Assert.AreEqual(utf16.length, 20); |
| for (int i = 0; i < 20; i++) |
| Assert.AreEqual(expected[i], utf16.result[i]); |
| } |
| } |
| |
| // LUCENE-510 |
| [Test] |
| public virtual void TestIncrementalUnicodeStrings() |
| { |
| r = NewRandom(); |
| char[] buffer = new char[20]; |
| char[] expected = new char[20]; |
| |
| UnicodeUtil.UTF8Result utf8 = new UnicodeUtil.UTF8Result(); |
| UnicodeUtil.UTF16Result utf16 = new UnicodeUtil.UTF16Result(); |
| UnicodeUtil.UTF16Result utf16a = new UnicodeUtil.UTF16Result(); |
| |
| bool hasIllegal = false; |
| byte[] last = new byte[60]; |
| |
| for (int iter = 0; iter < 100000; iter++) |
| { |
| |
| int prefix; |
| |
| if (iter == 0 || hasIllegal) |
| prefix = 0; |
| else |
| prefix = NextInt(20); |
| |
| hasIllegal = FillUnicode(buffer, expected, prefix, 20 - prefix); |
| |
| UnicodeUtil.UTF16toUTF8(buffer, 0, 20, utf8); |
| if (!hasIllegal) |
| { |
| byte[] b = System.Text.Encoding.GetEncoding("UTF-8").GetBytes(new System.String(buffer, 0, 20)); |
| Assert.AreEqual(b.Length, utf8.length); |
| for (int i = 0; i < b.Length; i++) |
| Assert.AreEqual(b[i], utf8.result[i]); |
| } |
| |
| int bytePrefix = 20; |
| if (iter == 0 || hasIllegal) |
| bytePrefix = 0; |
| else |
| for (int i = 0; i < 20; i++) |
| if (last[i] != utf8.result[i]) |
| { |
| bytePrefix = i; |
| break; |
| } |
| System.Array.Copy(utf8.result, 0, last, 0, utf8.length); |
| |
| UnicodeUtil.UTF8toUTF16(utf8.result, bytePrefix, utf8.length - bytePrefix, utf16); |
| Assert.AreEqual(20, utf16.length); |
| for (int i = 0; i < 20; i++) |
| Assert.AreEqual(expected[i], utf16.result[i]); |
| |
| UnicodeUtil.UTF8toUTF16(utf8.result, 0, utf8.length, utf16a); |
| Assert.AreEqual(20, utf16a.length); |
| for (int i = 0; i < 20; i++) |
| Assert.AreEqual(expected[i], utf16a.result[i]); |
| } |
| } |
| |
| // LUCENE-1255 |
| [Test] |
| public virtual void TestNegativePositions() |
| { |
| TokenStream tokens = new AnonymousClassTokenStream(this); |
| |
| MockRAMDirectory dir = new MockRAMDirectory(); |
| IndexWriter w = new IndexWriter(dir, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.UNLIMITED); |
| Document doc = new Document(); |
| doc.Add(new Field("field", tokens)); |
| w.AddDocument(doc); |
| w.Commit(); |
| |
| IndexSearcher s = new IndexSearcher(dir, false); |
| PhraseQuery pq = new PhraseQuery(); |
| pq.Add(new Term("field", "a")); |
| pq.Add(new Term("field", "b")); |
| pq.Add(new Term("field", "c")); |
| ScoreDoc[] hits = s.Search(pq, null, 1000).ScoreDocs; |
| Assert.AreEqual(1, hits.Length); |
| |
| Query q = new SpanTermQuery(new Term("field", "a")); |
| hits = s.Search(q, null, 1000).ScoreDocs; |
| Assert.AreEqual(1, hits.Length); |
| TermPositions tps = s.IndexReader.TermPositions(new Term("field", "a")); |
| Assert.IsTrue(tps.Next()); |
| Assert.AreEqual(1, tps.Freq); |
| Assert.AreEqual(0, tps.NextPosition()); |
| w.Close(); |
| |
| Assert.IsTrue(_TestUtil.CheckIndex(dir)); |
| s.Close(); |
| dir.Close(); |
| } |
| |
| // LUCENE-1274: test writer.prepareCommit() |
| [Test] |
| public virtual void TestPrepareCommit() |
| { |
| Directory dir = new MockRAMDirectory(); |
| |
| IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.LIMITED); |
| writer.SetMaxBufferedDocs(2); |
| writer.MergeFactor = 5; |
| |
| for (int i = 0; i < 23; i++) |
| AddDoc(writer); |
| |
| IndexReader reader = IndexReader.Open(dir, true); |
| Assert.AreEqual(0, reader.NumDocs()); |
| |
| writer.PrepareCommit(); |
| |
| IndexReader reader2 = IndexReader.Open(dir, true); |
| Assert.AreEqual(0, reader2.NumDocs()); |
| |
| writer.Commit(); |
| |
| IndexReader reader3 = reader.Reopen(); |
| Assert.AreEqual(0, reader.NumDocs()); |
| Assert.AreEqual(0, reader2.NumDocs()); |
| Assert.AreEqual(23, reader3.NumDocs()); |
| reader.Close(); |
| reader2.Close(); |
| |
| for (int i = 0; i < 17; i++) |
| AddDoc(writer); |
| |
| Assert.AreEqual(23, reader3.NumDocs()); |
| reader3.Close(); |
| reader = IndexReader.Open(dir, true); |
| Assert.AreEqual(23, reader.NumDocs()); |
| reader.Close(); |
| |
| writer.PrepareCommit(); |
| |
| reader = IndexReader.Open(dir, true); |
| Assert.AreEqual(23, reader.NumDocs()); |
| reader.Close(); |
| |
| writer.Commit(); |
| reader = IndexReader.Open(dir, true); |
| Assert.AreEqual(40, reader.NumDocs()); |
| reader.Close(); |
| writer.Close(); |
| dir.Close(); |
| } |
| |
| // LUCENE-1274: test writer.prepareCommit() |
| [Test] |
| public virtual void TestPrepareCommitRollback() |
| { |
| MockRAMDirectory dir = new MockRAMDirectory(); |
| dir.SetPreventDoubleWrite(false); |
| |
| IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.LIMITED); |
| |
| writer.SetMaxBufferedDocs(2); |
| writer.MergeFactor = 5; |
| |
| for (int i = 0; i < 23; i++) |
| AddDoc(writer); |
| |
| IndexReader reader = IndexReader.Open(dir, true); |
| Assert.AreEqual(0, reader.NumDocs()); |
| |
| writer.PrepareCommit(); |
| |
| IndexReader reader2 = IndexReader.Open(dir, true); |
| Assert.AreEqual(0, reader2.NumDocs()); |
| |
| writer.Rollback(); |
| |
| IndexReader reader3 = reader.Reopen(); |
| Assert.AreEqual(0, reader.NumDocs()); |
| Assert.AreEqual(0, reader2.NumDocs()); |
| Assert.AreEqual(0, reader3.NumDocs()); |
| reader.Close(); |
| reader2.Close(); |
| |
| writer = new IndexWriter(dir, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.LIMITED); |
| for (int i = 0; i < 17; i++) |
| AddDoc(writer); |
| |
| Assert.AreEqual(0, reader3.NumDocs()); |
| reader3.Close(); |
| reader = IndexReader.Open(dir, true); |
| Assert.AreEqual(0, reader.NumDocs()); |
| reader.Close(); |
| |
| writer.PrepareCommit(); |
| |
| reader = IndexReader.Open(dir, true); |
| Assert.AreEqual(0, reader.NumDocs()); |
| reader.Close(); |
| |
| writer.Commit(); |
| reader = IndexReader.Open(dir, true); |
| Assert.AreEqual(17, reader.NumDocs()); |
| reader.Close(); |
| writer.Close(); |
| dir.Close(); |
| } |
| |
| // LUCENE-1274 |
| [Test] |
| public virtual void TestPrepareCommitNoChanges() |
| { |
| MockRAMDirectory dir = new MockRAMDirectory(); |
| |
| IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.LIMITED); |
| writer.PrepareCommit(); |
| writer.Commit(); |
| writer.Close(); |
| |
| IndexReader reader = IndexReader.Open(dir, true); |
| Assert.AreEqual(0, reader.NumDocs()); |
| reader.Close(); |
| dir.Close(); |
| } |
| |
| private abstract class RunAddIndexesThreads |
| { |
| private class AnonymousClassThread2 : ThreadClass |
| { |
| public AnonymousClassThread2(int numIter, RunAddIndexesThreads enclosingInstance) |
| { |
| InitBlock(numIter, enclosingInstance); |
| } |
| private void InitBlock(int numIter, RunAddIndexesThreads enclosingInstance) |
| { |
| this.numIter = numIter; |
| this.enclosingInstance = enclosingInstance; |
| } |
| private int numIter; |
| private RunAddIndexesThreads enclosingInstance; |
| public RunAddIndexesThreads Enclosing_Instance |
| { |
| get |
| { |
| return enclosingInstance; |
| } |
| |
| } |
| override public void Run() |
| { |
| try |
| { |
| |
| Directory[] dirs = new Directory[Enclosing_Instance.NUM_COPY]; |
| for (int k = 0; k < Enclosing_Instance.NUM_COPY; k++) |
| dirs[k] = new MockRAMDirectory(Enclosing_Instance.dir); |
| |
| int j = 0; |
| |
| while (true) |
| { |
| // System.out.println(Thread.currentThread().getName() + ": iter j=" + j); |
| if (numIter > 0 && j == numIter) |
| break; |
| Enclosing_Instance.DoBody(j++, dirs); |
| } |
| } |
| catch (System.Exception t) |
| { |
| Enclosing_Instance.Handle(t); |
| } |
| } |
| } |
| private void InitBlock() |
| { |
| threads = new ThreadClass[NUM_THREADS]; |
| } |
| |
| internal Directory dir, dir2; |
| internal const int NUM_INIT_DOCS = 17; |
| internal IndexWriter writer2; |
| internal System.Collections.IList failures = new System.Collections.ArrayList(); |
| internal volatile bool didClose; |
| internal IndexReader[] readers; |
| internal int NUM_COPY; |
| internal const int NUM_THREADS = 5; |
| internal ThreadClass[] threads; |
| internal ConcurrentMergeScheduler cms; |
| |
| public RunAddIndexesThreads(int numCopy) |
| { |
| NUM_COPY = numCopy; |
| dir = new MockRAMDirectory(); |
| IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.LIMITED); |
| writer.SetMaxBufferedDocs(2); |
| for (int i = 0; i < NUM_INIT_DOCS; i++) |
| AddDoc(writer); |
| writer.Close(); |
| |
| dir2 = new MockRAMDirectory(); |
| writer2 = new IndexWriter(dir2, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.LIMITED); |
| cms = (ConcurrentMergeScheduler)writer2.MergeScheduler; |
| |
| readers = new IndexReader[NUM_COPY]; |
| for (int i = 0; i < NUM_COPY; i++) |
| readers[i] = IndexReader.Open(dir, true); |
| } |
| |
| internal virtual void LaunchThreads(int numIter) |
| { |
| threads = new ThreadClass[NUM_THREADS]; //{{DIGY}} Should this be created somewhere else? |
| for (int i = 0; i < NUM_THREADS; i++) |
| { |
| threads[i] = new AnonymousClassThread2(numIter, this); |
| } |
| |
| for (int i = 0; i < NUM_THREADS; i++) |
| threads[i].Start(); |
| } |
| |
| internal virtual void JoinThreads() |
| { |
| for (int i = 0; i < NUM_THREADS; i++) |
| threads[i].Join(); |
| } |
| |
| internal virtual void Close(bool doWait) |
| { |
| didClose = true; |
| writer2.Close(doWait); |
| } |
| |
| internal virtual void CloseDir() |
| { |
| for (int i = 0; i < NUM_COPY; i++) |
| readers[i].Close(); |
| dir2.Close(); |
| } |
| |
| public /*internal*/ abstract void DoBody(int j, Directory[] dirs); |
| internal abstract void Handle(System.Exception t); |
| } |
| |
| private class CommitAndAddIndexes : RunAddIndexesThreads |
| { |
| private void InitBlock(TestIndexWriter enclosingInstance) |
| { |
| this.enclosingInstance = enclosingInstance; |
| } |
| private TestIndexWriter enclosingInstance; |
| public TestIndexWriter Enclosing_Instance |
| { |
| get |
| { |
| return enclosingInstance; |
| } |
| |
| } |
| public CommitAndAddIndexes(TestIndexWriter enclosingInstance, int numCopy) |
| : base(numCopy) |
| { |
| InitBlock(enclosingInstance); |
| } |
| |
| internal override void Handle(System.Exception t) |
| { |
| System.Console.Out.WriteLine(t.StackTrace); |
| lock (failures.SyncRoot) |
| { |
| failures.Add(t); |
| } |
| } |
| |
| public /*internal*/ override /*virtual*/ void DoBody(int j, Directory[] dirs) |
| { |
| switch (j % 4) |
| { |
| |
| case 0: |
| writer2.AddIndexesNoOptimize(dirs); |
| writer2.Optimize(); |
| break; |
| |
| case 1: |
| writer2.AddIndexesNoOptimize(dirs); |
| break; |
| |
| case 2: |
| writer2.AddIndexes(readers); |
| break; |
| |
| case 3: |
| writer2.Commit(); |
| break; |
| } |
| } |
| } |
| |
| // LUCENE-1335: test simultaneous addIndexes & commits |
| // from multiple threads |
| [Test] |
| public virtual void TestAddIndexesWithThreads() |
| { |
| |
| int NUM_ITER = 12; |
| int NUM_COPY = 3; |
| CommitAndAddIndexes c = new CommitAndAddIndexes(this, NUM_COPY); |
| c.LaunchThreads(NUM_ITER); |
| |
| for (int i = 0; i < 100; i++) |
| AddDoc(c.writer2); |
| |
| c.JoinThreads(); |
| |
| Assert.AreEqual(100 + NUM_COPY * (3 * NUM_ITER / 4) * Lucene.Net.Index.TestIndexWriter.CommitAndAddIndexes.NUM_THREADS * Lucene.Net.Index.TestIndexWriter.CommitAndAddIndexes.NUM_INIT_DOCS, c.writer2.NumDocs()); |
| |
| c.Close(true); |
| |
| Assert.IsTrue(c.failures.Count == 0); |
| |
| _TestUtil.CheckIndex(c.dir2); |
| |
| IndexReader reader = IndexReader.Open(c.dir2, true); |
| Assert.AreEqual(100 + NUM_COPY * (3 * NUM_ITER / 4) * Lucene.Net.Index.TestIndexWriter.CommitAndAddIndexes.NUM_THREADS * Lucene.Net.Index.TestIndexWriter.CommitAndAddIndexes.NUM_INIT_DOCS, reader.NumDocs()); |
| reader.Close(); |
| |
| c.CloseDir(); |
| } |
| |
| private class CommitAndAddIndexes2 : CommitAndAddIndexes |
| { |
| private void InitBlock(TestIndexWriter enclosingInstance) |
| { |
| this.enclosingInstance = enclosingInstance; |
| } |
| private TestIndexWriter enclosingInstance; |
| public new TestIndexWriter Enclosing_Instance |
| { |
| get |
| { |
| return enclosingInstance; |
| } |
| |
| } |
| public CommitAndAddIndexes2(TestIndexWriter enclosingInstance, int numCopy) |
| : base(enclosingInstance, numCopy) |
| { |
| InitBlock(enclosingInstance); |
| } |
| |
| internal override void Handle(System.Exception t) |
| { |
| if (!(t is AlreadyClosedException) && !(t is System.NullReferenceException)) |
| { |
| System.Console.Out.WriteLine(t.StackTrace); |
| lock (failures.SyncRoot) |
| { |
| failures.Add(t); |
| } |
| } |
| } |
| } |
| |
| // LUCENE-1335: test simultaneous addIndexes & close |
| [Test] |
| public virtual void TestAddIndexesWithClose() |
| { |
| int NUM_COPY = 3; |
| CommitAndAddIndexes2 c = new CommitAndAddIndexes2(this, NUM_COPY); |
| //c.writer2.setInfoStream(System.out); |
| c.LaunchThreads(-1); |
| |
| // Close w/o first stopping/joining the threads |
| c.Close(true); |
| //c.writer2.close(); |
| |
| c.JoinThreads(); |
| |
| _TestUtil.CheckIndex(c.dir2); |
| |
| c.CloseDir(); |
| |
| Assert.IsTrue(c.failures.Count == 0); |
| } |
| |
| private class CommitAndAddIndexes3 : RunAddIndexesThreads |
| { |
| private void InitBlock(TestIndexWriter enclosingInstance) |
| { |
| this.enclosingInstance = enclosingInstance; |
| } |
| private TestIndexWriter enclosingInstance; |
| public TestIndexWriter Enclosing_Instance |
| { |
| get |
| { |
| return enclosingInstance; |
| } |
| |
| } |
| public CommitAndAddIndexes3(TestIndexWriter enclosingInstance, int numCopy) |
| : base(numCopy) |
| { |
| InitBlock(enclosingInstance); |
| } |
| |
| public /*internal*/ override /*virtual*/ void DoBody(int j, Directory[] dirs) |
| { |
| switch (j % 5) |
| { |
| |
| case 0: |
| writer2.AddIndexesNoOptimize(dirs); |
| writer2.Optimize(); |
| break; |
| |
| case 1: |
| writer2.AddIndexesNoOptimize(dirs); |
| break; |
| |
| case 2: |
| writer2.AddIndexes(readers); |
| break; |
| |
| case 3: |
| writer2.Optimize(); |
| goto case 4; |
| |
| case 4: |
| writer2.Commit(); |
| break; |
| } |
| } |
| |
| internal override void Handle(System.Exception t) |
| { |
| bool report = true; |
| |
| if (t is AlreadyClosedException || t is MergePolicy.MergeAbortedException || t is System.NullReferenceException) |
| { |
| report = !didClose; |
| } |
| else if (t is System.IO.IOException) |
| { |
| System.Exception t2 = t.InnerException; |
| if (t2 is MergePolicy.MergeAbortedException) |
| { |
| report = !didClose; |
| } |
| } |
| if (report) |
| { |
| System.Console.Out.WriteLine(t.StackTrace); |
| lock (failures.SyncRoot) |
| { |
| failures.Add(t); |
| } |
| } |
| } |
| } |
| |
| // LUCENE-1335: test simultaneous addIndexes & close |
| [Test] |
| public virtual void TestAddIndexesWithCloseNoWait() |
| { |
| |
| int NUM_COPY = 50; |
| CommitAndAddIndexes3 c = new CommitAndAddIndexes3(this, NUM_COPY); |
| c.LaunchThreads(-1); |
| |
| System.Threading.Thread.Sleep(new System.TimeSpan((System.Int64)10000 * 500)); |
| |
| // Close w/o first stopping/joining the threads |
| c.Close(false); |
| |
| c.JoinThreads(); |
| |
| _TestUtil.CheckIndex(c.dir2); |
| |
| c.CloseDir(); |
| |
| Assert.IsTrue(c.failures.Count == 0); |
| } |
| |
| // LUCENE-1335: test simultaneous addIndexes & close |
| [Test] |
| public virtual void TestAddIndexesWithRollback() |
| { |
| |
| int NUM_COPY = 50; |
| CommitAndAddIndexes3 c = new CommitAndAddIndexes3(this, NUM_COPY); |
| c.LaunchThreads(-1); |
| |
| System.Threading.Thread.Sleep(new System.TimeSpan((System.Int64)10000 * 500)); |
| |
| // Close w/o first stopping/joining the threads |
| c.didClose = true; |
| c.writer2.Rollback(); |
| |
| c.JoinThreads(); |
| |
| _TestUtil.CheckIndex(c.dir2); |
| |
| c.CloseDir(); |
| |
| Assert.IsTrue(c.failures.Count == 0); |
| } |
| |
| // LUCENE-1347 |
| public class MockIndexWriter4 : IndexWriter |
| { |
| private void InitBlock(TestIndexWriter enclosingInstance) |
| { |
| this.enclosingInstance = enclosingInstance; |
| } |
| private TestIndexWriter enclosingInstance; |
| public TestIndexWriter Enclosing_Instance |
| { |
| get |
| { |
| return enclosingInstance; |
| } |
| |
| } |
| |
| public MockIndexWriter4(TestIndexWriter enclosingInstance, Directory dir, Analyzer a, bool create, MaxFieldLength mfl) |
| : base(dir, a, create, mfl) |
| { |
| InitBlock(enclosingInstance); |
| } |
| |
| internal bool doFail; |
| |
| public override bool TestPoint(System.String name) |
| { |
| if (doFail && name.Equals("rollback before checkpoint")) |
| throw new System.SystemException("intentionally failing"); |
| return true; |
| } |
| } |
| |
| // LUCENE-1347 |
| [Test] |
| public virtual void TestRollbackExceptionHang() |
| { |
| MockRAMDirectory dir = new MockRAMDirectory(); |
| MockIndexWriter4 w = new MockIndexWriter4(this, dir, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED); |
| |
| AddDoc(w); |
| w.doFail = true; |
| try |
| { |
| w.Rollback(); |
| if (BuildType.Debug) |
| Assert.Fail("did not hit intentional RuntimeException"); |
| else |
| Assert.Ignore("This test is not executed in release mode"); |
| |
| } |
| catch (System.SystemException re) |
| { |
| // expected |
| } |
| |
| w.doFail = false; |
| w.Rollback(); |
| } |
| |
| |
| // LUCENE-1219 |
| [Test] |
| public virtual void TestBinaryFieldOffsetLength() |
| { |
| MockRAMDirectory dir = new MockRAMDirectory(); |
| IndexWriter w = new IndexWriter(dir, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.UNLIMITED); |
| byte[] b = new byte[50]; |
| for (int i = 0; i < 50; i++) |
| b[i] = (byte)(i + 77); |
| |
| Document doc = new Document(); |
| Field f = new Field("binary", b, 10, 17, Field.Store.YES); |
| byte[] bx = f.GetBinaryValue(); |
| Assert.IsTrue(bx != null); |
| Assert.AreEqual(50, bx.Length); |
| Assert.AreEqual(10, f.BinaryOffset); |
| Assert.AreEqual(17, f.BinaryLength); |
| doc.Add(f); |
| w.AddDocument(doc); |
| w.Close(); |
| |
| IndexReader ir = IndexReader.Open(dir, true); |
| doc = ir.Document(0); |
| f = doc.GetField("binary"); |
| b = f.GetBinaryValue(); |
| Assert.IsTrue(b != null); |
| Assert.AreEqual(17, b.Length, 17); |
| Assert.AreEqual(87, b[0]); |
| ir.Close(); |
| dir.Close(); |
| } |
| |
| // LUCENE-1382 |
| [Test] |
| public virtual void TestCommitUserData() |
| { |
| Directory dir = new MockRAMDirectory(); |
| IndexWriter w = new IndexWriter(dir, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.LIMITED); |
| w.SetMaxBufferedDocs(2); |
| for (int j = 0; j < 17; j++) |
| AddDoc(w); |
| w.Close(); |
| |
| Assert.AreEqual(0, IndexReader.GetCommitUserData(dir).Count); |
| |
| IndexReader r = IndexReader.Open(dir, true); |
| // commit(Map) never called for this index |
| Assert.AreEqual(0, r.CommitUserData.Count); |
| r.Close(); |
| |
| w = new IndexWriter(dir, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.LIMITED); |
| w.SetMaxBufferedDocs(2); |
| for (int j = 0; j < 17; j++) |
| AddDoc(w); |
| System.Collections.Generic.IDictionary<string, string> data = new System.Collections.Generic.Dictionary<string, string>(); |
| data["label"] = "test1"; |
| w.Commit(data); |
| w.Close(); |
| |
| Assert.AreEqual("test1", IndexReader.GetCommitUserData(dir)["label"]); |
| |
| r = IndexReader.Open(dir, true); |
| Assert.AreEqual("test1", r.CommitUserData["label"]); |
| r.Close(); |
| |
| w = new IndexWriter(dir, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.LIMITED); |
| w.Optimize(); |
| w.Close(); |
| |
| Assert.AreEqual("test1", IndexReader.GetCommitUserData(dir)["label"]); |
| |
| dir.Close(); |
| } |
| |
| [Test] |
| public virtual void TestOptimizeExceptions() |
| { |
| RAMDirectory startDir = new MockRAMDirectory(); |
| IndexWriter w = new IndexWriter(startDir, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.UNLIMITED); |
| w.SetMaxBufferedDocs(2); |
| w.MergeFactor = 100; |
| for (int i = 0; i < 27; i++) |
| AddDoc(w); |
| w.Close(); |
| |
| for (int i = 0; i < 200; i++) |
| { |
| MockRAMDirectory dir = new MockRAMDirectory(startDir); |
| w = new IndexWriter(dir, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.UNLIMITED); |
| ((ConcurrentMergeScheduler)w.MergeScheduler).SetSuppressExceptions(); |
| dir.SetRandomIOExceptionRate(0.5, 100); |
| try |
| { |
| w.Optimize(); |
| } |
| catch (System.IO.IOException ioe) |
| { |
| Assert.IsNotNull(ioe.InnerException, "optimize threw IOException without root cause"); |
| } |
| w.Close(); |
| dir.Close(); |
| } |
| } |
| |
| // LUCENE-1429 |
| [Test] |
| public virtual void TestOutOfMemoryErrorCausesCloseToFail() |
| { |
| |
| System.Collections.IList thrown = new System.Collections.ArrayList(); |
| |
| IndexWriter writer = new AnonymousClassIndexWriter(thrown, this, new MockRAMDirectory(), new StandardAnalyzer(Util.Version.LUCENE_CURRENT)); |
| |
| // need to set an info stream so message is called |
| writer.SetInfoStream(new System.IO.StreamWriter(new System.IO.MemoryStream())); |
| try |
| { |
| writer.Close(); |
| Assert.Fail("OutOfMemoryError expected"); |
| } |
| catch (System.OutOfMemoryException expected) |
| { |
| } |
| |
| // throws IllegalStateEx w/o bug fix |
| writer.Close(); |
| } |
| |
| // LUCENE-1442 |
| [Test] |
| public virtual void TestDoubleOffsetCounting() |
| { |
| MockRAMDirectory dir = new MockRAMDirectory(); |
| IndexWriter w = new IndexWriter(dir, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.LIMITED); |
| Document doc = new Document(); |
| Field f = new Field("field", "abcd", Field.Store.NO, Field.Index.NOT_ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS); |
| doc.Add(f); |
| doc.Add(f); |
| Field f2 = new Field("field", "", Field.Store.NO, Field.Index.NOT_ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS); |
| doc.Add(f2); |
| doc.Add(f); |
| w.AddDocument(doc); |
| w.Close(); |
| |
| IndexReader r = IndexReader.Open(dir, true); |
| TermVectorOffsetInfo[] termOffsets = ((TermPositionVector)r.GetTermFreqVector(0, "field")).GetOffsets(0); |
| |
| // Token "" occurred once |
| Assert.AreEqual(1, termOffsets.Length); |
| Assert.AreEqual(8, termOffsets[0].StartOffset); |
| Assert.AreEqual(8, termOffsets[0].EndOffset); |
| |
| // Token "abcd" occurred three times |
| termOffsets = ((TermPositionVector)r.GetTermFreqVector(0, "field")).GetOffsets(1); |
| Assert.AreEqual(3, termOffsets.Length); |
| Assert.AreEqual(0, termOffsets[0].StartOffset); |
| Assert.AreEqual(4, termOffsets[0].EndOffset); |
| Assert.AreEqual(4, termOffsets[1].StartOffset); |
| Assert.AreEqual(8, termOffsets[1].EndOffset); |
| Assert.AreEqual(8, termOffsets[2].StartOffset); |
| Assert.AreEqual(12, termOffsets[2].EndOffset); |
| r.Close(); |
| dir.Close(); |
| } |
| |
| // LUCENE-1442 |
| [Test] |
| public virtual void TestDoubleOffsetCounting2() |
| { |
| MockRAMDirectory dir = new MockRAMDirectory(); |
| IndexWriter w = new IndexWriter(dir, new SimpleAnalyzer(), IndexWriter.MaxFieldLength.LIMITED); |
| Document doc = new Document(); |
| Field f = new Field("field", "abcd", Field.Store.NO, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS); |
| doc.Add(f); |
| doc.Add(f); |
| w.AddDocument(doc); |
| w.Close(); |
| |
| IndexReader r = IndexReader.Open(dir, true); |
| TermVectorOffsetInfo[] termOffsets = ((TermPositionVector)r.GetTermFreqVector(0, "field")).GetOffsets(0); |
| Assert.AreEqual(2, termOffsets.Length); |
| Assert.AreEqual(0, termOffsets[0].StartOffset); |
| Assert.AreEqual(4, termOffsets[0].EndOffset); |
| Assert.AreEqual(5, termOffsets[1].StartOffset); |
| Assert.AreEqual(9, termOffsets[1].EndOffset); |
| r.Close(); |
| dir.Close(); |
| } |
| |
| // LUCENE-1448 |
| [Test] |
| public virtual void TestEndOffsetPositionCharAnalyzer() |
| { |
| MockRAMDirectory dir = new MockRAMDirectory(); |
| IndexWriter w = new IndexWriter(dir, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.LIMITED); |
| Document doc = new Document(); |
| Field f = new Field("field", "abcd ", Field.Store.NO, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS); |
| doc.Add(f); |
| doc.Add(f); |
| w.AddDocument(doc); |
| w.Close(); |
| |
| IndexReader r = IndexReader.Open(dir, true); |
| TermVectorOffsetInfo[] termOffsets = ((TermPositionVector)r.GetTermFreqVector(0, "field")).GetOffsets(0); |
| Assert.AreEqual(2, termOffsets.Length); |
| Assert.AreEqual(0, termOffsets[0].StartOffset); |
| Assert.AreEqual(4, termOffsets[0].EndOffset); |
| Assert.AreEqual(8, termOffsets[1].StartOffset); |
| Assert.AreEqual(12, termOffsets[1].EndOffset); |
| r.Close(); |
| dir.Close(); |
| } |
| |
| // LUCENE-1448 |
| [Test] |
| public virtual void TestEndOffsetPositionWithCachingTokenFilter() |
| { |
| MockRAMDirectory dir = new MockRAMDirectory(); |
| Analyzer analyzer = new WhitespaceAnalyzer(); |
| IndexWriter w = new IndexWriter(dir, analyzer, IndexWriter.MaxFieldLength.LIMITED); |
| Document doc = new Document(); |
| TokenStream stream = new CachingTokenFilter(analyzer.TokenStream("field", new System.IO.StringReader("abcd "))); |
| Field f = new Field("field", stream, Field.TermVector.WITH_POSITIONS_OFFSETS); |
| doc.Add(f); |
| doc.Add(f); |
| w.AddDocument(doc); |
| w.Close(); |
| |
| IndexReader r = IndexReader.Open(dir, true); |
| TermVectorOffsetInfo[] termOffsets = ((TermPositionVector)r.GetTermFreqVector(0, "field")).GetOffsets(0); |
| Assert.AreEqual(2, termOffsets.Length); |
| Assert.AreEqual(0, termOffsets[0].StartOffset); |
| Assert.AreEqual(4, termOffsets[0].EndOffset); |
| Assert.AreEqual(8, termOffsets[1].StartOffset); |
| Assert.AreEqual(12, termOffsets[1].EndOffset); |
| r.Close(); |
| dir.Close(); |
| } |
| |
| // LUCENE-1448 |
| [Test] |
| public virtual void TestEndOffsetPositionWithTeeSinkTokenFilter() |
| { |
| MockRAMDirectory dir = new MockRAMDirectory(); |
| Analyzer analyzer = new WhitespaceAnalyzer(); |
| IndexWriter w = new IndexWriter(dir, analyzer, IndexWriter.MaxFieldLength.LIMITED); |
| Document doc = new Document(); |
| TeeSinkTokenFilter tee = new TeeSinkTokenFilter(analyzer.TokenStream("field", new System.IO.StringReader("abcd "))); |
| TokenStream sink = tee.NewSinkTokenStream(); |
| Field f1 = new Field("field", tee, Field.TermVector.WITH_POSITIONS_OFFSETS); |
| Field f2 = new Field("field", sink, Field.TermVector.WITH_POSITIONS_OFFSETS); |
| doc.Add(f1); |
| doc.Add(f2); |
| w.AddDocument(doc); |
| w.Close(); |
| |
| IndexReader r = IndexReader.Open(dir, true); |
| TermVectorOffsetInfo[] termOffsets = ((TermPositionVector)r.GetTermFreqVector(0, "field")).GetOffsets(0); |
| Assert.AreEqual(2, termOffsets.Length); |
| Assert.AreEqual(0, termOffsets[0].StartOffset); |
| Assert.AreEqual(4, termOffsets[0].EndOffset); |
| Assert.AreEqual(8, termOffsets[1].StartOffset); |
| Assert.AreEqual(12, termOffsets[1].EndOffset); |
| r.Close(); |
| dir.Close(); |
| } |
| |
| // LUCENE-1448 |
| [Test] |
| public virtual void TestEndOffsetPositionStopFilter() |
| { |
| MockRAMDirectory dir = new MockRAMDirectory(); |
| IndexWriter w = new IndexWriter(dir, new StopAnalyzer(Util.Version.LUCENE_CURRENT), IndexWriter.MaxFieldLength.LIMITED); |
| Document doc = new Document(); |
| Field f = new Field("field", "abcd the", Field.Store.NO, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS); |
| doc.Add(f); |
| doc.Add(f); |
| w.AddDocument(doc); |
| w.Close(); |
| |
| IndexReader r = IndexReader.Open(dir, true); |
| TermVectorOffsetInfo[] termOffsets = ((TermPositionVector)r.GetTermFreqVector(0, "field")).GetOffsets(0); |
| Assert.AreEqual(2, termOffsets.Length); |
| Assert.AreEqual(0, termOffsets[0].StartOffset); |
| Assert.AreEqual(4, termOffsets[0].EndOffset); |
| Assert.AreEqual(9, termOffsets[1].StartOffset); |
| Assert.AreEqual(13, termOffsets[1].EndOffset); |
| r.Close(); |
| dir.Close(); |
| } |
| |
| // LUCENE-1448 |
| [Test] |
| public virtual void TestEndOffsetPositionStandard() |
| { |
| MockRAMDirectory dir = new MockRAMDirectory(); |
| IndexWriter w = new IndexWriter(dir, new StandardAnalyzer(Util.Version.LUCENE_CURRENT), IndexWriter.MaxFieldLength.LIMITED); |
| Document doc = new Document(); |
| Field f = new Field("field", "abcd the ", Field.Store.NO, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS); |
| Field f2 = new Field("field", "crunch man", Field.Store.NO, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS); |
| doc.Add(f); |
| doc.Add(f2); |
| w.AddDocument(doc); |
| w.Close(); |
| |
| IndexReader r = IndexReader.Open(dir, true); |
| TermPositionVector tpv = ((TermPositionVector)r.GetTermFreqVector(0, "field")); |
| TermVectorOffsetInfo[] termOffsets = tpv.GetOffsets(0); |
| Assert.AreEqual(1, termOffsets.Length); |
| Assert.AreEqual(0, termOffsets[0].StartOffset); |
| Assert.AreEqual(4, termOffsets[0].EndOffset); |
| termOffsets = tpv.GetOffsets(1); |
| Assert.AreEqual(11, termOffsets[0].StartOffset); |
| Assert.AreEqual(17, termOffsets[0].EndOffset); |
| termOffsets = tpv.GetOffsets(2); |
| Assert.AreEqual(18, termOffsets[0].StartOffset); |
| Assert.AreEqual(21, termOffsets[0].EndOffset); |
| r.Close(); |
| dir.Close(); |
| } |
| |
| // LUCENE-1448 |
| [Test] |
| public virtual void TestEndOffsetPositionStandardEmptyField() |
| { |
| MockRAMDirectory dir = new MockRAMDirectory(); |
| IndexWriter w = new IndexWriter(dir, new StandardAnalyzer(Util.Version.LUCENE_CURRENT), IndexWriter.MaxFieldLength.LIMITED); |
| Document doc = new Document(); |
| Field f = new Field("field", "", Field.Store.NO, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS); |
| Field f2 = new Field("field", "crunch man", Field.Store.NO, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS); |
| doc.Add(f); |
| doc.Add(f2); |
| w.AddDocument(doc); |
| w.Close(); |
| |
| IndexReader r = IndexReader.Open(dir, true); |
| TermPositionVector tpv = ((TermPositionVector)r.GetTermFreqVector(0, "field")); |
| TermVectorOffsetInfo[] termOffsets = tpv.GetOffsets(0); |
| Assert.AreEqual(1, termOffsets.Length); |
| Assert.AreEqual(0, termOffsets[0].StartOffset); |
| Assert.AreEqual(6, termOffsets[0].EndOffset); |
| termOffsets = tpv.GetOffsets(1); |
| Assert.AreEqual(7, termOffsets[0].StartOffset); |
| Assert.AreEqual(10, termOffsets[0].EndOffset); |
| r.Close(); |
| dir.Close(); |
| } |
| |
| // LUCENE-1448 |
| [Test] |
| public virtual void TestEndOffsetPositionStandardEmptyField2() |
| { |
| MockRAMDirectory dir = new MockRAMDirectory(); |
| IndexWriter w = new IndexWriter(dir, new StandardAnalyzer(Util.Version.LUCENE_CURRENT), IndexWriter.MaxFieldLength.LIMITED); |
| Document doc = new Document(); |
| |
| Field f = new Field("field", "abcd", Field.Store.NO, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS); |
| doc.Add(f); |
| doc.Add(new Field("field", "", Field.Store.NO, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS)); |
| |
| Field f2 = new Field("field", "crunch", Field.Store.NO, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS); |
| doc.Add(f2); |
| |
| w.AddDocument(doc); |
| w.Close(); |
| |
| IndexReader r = IndexReader.Open(dir, true); |
| TermPositionVector tpv = ((TermPositionVector)r.GetTermFreqVector(0, "field")); |
| TermVectorOffsetInfo[] termOffsets = tpv.GetOffsets(0); |
| Assert.AreEqual(1, termOffsets.Length); |
| Assert.AreEqual(0, termOffsets[0].StartOffset); |
| Assert.AreEqual(4, termOffsets[0].EndOffset); |
| termOffsets = tpv.GetOffsets(1); |
| Assert.AreEqual(5, termOffsets[0].StartOffset); |
| Assert.AreEqual(11, termOffsets[0].EndOffset); |
| r.Close(); |
| dir.Close(); |
| } |
| |
| |
| // LUCENE-1468 -- make sure opening an IndexWriter with |
| // create=true does not remove non-index files |
| |
| [Test] |
| public virtual void TestOtherFiles() |
| { |
| System.IO.DirectoryInfo indexDir = new System.IO.DirectoryInfo(System.IO.Path.Combine(AppSettings.Get("tempDir", ""), "otherfiles")); |
| Directory dir = FSDirectory.Open(indexDir); |
| try |
| { |
| // Create my own random file: |
| |
| IndexOutput out_Renamed = dir.CreateOutput("myrandomfile"); |
| out_Renamed.WriteByte((byte)42); |
| out_Renamed.Close(); |
| |
| new IndexWriter(dir, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED).Close(); |
| |
| Assert.IsTrue(dir.FileExists("myrandomfile")); |
| |
| // Make sure this does not copy myrandomfile: |
| Directory dir2 = new RAMDirectory(dir); |
| Assert.IsTrue(!dir2.FileExists("myrandomfile")); |
| } |
| finally |
| { |
| dir.Close(); |
| _TestUtil.RmDir(indexDir); |
| } |
| } |
| |
| [Test] |
| public virtual void TestDeadlock() |
| { |
| MockRAMDirectory dir = new MockRAMDirectory(); |
| IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.UNLIMITED); |
| writer.SetMaxBufferedDocs(2); |
| Document doc = new Document(); |
| doc.Add(new Field("content", "aaa bbb ccc ddd eee fff ggg hhh iii", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS)); |
| writer.AddDocument(doc); |
| writer.AddDocument(doc); |
| writer.AddDocument(doc); |
| writer.Commit(); |
| // index has 2 segments |
| |
| MockRAMDirectory dir2 = new MockRAMDirectory(); |
| IndexWriter writer2 = new IndexWriter(dir2, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.LIMITED); |
| writer2.AddDocument(doc); |
| writer2.Close(); |
| |
| IndexReader r1 = IndexReader.Open(dir2, true); |
| IndexReader r2 = (IndexReader)r1.Clone(); |
| writer.AddIndexes(new IndexReader[] { r1, r2 }); |
| writer.Close(); |
| |
| IndexReader r3 = IndexReader.Open(dir, true); |
| Assert.AreEqual(5, r3.NumDocs()); |
| r3.Close(); |
| |
| r1.Close(); |
| r2.Close(); |
| |
| dir2.Close(); |
| dir.Close(); |
| } |
| |
| private class IndexerThreadInterrupt : ThreadClass |
| { |
| public IndexerThreadInterrupt(TestIndexWriter enclosingInstance) |
| { |
| InitBlock(enclosingInstance); |
| } |
| private void InitBlock(TestIndexWriter enclosingInstance) |
| { |
| this.enclosingInstance = enclosingInstance; |
| } |
| private TestIndexWriter enclosingInstance; |
| public TestIndexWriter Enclosing_Instance |
| { |
| get |
| { |
| return enclosingInstance; |
| } |
| |
| } |
| internal volatile bool failed; |
| internal volatile bool finish; |
| |
| internal bool AllowInterrupt = false; |
| |
| override public void Run() |
| { |
| bool endLoop = false; |
| RAMDirectory dir = new RAMDirectory(); |
| IndexWriter w = null; |
| bool first = true; |
| while (!finish) |
| { |
| try |
| { |
| while (true) |
| { |
| if (w != null) |
| { |
| w.Close(); |
| } |
| w = new IndexWriter(dir, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.UNLIMITED); |
| //((ConcurrentMergeScheduler) w.GetMergeScheduler()).SetSuppressExceptions(); |
| if (!first && !AllowInterrupt) |
| { |
| // tell main thread it can interrupt us at any time, |
| // starting now |
| AllowInterrupt = true; |
| } |
| |
| w.SetMaxBufferedDocs(2); |
| w.MergeFactor = 2; |
| Document doc = new Document(); |
| doc.Add(new Field("field", "some text contents", Field.Store.YES, Field.Index.ANALYZED)); |
| for (int i = 0; i < 100; i++) |
| { |
| w.AddDocument(doc); |
| w.Commit(); |
| } |
| w.Close(); |
| _TestUtil.CheckIndex(dir); |
| IndexReader.Open(dir, true).Close(); |
| if (first && !AllowInterrupt) |
| { |
| // Strangely, if we interrupt a thread before |
| // all classes are loaded, the class loader |
| // seems to do scary things with the interrupt |
| // status. In java 1.5, it'll throw an |
| // incorrect ClassNotFoundException. In java |
| // 1.6, it'll silently clear the interrupt. |
| // So, on first iteration through here we |
| // don't open ourselves up for interrupts |
| // until we've done the above loop. |
| AllowInterrupt = true; |
| first = false; |
| } |
| } |
| } |
| catch (System.Threading.ThreadInterruptedException re) |
| { |
| if (finish) |
| { |
| break; |
| } |
| |
| // Make sure IW cleared the interrupted bit |
| // TODO: remove that flase once test is fixed for real |
| if (false)// && interrupted()) |
| { |
| Console.Out.WriteLine("FAILED; InterruptedException hit but thread.interrupted() was true"); |
| Console.Out.WriteLine(re.StackTrace); |
| failed = true; |
| break; |
| } |
| } |
| catch (System.Exception t) |
| { |
| System.Console.Out.WriteLine("FAILED; unexpected exception"); |
| System.Console.Out.WriteLine(t.StackTrace); |
| failed = true; |
| break; |
| } |
| } |
| |
| if (!failed) |
| { |
| try |
| { |
| _TestUtil.CheckIndex(dir); |
| } |
| catch (System.Exception e) |
| { |
| failed = true; |
| System.Console.Out.WriteLine("CheckIndex FAILED: unexpected exception"); |
| System.Console.Out.WriteLine(e.StackTrace); |
| } |
| try |
| { |
| IndexReader r = IndexReader.Open(dir, true); |
| //System.out.println("doc count=" + r.numDocs()); |
| r.Close(); |
| } |
| catch (System.Exception e) |
| { |
| failed = true; |
| System.Console.Out.WriteLine("IndexReader.open FAILED: unexpected exception"); |
| System.Console.Out.WriteLine(e.StackTrace); |
| } |
| } |
| } |
| } |
| |
| [Test] |
| public virtual void TestThreadInterruptDeadlock() |
| { |
| IndexerThreadInterrupt t = new IndexerThreadInterrupt(this); |
| t.IsBackground = true; |
| t.Start(); |
| // issue 100 interrupts to child thread |
| for (int i = 0; i < 100; i++) |
| { |
| Thread.Sleep(1); |
| if (t.AllowInterrupt) |
| { |
| i++; |
| t.AllowInterrupt = false; |
| t.Interrupt(); |
| } |
| if (!t.IsAlive) |
| { |
| break; |
| } |
| } |
| t.AllowInterrupt = false; |
| t.finish = true; |
| t.Interrupt(); |
| t.Join(); |
| Assert.IsFalse(t.failed); |
| } |
| |
| |
| [Test] |
| public virtual void TestIndexStoreCombos() |
| { |
| MockRAMDirectory dir = new MockRAMDirectory(); |
| IndexWriter w = new IndexWriter(dir, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.UNLIMITED); |
| byte[] b = new byte[50]; |
| for (int i = 0; i < 50; i++) |
| b[i] = (byte)(i + 77); |
| |
| Document doc = new Document(); |
| Field f = new Field("binary", b, 10, 17, Field.Store.YES); |
| f.SetTokenStream(new WhitespaceTokenizer(new System.IO.StringReader("doc1field1"))); |
| Field f2 = new Field("string", "value", Field.Store.YES, Field.Index.ANALYZED); |
| f2.SetTokenStream(new WhitespaceTokenizer(new System.IO.StringReader("doc1field2"))); |
| doc.Add(f); |
| doc.Add(f2); |
| w.AddDocument(doc); |
| |
| // add 2 docs to test in-memory merging |
| f.SetTokenStream(new WhitespaceTokenizer(new System.IO.StringReader("doc2field1"))); |
| f2.SetTokenStream(new WhitespaceTokenizer(new System.IO.StringReader("doc2field2"))); |
| w.AddDocument(doc); |
| |
| // force segment flush so we can force a segment merge with doc3 later. |
| w.Commit(); |
| |
| f.SetTokenStream(new WhitespaceTokenizer(new System.IO.StringReader("doc3field1"))); |
| f2.SetTokenStream(new WhitespaceTokenizer(new System.IO.StringReader("doc3field2"))); |
| |
| w.AddDocument(doc); |
| w.Commit(); |
| w.Optimize(); // force segment merge. |
| |
| IndexReader ir = IndexReader.Open(dir, true); |
| doc = ir.Document(0); |
| f = doc.GetField("binary"); |
| b = f.GetBinaryValue(); |
| Assert.IsTrue(b != null); |
| Assert.AreEqual(17, b.Length, 17); |
| Assert.AreEqual(87, b[0]); |
| |
| Assert.IsTrue(ir.Document(0).GetFieldable("binary").IsBinary); |
| Assert.IsTrue(ir.Document(1).GetFieldable("binary").IsBinary); |
| Assert.IsTrue(ir.Document(2).GetFieldable("binary").IsBinary); |
| |
| Assert.AreEqual("value", ir.Document(0).Get("string")); |
| Assert.AreEqual("value", ir.Document(1).Get("string")); |
| Assert.AreEqual("value", ir.Document(2).Get("string")); |
| |
| |
| // test that the terms were indexed. |
| Assert.IsTrue(ir.TermDocs(new Term("binary", "doc1field1")).Next()); |
| Assert.IsTrue(ir.TermDocs(new Term("binary", "doc2field1")).Next()); |
| Assert.IsTrue(ir.TermDocs(new Term("binary", "doc3field1")).Next()); |
| Assert.IsTrue(ir.TermDocs(new Term("string", "doc1field2")).Next()); |
| Assert.IsTrue(ir.TermDocs(new Term("string", "doc2field2")).Next()); |
| Assert.IsTrue(ir.TermDocs(new Term("string", "doc3field2")).Next()); |
| |
| ir.Close(); |
| dir.Close(); |
| } |
| |
| // LUCENE-1727: make sure doc fields are stored in order |
| [Test] |
| public virtual void TestStoredFieldsOrder() |
| { |
| Directory d = new MockRAMDirectory(); |
| IndexWriter w = new IndexWriter(d, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.UNLIMITED); |
| Document doc = new Document(); |
| doc.Add(new Field("zzz", "a b c", Field.Store.YES, Field.Index.NO)); |
| doc.Add(new Field("aaa", "a b c", Field.Store.YES, Field.Index.NO)); |
| doc.Add(new Field("zzz", "1 2 3", Field.Store.YES, Field.Index.NO)); |
| w.AddDocument(doc); |
| IndexReader r = w.GetReader(); |
| doc = r.Document(0); |
| System.Collections.IEnumerator it = doc.GetFields().GetEnumerator(); |
| Assert.IsTrue(it.MoveNext()); |
| Field f = (Field)it.Current; |
| Assert.AreEqual(f.Name, "zzz"); |
| Assert.AreEqual(f.StringValue, "a b c"); |
| |
| Assert.IsTrue(it.MoveNext()); |
| f = (Field)it.Current; |
| Assert.AreEqual(f.Name, "aaa"); |
| Assert.AreEqual(f.StringValue, "a b c"); |
| |
| Assert.IsTrue(it.MoveNext()); |
| f = (Field)it.Current; |
| Assert.AreEqual(f.Name, "zzz"); |
| Assert.AreEqual(f.StringValue, "1 2 3"); |
| Assert.IsFalse(it.MoveNext()); |
| r.Close(); |
| w.Close(); |
| d.Close(); |
| } |
| |
| [Test] |
| public void TestEmbeddedFFFF() |
| { |
| |
| Directory d = new MockRAMDirectory(); |
| IndexWriter w = new IndexWriter(d, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.UNLIMITED); |
| Document doc = new Document(); |
| doc.Add(new Field("field", "a a\uffffb", Field.Store.NO, Field.Index.ANALYZED)); |
| w.AddDocument(doc); |
| doc = new Document(); |
| doc.Add(new Field("field", "a", Field.Store.NO, Field.Index.ANALYZED)); |
| w.AddDocument(doc); |
| w.Close(); |
| |
| _TestUtil.CheckIndex(d); |
| d.Close(); |
| } |
| |
| [Test] |
| public void TestNoDocsIndex() |
| { |
| Directory dir = new MockRAMDirectory(); |
| IndexWriter writer = new IndexWriter(dir, new SimpleAnalyzer(), IndexWriter.MaxFieldLength.UNLIMITED); |
| writer.UseCompoundFile = false; |
| //ByteArrayOutputStream bos = new ByteArrayOutputStream(1024); |
| //writer.SetInfoStream(new PrintStream(bos)); |
| writer.AddDocument(new Document()); |
| writer.Close(); |
| |
| _TestUtil.CheckIndex(dir); |
| dir.Close(); |
| } |
| |
| class LUCENE_2095_Thread : ThreadClass |
| { |
| IndexWriter w = null; |
| Directory dir = null; |
| long endTime = 0; |
| volatile bool failed = false; |
| int finalI = 0; |
| |
| public LUCENE_2095_Thread(IndexWriter w, long endTime, Directory dir, bool failed, int finalI) |
| { |
| this.w = w; |
| this.dir = dir; |
| this.endTime = endTime; |
| this.failed = failed; |
| this.finalI = finalI; |
| } |
| |
| override public void Run() |
| { |
| try |
| { |
| Document doc = new Document(); |
| IndexReader r = IndexReader.Open(dir, true); |
| Field f = new Field("f", "", Field.Store.NO, Field.Index.NOT_ANALYZED); |
| doc.Add(f); |
| int count = 0; |
| while ((DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) < endTime && !failed) |
| { |
| for (int j = 0; j < 10; j++) |
| { |
| String s = finalI + "_" + (count++).ToString(); |
| f.SetValue(s); |
| w.AddDocument(doc); |
| w.Commit(); |
| IndexReader r2 = r.Reopen(); |
| Assert.IsTrue(r2 != r); |
| r.Close(); |
| r = r2; |
| Assert.AreEqual(1, r.DocFreq(new Term("f", s)), "term=f:" + s); |
| } |
| } |
| r.Close(); |
| } |
| catch (Exception t) |
| { |
| failed = true; |
| throw; |
| } |
| } |
| } |
| |
| // LUCENE-2095: make sure with multiple threads commit |
| // doesn't return until all changes are in fact in the |
| // index |
| [Test] |
| public void TestCommitThreadSafety() |
| { |
| int NUM_THREADS = 5; |
| double RUN_SEC = 0.5; |
| Directory dir = new MockRAMDirectory(); |
| IndexWriter w = new IndexWriter(dir, new SimpleAnalyzer(), IndexWriter.MaxFieldLength.UNLIMITED); |
| w.Commit(); |
| bool failed = false; // TODO: Java uses AtomicBoolean, r/w of bool in .net is inherantly atomic |
| LUCENE_2095_Thread[] threads = new LUCENE_2095_Thread[NUM_THREADS]; |
| long endTime = (DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) + ((long)(RUN_SEC * 1000)); |
| for (int i = 0; i < NUM_THREADS; i++) |
| { |
| int finalI = i; |
| |
| threads[i] = new LUCENE_2095_Thread(w, endTime, dir, failed, finalI); |
| threads[i].Start(); |
| } |
| for (int i = 0; i < NUM_THREADS; i++) |
| { |
| threads[i].Join(); |
| } |
| w.Close(); |
| dir.Close(); |
| Assert.False(failed); |
| } |
| |
| |
| private class FailTwiceDuringMerge : MockRAMDirectory.Failure |
| { |
| public bool didFail1; |
| public bool didFail2; |
| |
| public override void Eval(MockRAMDirectory dir) |
| { |
| if (!doFail) |
| { |
| return; |
| } |
| |
| System.Diagnostics.StackTrace trace = new System.Diagnostics.StackTrace(); |
| for (int i = 0; i < trace.FrameCount; i++) |
| { |
| System.Diagnostics.StackFrame sf = trace.GetFrame(i); |
| string className = sf.GetMethod().DeclaringType.Namespace + "." + sf.GetMethod().DeclaringType.Name; |
| if ("Lucene.Net.Index.SegmentMerger".Equals(className) && "MergeTerms".Equals(sf.GetMethod().Name) && !didFail1) |
| { |
| didFail1 = true; |
| throw new System.IO.IOException("fake disk full during mergeTerms"); |
| } |
| if ("Lucene.Net.Util.BitVector".Equals(sf.GetType().Name) && "Write".Equals(sf.GetMethod().Name) && !didFail2) |
| { |
| didFail2 = true; |
| throw new System.IO.IOException("fake disk full while writing BitVector"); |
| } |
| } |
| } |
| } |
| |
| // LUCENE-2593 |
| [Test] |
| public void TestCorruptionAfterDiskFullDuringMerge() |
| { |
| MockRAMDirectory dir = new MockRAMDirectory(); |
| dir.SetPreventDoubleWrite(false); |
| IndexWriter w = new IndexWriter(dir, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.UNLIMITED); |
| w.SetMergeScheduler(new SerialMergeScheduler()); |
| |
| ((LogMergePolicy)w.MergePolicy).MergeFactor = 2; |
| |
| Document doc = new Document(); |
| doc.Add(new Field("f", "doctor who", Field.Store.YES, Field.Index.ANALYZED)); |
| w.AddDocument(doc); |
| |
| w.Commit(); |
| |
| w.DeleteDocuments(new Term("f", "who")); |
| w.AddDocument(doc); |
| |
| // disk fills up! |
| FailTwiceDuringMerge ftdm = new FailTwiceDuringMerge(); |
| ftdm.SetDoFail(); |
| dir.FailOn(ftdm); |
| |
| Assert.Throws<System.IO.IOException>(w.Commit, "fake disk full IOExceptions not hit"); |
| Assert.IsTrue(ftdm.didFail1 || ftdm.didFail2); |
| |
| _TestUtil.CheckIndex(dir); |
| ftdm.ClearDoFail(); |
| w.AddDocument(doc); |
| w.Close(); |
| |
| _TestUtil.CheckIndex(dir); |
| dir.Close(); |
| } |
| |
| private class NoDeletionPolicy : IndexDeletionPolicy |
| { |
| public void OnCommit<T>(IList<T> commits) |
| where T : IndexCommit |
| { |
| } |
| public void OnInit<T>(IList<T> commits) |
| where T : IndexCommit |
| { |
| } |
| } |
| |
| #if GALLIO |
| [Ignore] |
| // TODO: figure out why this fails with nunit & gallio in release mode |
| #endif |
| [Test] |
| public void TestFutureCommit() |
| { |
| Directory dir = new MockRAMDirectory(); |
| |
| IndexWriter w = new IndexWriter(dir, new WhitespaceAnalyzer(), new NoDeletionPolicy(), IndexWriter.MaxFieldLength.UNLIMITED); |
| Document doc = new Document(); |
| w.AddDocument(doc); |
| |
| // commit to "first" |
| IDictionary<string, string> commitData = new HashMap<string, string>(); |
| commitData["tag"]="first"; |
| w.Commit(commitData); |
| |
| // commit to "second" |
| w.AddDocument(doc); |
| commitData["tag"]="second"; |
| w.Commit(commitData); |
| w.Close(); |
| |
| // open "first" with IndexWriter |
| IndexCommit commit = null; |
| foreach(var c in IndexReader.ListCommits(dir)) |
| { |
| //string tag = c.GetUserData()["tag"]; |
| var thing = c.UserData; |
| string tag = thing["tag"]; |
| if ("first".Equals(tag)) |
| { |
| commit = c; |
| break; |
| } |
| } |
| |
| Assert.NotNull(commit); |
| |
| w = new IndexWriter(dir, new WhitespaceAnalyzer(), new NoDeletionPolicy(), IndexWriter.MaxFieldLength.UNLIMITED, commit); |
| |
| Assert.AreEqual(1, w.NumDocs()); |
| |
| // commit IndexWriter to "third" |
| w.AddDocument(doc); |
| commitData["tag"]="third"; |
| w.Commit(commitData); |
| w.Close(); |
| |
| // make sure "second" commit is still there |
| commit = null; |
| foreach(var c in IndexReader.ListCommits(dir)) |
| { |
| string tag = c.UserData["tag"]; |
| if ("second".Equals(tag)) |
| { |
| commit = c; |
| break; |
| } |
| } |
| |
| Assert.NotNull(commit); |
| |
| IndexReader r = IndexReader.Open(commit, true); |
| Assert.AreEqual(2, r.NumDocs()); |
| r.Close(); |
| |
| // open "second", w/ writeable IndexReader & commit |
| r = IndexReader.Open(commit, new NoDeletionPolicy(), false); |
| Assert.AreEqual(2, r.NumDocs()); |
| r.DeleteDocument(0); |
| r.DeleteDocument(1); |
| commitData["tag"]="fourth"; |
| r.Commit(commitData); |
| r.Close(); |
| |
| // make sure "third" commit is still there |
| commit = null; |
| foreach(var c in IndexReader.ListCommits(dir)) |
| { |
| string tag = c.UserData["tag"]; |
| if ("third".Equals(tag)) |
| { |
| commit = c; |
| break; |
| } |
| } |
| Assert.NotNull(commit); |
| |
| dir.Close(); |
| } |
| |
| public void testNoUnwantedTVFiles() |
| { |
| |
| Directory dir = new MockRAMDirectory(); |
| IndexWriter indexWriter = new IndexWriter(dir, new WhitespaceAnalyzer(), IndexWriter.MaxFieldLength.UNLIMITED); |
| indexWriter.SetRAMBufferSizeMB(0.01); |
| indexWriter.UseCompoundFile = false; |
| |
| String BIG = "alskjhlaksjghlaksjfhalksvjepgjioefgjnsdfjgefgjhelkgjhqewlrkhgwlekgrhwelkgjhwelkgrhwlkejg"; |
| BIG = BIG + BIG + BIG + BIG; |
| |
| for (int i = 0; i < 2; i++) |
| { |
| Document doc = new Document(); |
| doc.Add(new Field("id", i.ToString() + BIG, Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS)); |
| doc.Add(new Field("str", i.ToString() + BIG, Field.Store.YES, Field.Index.NOT_ANALYZED)); |
| doc.Add(new Field("str2", i.ToString() + BIG, Field.Store.YES, Field.Index.ANALYZED)); |
| doc.Add(new Field("str3", i.ToString() + BIG, Field.Store.YES, Field.Index.ANALYZED_NO_NORMS)); |
| indexWriter.AddDocument(doc); |
| } |
| |
| indexWriter.Close(); |
| |
| _TestUtil.CheckIndex(dir); |
| |
| AssertNoUnreferencedFiles(dir, "no tv files"); |
| String[] files = dir.ListAll(); |
| foreach(var file in files) |
| { |
| Assert.IsTrue(!file.EndsWith(IndexFileNames.VECTORS_FIELDS_EXTENSION)); |
| Assert.IsTrue(!file.EndsWith(IndexFileNames.VECTORS_INDEX_EXTENSION)); |
| Assert.IsTrue(!file.EndsWith(IndexFileNames.VECTORS_DOCUMENTS_EXTENSION)); |
| } |
| |
| dir.Close(); |
| } |
| } |
| } |