blob: 954d323a5f7c383a38e76bb7d576482053dc3125 [file] [log] [blame]
using Lucene.Net.Documents;
using Lucene.Net.Util;
using System.Collections.Generic;
using System.Reflection;
namespace Lucene.Net.Index
{
//using AlreadySetException = Lucene.Net.Util.SetOnce.AlreadySetException;
using NUnit.Framework;
using Codec = Lucene.Net.Codecs.Codec;
using DefaultSimilarity = Lucene.Net.Search.Similarities.DefaultSimilarity;
using Directory = Lucene.Net.Store.Directory;
using Document = Documents.Document;
using IndexingChain = Lucene.Net.Index.DocumentsWriterPerThread.IndexingChain;
using IndexSearcher = Lucene.Net.Search.IndexSearcher;
using InfoStream = Lucene.Net.Util.InfoStream;
using LuceneTestCase = Lucene.Net.Util.LuceneTestCase;
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using MockAnalyzer = Lucene.Net.Analysis.MockAnalyzer;
using OpenMode_e = Lucene.Net.Index.IndexWriterConfig.OpenMode_e;
using Store = Field.Store;
[TestFixture]
public class TestIndexWriterConfig : LuceneTestCase
{
private sealed class MySimilarity : DefaultSimilarity
{
// Does not implement anything - used only for type checking on IndexWriterConfig.
}
public class MyIndexingChain : IndexingChain
{
// Does not implement anything - used only for type checking on IndexWriterConfig.
public override DocConsumer GetChain(DocumentsWriterPerThread documentsWriter)
{
return null;
}
}
[Test]
public virtual void TestDefaults()
{
IndexWriterConfig conf = new IndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random()));
Assert.AreEqual(typeof(MockAnalyzer), conf.Analyzer.GetType());
Assert.IsNull(conf.IndexCommit);
Assert.AreEqual(typeof(KeepOnlyLastCommitDeletionPolicy), conf.DelPolicy.GetType());
Assert.AreEqual(typeof(ConcurrentMergeScheduler), conf.MergeScheduler.GetType());
Assert.AreEqual(OpenMode_e.CREATE_OR_APPEND, conf.OpenMode);
// we don't need to assert this, it should be unspecified
Assert.IsTrue(IndexSearcher.DefaultSimilarity == conf.Similarity);
Assert.AreEqual(IndexWriterConfig.DEFAULT_TERM_INDEX_INTERVAL, conf.TermIndexInterval);
Assert.AreEqual(IndexWriterConfig.DefaultWriteLockTimeout, conf.WriteLockTimeout);
Assert.AreEqual(IndexWriterConfig.WRITE_LOCK_TIMEOUT, IndexWriterConfig.DefaultWriteLockTimeout);
Assert.AreEqual(IndexWriterConfig.DEFAULT_MAX_BUFFERED_DELETE_TERMS, conf.MaxBufferedDeleteTerms);
Assert.AreEqual(IndexWriterConfig.DEFAULT_RAM_BUFFER_SIZE_MB, conf.RAMBufferSizeMB, 0.0);
Assert.AreEqual(IndexWriterConfig.DEFAULT_MAX_BUFFERED_DOCS, conf.MaxBufferedDocs);
Assert.AreEqual(IndexWriterConfig.DEFAULT_READER_POOLING, conf.ReaderPooling);
Assert.IsTrue(DocumentsWriterPerThread.DefaultIndexingChain == conf.IndexingChain);
Assert.IsNull(conf.MergedSegmentWarmer);
Assert.AreEqual(IndexWriterConfig.DEFAULT_READER_TERMS_INDEX_DIVISOR, conf.ReaderTermsIndexDivisor);
Assert.AreEqual(typeof(TieredMergePolicy), conf.MergePolicy.GetType());
Assert.AreEqual(typeof(ThreadAffinityDocumentsWriterThreadPool), conf.IndexerThreadPool.GetType());
Assert.AreEqual(typeof(FlushByRamOrCountsPolicy), conf.FlushPolicy.GetType());
Assert.AreEqual(IndexWriterConfig.DEFAULT_RAM_PER_THREAD_HARD_LIMIT_MB, conf.RAMPerThreadHardLimitMB);
Assert.AreEqual(Codec.Default, conf.Codec);
Assert.AreEqual(InfoStream.Default, conf.InfoStream);
Assert.AreEqual(IndexWriterConfig.DEFAULT_USE_COMPOUND_FILE_SYSTEM, conf.UseCompoundFile);
// Sanity check - validate that all getters are covered.
HashSet<string> getters = new HashSet<string>();
getters.Add("getAnalyzer");
getters.Add("getIndexCommit");
getters.Add("getIndexDeletionPolicy");
getters.Add("getMaxFieldLength");
getters.Add("getMergeScheduler");
getters.Add("getOpenMode");
getters.Add("getSimilarity");
getters.Add("getTermIndexInterval");
getters.Add("getWriteLockTimeout");
getters.Add("getDefaultWriteLockTimeout");
getters.Add("getMaxBufferedDeleteTerms");
getters.Add("getRAMBufferSizeMB");
getters.Add("getMaxBufferedDocs");
getters.Add("getIndexingChain");
getters.Add("getMergedSegmentWarmer");
getters.Add("getMergePolicy");
getters.Add("getMaxThreadStates");
getters.Add("getReaderPooling");
getters.Add("getIndexerThreadPool");
getters.Add("getReaderTermsIndexDivisor");
getters.Add("getFlushPolicy");
getters.Add("getRAMPerThreadHardLimitMB");
getters.Add("getCodec");
getters.Add("getInfoStream");
getters.Add("getUseCompoundFile");
foreach (MethodInfo m in typeof(IndexWriterConfig).GetMethods())
{
if (m.DeclaringType == typeof(IndexWriterConfig) && m.Name.StartsWith("get") && !m.Name.StartsWith("get_"))
{
Assert.IsTrue(getters.Contains(m.Name), "method " + m.Name + " is not tested for defaults");
}
}
}
[Test]
public virtual void TestSettersChaining()
{
// Ensures that every setter returns IndexWriterConfig to allow chaining.
HashSet<string> liveSetters = new HashSet<string>();
HashSet<string> allSetters = new HashSet<string>();
foreach (MethodInfo m in typeof(IndexWriterConfig).GetMethods())
{
if (m.Name.StartsWith("Set") && !m.IsStatic)
{
allSetters.Add(m.Name);
// setters overridden from LiveIndexWriterConfig are returned twice, once with
// IndexWriterConfig return type and second with LiveIndexWriterConfig. The ones
// from LiveIndexWriterConfig are marked 'synthetic', so just collect them and
// assert in the end that we also received them from IWC.
// In C# we do not have them marked synthetic so we look at the declaring type instead.
if (m.DeclaringType.Name == "LiveIndexWriterConfig")
{
liveSetters.Add(m.Name);
}
else
{
Assert.AreEqual(typeof(IndexWriterConfig), m.ReturnType, "method " + m.Name + " does not return IndexWriterConfig");
}
}
}
foreach (string setter in liveSetters)
{
Assert.IsTrue(allSetters.Contains(setter), "setter method not overridden by IndexWriterConfig: " + setter);
}
}
[Test]
public virtual void TestReuse()
{
Directory dir = NewDirectory();
// test that IWC cannot be reused across two IWs
IndexWriterConfig conf = NewIndexWriterConfig(TEST_VERSION_CURRENT, null);
(new RandomIndexWriter(Random(), dir, conf)).Dispose();
// this should fail
try
{
Assert.IsNotNull(new RandomIndexWriter(Random(), dir, conf));
Assert.Fail("should have hit AlreadySetException");
}
catch (SetOnce<IndexWriter>.AlreadySetException e)
{
// expected
}
// also cloning it won't help, after it has been used already
try
{
Assert.IsNotNull(new RandomIndexWriter(Random(), dir, (IndexWriterConfig)conf.Clone()));
Assert.Fail("should have hit AlreadySetException");
}
catch (SetOnce<IndexWriter>.AlreadySetException e)
{
// expected
}
// if it's cloned in advance, it should be ok
conf = NewIndexWriterConfig(TEST_VERSION_CURRENT, null);
(new RandomIndexWriter(Random(), dir, (IndexWriterConfig)conf.Clone())).Dispose();
(new RandomIndexWriter(Random(), dir, (IndexWriterConfig)conf.Clone())).Dispose();
dir.Dispose();
}
[Test]
public virtual void TestOverrideGetters()
{
// Test that IndexWriterConfig overrides all getters, so that javadocs
// contain all methods for the users. Also, ensures that IndexWriterConfig
// doesn't declare getters that are not declared on LiveIWC.
HashSet<string> liveGetters = new HashSet<string>();
foreach (MethodInfo m in typeof(LiveIndexWriterConfig).GetMethods())
{
if (m.Name.StartsWith("get") && !m.IsStatic)
{
liveGetters.Add(m.Name);
}
}
foreach (MethodInfo m in typeof(IndexWriterConfig).GetMethods())
{
if (m.Name.StartsWith("get") && !m.Name.StartsWith("get_") && !m.IsStatic)
{
Assert.AreEqual(typeof(IndexWriterConfig), m.DeclaringType, "method " + m.Name + " not overrided by IndexWriterConfig");
Assert.IsTrue(liveGetters.Contains(m.Name), "method " + m.Name + " not declared on LiveIndexWriterConfig");
}
}
}
[Test]
public virtual void TestConstants()
{
// Tests that the values of the constants does not change
Assert.AreEqual(1000, IndexWriterConfig.WRITE_LOCK_TIMEOUT);
Assert.AreEqual(32, IndexWriterConfig.DEFAULT_TERM_INDEX_INTERVAL);
Assert.AreEqual(-1, IndexWriterConfig.DISABLE_AUTO_FLUSH);
Assert.AreEqual(IndexWriterConfig.DISABLE_AUTO_FLUSH, IndexWriterConfig.DEFAULT_MAX_BUFFERED_DELETE_TERMS);
Assert.AreEqual(IndexWriterConfig.DISABLE_AUTO_FLUSH, IndexWriterConfig.DEFAULT_MAX_BUFFERED_DOCS);
Assert.AreEqual(16.0, IndexWriterConfig.DEFAULT_RAM_BUFFER_SIZE_MB, 0.0);
Assert.AreEqual(false, IndexWriterConfig.DEFAULT_READER_POOLING);
Assert.AreEqual(true, IndexWriterConfig.DEFAULT_USE_COMPOUND_FILE_SYSTEM);
Assert.AreEqual(DirectoryReader.DEFAULT_TERMS_INDEX_DIVISOR, IndexWriterConfig.DEFAULT_READER_TERMS_INDEX_DIVISOR);
}
//LUCENE TODO: Compilation problems
/*[Test]
public virtual void TestToString()
{
string str = (new IndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random()))).ToString();
foreach (Field f in typeof(IndexWriterConfig).DeclaredFields)
{
int modifiers = f.Modifiers;
if (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers))
{
// Skip static final fields, they are only constants
continue;
}
else if ("indexingChain".Equals(f.Name))
{
// indexingChain is a package-private setting and thus is not output by
// toString.
continue;
}
if (f.Name.Equals("inUseByIndexWriter"))
{
continue;
}
Assert.IsTrue(str.IndexOf(f.Name) != -1, f.Name + " not found in toString");
}
}*/
[Test]
public virtual void TestClone()
{
IndexWriterConfig conf = new IndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random()));
IndexWriterConfig clone = (IndexWriterConfig)conf.Clone();
// Make sure parameters that can't be reused are cloned
IndexDeletionPolicy delPolicy = conf.DelPolicy;
IndexDeletionPolicy delPolicyClone = clone.DelPolicy;
Assert.IsTrue(delPolicy.GetType() == delPolicyClone.GetType() && (delPolicy != delPolicyClone || delPolicy.Clone() == delPolicyClone.Clone()));
FlushPolicy flushPolicy = conf.FlushPolicy;
FlushPolicy flushPolicyClone = clone.FlushPolicy;
Assert.IsTrue(flushPolicy.GetType() == flushPolicyClone.GetType() && (flushPolicy != flushPolicyClone || flushPolicy.Clone() == flushPolicyClone.Clone()));
DocumentsWriterPerThreadPool pool = conf.IndexerThreadPool;
DocumentsWriterPerThreadPool poolClone = clone.IndexerThreadPool;
Assert.IsTrue(pool.GetType() == poolClone.GetType() && (pool != poolClone || pool.Clone() == poolClone.Clone()));
MergePolicy mergePolicy = conf.MergePolicy;
MergePolicy mergePolicyClone = clone.MergePolicy;
Assert.IsTrue(mergePolicy.GetType() == mergePolicyClone.GetType() && (mergePolicy != mergePolicyClone || mergePolicy.Clone() == mergePolicyClone.Clone()));
IMergeScheduler mergeSched = conf.MergeScheduler;
IMergeScheduler mergeSchedClone = clone.MergeScheduler;
Assert.IsTrue(mergeSched.GetType() == mergeSchedClone.GetType() && (mergeSched != mergeSchedClone || mergeSched.Clone() == mergeSchedClone.Clone()));
conf.SetMergeScheduler(new SerialMergeScheduler());
Assert.AreEqual(typeof(ConcurrentMergeScheduler), clone.MergeScheduler.GetType());
}
[Test]
public virtual void TestInvalidValues()
{
IndexWriterConfig conf = new IndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random()));
// Test IndexDeletionPolicy
Assert.AreEqual(typeof(KeepOnlyLastCommitDeletionPolicy), conf.DelPolicy.GetType());
conf.SetIndexDeletionPolicy(new SnapshotDeletionPolicy(null));
Assert.AreEqual(typeof(SnapshotDeletionPolicy), conf.DelPolicy.GetType());
try
{
conf.SetIndexDeletionPolicy(null);
Assert.Fail();
}
catch (System.ArgumentException e)
{
// ok
}
// Test MergeScheduler
Assert.AreEqual(typeof(ConcurrentMergeScheduler), conf.MergeScheduler.GetType());
conf.SetMergeScheduler(new SerialMergeScheduler());
Assert.AreEqual(typeof(SerialMergeScheduler), conf.MergeScheduler.GetType());
try
{
conf.SetMergeScheduler(null);
Assert.Fail();
}
catch (System.ArgumentException e)
{
// ok
}
// Test Similarity:
// we shouldnt assert what the default is, just that its not null.
Assert.IsTrue(IndexSearcher.DefaultSimilarity == conf.Similarity);
conf.SetSimilarity(new MySimilarity());
Assert.AreEqual(typeof(MySimilarity), conf.Similarity.GetType());
try
{
conf.SetSimilarity(null);
Assert.Fail();
}
catch (System.ArgumentException e)
{
// ok
}
// Test IndexingChain
Assert.IsTrue(DocumentsWriterPerThread.DefaultIndexingChain == conf.IndexingChain);
conf.SetIndexingChain(new MyIndexingChain());
Assert.AreEqual(typeof(MyIndexingChain), conf.IndexingChain.GetType());
try
{
conf.SetIndexingChain(null);
Assert.Fail();
}
catch (System.ArgumentException e)
{
// ok
}
try
{
conf.SetMaxBufferedDeleteTerms(0);
Assert.Fail("should not have succeeded to set maxBufferedDeleteTerms to 0");
}
catch (System.ArgumentException e)
{
// this is expected
}
try
{
conf.SetMaxBufferedDocs(1);
Assert.Fail("should not have succeeded to set maxBufferedDocs to 1");
}
catch (System.ArgumentException e)
{
// this is expected
}
try
{
// Disable both MAX_BUF_DOCS and RAM_SIZE_MB
conf.SetMaxBufferedDocs(4);
conf.SetRAMBufferSizeMB(IndexWriterConfig.DISABLE_AUTO_FLUSH);
conf.SetMaxBufferedDocs(IndexWriterConfig.DISABLE_AUTO_FLUSH);
Assert.Fail("should not have succeeded to disable maxBufferedDocs when ramBufferSizeMB is disabled as well");
}
catch (System.ArgumentException e)
{
// this is expected
}
conf.SetRAMBufferSizeMB(IndexWriterConfig.DEFAULT_RAM_BUFFER_SIZE_MB);
conf.SetMaxBufferedDocs(IndexWriterConfig.DEFAULT_MAX_BUFFERED_DOCS);
try
{
conf.SetRAMBufferSizeMB(IndexWriterConfig.DISABLE_AUTO_FLUSH);
Assert.Fail("should not have succeeded to disable ramBufferSizeMB when maxBufferedDocs is disabled as well");
}
catch (System.ArgumentException e)
{
// this is expected
}
// Test setReaderTermsIndexDivisor
try
{
conf.SetReaderTermsIndexDivisor(0);
Assert.Fail("should not have succeeded to set termsIndexDivisor to 0");
}
catch (System.ArgumentException e)
{
// this is expected
}
// Setting to -1 is ok
conf.SetReaderTermsIndexDivisor(-1);
try
{
conf.SetReaderTermsIndexDivisor(-2);
Assert.Fail("should not have succeeded to set termsIndexDivisor to < -1");
}
catch (System.ArgumentException e)
{
// this is expected
}
try
{
conf.SetRAMPerThreadHardLimitMB(2048);
Assert.Fail("should not have succeeded to set RAMPerThreadHardLimitMB to >= 2048");
}
catch (System.ArgumentException e)
{
// this is expected
}
try
{
conf.SetRAMPerThreadHardLimitMB(0);
Assert.Fail("should not have succeeded to set RAMPerThreadHardLimitMB to 0");
}
catch (System.ArgumentException e)
{
// this is expected
}
// Test MergePolicy
Assert.AreEqual(typeof(TieredMergePolicy), conf.MergePolicy.GetType());
conf.SetMergePolicy(new LogDocMergePolicy());
Assert.AreEqual(typeof(LogDocMergePolicy), conf.MergePolicy.GetType());
try
{
conf.SetMergePolicy(null);
Assert.Fail();
}
catch (System.ArgumentException e)
{
// ok
}
}
[Test]
public virtual void TestLiveChangeToCFS()
{
Directory dir = NewDirectory();
IndexWriterConfig iwc = new IndexWriterConfig(TEST_VERSION_CURRENT, new MockAnalyzer(Random()));
iwc.SetMergePolicy(NewLogMergePolicy(true));
// Start false:
iwc.SetUseCompoundFile(false);
iwc.MergePolicy.NoCFSRatio = 0.0d;
IndexWriter w = new IndexWriter(dir, iwc);
// Change to true:
w.Config.SetUseCompoundFile(true);
Document doc = new Document();
doc.Add(NewStringField("field", "foo", Store.NO));
w.AddDocument(doc);
w.Commit();
Assert.IsTrue(w.NewestSegment().Info.UseCompoundFile, "Expected CFS after commit");
doc.Add(NewStringField("field", "foo", Store.NO));
w.AddDocument(doc);
w.Commit();
w.ForceMerge(1);
w.Commit();
// no compound files after merge
Assert.IsFalse(w.NewestSegment().Info.UseCompoundFile, "Expected Non-CFS after merge");
MergePolicy lmp = w.Config.MergePolicy;
lmp.NoCFSRatio = 1.0;
lmp.MaxCFSSegmentSizeMB = double.PositiveInfinity;
w.AddDocument(doc);
w.ForceMerge(1);
w.Commit();
Assert.IsTrue(w.NewestSegment().Info.UseCompoundFile, "Expected CFS after merge");
w.Dispose();
dir.Dispose();
}
}
}