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 2014/05/01 15:19:22 UTC

svn commit: r1591652 - in /lucene/dev/trunk/lucene: core/src/test/org/apache/lucene/index/ test-framework/src/java/org/apache/lucene/analysis/ test-framework/src/java/org/apache/lucene/codecs/cranky/

Author: rmuir
Date: Thu May  1 13:19:21 2014
New Revision: 1591652

URL: http://svn.apache.org/r1591652
Log:
LUCENE-5635: add a prototype test (currently disabled with AwaitsFix)

Added:
    lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterExceptions2.java   (with props)
    lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/
    lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/CrankyCodec.java   (with props)
    lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/CrankyDocValuesFormat.java   (with props)
    lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/CrankyFieldInfosFormat.java   (with props)
    lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/CrankyLiveDocsFormat.java   (with props)
    lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/CrankyNormsFormat.java   (with props)
    lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/CrankyPostingsFormat.java   (with props)
    lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/CrankySegmentInfoFormat.java   (with props)
    lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/CrankyStoredFieldsFormat.java   (with props)
    lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/CrankyTermVectorsFormat.java   (with props)
    lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/package.html   (with props)
Modified:
    lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/analysis/CrankyTokenFilter.java

Added: lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterExceptions2.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterExceptions2.java?rev=1591652&view=auto
==============================================================================
--- lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterExceptions2.java (added)
+++ lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/index/TestIndexWriterExceptions2.java Thu May  1 13:19:21 2014
@@ -0,0 +1,132 @@
+package org.apache.lucene.index;
+
+/*
+ * 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.
+ */
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.nio.charset.Charset;
+import java.util.Random;
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.CrankyTokenFilter;
+import org.apache.lucene.analysis.MockTokenizer;
+import org.apache.lucene.analysis.TokenStream;
+import org.apache.lucene.codecs.Codec;
+import org.apache.lucene.codecs.cranky.CrankyCodec;
+import org.apache.lucene.document.Document;
+import org.apache.lucene.document.Field;
+import org.apache.lucene.document.NumericDocValuesField;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.util.LuceneTestCase;
+import org.apache.lucene.util.LuceneTestCase.AwaitsFix;
+import org.apache.lucene.util.TestUtil;
+import org.apache.lucene.util.Rethrow;
+
+/** 
+ * Causes a bunch of non-aborting and aborting exceptions and checks that
+ * no index corruption is ever created
+ */
+// TODO: not sure which fails are test bugs or real bugs yet...
+// also sometimes when it fails, the exception-stream printing doesnt seem to be working yet
+// ant test  -Dtestcase=TestIndexWriterExceptions2 -Dtests.method=testSimple -Dtests.seed=A6FF4AD6F371A22E -Dtests.locale=tr_TR -Dtests.timezone=America/Cancun -Dtests.file.encoding=US-ASCII
+// 
+@AwaitsFix(bugUrl = "https://issues.apache.org/jira/browse/LUCENE-5635")
+public class TestIndexWriterExceptions2 extends LuceneTestCase {
+  
+  // just one thread, serial merge policy, hopefully debuggable
+  public void testSimple() throws Exception {
+    Directory dir = newDirectory();
+    
+    // log all exceptions we hit, in case we fail (for debugging)
+    ByteArrayOutputStream exceptionLog = new ByteArrayOutputStream();
+    PrintStream exceptionStream = new PrintStream(exceptionLog, true, "UTF-8");
+    
+    // create lots of non-aborting exceptions with a broken analyzer
+    final long analyzerSeed = random().nextLong();
+    Analyzer analyzer = new Analyzer() {
+      @Override
+      protected TokenStreamComponents createComponents(String fieldName) {
+        MockTokenizer tokenizer = new MockTokenizer(MockTokenizer.SIMPLE, false);
+        tokenizer.setEnableChecks(false); // TODO: can we turn this on? our filter is probably too evil
+        TokenStream stream = new CrankyTokenFilter(tokenizer, new Random(analyzerSeed));
+        return new TokenStreamComponents(tokenizer, stream);
+      }
+    };
+    
+    // create lots of aborting exceptions with a broken codec
+    Codec codec = new CrankyCodec(Codec.getDefault(), new Random(random().nextLong()));
+    
+    IndexWriterConfig conf = newIndexWriterConfig(TEST_VERSION_CURRENT, analyzer);
+    // just for now, try to keep this test reproducible
+    conf.setMergeScheduler(new SerialMergeScheduler());
+    conf.setCodec(codec);
+    
+    // TODO: too much?
+    int numDocs = RANDOM_MULTIPLIER * 1000;
+    
+    IndexWriter iw = new IndexWriter(dir, conf);
+    try {
+      for (int i = 0; i < numDocs; i++) {
+        // TODO: add crankyDocValuesFields, etc
+        Document doc = new Document();
+        doc.add(newStringField("id", Integer.toString(i), Field.Store.NO));
+        doc.add(new NumericDocValuesField("dv", i));
+        doc.add(newTextField("text1", TestUtil.randomAnalysisString(random(), 20, true), Field.Store.NO));
+        // TODO: sometimes update dv
+        try {
+          iw.addDocument(doc);
+        } catch (Exception e) {
+          if (e.getMessage() != null && e.getMessage().startsWith("Fake IOException")) {
+            e.printStackTrace(exceptionStream);
+          } else {
+            Rethrow.rethrow(e);
+          }
+        }
+        if (random().nextInt(10) == 0) {
+          // trigger flush: TODO: sometimes reopen
+          try {
+            iw.commit();
+            if (DirectoryReader.indexExists(dir)) {
+              TestUtil.checkIndex(dir);
+            }
+          } catch (Exception e) {
+            if (e.getMessage() != null && e.getMessage().startsWith("Fake IOException")) {
+              e.printStackTrace(exceptionStream);
+            } else {
+              Rethrow.rethrow(e);
+            }
+          }
+        }
+      }
+      
+      iw.close();
+      dir.close();
+    } catch (Throwable t) {
+      System.out.println("Unexpected exception: dumping fake-exception-log:...");
+      exceptionStream.flush();
+      System.out.println(exceptionLog.toString("UTF-8"));
+      System.out.flush();
+      Rethrow.rethrow(t);
+    }
+    
+    if (VERBOSE) {
+      System.out.println("TEST PASSED: dumping fake-exception-log:...");
+      System.out.println(exceptionLog.toString("UTF-8"));
+    }
+  }
+}

Modified: lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/analysis/CrankyTokenFilter.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/analysis/CrankyTokenFilter.java?rev=1591652&r1=1591651&r2=1591652&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/analysis/CrankyTokenFilter.java (original)
+++ lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/analysis/CrankyTokenFilter.java Thu May  1 13:19:21 2014
@@ -55,7 +55,7 @@ public final class CrankyTokenFilter ext
   @Override
   public void reset() throws IOException {
     super.reset();
-    thingToDo = random.nextInt(10);
+    thingToDo = random.nextInt(100);
     if (thingToDo == 2 && random.nextBoolean()) {
       throw new IOException("Fake IOException from TokenStream.reset()");
     }

Added: lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/CrankyCodec.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/CrankyCodec.java?rev=1591652&view=auto
==============================================================================
--- lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/CrankyCodec.java (added)
+++ lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/CrankyCodec.java Thu May  1 13:19:21 2014
@@ -0,0 +1,87 @@
+package org.apache.lucene.codecs.cranky;
+
+/*
+ * 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.
+ */
+
+import java.util.Random;
+
+import org.apache.lucene.codecs.Codec;
+import org.apache.lucene.codecs.DocValuesFormat;
+import org.apache.lucene.codecs.FieldInfosFormat;
+import org.apache.lucene.codecs.FilterCodec;
+import org.apache.lucene.codecs.LiveDocsFormat;
+import org.apache.lucene.codecs.NormsFormat;
+import org.apache.lucene.codecs.PostingsFormat;
+import org.apache.lucene.codecs.SegmentInfoFormat;
+import org.apache.lucene.codecs.StoredFieldsFormat;
+import org.apache.lucene.codecs.TermVectorsFormat;
+
+/** Codec for testing that throws random IOExceptions */
+public class CrankyCodec extends FilterCodec {
+  final Random random;
+  
+  /** 
+   * Wrap the provided codec with crankiness.
+   * Try passing Asserting for the most fun.
+   */
+  public CrankyCodec(Codec delegate, Random random) {
+    // we impersonate the passed-in codec, so we don't need to be in SPI,
+    // and so we dont change file formats
+    super(delegate.getName(), delegate);
+    this.random = random;
+  }
+
+  @Override
+  public DocValuesFormat docValuesFormat() {
+    return new CrankyDocValuesFormat(delegate.docValuesFormat(), random);
+  }
+
+  @Override
+  public FieldInfosFormat fieldInfosFormat() {
+    return new CrankyFieldInfosFormat(delegate.fieldInfosFormat(), random);
+  }
+
+  @Override
+  public LiveDocsFormat liveDocsFormat() {
+    return new CrankyLiveDocsFormat(delegate.liveDocsFormat(), random);
+  }
+
+  @Override
+  public NormsFormat normsFormat() {
+    return new CrankyNormsFormat(delegate.normsFormat(), random);
+  }
+
+  @Override
+  public PostingsFormat postingsFormat() {
+    return new CrankyPostingsFormat(delegate.postingsFormat(), random);
+  }
+
+  @Override
+  public SegmentInfoFormat segmentInfoFormat() {
+    return new CrankySegmentInfoFormat(delegate.segmentInfoFormat(), random);
+  }
+
+  @Override
+  public StoredFieldsFormat storedFieldsFormat() {
+    return new CrankyStoredFieldsFormat(delegate.storedFieldsFormat(), random);
+  }
+
+  @Override
+  public TermVectorsFormat termVectorsFormat() {
+    return new CrankyTermVectorsFormat(delegate.termVectorsFormat(), random);
+  }
+}

Added: lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/CrankyDocValuesFormat.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/CrankyDocValuesFormat.java?rev=1591652&view=auto
==============================================================================
--- lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/CrankyDocValuesFormat.java (added)
+++ lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/CrankyDocValuesFormat.java Thu May  1 13:19:21 2014
@@ -0,0 +1,105 @@
+package org.apache.lucene.codecs.cranky;
+
+/*
+ * 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.
+ */
+
+import java.io.IOException;
+import java.util.Random;
+
+import org.apache.lucene.codecs.DocValuesConsumer;
+import org.apache.lucene.codecs.DocValuesFormat;
+import org.apache.lucene.codecs.DocValuesProducer;
+import org.apache.lucene.index.FieldInfo;
+import org.apache.lucene.index.SegmentReadState;
+import org.apache.lucene.index.SegmentWriteState;
+import org.apache.lucene.util.BytesRef;
+
+class CrankyDocValuesFormat extends DocValuesFormat {
+  final DocValuesFormat delegate;
+  final Random random;
+  
+  CrankyDocValuesFormat(DocValuesFormat delegate, Random random) {
+    // we impersonate the passed-in codec, so we don't need to be in SPI,
+    // and so we dont change file formats
+    super(delegate.getName());
+    this.delegate = delegate;
+    this.random = random;
+  }
+
+  @Override
+  public DocValuesConsumer fieldsConsumer(SegmentWriteState state) throws IOException {
+    if (random.nextInt(1000) == 0) {
+      throw new IOException("Fake IOException from DocValuesFormat.fieldsConsumer()");
+    }
+    return new CrankyDocValuesConsumer(delegate.fieldsConsumer(state), random);
+  }
+
+  @Override
+  public DocValuesProducer fieldsProducer(SegmentReadState state) throws IOException {
+    return delegate.fieldsProducer(state);
+  }
+  
+  static class CrankyDocValuesConsumer extends DocValuesConsumer {
+    final DocValuesConsumer delegate;
+    final Random random;
+    
+    CrankyDocValuesConsumer(DocValuesConsumer delegate, Random random) {
+      this.delegate = delegate;
+      this.random = random;
+    }
+    
+    @Override
+    public void close() throws IOException {
+      delegate.close();
+      if (random.nextInt(1000) == 0) {
+        throw new IOException("Fake IOException from DocValuesConsumer.close()");
+      }
+    }
+
+    @Override
+    public void addNumericField(FieldInfo field, Iterable<Number> values) throws IOException {
+      if (random.nextInt(1000) == 0) {
+        throw new IOException("Fake IOException from DocValuesConsumer.addNumericField()");
+      }
+      delegate.addNumericField(field, values);
+    }
+
+    @Override
+    public void addBinaryField(FieldInfo field, Iterable<BytesRef> values) throws IOException {
+      if (random.nextInt(1000) == 0) {
+        throw new IOException("Fake IOException from DocValuesConsumer.addBinaryField()");
+      }
+      delegate.addBinaryField(field, values);
+    }
+
+    @Override
+    public void addSortedField(FieldInfo field, Iterable<BytesRef> values, Iterable<Number> docToOrd) throws IOException {
+      if (random.nextInt(1000) == 0) {
+        throw new IOException("Fake IOException from DocValuesConsumer.addSortedField()");
+      }
+      delegate.addSortedField(field, values, docToOrd);
+    }
+
+    @Override
+    public void addSortedSetField(FieldInfo field, Iterable<BytesRef> values, Iterable<Number> docToOrdCount, Iterable<Number> ords) throws IOException {
+      if (random.nextInt(1000) == 0) {
+        throw new IOException("Fake IOException from DocValuesConsumer.addSortedSetField()");
+      }
+      delegate.addSortedSetField(field, values, docToOrdCount, ords);
+    }
+  }
+}

Added: lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/CrankyFieldInfosFormat.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/CrankyFieldInfosFormat.java?rev=1591652&view=auto
==============================================================================
--- lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/CrankyFieldInfosFormat.java (added)
+++ lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/CrankyFieldInfosFormat.java Thu May  1 13:19:21 2014
@@ -0,0 +1,69 @@
+package org.apache.lucene.codecs.cranky;
+
+/*
+ * 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.
+ */
+
+import java.io.IOException;
+import java.util.Random;
+
+import org.apache.lucene.codecs.FieldInfosFormat;
+import org.apache.lucene.codecs.FieldInfosReader;
+import org.apache.lucene.codecs.FieldInfosWriter;
+import org.apache.lucene.index.FieldInfos;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.store.IOContext;
+
+class CrankyFieldInfosFormat extends FieldInfosFormat {
+  final FieldInfosFormat delegate;
+  final Random random;
+  
+  CrankyFieldInfosFormat(FieldInfosFormat delegate, Random random) {
+    this.delegate = delegate;
+    this.random = random;
+  }
+  
+  @Override
+  public FieldInfosReader getFieldInfosReader() throws IOException {
+    return delegate.getFieldInfosReader();
+  }
+
+  @Override
+  public FieldInfosWriter getFieldInfosWriter() throws IOException {
+    if (random.nextInt(1000) == 0) {
+      throw new IOException("Fake IOException from FieldInfosFormat.getFieldInfosWriter()");
+    }
+    return new CrankyFieldInfosWriter(delegate.getFieldInfosWriter(), random);
+  }
+  
+  static class CrankyFieldInfosWriter extends FieldInfosWriter {
+    final FieldInfosWriter delegate;
+    final Random random;
+    
+    CrankyFieldInfosWriter(FieldInfosWriter delegate, Random random) {
+      this.delegate = delegate;
+      this.random = random;
+    }
+
+    @Override
+    public void write(Directory directory, String segmentName, String segmentSuffix, FieldInfos infos, IOContext context) throws IOException {
+      if (random.nextInt(1000) == 0) {
+        throw new IOException("Fake IOException from FieldInfosWriter.write()");
+      }
+      delegate.write(directory, segmentName, segmentSuffix, infos, context);
+    }
+  }
+}

Added: lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/CrankyLiveDocsFormat.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/CrankyLiveDocsFormat.java?rev=1591652&view=auto
==============================================================================
--- lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/CrankyLiveDocsFormat.java (added)
+++ lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/CrankyLiveDocsFormat.java Thu May  1 13:19:21 2014
@@ -0,0 +1,68 @@
+package org.apache.lucene.codecs.cranky;
+
+/*
+ * 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.
+ */
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Random;
+
+import org.apache.lucene.codecs.LiveDocsFormat;
+import org.apache.lucene.index.SegmentCommitInfo;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.store.IOContext;
+import org.apache.lucene.util.Bits;
+import org.apache.lucene.util.MutableBits;
+
+class CrankyLiveDocsFormat extends LiveDocsFormat {
+  final LiveDocsFormat delegate;
+  final Random random;
+  
+  CrankyLiveDocsFormat(LiveDocsFormat delegate, Random random) {
+    this.delegate = delegate;
+    this.random = random;
+  }
+
+  @Override
+  public MutableBits newLiveDocs(int size) throws IOException {
+    return delegate.newLiveDocs(size);
+  }
+
+  @Override
+  public MutableBits newLiveDocs(Bits existing) throws IOException {
+    return delegate.newLiveDocs(existing);
+  }
+
+  @Override
+  public Bits readLiveDocs(Directory dir, SegmentCommitInfo info, IOContext context) throws IOException {
+    return delegate.readLiveDocs(dir, info, context);
+  }
+
+  @Override
+  public void writeLiveDocs(MutableBits bits, Directory dir, SegmentCommitInfo info, int newDelCount, IOContext context) throws IOException {
+    if (random.nextInt(1000) == 0) {
+      throw new IOException("Fake IOException from LiveDocsFormat.writeLiveDocs()");
+    }
+    delegate.writeLiveDocs(bits, dir, info, newDelCount, context);
+  }
+
+  @Override
+  public void files(SegmentCommitInfo info, Collection<String> files) throws IOException {
+    // TODO: is this called only from write? if so we should throw exception!
+    delegate.files(info, files);
+  }
+}

Added: lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/CrankyNormsFormat.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/CrankyNormsFormat.java?rev=1591652&view=auto
==============================================================================
--- lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/CrankyNormsFormat.java (added)
+++ lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/CrankyNormsFormat.java Thu May  1 13:19:21 2014
@@ -0,0 +1,50 @@
+package org.apache.lucene.codecs.cranky;
+
+/*
+ * 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.
+ */
+
+import java.io.IOException;
+import java.util.Random;
+
+import org.apache.lucene.codecs.DocValuesConsumer;
+import org.apache.lucene.codecs.DocValuesProducer;
+import org.apache.lucene.codecs.NormsFormat;
+import org.apache.lucene.index.SegmentReadState;
+import org.apache.lucene.index.SegmentWriteState;
+
+class CrankyNormsFormat extends NormsFormat {
+  final NormsFormat delegate;
+  final Random random;
+  
+  CrankyNormsFormat(NormsFormat delegate, Random random) {
+    this.delegate = delegate;
+    this.random = random;
+  }
+
+  @Override
+  public DocValuesConsumer normsConsumer(SegmentWriteState state) throws IOException {
+    if (random.nextInt(1000) == 0) {
+      throw new IOException("Fake IOException from NormsFormat.fieldsConsumer()");
+    }
+    return new CrankyDocValuesFormat.CrankyDocValuesConsumer(delegate.normsConsumer(state), random);
+  }
+
+  @Override
+  public DocValuesProducer normsProducer(SegmentReadState state) throws IOException {
+    return delegate.normsProducer(state);
+  }
+}

Added: lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/CrankyPostingsFormat.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/CrankyPostingsFormat.java?rev=1591652&view=auto
==============================================================================
--- lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/CrankyPostingsFormat.java (added)
+++ lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/CrankyPostingsFormat.java Thu May  1 13:19:21 2014
@@ -0,0 +1,71 @@
+package org.apache.lucene.codecs.cranky;
+
+/*
+ * 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.
+ */
+
+import java.io.IOException;
+import java.util.Random;
+
+import org.apache.lucene.codecs.FieldsConsumer;
+import org.apache.lucene.codecs.FieldsProducer;
+import org.apache.lucene.codecs.PostingsFormat;
+import org.apache.lucene.index.Fields;
+import org.apache.lucene.index.SegmentReadState;
+import org.apache.lucene.index.SegmentWriteState;
+
+class CrankyPostingsFormat extends PostingsFormat {
+  final PostingsFormat delegate;
+  final Random random;
+  
+  CrankyPostingsFormat(PostingsFormat delegate, Random random) {
+    // we impersonate the passed-in codec, so we don't need to be in SPI,
+    // and so we dont change file formats
+    super(delegate.getName());
+    this.delegate = delegate;
+    this.random = random;
+  }
+  
+  @Override
+  public FieldsConsumer fieldsConsumer(SegmentWriteState state) throws IOException {
+    if (random.nextInt(1000) == 0) {
+      throw new IOException("Fake IOException from PostingsFormat.fieldsConsumer()");
+    }  
+    return new CrankyFieldsConsumer(delegate.fieldsConsumer(state), random);
+  }
+
+  @Override
+  public FieldsProducer fieldsProducer(SegmentReadState state) throws IOException {
+    return delegate.fieldsProducer(state);
+  }
+  
+  static class CrankyFieldsConsumer extends FieldsConsumer {
+    final FieldsConsumer delegate;
+    final Random random;
+    
+    CrankyFieldsConsumer(FieldsConsumer delegate, Random random) {
+      this.delegate = delegate;
+      this.random = random;
+    }
+    
+    @Override
+    public void write(Fields fields) throws IOException {
+      if (random.nextInt(1000) == 0) {
+        throw new IOException("Fake IOException from FieldsConsumer.write()");
+      }  
+    }
+  }
+}

Added: lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/CrankySegmentInfoFormat.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/CrankySegmentInfoFormat.java?rev=1591652&view=auto
==============================================================================
--- lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/CrankySegmentInfoFormat.java (added)
+++ lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/CrankySegmentInfoFormat.java Thu May  1 13:19:21 2014
@@ -0,0 +1,67 @@
+package org.apache.lucene.codecs.cranky;
+
+/*
+ * 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.
+ */
+
+import java.io.IOException;
+import java.util.Random;
+
+import org.apache.lucene.codecs.SegmentInfoFormat;
+import org.apache.lucene.codecs.SegmentInfoReader;
+import org.apache.lucene.codecs.SegmentInfoWriter;
+import org.apache.lucene.index.FieldInfos;
+import org.apache.lucene.index.SegmentInfo;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.store.IOContext;
+
+class CrankySegmentInfoFormat extends SegmentInfoFormat {
+  final SegmentInfoFormat delegate;
+  final Random random;
+  
+  CrankySegmentInfoFormat(SegmentInfoFormat delegate, Random random) {
+    this.delegate = delegate;
+    this.random = random;
+  }
+  
+  @Override
+  public SegmentInfoReader getSegmentInfoReader() {
+    return delegate.getSegmentInfoReader();
+  }
+
+  @Override
+  public SegmentInfoWriter getSegmentInfoWriter() {
+    return new CrankySegmentInfoWriter(delegate.getSegmentInfoWriter(), random);
+  }
+  
+  static class CrankySegmentInfoWriter extends SegmentInfoWriter {
+    final SegmentInfoWriter delegate;
+    final Random random;
+    
+    CrankySegmentInfoWriter(SegmentInfoWriter delegate, Random random) {
+      this.delegate = delegate;
+      this.random = random;
+    }
+    
+    @Override
+    public void write(Directory dir, SegmentInfo info, FieldInfos fis, IOContext ioContext) throws IOException {
+      if (random.nextInt(1000) == 0) {
+        throw new IOException("Fake IOException from SegmentInfoWriter.write()");
+      }
+      delegate.write(dir, info, fis, ioContext);
+    }
+  }
+}

Added: lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/CrankyStoredFieldsFormat.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/CrankyStoredFieldsFormat.java?rev=1591652&view=auto
==============================================================================
--- lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/CrankyStoredFieldsFormat.java (added)
+++ lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/CrankyStoredFieldsFormat.java Thu May  1 13:19:21 2014
@@ -0,0 +1,121 @@
+package org.apache.lucene.codecs.cranky;
+
+/*
+ * 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.
+ */
+
+import java.io.IOException;
+import java.util.Random;
+
+import org.apache.lucene.codecs.StoredFieldsFormat;
+import org.apache.lucene.codecs.StoredFieldsReader;
+import org.apache.lucene.codecs.StoredFieldsWriter;
+import org.apache.lucene.index.FieldInfo;
+import org.apache.lucene.index.FieldInfos;
+import org.apache.lucene.index.MergeState;
+import org.apache.lucene.index.SegmentInfo;
+import org.apache.lucene.index.StorableField;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.store.IOContext;
+
+class CrankyStoredFieldsFormat extends StoredFieldsFormat {
+  final StoredFieldsFormat delegate;
+  final Random random;
+  
+  CrankyStoredFieldsFormat(StoredFieldsFormat delegate, Random random) {
+    this.delegate = delegate;
+    this.random = random;
+  }
+
+  @Override
+  public StoredFieldsReader fieldsReader(Directory directory, SegmentInfo si, FieldInfos fn, IOContext context) throws IOException {
+    return delegate.fieldsReader(directory, si, fn, context);
+  }
+
+  @Override
+  public StoredFieldsWriter fieldsWriter(Directory directory, SegmentInfo si, IOContext context) throws IOException {
+    if (random.nextInt(1000) == 0) {
+      throw new IOException("Fake IOException from StoredFieldsFormat.fieldsWriter()");
+    }
+    return new CrankyStoredFieldsWriter(delegate.fieldsWriter(directory, si, context), random);
+  }
+  
+  static class CrankyStoredFieldsWriter extends StoredFieldsWriter {
+    
+    final StoredFieldsWriter delegate;
+    final Random random;
+    
+    CrankyStoredFieldsWriter(StoredFieldsWriter delegate, Random random) {
+      this.delegate = delegate;
+      this.random = random;
+    }
+
+    @Override
+    public void abort() {
+      delegate.abort();
+    }
+
+    @Override
+    public void finish(FieldInfos fis, int numDocs) throws IOException {
+      if (random.nextInt(1000) == 0) {
+        throw new IOException("Fake IOException from StoredFieldsWriter.finish()");
+      }
+      delegate.finish(fis, numDocs);
+    }
+
+    @Override
+    public int merge(MergeState mergeState) throws IOException {
+      if (random.nextInt(1000) == 0) {
+        throw new IOException("Fake IOException from StoredFieldsWriter.merge()");
+      }
+      return super.merge(mergeState);
+    }
+    
+    @Override
+    public void close() throws IOException {
+      delegate.close();
+      if (random.nextInt(1000) == 0) {
+        throw new IOException("Fake IOException from StoredFieldsWriter.close()");
+      }
+    }
+    
+    // per doc/field methods: lower probability since they are invoked so many times.
+
+    @Override
+    public void startDocument() throws IOException {
+      if (random.nextInt(1000000) == 0) {
+        throw new IOException("Fake IOException from StoredFieldsWriter.startDocument()");
+      }
+      delegate.startDocument();
+    }
+    
+    @Override
+    public void finishDocument() throws IOException {
+      if (random.nextInt(1000000) == 0) {
+        throw new IOException("Fake IOException from StoredFieldsWriter.finishDocument()");
+      }
+      delegate.finishDocument();
+    }
+
+    @Override
+    public void writeField(FieldInfo info, StorableField field) throws IOException {
+      if (random.nextInt(1000000) == 0) {
+        throw new IOException("Fake IOException from StoredFieldsWriter.writeField()");
+      }
+      delegate.writeField(info, field);
+    }
+  }
+}

Added: lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/CrankyTermVectorsFormat.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/CrankyTermVectorsFormat.java?rev=1591652&view=auto
==============================================================================
--- lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/CrankyTermVectorsFormat.java (added)
+++ lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/CrankyTermVectorsFormat.java Thu May  1 13:19:21 2014
@@ -0,0 +1,161 @@
+package org.apache.lucene.codecs.cranky;
+
+/*
+ * 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.
+ */
+
+import java.io.IOException;
+import java.util.Random;
+
+import org.apache.lucene.codecs.TermVectorsFormat;
+import org.apache.lucene.codecs.TermVectorsReader;
+import org.apache.lucene.codecs.TermVectorsWriter;
+import org.apache.lucene.index.FieldInfo;
+import org.apache.lucene.index.FieldInfos;
+import org.apache.lucene.index.MergeState;
+import org.apache.lucene.index.SegmentInfo;
+import org.apache.lucene.store.DataInput;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.store.IOContext;
+import org.apache.lucene.util.BytesRef;
+
+class CrankyTermVectorsFormat extends TermVectorsFormat {
+  final TermVectorsFormat delegate;
+  final Random random;
+  
+  CrankyTermVectorsFormat(TermVectorsFormat delegate, Random random) {
+    this.delegate = delegate;
+    this.random = random;
+  }
+
+  @Override
+  public TermVectorsReader vectorsReader(Directory directory, SegmentInfo segmentInfo, FieldInfos fieldInfos, IOContext context) throws IOException {
+    return delegate.vectorsReader(directory, segmentInfo, fieldInfos, context);
+  }
+
+  @Override
+  public TermVectorsWriter vectorsWriter(Directory directory, SegmentInfo segmentInfo, IOContext context) throws IOException {
+    if (random.nextInt(1000) == 0) {
+      throw new IOException("Fake IOException from TermVectorsFormat.vectorsWriter()");
+    }
+    return new CrankyTermVectorsWriter(delegate.vectorsWriter(directory, segmentInfo, context), random);
+  }
+  
+  static class CrankyTermVectorsWriter extends TermVectorsWriter {
+    final TermVectorsWriter delegate;
+    final Random random;
+    
+    CrankyTermVectorsWriter(TermVectorsWriter delegate, Random random) {
+      this.delegate = delegate;
+      this.random = random;
+    }
+    
+    @Override
+    public void abort() {
+      delegate.abort();
+    }
+    
+    @Override
+    public int merge(MergeState mergeState) throws IOException {
+      if (random.nextInt(1000) == 0) {
+        throw new IOException("Fake IOException from TermVectorsWriter.merge()");
+      }
+      return super.merge(mergeState);
+    }
+
+    @Override
+    public void finish(FieldInfos fis, int numDocs) throws IOException {
+      if (random.nextInt(1000) == 0) {
+        throw new IOException("Fake IOException from TermVectorsWriter.finish()");
+      }
+      delegate.finish(fis, numDocs);
+    }
+
+    @Override
+    public void close() throws IOException {
+      delegate.close();
+      if (random.nextInt(1000) == 0) {
+        throw new IOException("Fake IOException from TermVectorsWriter.close()");
+      }
+    }
+
+    // per doc/field methods: lower probability since they are invoked so many times.
+
+    @Override
+    public void startDocument(int numVectorFields) throws IOException {
+      if (random.nextInt(1000000) == 0) {
+        throw new IOException("Fake IOException from TermVectorsWriter.startDocument()");
+      }
+      delegate.startDocument(numVectorFields);
+    }
+    
+    @Override
+    public void finishDocument() throws IOException {
+      if (random.nextInt(1000000) == 0) {
+        throw new IOException("Fake IOException from TermVectorsWriter.finishDocument()");
+      }
+      delegate.finishDocument();
+    }
+    
+    @Override
+    public void startField(FieldInfo info, int numTerms, boolean positions, boolean offsets, boolean payloads) throws IOException {
+      if (random.nextInt(1000000) == 0) {
+        throw new IOException("Fake IOException from TermVectorsWriter.startField()");
+      }
+      delegate.startField(info, numTerms, positions, offsets, payloads);
+    }
+
+    @Override
+    public void finishField() throws IOException {
+      if (random.nextInt(1000000) == 0) {
+        throw new IOException("Fake IOException from TermVectorsWriter.finishField()");
+      }
+      delegate.finishField();
+    }
+    
+    @Override
+    public void startTerm(BytesRef term, int freq) throws IOException {
+      if (random.nextInt(1000000) == 0) {
+        throw new IOException("Fake IOException from TermVectorsWriter.startTerm()");
+      }
+      delegate.startTerm(term, freq);
+    }
+
+    @Override
+    public void finishTerm() throws IOException {
+      if (random.nextInt(1000000) == 0) {
+        throw new IOException("Fake IOException from TermVectorsWriter.finishTerm()");
+      }
+      delegate.finishTerm();
+    }
+    
+    @Override
+    public void addPosition(int position, int startOffset, int endOffset, BytesRef payload) throws IOException {
+      if (random.nextInt(1000000) == 0) {
+        throw new IOException("Fake IOException from TermVectorsWriter.addPosition()");
+      }
+      delegate.addPosition(position, startOffset, endOffset, payload);
+    }
+
+    @Override
+    public void addProx(int numProx, DataInput positions, DataInput offsets) throws IOException {
+      if (random.nextInt(1000000) == 0) {
+        throw new IOException("Fake IOException from TermVectorsWriter.addProx()");
+      }
+      super.addProx(numProx, positions, offsets);
+    }
+  }
+}

Added: lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/package.html
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/package.html?rev=1591652&view=auto
==============================================================================
--- lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/package.html (added)
+++ lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/codecs/cranky/package.html Thu May  1 13:19:21 2014
@@ -0,0 +1,25 @@
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<!--
+ 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.
+-->
+<html>
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+</head>
+<body>
+Codec for testing that throws random IOExceptions
+</body>
+</html>
\ No newline at end of file