Skip to content

Commit

Permalink
Simple unit test for basic components of new indexing infrastructure
Browse files Browse the repository at this point in the history
Add base unit tests for indexing components which covers only most basic non-integration scenarios
for simple cases only.
  • Loading branch information
MishaDemianenko committed Jan 21, 2016
1 parent 1c9629a commit 1ad1c64
Show file tree
Hide file tree
Showing 14 changed files with 470 additions and 57 deletions.
52 changes: 52 additions & 0 deletions community/io/src/test/java/org/neo4j/io/IOUtilsTest.java
@@ -0,0 +1,52 @@
package org.neo4j.io;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

import java.io.IOException;

import org.neo4j.test.NestedThrowableMatcher;

import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.verify;

@RunWith( MockitoJUnitRunner.class )
public class IOUtilsTest
{
@Rule
public ExpectedException expectedException = ExpectedException.none();

@Mock
private AutoCloseable faultyClosable;
@Mock
private AutoCloseable goodClosable1;
@Mock
private AutoCloseable goodClosable2;

@Test
public void closeAllSilently() throws Exception
{
IOUtils.closeAllSilently( goodClosable1, faultyClosable, goodClosable2 );

verify( goodClosable1 ).close();
verify( goodClosable2 ).close();
verify( faultyClosable ).close();
}

@Test
public void closeAllAndRethrowException() throws Exception
{
doThrow( new IOException( "Faulty closable" ) ).when( faultyClosable ).close();

expectedException.expect( IOException.class );
expectedException.expectMessage( "Exception closing multiple resources" );
expectedException.expect( new NestedThrowableMatcher( IOException.class ) );

IOUtils.closeAll( goodClosable1, faultyClosable, goodClosable2 );
}

}
@@ -0,0 +1,38 @@
package org.neo4j.test;

import org.hamcrest.Description;
import org.hamcrest.TypeSafeMatcher;

public class NestedThrowableMatcher extends TypeSafeMatcher<Throwable>
{
private final Class<? extends Throwable> expectedType;

public NestedThrowableMatcher( Class<? extends Throwable> expectedType )
{
this.expectedType = expectedType;
}

@Override
public void describeTo( Description description )
{
description.appendText( "expect " )
.appendValue( expectedType )
.appendText( " to be exception cause." );
}

@Override
protected boolean matchesSafely( Throwable item )
{
Throwable currentThrowable = item;
do
{
if ( expectedType.isInstance( currentThrowable ) )
{
return true;
}
currentThrowable = currentThrowable.getCause();
}
while ( currentThrowable != null );
return false;
}
}
Expand Up @@ -63,7 +63,7 @@ public LuceneSchemaIndexProvider( FileSystemAbstraction fileSystem, DirectoryFac
/**
* Visible <b>only</b> for testing.
*/
LuceneSchemaIndexProvider( FileSystemAbstraction fileSystem, IndexStorageFactory indexStorageFactory )
LuceneSchemaIndexProvider( IndexStorageFactory indexStorageFactory )
{
super( LuceneSchemaIndexProviderFactory.PROVIDER_DESCRIPTOR, 1 );
this.indexStorageFactory = indexStorageFactory;
Expand Down
Expand Up @@ -43,14 +43,14 @@ public class LuceneIndexSnapshotFileIterator extends PrefetchingIterator<File> i
private final Iterator<String> fileNames;
private final IndexCommit snapshot;

public static ResourceIterator<File> forIndex( File indexDirectory, IndexWriter indexWriter ) throws IOException
public static ResourceIterator<File> forIndex( File indexFolder, IndexWriter indexWriter ) throws IOException
{
IndexDeletionPolicy deletionPolicy = indexWriter.getConfig().getIndexDeletionPolicy();
if ( deletionPolicy instanceof SnapshotDeletionPolicy )
{
SnapshotDeletionPolicy policy = (SnapshotDeletionPolicy) deletionPolicy;
return hasCommits( indexWriter )
? new LuceneIndexSnapshotFileIterator( indexDirectory, policy )
? new LuceneIndexSnapshotFileIterator( indexFolder, policy )
: emptyIterator();
}
else
Expand Down Expand Up @@ -98,9 +98,7 @@ public void close()
private static boolean hasCommits( IndexWriter indexWriter ) throws IOException
{
Directory directory = indexWriter.getDirectory();
return DirectoryReader.indexExists( directory ) &&
SegmentInfos.readLatestCommit( directory ) != null;
return DirectoryReader.indexExists( directory ) && SegmentInfos.readLatestCommit( directory ) != null;
}


}
Expand Up @@ -38,11 +38,11 @@ public class IndexPartition implements Closeable
private final IndexWriter indexWriter;
private final Directory directory;
private final SearcherManager searcherManager;
private final File indexDirectory;
private final File indexFolder;

public IndexPartition( File indexDirectory, Directory directory ) throws IOException
public IndexPartition( File partitionFolder, Directory directory ) throws IOException
{
this.indexDirectory = indexDirectory;
this.indexFolder = partitionFolder;
this.directory = directory;
this.indexWriter = new IndexWriter( directory, IndexWriterConfigs.standardConfig() );
this.searcherManager = new SearcherManager( indexWriter, true, new SearcherFactory() );
Expand All @@ -58,6 +58,13 @@ public Directory getDirectory()
return directory;
}

/**
* Return searcher for requested partition.
* There is no tracking of acquired searchers, so the expectation is that callers will call close on acquired
* searchers to release resources.
* @return partition searcher
* @throws IOException if exception happened during searcher acquisition
*/
public PartitionSearcher acquireSearcher() throws IOException
{
return new PartitionSearcher( searcherManager );
Expand All @@ -76,6 +83,6 @@ public void close() throws IOException

public ResourceIterator<File> snapshot() throws IOException
{
return LuceneIndexSnapshotFileIterator.forIndex( indexDirectory, indexWriter );
return LuceneIndexSnapshotFileIterator.forIndex( indexFolder, indexWriter );
}
}
Expand Up @@ -20,20 +20,20 @@
package org.neo4j.kernel.api.impl.index.partition;

import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.SearcherManager;
import org.apache.lucene.search.ReferenceManager;

import java.io.Closeable;
import java.io.IOException;

public class PartitionSearcher implements Closeable
{
private IndexSearcher indexSearcher;
private SearcherManager searcherManager;
private ReferenceManager<IndexSearcher> referenceManager;

public PartitionSearcher( SearcherManager searcherManager ) throws IOException
public PartitionSearcher( ReferenceManager<IndexSearcher> referenceManager ) throws IOException
{
this.searcherManager = searcherManager;
this.indexSearcher = searcherManager.acquire();
this.referenceManager = referenceManager;
this.indexSearcher = referenceManager.acquire();
}

public IndexSearcher getIndexSearcher()
Expand All @@ -44,6 +44,6 @@ public IndexSearcher getIndexSearcher()
@Override
public void close() throws IOException
{
searcherManager.release( indexSearcher );
referenceManager.release( indexSearcher );
}
}
Expand Up @@ -34,8 +34,8 @@
*/
public class FailureStorage
{
public static final int MAX_FAILURE_SIZE = 16384;
public static final String DEFAULT_FAILURE_FILE_NAME = "failure-message";
private static final int MAX_FAILURE_SIZE = 16384;
private static final String DEFAULT_FAILURE_FILE_NAME = "failure-message";

private final FileSystemAbstraction fs;
private final FolderLayout folderLayout;
Expand Down
Expand Up @@ -130,7 +130,7 @@ public void shouldDenyFailureForNonFailedIndex() throws Exception
private LuceneSchemaIndexProvider newFaultySchemaIndexProvider( long faultyIndexId, Exception error )
{
FaultyIndexStorageFactory storageFactory = new FaultyIndexStorageFactory( faultyIndexId, error );
return new LuceneSchemaIndexProvider( fs.get(), storageFactory );
return new LuceneSchemaIndexProvider( storageFactory );
}

private class FaultyIndexStorageFactory extends IndexStorageFactory
Expand Down
Expand Up @@ -45,7 +45,7 @@
import static junit.framework.TestCase.assertFalse;
import static org.junit.Assert.assertEquals;

public class LuceneSnapshotterTest
public class LuceneIndexSnapshotFileIteratorTest
{
@Rule
public final TargetDirectory.TestDirectory testDir = TargetDirectory.testDirForTest( getClass() );
Expand Down Expand Up @@ -86,7 +86,6 @@ public void shouldReturnRealSnapshotIfIndexAllowsIt() throws IOException
@Test
public void shouldReturnEmptyIteratorWhenNoCommitsHaveBeenMade() throws IOException
{
String[] strings = dir.listAll();
try ( ResourceIterator<File> snapshot = LuceneIndexSnapshotFileIterator.forIndex( indexDir, writer ) )
{
assertFalse( snapshot.hasNext() );
Expand Down
@@ -0,0 +1,138 @@
package org.neo4j.kernel.api.impl.index.reader;

import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.MatchAllDocsQuery;
import org.apache.lucene.search.NumericRangeQuery;
import org.apache.lucene.search.PrefixQuery;
import org.apache.lucene.search.TermQuery;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

import org.neo4j.helpers.TaskCoordinator;
import org.neo4j.kernel.api.impl.index.DocValuesCollector;
import org.neo4j.kernel.api.impl.index.partition.PartitionSearcher;
import org.neo4j.kernel.api.impl.index.sampler.NonUniqueLuceneIndexSampler;
import org.neo4j.kernel.api.impl.index.sampler.UniqueLuceneIndexSampler;
import org.neo4j.kernel.api.index.IndexConfiguration;
import org.neo4j.kernel.configuration.Config;
import org.neo4j.kernel.impl.api.index.sampling.IndexSamplingConfig;
import org.neo4j.storageengine.api.schema.IndexReader;

import static org.hamcrest.Matchers.instanceOf;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

public class SimpleIndexReaderTest
{
private final PartitionSearcher partitionSearcher = mock( PartitionSearcher.class );
private final IndexSearcher indexSearcher = mock( IndexSearcher.class );
private final IndexSamplingConfig samplingConfig = new IndexSamplingConfig( new Config() );
private final TaskCoordinator taskCoordinator = new TaskCoordinator( 0, TimeUnit.MILLISECONDS );

@Before
public void setUp()
{
when( partitionSearcher.getIndexSearcher() ).thenReturn( indexSearcher );
}

@Test
public void releaseSearcherOnClose() throws IOException
{
IndexReader simpleIndexReader = getUniqueSimpleReader();

simpleIndexReader.close();

verify( partitionSearcher ).close();
}

@Test
public void seekQueryReachSearcher() throws IOException
{
IndexReader simpleIndexReader = getUniqueSimpleReader();

simpleIndexReader.seek( "test" );

verify( indexSearcher ).search( any( TermQuery.class ), any( DocValuesCollector.class ) );
}

@Test
public void scanQueryReachSearcher() throws IOException
{
IndexReader simpleIndexReader = getUniqueSimpleReader();

simpleIndexReader.scan();

verify( indexSearcher ).search( any( MatchAllDocsQuery.class ), any( DocValuesCollector.class ) );
}

@Test
public void stringRangeSeekQueryReachSearcher() throws IOException
{
IndexReader simpleIndexReader = getUniqueSimpleReader();

simpleIndexReader.rangeSeekByString( "a", false, "b", true );

verify( indexSearcher ).search( any( TermQuery.class ), any( DocValuesCollector.class ) );
}

@Test
public void prefixRangeSeekQueryReachSearcher() throws IOException
{
IndexReader simpleIndexReader = getUniqueSimpleReader();

simpleIndexReader.rangeSeekByPrefix( "bb" );

verify( indexSearcher ).search( any( PrefixQuery.class ), any( DocValuesCollector.class ) );
}

@Test
public void numberRangeSeekQueryReachSearcher() throws IOException
{
IndexReader simpleIndexReader = getUniqueSimpleReader();

simpleIndexReader.rangeSeekByNumberInclusive( 7, 8 );

verify( indexSearcher ).search( any( NumericRangeQuery.class ), any( DocValuesCollector.class ) );
}

@Test
public void countIndexedNodesReachSearcher() throws IOException
{
IndexReader simpleIndexReader = getUniqueSimpleReader();

simpleIndexReader.countIndexedNodes( 2, "testValue" );

verify( indexSearcher ).search( any( BooleanQuery.class ), any( DocValuesCollector.class ) );
}

@Test
public void uniqueIndexSamplerForUniqueIndex()
{
SimpleIndexReader uniqueSimpleReader = getUniqueSimpleReader();
Assert.assertThat( uniqueSimpleReader.createSampler(), instanceOf( UniqueLuceneIndexSampler.class ) );
}

@Test
public void nonUuniqueIndexSamplerForNonUniqueIndex()
{
SimpleIndexReader uniqueSimpleReader = getNonUniqueSimpleReader();
Assert.assertThat( uniqueSimpleReader.createSampler(), instanceOf( NonUniqueLuceneIndexSampler.class) );
}

private SimpleIndexReader getNonUniqueSimpleReader()
{
return new SimpleIndexReader( partitionSearcher, IndexConfiguration.NON_UNIQUE, samplingConfig, taskCoordinator );
}

private SimpleIndexReader getUniqueSimpleReader()
{
return new SimpleIndexReader( partitionSearcher, IndexConfiguration.UNIQUE, samplingConfig, taskCoordinator );
}
}

0 comments on commit 1ad1c64

Please sign in to comment.