mirror of https://github.com/apache/lucene.git
LUCENE-6405: add infos exc unit tests. fix TestTransactions to handle exceptions on openInput and let MDW do it
git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1671995 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
1780ea3488
commit
d64899ff18
|
@ -28,6 +28,7 @@ import org.apache.lucene.store.Directory;
|
|||
import org.apache.lucene.store.MockDirectoryWrapper;
|
||||
import org.apache.lucene.store.RAMDirectory;
|
||||
import org.apache.lucene.util.English;
|
||||
import org.apache.lucene.util.IOUtils;
|
||||
import org.apache.lucene.util.LuceneTestCase;
|
||||
|
||||
public class TestTransactions extends LuceneTestCase {
|
||||
|
@ -127,15 +128,25 @@ public class TestTransactions extends LuceneTestCase {
|
|||
try {
|
||||
writer1.prepareCommit();
|
||||
} catch (Throwable t) {
|
||||
writer1.rollback();
|
||||
writer2.rollback();
|
||||
// release resources
|
||||
try {
|
||||
writer1.rollback();
|
||||
} catch (Throwable ignore) {}
|
||||
try {
|
||||
writer2.rollback();
|
||||
} catch (Throwable ignore) {}
|
||||
return;
|
||||
}
|
||||
try {
|
||||
writer2.prepareCommit();
|
||||
} catch (Throwable t) {
|
||||
writer1.rollback();
|
||||
writer2.rollback();
|
||||
// release resources
|
||||
try {
|
||||
writer1.rollback();
|
||||
} catch (Throwable ignore) {}
|
||||
try {
|
||||
writer2.rollback();
|
||||
} catch (Throwable ignore) {}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -190,24 +201,20 @@ public class TestTransactions extends LuceneTestCase {
|
|||
try {
|
||||
r1 = DirectoryReader.open(dir1);
|
||||
r2 = DirectoryReader.open(dir2);
|
||||
} catch (IOException e) {
|
||||
} catch (Exception e) {
|
||||
// can be rethrown as RuntimeException if it happens during a close listener
|
||||
if (!e.getMessage().contains("on purpose")) {
|
||||
throw e;
|
||||
}
|
||||
if (r1 != null) {
|
||||
r1.close();
|
||||
}
|
||||
if (r2 != null) {
|
||||
r2.close();
|
||||
}
|
||||
// release resources
|
||||
IOUtils.closeWhileHandlingException(r1, r2);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (r1.numDocs() != r2.numDocs()) {
|
||||
throw new RuntimeException("doc counts differ: r1=" + r1.numDocs() + " r2=" + r2.numDocs());
|
||||
}
|
||||
r1.close();
|
||||
r2.close();
|
||||
IOUtils.closeWhileHandlingException(r1, r2);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -32,6 +32,9 @@ import org.apache.lucene.document.StoredField;
|
|||
import org.apache.lucene.document.TextField;
|
||||
import org.apache.lucene.store.Directory;
|
||||
import org.apache.lucene.store.IOContext;
|
||||
import org.apache.lucene.store.MockDirectoryWrapper;
|
||||
import org.apache.lucene.store.MockDirectoryWrapper.Failure;
|
||||
import org.apache.lucene.store.MockDirectoryWrapper.FakeIOException;
|
||||
import org.apache.lucene.util.StringHelper;
|
||||
import org.apache.lucene.util.TestUtil;
|
||||
import org.apache.lucene.util.Version;
|
||||
|
@ -94,6 +97,164 @@ public abstract class BaseFieldInfoFormatTestCase extends BaseIndexFileFormatTes
|
|||
dir.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test field infos write that hits exception immediately on open.
|
||||
* make sure we get our exception back, no file handle leaks, etc.
|
||||
*/
|
||||
public void testExceptionOnCreateOutput() throws Exception {
|
||||
Failure fail = new Failure() {
|
||||
@Override
|
||||
public void eval(MockDirectoryWrapper dir) throws IOException {
|
||||
for (StackTraceElement e : Thread.currentThread().getStackTrace()) {
|
||||
if (doFail && "createOutput".equals(e.getMethodName())) {
|
||||
throw new FakeIOException();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
MockDirectoryWrapper dir = newMockDirectory();
|
||||
dir.failOn(fail);
|
||||
Codec codec = getCodec();
|
||||
SegmentInfo segmentInfo = newSegmentInfo(dir, "_123");
|
||||
FieldInfos.Builder builder = new FieldInfos.Builder();
|
||||
FieldInfo fi = builder.getOrAdd("field");
|
||||
fi.setIndexOptions(TextField.TYPE_STORED.indexOptions());
|
||||
addAttributes(fi);
|
||||
FieldInfos infos = builder.finish();
|
||||
|
||||
fail.setDoFail();
|
||||
try {
|
||||
codec.fieldInfosFormat().write(dir, segmentInfo, "", infos, IOContext.DEFAULT);
|
||||
fail("didn't get expected exception");
|
||||
} catch (FakeIOException expected) {
|
||||
// ok
|
||||
} finally {
|
||||
fail.clearDoFail();
|
||||
}
|
||||
|
||||
dir.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test field infos write that hits exception on close.
|
||||
* make sure we get our exception back, no file handle leaks, etc.
|
||||
*/
|
||||
public void testExceptionOnCloseOutput() throws Exception {
|
||||
Failure fail = new Failure() {
|
||||
@Override
|
||||
public void eval(MockDirectoryWrapper dir) throws IOException {
|
||||
for (StackTraceElement e : Thread.currentThread().getStackTrace()) {
|
||||
if (doFail && "close".equals(e.getMethodName())) {
|
||||
throw new FakeIOException();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
MockDirectoryWrapper dir = newMockDirectory();
|
||||
dir.failOn(fail);
|
||||
Codec codec = getCodec();
|
||||
SegmentInfo segmentInfo = newSegmentInfo(dir, "_123");
|
||||
FieldInfos.Builder builder = new FieldInfos.Builder();
|
||||
FieldInfo fi = builder.getOrAdd("field");
|
||||
fi.setIndexOptions(TextField.TYPE_STORED.indexOptions());
|
||||
addAttributes(fi);
|
||||
FieldInfos infos = builder.finish();
|
||||
|
||||
fail.setDoFail();
|
||||
try {
|
||||
codec.fieldInfosFormat().write(dir, segmentInfo, "", infos, IOContext.DEFAULT);
|
||||
fail("didn't get expected exception");
|
||||
} catch (FakeIOException expected) {
|
||||
// ok
|
||||
} finally {
|
||||
fail.clearDoFail();
|
||||
}
|
||||
|
||||
dir.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test field infos read that hits exception immediately on open.
|
||||
* make sure we get our exception back, no file handle leaks, etc.
|
||||
*/
|
||||
public void testExceptionOnOpenInput() throws Exception {
|
||||
Failure fail = new Failure() {
|
||||
@Override
|
||||
public void eval(MockDirectoryWrapper dir) throws IOException {
|
||||
for (StackTraceElement e : Thread.currentThread().getStackTrace()) {
|
||||
if (doFail && "openInput".equals(e.getMethodName())) {
|
||||
throw new FakeIOException();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
MockDirectoryWrapper dir = newMockDirectory();
|
||||
dir.failOn(fail);
|
||||
Codec codec = getCodec();
|
||||
SegmentInfo segmentInfo = newSegmentInfo(dir, "_123");
|
||||
FieldInfos.Builder builder = new FieldInfos.Builder();
|
||||
FieldInfo fi = builder.getOrAdd("field");
|
||||
fi.setIndexOptions(TextField.TYPE_STORED.indexOptions());
|
||||
addAttributes(fi);
|
||||
FieldInfos infos = builder.finish();
|
||||
codec.fieldInfosFormat().write(dir, segmentInfo, "", infos, IOContext.DEFAULT);
|
||||
|
||||
fail.setDoFail();
|
||||
try {
|
||||
codec.fieldInfosFormat().read(dir, segmentInfo, "", IOContext.DEFAULT);
|
||||
fail("didn't get expected exception");
|
||||
} catch (FakeIOException expected) {
|
||||
// ok
|
||||
} finally {
|
||||
fail.clearDoFail();
|
||||
}
|
||||
|
||||
dir.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test field infos read that hits exception on close.
|
||||
* make sure we get our exception back, no file handle leaks, etc.
|
||||
*/
|
||||
public void testExceptionOnCloseInput() throws Exception {
|
||||
Failure fail = new Failure() {
|
||||
@Override
|
||||
public void eval(MockDirectoryWrapper dir) throws IOException {
|
||||
for (StackTraceElement e : Thread.currentThread().getStackTrace()) {
|
||||
if (doFail && "close".equals(e.getMethodName())) {
|
||||
throw new FakeIOException();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
MockDirectoryWrapper dir = newMockDirectory();
|
||||
dir.failOn(fail);
|
||||
Codec codec = getCodec();
|
||||
SegmentInfo segmentInfo = newSegmentInfo(dir, "_123");
|
||||
FieldInfos.Builder builder = new FieldInfos.Builder();
|
||||
FieldInfo fi = builder.getOrAdd("field");
|
||||
fi.setIndexOptions(TextField.TYPE_STORED.indexOptions());
|
||||
addAttributes(fi);
|
||||
FieldInfos infos = builder.finish();
|
||||
codec.fieldInfosFormat().write(dir, segmentInfo, "", infos, IOContext.DEFAULT);
|
||||
|
||||
fail.setDoFail();
|
||||
try {
|
||||
codec.fieldInfosFormat().read(dir, segmentInfo, "", IOContext.DEFAULT);
|
||||
fail("didn't get expected exception");
|
||||
} catch (FakeIOException expected) {
|
||||
// ok
|
||||
} finally {
|
||||
fail.clearDoFail();
|
||||
}
|
||||
|
||||
dir.close();
|
||||
}
|
||||
|
||||
// TODO: more tests
|
||||
|
||||
/** Test field infos read/write with random fields, with different values. */
|
||||
|
|
|
@ -27,8 +27,12 @@ import java.util.Set;
|
|||
import org.apache.lucene.codecs.Codec;
|
||||
import org.apache.lucene.document.Document;
|
||||
import org.apache.lucene.document.StoredField;
|
||||
import org.apache.lucene.document.TextField;
|
||||
import org.apache.lucene.store.Directory;
|
||||
import org.apache.lucene.store.IOContext;
|
||||
import org.apache.lucene.store.MockDirectoryWrapper;
|
||||
import org.apache.lucene.store.MockDirectoryWrapper.Failure;
|
||||
import org.apache.lucene.store.MockDirectoryWrapper.FakeIOException;
|
||||
import org.apache.lucene.util.StringHelper;
|
||||
import org.apache.lucene.util.TestUtil;
|
||||
import org.apache.lucene.util.Version;
|
||||
|
@ -159,6 +163,155 @@ public abstract class BaseSegmentInfoFormatTestCase extends BaseIndexFileFormatT
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test segment infos write that hits exception immediately on open.
|
||||
* make sure we get our exception back, no file handle leaks, etc.
|
||||
*/
|
||||
public void testExceptionOnCreateOutput() throws Exception {
|
||||
Failure fail = new Failure() {
|
||||
@Override
|
||||
public void eval(MockDirectoryWrapper dir) throws IOException {
|
||||
for (StackTraceElement e : Thread.currentThread().getStackTrace()) {
|
||||
if (doFail && "createOutput".equals(e.getMethodName())) {
|
||||
throw new FakeIOException();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
MockDirectoryWrapper dir = newMockDirectory();
|
||||
dir.failOn(fail);
|
||||
Codec codec = getCodec();
|
||||
byte id[] = StringHelper.randomId();
|
||||
SegmentInfo info = new SegmentInfo(dir, getVersions()[0], "_123", 1, false, codec,
|
||||
Collections.<String,String>emptyMap(), id, new HashMap<>());
|
||||
info.setFiles(Collections.<String>emptySet());
|
||||
|
||||
fail.setDoFail();
|
||||
try {
|
||||
codec.segmentInfoFormat().write(dir, info, IOContext.DEFAULT);
|
||||
fail("didn't get expected exception");
|
||||
} catch (FakeIOException expected) {
|
||||
// ok
|
||||
} finally {
|
||||
fail.clearDoFail();
|
||||
}
|
||||
|
||||
dir.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test segment infos write that hits exception on close.
|
||||
* make sure we get our exception back, no file handle leaks, etc.
|
||||
*/
|
||||
public void testExceptionOnCloseOutput() throws Exception {
|
||||
Failure fail = new Failure() {
|
||||
@Override
|
||||
public void eval(MockDirectoryWrapper dir) throws IOException {
|
||||
for (StackTraceElement e : Thread.currentThread().getStackTrace()) {
|
||||
if (doFail && "close".equals(e.getMethodName())) {
|
||||
throw new FakeIOException();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
MockDirectoryWrapper dir = newMockDirectory();
|
||||
dir.failOn(fail);
|
||||
Codec codec = getCodec();
|
||||
byte id[] = StringHelper.randomId();
|
||||
SegmentInfo info = new SegmentInfo(dir, getVersions()[0], "_123", 1, false, codec,
|
||||
Collections.<String,String>emptyMap(), id, new HashMap<>());
|
||||
info.setFiles(Collections.<String>emptySet());
|
||||
|
||||
fail.setDoFail();
|
||||
try {
|
||||
codec.segmentInfoFormat().write(dir, info, IOContext.DEFAULT);
|
||||
fail("didn't get expected exception");
|
||||
} catch (FakeIOException expected) {
|
||||
// ok
|
||||
} finally {
|
||||
fail.clearDoFail();
|
||||
}
|
||||
|
||||
dir.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test segment infos read that hits exception immediately on open.
|
||||
* make sure we get our exception back, no file handle leaks, etc.
|
||||
*/
|
||||
public void testExceptionOnOpenInput() throws Exception {
|
||||
Failure fail = new Failure() {
|
||||
@Override
|
||||
public void eval(MockDirectoryWrapper dir) throws IOException {
|
||||
for (StackTraceElement e : Thread.currentThread().getStackTrace()) {
|
||||
if (doFail && "openInput".equals(e.getMethodName())) {
|
||||
throw new FakeIOException();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
MockDirectoryWrapper dir = newMockDirectory();
|
||||
dir.failOn(fail);
|
||||
Codec codec = getCodec();
|
||||
byte id[] = StringHelper.randomId();
|
||||
SegmentInfo info = new SegmentInfo(dir, getVersions()[0], "_123", 1, false, codec,
|
||||
Collections.<String,String>emptyMap(), id, new HashMap<>());
|
||||
info.setFiles(Collections.<String>emptySet());
|
||||
codec.segmentInfoFormat().write(dir, info, IOContext.DEFAULT);
|
||||
|
||||
fail.setDoFail();
|
||||
try {
|
||||
codec.segmentInfoFormat().read(dir, "_123", id, IOContext.DEFAULT);
|
||||
fail("didn't get expected exception");
|
||||
} catch (FakeIOException expected) {
|
||||
// ok
|
||||
} finally {
|
||||
fail.clearDoFail();
|
||||
}
|
||||
|
||||
dir.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test segment infos read that hits exception on close
|
||||
* make sure we get our exception back, no file handle leaks, etc.
|
||||
*/
|
||||
public void testExceptionOnCloseInput() throws Exception {
|
||||
Failure fail = new Failure() {
|
||||
@Override
|
||||
public void eval(MockDirectoryWrapper dir) throws IOException {
|
||||
for (StackTraceElement e : Thread.currentThread().getStackTrace()) {
|
||||
if (doFail && "close".equals(e.getMethodName())) {
|
||||
throw new FakeIOException();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
MockDirectoryWrapper dir = newMockDirectory();
|
||||
dir.failOn(fail);
|
||||
Codec codec = getCodec();
|
||||
byte id[] = StringHelper.randomId();
|
||||
SegmentInfo info = new SegmentInfo(dir, getVersions()[0], "_123", 1, false, codec,
|
||||
Collections.<String,String>emptyMap(), id, new HashMap<>());
|
||||
info.setFiles(Collections.<String>emptySet());
|
||||
codec.segmentInfoFormat().write(dir, info, IOContext.DEFAULT);
|
||||
|
||||
fail.setDoFail();
|
||||
try {
|
||||
codec.segmentInfoFormat().read(dir, "_123", id, IOContext.DEFAULT);
|
||||
fail("didn't get expected exception");
|
||||
} catch (FakeIOException expected) {
|
||||
// ok
|
||||
} finally {
|
||||
fail.clearDoFail();
|
||||
}
|
||||
dir.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets some otherwise hard-to-test properties:
|
||||
* random segment names, ID values, document count, etc and round-trips
|
||||
|
|
|
@ -44,9 +44,6 @@ public class MockIndexInputWrapper extends IndexInput {
|
|||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
// TODO turn on the following to look for leaks closing inputs,
|
||||
// after fixing TestTransactions
|
||||
// dir.maybeThrowDeterministicException();
|
||||
if (closed) {
|
||||
delegate.close(); // don't mask double-close bugs
|
||||
return;
|
||||
|
@ -61,6 +58,7 @@ public class MockIndexInputWrapper extends IndexInput {
|
|||
if (!isClone) {
|
||||
dir.removeIndexInput(this, name);
|
||||
}
|
||||
dir.maybeThrowDeterministicException();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue