You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by rm...@apache.org on 2015/04/08 04:47:11 UTC

svn commit: r1671995 - in /lucene/dev/trunk/lucene: core/src/test/org/apache/lucene/index/ test-framework/src/java/org/apache/lucene/index/ test-framework/src/java/org/apache/lucene/store/

Author: rmuir
Date: Wed Apr  8 02:47:11 2015
New Revision: 1671995

URL: http://svn.apache.org/r1671995
Log:
LUCENE-6405: add infos exc unit tests. fix TestTransactions to handle exceptions on openInput and let MDW do it

Modified:
    lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestTransactions.java
    lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/index/BaseFieldInfoFormatTestCase.java
    lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/index/BaseSegmentInfoFormatTestCase.java
    lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/store/MockIndexInputWrapper.java

Modified: lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestTransactions.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestTransactions.java?rev=1671995&r1=1671994&r2=1671995&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestTransactions.java (original)
+++ lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestTransactions.java Wed Apr  8 02:47:11 2015
@@ -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 Lu
           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 Lu
         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);
     }
   }
 

Modified: lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/index/BaseFieldInfoFormatTestCase.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/index/BaseFieldInfoFormatTestCase.java?rev=1671995&r1=1671994&r2=1671995&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/index/BaseFieldInfoFormatTestCase.java (original)
+++ lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/index/BaseFieldInfoFormatTestCase.java Wed Apr  8 02:47:11 2015
@@ -32,6 +32,9 @@ import org.apache.lucene.document.Stored
 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 BaseFieldInfoForma
     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. */

Modified: lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/index/BaseSegmentInfoFormatTestCase.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/index/BaseSegmentInfoFormatTestCase.java?rev=1671995&r1=1671994&r2=1671995&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/index/BaseSegmentInfoFormatTestCase.java (original)
+++ lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/index/BaseSegmentInfoFormatTestCase.java Wed Apr  8 02:47:11 2015
@@ -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;
@@ -160,6 +164,155 @@ public abstract class BaseSegmentInfoFor
   }
   
   /** 
+   * 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
    */

Modified: lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/store/MockIndexInputWrapper.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/store/MockIndexInputWrapper.java?rev=1671995&r1=1671994&r2=1671995&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/store/MockIndexInputWrapper.java (original)
+++ lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/store/MockIndexInputWrapper.java Wed Apr  8 02:47:11 2015
@@ -44,9 +44,6 @@ public class MockIndexInputWrapper exten
 
   @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 exten
       if (!isClone) {
         dir.removeIndexInput(this, name);
       }
+      dir.maybeThrowDeterministicException();
     }
   }