blob: b4bda428eca13cfececa81c1546a426fd569d9dd [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Collections.Generic;
using Lucene.Net.Support;
using NUnit.Framework;
using WhitespaceAnalyzer = Lucene.Net.Analysis.WhitespaceAnalyzer;
using Lucene.Net.Documents;
using AlreadyClosedException = Lucene.Net.Store.AlreadyClosedException;
using BufferedIndexInput = Lucene.Net.Store.BufferedIndexInput;
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 RAMDirectory = Lucene.Net.Store.RAMDirectory;
using LuceneTestCase = Lucene.Net.Util.LuceneTestCase;
using _TestUtil = Lucene.Net.Util._TestUtil;
namespace Lucene.Net.Index
{
[TestFixture]
public class TestFieldsReader : LuceneTestCase
{
[Serializable]
private class AnonymousClassFieldSelector : FieldSelector
{
public AnonymousClassFieldSelector(TestFieldsReader enclosingInstance)
{
InitBlock(enclosingInstance);
}
private void InitBlock(TestFieldsReader enclosingInstance)
{
this.enclosingInstance = enclosingInstance;
}
private TestFieldsReader enclosingInstance;
public TestFieldsReader Enclosing_Instance
{
get
{
return enclosingInstance;
}
}
public virtual FieldSelectorResult Accept(System.String fieldName)
{
if (fieldName.Equals(DocHelper.TEXT_FIELD_1_KEY) || fieldName.Equals(DocHelper.LAZY_FIELD_BINARY_KEY))
return FieldSelectorResult.SIZE;
else if (fieldName.Equals(DocHelper.TEXT_FIELD_3_KEY))
return FieldSelectorResult.LOAD;
else
return FieldSelectorResult.NO_LOAD;
}
}
private RAMDirectory dir = new RAMDirectory();
private Document testDoc = new Document();
private FieldInfos fieldInfos = null;
private const System.String TEST_SEGMENT_NAME = "_0";
public TestFieldsReader(System.String s):base(s)
{
}
public TestFieldsReader() : base("")
{
}
[SetUp]
public override void SetUp()
{
base.SetUp();
fieldInfos = new FieldInfos();
DocHelper.SetupDoc(testDoc);
fieldInfos.Add(testDoc);
IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED);
writer.UseCompoundFile = false;
writer.AddDocument(testDoc);
writer.Close();
}
[TearDown]
public override void TearDown()
{
fieldInfos = null;
testDoc = new Document();
dir = new RAMDirectory();
}
[Test]
public virtual void Test()
{
Assert.IsTrue(dir != null);
Assert.IsTrue(fieldInfos != null);
FieldsReader reader = new FieldsReader(dir, TEST_SEGMENT_NAME, fieldInfos);
Assert.IsTrue(reader != null);
Assert.IsTrue(reader.Size() == 1);
Document doc = reader.Doc(0, null);
Assert.IsTrue(doc != null);
Assert.IsTrue(doc.GetField(DocHelper.TEXT_FIELD_1_KEY) != null);
IFieldable field = doc.GetField(DocHelper.TEXT_FIELD_2_KEY);
Assert.IsTrue(field != null);
Assert.IsTrue(field.IsTermVectorStored == true);
Assert.IsTrue(field.IsStoreOffsetWithTermVector == true);
Assert.IsTrue(field.IsStorePositionWithTermVector == true);
Assert.IsTrue(field.OmitNorms == false);
Assert.IsTrue(field.OmitTermFreqAndPositions == false);
field = doc.GetField(DocHelper.TEXT_FIELD_3_KEY);
Assert.IsTrue(field != null);
Assert.IsTrue(field.IsTermVectorStored == false);
Assert.IsTrue(field.IsStoreOffsetWithTermVector == false);
Assert.IsTrue(field.IsStorePositionWithTermVector == false);
Assert.IsTrue(field.OmitNorms == true);
Assert.IsTrue(field.OmitTermFreqAndPositions == false);
field = doc.GetField(DocHelper.NO_TF_KEY);
Assert.IsTrue(field != null);
Assert.IsTrue(field.IsTermVectorStored == false);
Assert.IsTrue(field.IsStoreOffsetWithTermVector == false);
Assert.IsTrue(field.IsStorePositionWithTermVector == false);
Assert.IsTrue(field.OmitNorms == false);
Assert.IsTrue(field.OmitTermFreqAndPositions == true);
reader.Dispose();
}
[Test]
public virtual void TestLazyFields()
{
Assert.IsTrue(dir != null);
Assert.IsTrue(fieldInfos != null);
FieldsReader reader = new FieldsReader(dir, TEST_SEGMENT_NAME, fieldInfos);
Assert.IsTrue(reader != null);
Assert.IsTrue(reader.Size() == 1);
ISet<string> loadFieldNames = Support.Compatibility.SetFactory.GetSet<string>();
loadFieldNames.Add(DocHelper.TEXT_FIELD_1_KEY);
loadFieldNames.Add(DocHelper.TEXT_FIELD_UTF1_KEY);
ISet<string> lazyFieldNames = Support.Compatibility.SetFactory.GetSet<string>();
//new String[]{DocHelper.LARGE_LAZY_FIELD_KEY, DocHelper.LAZY_FIELD_KEY, DocHelper.LAZY_FIELD_BINARY_KEY};
lazyFieldNames.Add(DocHelper.LARGE_LAZY_FIELD_KEY);
lazyFieldNames.Add(DocHelper.LAZY_FIELD_KEY);
lazyFieldNames.Add(DocHelper.LAZY_FIELD_BINARY_KEY);
lazyFieldNames.Add(DocHelper.TEXT_FIELD_UTF2_KEY);
SetBasedFieldSelector fieldSelector = new SetBasedFieldSelector(loadFieldNames, lazyFieldNames);
Document doc = reader.Doc(0, fieldSelector);
Assert.IsTrue(doc != null, "doc is null and it shouldn't be");
IFieldable field = doc.GetFieldable(DocHelper.LAZY_FIELD_KEY);
Assert.IsTrue(field != null, "field is null and it shouldn't be");
Assert.IsTrue(field.IsLazy, "field is not lazy and it should be");
System.String value_Renamed = field.StringValue;
Assert.IsTrue(value_Renamed != null, "value is null and it shouldn't be");
Assert.IsTrue(value_Renamed.Equals(DocHelper.LAZY_FIELD_TEXT) == true, value_Renamed + " is not equal to " + DocHelper.LAZY_FIELD_TEXT);
field = doc.GetFieldable(DocHelper.TEXT_FIELD_1_KEY);
Assert.IsTrue(field != null, "field is null and it shouldn't be");
Assert.IsTrue(field.IsLazy == false, "Field is lazy and it should not be");
field = doc.GetFieldable(DocHelper.TEXT_FIELD_UTF1_KEY);
Assert.IsTrue(field != null, "field is null and it shouldn't be");
Assert.IsTrue(field.IsLazy == false, "Field is lazy and it should not be");
Assert.IsTrue(field.StringValue.Equals(DocHelper.FIELD_UTF1_TEXT) == true, field.StringValue + " is not equal to " + DocHelper.FIELD_UTF1_TEXT);
field = doc.GetFieldable(DocHelper.TEXT_FIELD_UTF2_KEY);
Assert.IsTrue(field != null, "field is null and it shouldn't be");
Assert.IsTrue(field.IsLazy == true, "Field is lazy and it should not be");
Assert.IsTrue(field.StringValue.Equals(DocHelper.FIELD_UTF2_TEXT) == true, field.StringValue + " is not equal to " + DocHelper.FIELD_UTF2_TEXT);
field = doc.GetFieldable(DocHelper.LAZY_FIELD_BINARY_KEY);
Assert.IsTrue(field != null, "field is null and it shouldn't be");
Assert.IsTrue(field.StringValue == null, "stringValue isn't null for lazy binary field");
byte[] bytes = field.GetBinaryValue();
Assert.IsTrue(bytes != null, "bytes is null and it shouldn't be");
Assert.IsTrue(DocHelper.LAZY_FIELD_BINARY_BYTES.Length == bytes.Length, "");
for (int i = 0; i < bytes.Length; i++)
{
Assert.IsTrue(bytes[i] == DocHelper.LAZY_FIELD_BINARY_BYTES[i], "byte[" + i + "] is mismatched");
}
}
[Test]
public virtual void TestLazyFieldsAfterClose()
{
Assert.IsTrue(dir != null);
Assert.IsTrue(fieldInfos != null);
FieldsReader reader = new FieldsReader(dir, TEST_SEGMENT_NAME, fieldInfos);
Assert.IsTrue(reader != null);
Assert.IsTrue(reader.Size() == 1);
ISet<string> loadFieldNames = Support.Compatibility.SetFactory.GetSet<string>();
loadFieldNames.Add(DocHelper.TEXT_FIELD_1_KEY);
loadFieldNames.Add(DocHelper.TEXT_FIELD_UTF1_KEY);
ISet<string> lazyFieldNames = Support.Compatibility.SetFactory.GetSet<string>();
lazyFieldNames.Add(DocHelper.LARGE_LAZY_FIELD_KEY);
lazyFieldNames.Add(DocHelper.LAZY_FIELD_KEY);
lazyFieldNames.Add(DocHelper.LAZY_FIELD_BINARY_KEY);
lazyFieldNames.Add(DocHelper.TEXT_FIELD_UTF2_KEY);
SetBasedFieldSelector fieldSelector = new SetBasedFieldSelector(loadFieldNames, lazyFieldNames);
Document doc = reader.Doc(0, fieldSelector);
Assert.IsTrue(doc != null, "doc is null and it shouldn't be");
IFieldable field = doc.GetFieldable(DocHelper.LAZY_FIELD_KEY);
Assert.IsTrue(field != null, "field is null and it shouldn't be");
Assert.IsTrue(field.IsLazy, "field is not lazy and it should be");
reader.Dispose();
Assert.Throws<AlreadyClosedException>(() => { var value = field.StringValue; },
"did not hit AlreadyClosedException as expected");
}
[Test]
public virtual void TestLoadFirst()
{
Assert.IsTrue(dir != null);
Assert.IsTrue(fieldInfos != null);
FieldsReader reader = new FieldsReader(dir, TEST_SEGMENT_NAME, fieldInfos);
Assert.IsTrue(reader != null);
Assert.IsTrue(reader.Size() == 1);
LoadFirstFieldSelector fieldSelector = new LoadFirstFieldSelector();
Document doc = reader.Doc(0, fieldSelector);
Assert.IsTrue(doc != null, "doc is null and it shouldn't be");
int count = 0;
var l = doc.GetFields();
for (System.Collections.IEnumerator iter = l.GetEnumerator(); iter.MoveNext(); )
{
Field field = (Field) iter.Current;
Assert.IsTrue(field != null, "field is null and it shouldn't be");
System.String sv = field.StringValue;
Assert.IsTrue(sv != null, "sv is null and it shouldn't be");
count++;
}
Assert.IsTrue(count == 1, count + " does not equal: " + 1);
}
/// <summary> Not really a test per se, but we should have some way of assessing whether this is worthwhile.
/// <p/>
/// Must test using a File based directory
///
/// </summary>
/// <throws> Exception </throws>
[Test]
public virtual void TestLazyPerformance()
{
System.String tmpIODir = AppSettings.Get("tempDir", "");
System.String userName = System.Environment.UserName;
System.String path = tmpIODir + System.IO.Path.DirectorySeparatorChar.ToString() + "lazyDir" + userName;
System.IO.DirectoryInfo file = new System.IO.DirectoryInfo(path);
_TestUtil.RmDir(file);
FSDirectory tmpDir = FSDirectory.Open(file);
Assert.IsTrue(tmpDir != null);
IndexWriter writer = new IndexWriter(tmpDir, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED);
writer.UseCompoundFile = false;
writer.AddDocument(testDoc);
writer.Close();
Assert.IsTrue(fieldInfos != null);
FieldsReader reader;
long lazyTime = 0;
long regularTime = 0;
int length = 50;
ISet<string> lazyFieldNames = Support.Compatibility.SetFactory.GetSet<string>();
lazyFieldNames.Add(DocHelper.LARGE_LAZY_FIELD_KEY);
SetBasedFieldSelector fieldSelector = new SetBasedFieldSelector(Support.Compatibility.SetFactory.GetSet<string>(), lazyFieldNames);
for (int i = 0; i < length; i++)
{
reader = new FieldsReader(tmpDir, TEST_SEGMENT_NAME, fieldInfos);
Assert.IsTrue(reader != null);
Assert.IsTrue(reader.Size() == 1);
Document doc;
doc = reader.Doc(0, null); //Load all of them
Assert.IsTrue(doc != null, "doc is null and it shouldn't be");
IFieldable field = doc.GetFieldable(DocHelper.LARGE_LAZY_FIELD_KEY);
Assert.IsTrue(field.IsLazy == false, "field is lazy");
System.String value_Renamed;
long start;
long finish;
start = (DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond);
//On my machine this was always 0ms.
value_Renamed = field.StringValue;
finish = (DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond);
Assert.IsTrue(value_Renamed != null, "value is null and it shouldn't be");
Assert.IsTrue(field != null, "field is null and it shouldn't be");
regularTime += (finish - start);
reader.Dispose();
reader = null;
doc = null;
//Hmmm, are we still in cache???
System.GC.Collect();
reader = new FieldsReader(tmpDir, TEST_SEGMENT_NAME, fieldInfos);
doc = reader.Doc(0, fieldSelector);
field = doc.GetFieldable(DocHelper.LARGE_LAZY_FIELD_KEY);
Assert.IsTrue(field.IsLazy == true, "field is not lazy");
start = (DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond);
//On my machine this took around 50 - 70ms
value_Renamed = field.StringValue;
finish = (DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond);
Assert.IsTrue(value_Renamed != null, "value is null and it shouldn't be");
lazyTime += (finish - start);
reader.Dispose();
}
System.Console.Out.WriteLine("Average Non-lazy time (should be very close to zero): " + regularTime / length + " ms for " + length + " reads");
System.Console.Out.WriteLine("Average Lazy Time (should be greater than zero): " + lazyTime / length + " ms for " + length + " reads");
}
[Test]
public virtual void TestLoadSize()
{
FieldsReader reader = new FieldsReader(dir, TEST_SEGMENT_NAME, fieldInfos);
Document doc;
doc = reader.Doc(0, new AnonymousClassFieldSelector(this));
IFieldable f1 = doc.GetFieldable(DocHelper.TEXT_FIELD_1_KEY);
IFieldable f3 = doc.GetFieldable(DocHelper.TEXT_FIELD_3_KEY);
IFieldable fb = doc.GetFieldable(DocHelper.LAZY_FIELD_BINARY_KEY);
Assert.IsTrue(f1.IsBinary);
Assert.IsTrue(!f3.IsBinary);
Assert.IsTrue(fb.IsBinary);
AssertSizeEquals(2 * DocHelper.FIELD_1_TEXT.Length, f1.GetBinaryValue());
Assert.AreEqual(DocHelper.FIELD_3_TEXT, f3.StringValue);
AssertSizeEquals(DocHelper.LAZY_FIELD_BINARY_BYTES.Length, fb.GetBinaryValue());
reader.Dispose();
}
private void AssertSizeEquals(int size, byte[] sizebytes)
{
Assert.AreEqual((byte) (Number.URShift(size, 24)), sizebytes[0]);
Assert.AreEqual((byte) (Number.URShift(size, 16)), sizebytes[1]);
Assert.AreEqual((byte) (Number.URShift(size, 8)), sizebytes[2]);
Assert.AreEqual((byte) size, sizebytes[3]);
}
public class FaultyFSDirectory:Directory
{
private bool isDisposed;
internal FSDirectory fsDir;
public FaultyFSDirectory(System.IO.DirectoryInfo dir)
{
fsDir = FSDirectory.Open(dir);
interalLockFactory = fsDir.LockFactory;
}
public override IndexInput OpenInput(System.String name)
{
return new FaultyIndexInput(fsDir.OpenInput(name));
}
public override System.String[] ListAll()
{
return fsDir.ListAll();
}
public override bool FileExists(System.String name)
{
return fsDir.FileExists(name);
}
public override long FileModified(System.String name)
{
return fsDir.FileModified(name);
}
public override void TouchFile(System.String name)
{
fsDir.TouchFile(name);
}
public override void DeleteFile(System.String name)
{
fsDir.DeleteFile(name);
}
public override long FileLength(System.String name)
{
return fsDir.FileLength(name);
}
public override IndexOutput CreateOutput(System.String name)
{
return fsDir.CreateOutput(name);
}
protected override void Dispose(bool disposing)
{
if (isDisposed) return;
if (disposing)
{
if (fsDir != null)
{
fsDir.Close();
}
}
fsDir = null;
isDisposed = true;
}
}
private class FaultyIndexInput:BufferedIndexInput, System.ICloneable
{
internal IndexInput delegate_Renamed;
internal static bool doFail;
private bool isDisposed;
internal int count;
internal FaultyIndexInput(IndexInput delegate_Renamed)
{
this.delegate_Renamed = delegate_Renamed;
}
private void SimOutage()
{
if (doFail && count++ % 2 == 1)
{
throw new System.IO.IOException("Simulated network outage");
}
}
public override void ReadInternal(byte[] b, int offset, int length)
{
SimOutage();
delegate_Renamed.ReadBytes(b, offset, length);
}
public override void SeekInternal(long pos)
{
//simOutage();
delegate_Renamed.Seek(pos);
}
public override long Length()
{
return delegate_Renamed.Length();
}
protected override void Dispose(bool disposing)
{
if (isDisposed) return;
if (disposing)
{
if (delegate_Renamed != null)
{
delegate_Renamed.Close();
}
}
delegate_Renamed = null;
isDisposed = true;
}
public override System.Object Clone()
{
return new FaultyIndexInput((IndexInput) delegate_Renamed.Clone());
}
}
// LUCENE-1262
[Test]
public virtual void TestExceptions()
{
System.String tempDir = System.IO.Path.GetTempPath();
if (tempDir == null)
throw new System.IO.IOException("java.io.tmpdir undefined, cannot run test");
System.IO.DirectoryInfo indexDir = new System.IO.DirectoryInfo(System.IO.Path.Combine(tempDir, "testfieldswriterexceptions"));
try
{
Directory dir = new FaultyFSDirectory(indexDir);
IndexWriter writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true, IndexWriter.MaxFieldLength.LIMITED);
for (int i = 0; i < 2; i++)
writer.AddDocument(testDoc);
writer.Optimize();
writer.Close();
IndexReader reader = IndexReader.Open(dir, true);
FaultyIndexInput.doFail = true;
bool exc = false;
for (int i = 0; i < 2; i++)
{
try
{
reader.Document(i);
}
catch (System.IO.IOException ioe)
{
// expected
exc = true;
}
try
{
reader.Document(i);
}
catch (System.IO.IOException ioe)
{
// expected
exc = true;
}
}
Assert.IsTrue(exc);
reader.Close();
dir.Close();
}
finally
{
_TestUtil.RmDir(indexDir);
}
}
}
}