blob: 4d1913e5cdb9df342fbc770575094638e491f6c2 [file] [log] [blame]
using J2N;
using J2N.Threading;
using Lucene.Net.Attributes;
using Lucene.Net.Support;
using Lucene.Net.Util;
using NUnit.Framework;
using System;
using System.IO;
using System.Threading;
using Assert = Lucene.Net.TestFramework.Assert;
using Console = Lucene.Net.Util.SystemConsole;
namespace Lucene.Net.Store
{
/*
* 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 LuceneTestCase = Lucene.Net.Util.LuceneTestCase;
using TestUtil = Lucene.Net.Util.TestUtil;
[TestFixture]
public class TestDirectory : LuceneTestCase
{
[Test]
public virtual void TestDetectClose()
{
DirectoryInfo tempDir = CreateTempDir(GetType().Name);
Directory[] dirs = new Directory[] { new RAMDirectory(), new SimpleFSDirectory(tempDir), new NIOFSDirectory(tempDir) };
foreach (Directory dir in dirs)
{
dir.Dispose();
try
{
dir.CreateOutput("test", NewIOContext(Random));
Assert.Fail("did not hit expected exception");
}
#pragma warning disable 168
catch (ObjectDisposedException ace)
#pragma warning restore 168
{
}
}
}
// test is occasionally very slow, i dont know why
// try this seed: 7D7E036AD12927F5:93333EF9E6DE44DE
[Test]
[Slow]
//[Nightly] // This was marked Nightly in Java, but we are not seeing very bad performance, so leaving it in the normal flow
public virtual void TestThreadSafety()
{
BaseDirectoryWrapper dir = NewDirectory();
dir.CheckIndexOnDispose = false; // we arent making an index
if (dir is MockDirectoryWrapper)
{
((MockDirectoryWrapper)dir).Throttling = Throttling.NEVER; // makes this test really slow
}
if (Verbose)
{
Console.WriteLine(dir);
}
TheThread theThread = new TheThread("t1", dir);
TheThread2 theThread2 = new TheThread2("t2", dir);
theThread.Start();
theThread2.Start();
theThread.Join();
theThread2.Join();
dir.Dispose();
}
private class TheThread : ThreadJob
{
private readonly string name;
private readonly BaseDirectoryWrapper outerBDWrapper;
public TheThread(string name, BaseDirectoryWrapper baseDirectoryWrapper)
{
this.name = name;
outerBDWrapper = baseDirectoryWrapper;
}
public override void Run()
{
for (int i = 0; i < 3000; ++i)
{
string fileName = this.name + i;
try
{
using (IndexOutput output = outerBDWrapper.CreateOutput(fileName, NewIOContext(Random))) { }
Assert.IsTrue(SlowFileExists(outerBDWrapper, fileName));
}
catch (IOException e)
{
throw new Exception(e.ToString(), e);
}
}
}
}
private class TheThread2 : ThreadJob
{
private string name;
private readonly BaseDirectoryWrapper outerBDWrapper;
public TheThread2(string name, BaseDirectoryWrapper baseDirectoryWrapper)
{
this.name = name;
outerBDWrapper = baseDirectoryWrapper;
}
public override void Run()
{
for (int i = 0; i < 10000; i++)
{
try
{
string[] files = outerBDWrapper.ListAll();
foreach (string file in files)
{
try
{
using IndexInput input = outerBDWrapper.OpenInput(file, NewIOContext(Random));
}
#pragma warning disable 168
catch (FileNotFoundException fne)
#pragma warning restore 168
{
}
// LUCENENET specific - since NoSuchDirectoryException subclasses FileNotFoundException
// in Lucene, we need to catch it here to be on the safe side.
catch (DirectoryNotFoundException)
{
}
catch (IOException e)
{
if (!e.Message.Contains("still open for writing"))
{
throw new Exception(e.ToString(), e);
}
}
if (Random.NextBoolean())
{
break;
}
}
}
catch (IOException e)
{
throw new Exception(e.ToString(), e);
}
}
}
}
// Test that different instances of FSDirectory can coexist on the same
// path, can read, write, and lock files.
[Test]
public virtual void TestDirectInstantiation()
{
DirectoryInfo path = CreateTempDir("testDirectInstantiation");
byte[] largeBuffer = new byte[Random.Next(256 * 1024)], largeReadBuffer = new byte[largeBuffer.Length];
for (int i = 0; i < largeBuffer.Length; i++)
{
largeBuffer[i] = (byte)i; // automatically loops with modulo
}
var dirs = new FSDirectory[] { new SimpleFSDirectory(path, null), new NIOFSDirectory(path, null), new MMapDirectory(path, null) };
for (int i = 0; i < dirs.Length; i++)
{
FSDirectory dir = dirs[i];
dir.EnsureOpen();
string fname = "foo." + i;
string lockname = "foo" + i + ".lck";
IndexOutput @out = dir.CreateOutput(fname, NewIOContext(Random));
@out.WriteByte((byte)i);
@out.WriteBytes(largeBuffer, largeBuffer.Length);
@out.Dispose();
for (int j = 0; j < dirs.Length; j++)
{
FSDirectory d2 = dirs[j];
d2.EnsureOpen();
Assert.IsTrue(SlowFileExists(d2, fname));
Assert.AreEqual(1 + largeBuffer.Length, d2.FileLength(fname));
// LUCENENET specific - unmap hack not needed
//// don't do read tests if unmapping is not supported!
//if (d2 is MMapDirectory && !((MMapDirectory)d2).UseUnmap)
//{
// continue;
//}
IndexInput input = d2.OpenInput(fname, NewIOContext(Random));
Assert.AreEqual((byte)i, input.ReadByte());
// read array with buffering enabled
Arrays.Fill(largeReadBuffer, (byte)0);
input.ReadBytes(largeReadBuffer, 0, largeReadBuffer.Length, true);
Assert.AreEqual(largeBuffer, largeReadBuffer);
// read again without using buffer
input.Seek(1L);
Arrays.Fill(largeReadBuffer, (byte)0);
input.ReadBytes(largeReadBuffer, 0, largeReadBuffer.Length, false);
Assert.AreEqual(largeBuffer, largeReadBuffer);
input.Dispose();
}
// delete with a different dir
dirs[(i + 1) % dirs.Length].DeleteFile(fname);
for (int j = 0; j < dirs.Length; j++)
{
FSDirectory d2 = dirs[j];
Assert.IsFalse(SlowFileExists(d2, fname));
}
Lock @lock = dir.MakeLock(lockname);
Assert.IsTrue(@lock.Obtain());
for (int j = 0; j < dirs.Length; j++)
{
FSDirectory d2 = dirs[j];
Lock lock2 = d2.MakeLock(lockname);
try
{
Assert.IsFalse(lock2.Obtain(1));
}
#pragma warning disable 168
catch (LockObtainFailedException e)
#pragma warning restore 168
{
// OK
}
}
@lock.Dispose();
// now lock with different dir
@lock = dirs[(i + 1) % dirs.Length].MakeLock(lockname);
Assert.IsTrue(@lock.Obtain());
@lock.Dispose();
}
for (int i = 0; i < dirs.Length; i++)
{
FSDirectory dir = dirs[i];
dir.EnsureOpen();
dir.Dispose();
Assert.IsFalse(dir.IsOpen);
}
}
// LUCENE-1464
[Test]
public virtual void TestDontCreate()
{
var parentFolder = CreateTempDir(this.GetType().Name.ToLowerInvariant());
var path = new DirectoryInfo(Path.Combine(parentFolder.FullName, "doesnotexist"));
try
{
Assert.IsTrue(!path.Exists);
Directory dir = new SimpleFSDirectory(path, null);
Assert.IsTrue(!path.Exists);
dir.Dispose();
}
finally
{
if (path.Exists) System.IO.Directory.Delete(path.FullName, true);
}
}
// LUCENE-1468
[Test]
public virtual void TestRAMDirectoryFilter()
{
CheckDirectoryFilter(new RAMDirectory());
}
// LUCENE-1468
[Test]
public virtual void TestFSDirectoryFilter()
{
CheckDirectoryFilter(NewFSDirectory(CreateTempDir("test")));
}
private static bool ContainsFile(Directory directory, string file) // LUCENENET specific method to prevent having to use Arrays.AsList(), which creates unnecessary memory allocations
{
return Array.IndexOf(directory.ListAll(), file) > -1;
}
// LUCENE-1468
private void CheckDirectoryFilter(Directory dir)
{
string name = "file";
try
{
dir.CreateOutput(name, NewIOContext(Random)).Dispose();
Assert.IsTrue(SlowFileExists(dir, name));
Assert.IsTrue(ContainsFile(dir, name));
}
finally
{
dir.Dispose();
}
}
// LUCENE-1468
[Test]
public virtual void TestCopySubdir()
{
DirectoryInfo path = CreateTempDir("testsubdir");
try
{
//path.mkdirs();
System.IO.Directory.CreateDirectory(path.FullName);
//(new File(path, "subdir")).mkdirs();
System.IO.Directory.CreateDirectory(new DirectoryInfo(Path.Combine(path.FullName, "subdir")).FullName);
Directory fsDir = new SimpleFSDirectory(path, null);
Assert.AreEqual(0, (new RAMDirectory(fsDir, NewIOContext(Random))).ListAll().Length);
}
finally
{
System.IO.Directory.Delete(path.FullName, true);
}
}
// LUCENE-1468
[Test]
public virtual void TestNotDirectory()
{
DirectoryInfo path = CreateTempDir("testnotdir");
Directory fsDir = new SimpleFSDirectory(path, null);
try
{
IndexOutput @out = fsDir.CreateOutput("afile", NewIOContext(Random));
@out.Dispose();
Assert.IsTrue(SlowFileExists(fsDir, "afile"));
try
{
var d = new SimpleFSDirectory(new DirectoryInfo(Path.Combine(path.FullName, "afile")), null);
Assert.Fail("did not hit expected exception");
}
#pragma warning disable 168
catch (DirectoryNotFoundException nsde)
#pragma warning restore 168
{
// Expected
}
}
finally
{
fsDir.Dispose();
System.IO.Directory.Delete(path.FullName, true);
}
}
[Test]
public virtual void TestFsyncDoesntCreateNewFiles()
{
var path = CreateTempDir("nocreate");
Console.WriteLine(path.FullName);
using Directory fsdir = new SimpleFSDirectory(path);
// write a file
using (var o = fsdir.CreateOutput("afile", NewIOContext(Random)))
{
o.WriteString("boo");
}
// delete it
try
{
File.Delete(Path.Combine(path.FullName, "afile"));
}
catch (Exception e)
{
Assert.Fail("Deletion of new Directory should never fail.\nException thrown: {0}", e);
}
// directory is empty
Assert.AreEqual(0, fsdir.ListAll().Length);
// LUCENENET specific: Since FSDirectory.Sync() does not actually do anything in .NET
// we decided to remove the exception as well. This is safe to ignore here.
//// fsync it
//try
//{
// fsdir.Sync(Collections.Singleton("afile"));
// Assert.Fail("didn't get expected exception, instead fsync created new files: " +
// Collections.ToString(fsdir.ListAll()));
//}
//catch (FileNotFoundException)
//{
// // ok
//}
//// LUCENENET specific - since NoSuchDirectoryException subclasses FileNotFoundException
//// in Lucene, we need to catch it here to be on the safe side.
//catch (DirectoryNotFoundException)
//{
// // ok
//}
// directory is still empty
Assert.AreEqual(0, fsdir.ListAll().Length);
}
[Test]
[Slow]
[LuceneNetSpecific]
public virtual void ConcurrentIndexAccessThrowsWithoutSynchronizedStaleFiles()
{
DirectoryInfo tempDir = CreateTempDir(GetType().Name);
using Directory dir = new SimpleFSDirectory(tempDir);
var ioContext = NewIOContext(Random);
var threads = new Thread[Environment.ProcessorCount];
int file = 0;
Exception exception = null;
bool stopped = false;
using (var @event = new ManualResetEvent(false))
{
for (int i = 0; i < threads.Length; i++)
{
var thread = new Thread(() =>
{
while (!stopped)
{
int nextFile = Interlocked.Increment(ref file);
try
{
dir.CreateOutput("test" + nextFile, ioContext).Dispose();
}
catch (Exception ex)
{
exception = ex;
@event.Set();
break;
}
}
});
thread.Start();
threads[i] = thread;
}
bool raised = @event.WaitOne(TimeSpan.FromSeconds(5));
stopped = true;
if (raised)
throw new Exception("Test failed", exception);
}
foreach (var thread in threads)
{
thread.Join();
}
}
#pragma warning disable 612, 618
[Test]
[LuceneNetSpecific]
public void TestLUCENENET521()
{
var newDirectoryInfo = CreateTempDir("LUCENENET521");
using (var zipFileStream = this.GetType().FindAndGetManifestResourceStream("LUCENENET521.zip"))
{
TestUtil.Unzip(zipFileStream, newDirectoryInfo);
}
var newDirectory = new MMapDirectory(newDirectoryInfo);
var conf = new Index.IndexWriterConfig(LuceneVersion.LUCENE_30, new Analysis.Standard.StandardAnalyzer(LuceneVersion.LUCENE_30));
var indexWriter = new Index.IndexWriter(newDirectory, conf);
indexWriter.Dispose();
var sharedReader = Index.IndexReader.Open(newDirectory /*, true*/);
const int times = 10;
const int concurrentTaskCount = 10;
var task = new System.Threading.Tasks.Task[concurrentTaskCount];
for (int i = 0; i < concurrentTaskCount; i++)
{
task[i] = new System.Threading.Tasks.Task(() => Search(sharedReader, times));
task[i].Start();
}
System.Threading.Tasks.Task.WaitAll(task);
return;
}
#pragma warning restore 612, 618
private static void Search(Index.IndexReader r, int times)
{
var searcher = new Search.IndexSearcher(r);
var docs = new System.Collections.Generic.List<Documents.Document>(10000);
for (int i = 0; i < times; i++)
{
var q = new Search.TermQuery(new Index.Term("title", "volume"));
foreach (var scoreDoc in searcher.Search(q, 100).ScoreDocs)
{
docs.Add(searcher.Doc(scoreDoc.Doc));
}
}
}
}
}