Index: lucene/test-framework/src/java/org/apache/lucene/index/AssertingAtomicReader.java
===================================================================
--- lucene/test-framework/src/java/org/apache/lucene/index/AssertingAtomicReader.java	(revision 0)
+++ lucene/test-framework/src/java/org/apache/lucene/index/AssertingAtomicReader.java	(working copy)
@@ -0,0 +1,142 @@
+package org.apache.lucene.index;
+
+import java.io.IOException;
+
+import org.apache.lucene.util.Bits;
+import org.apache.lucene.util.BytesRef;
+import org.apache.lucene.util.automaton.CompiledAutomaton;
+
+/*
+ * 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.
+ */
+
+/**
+ * A {@link FilterAtomicReader} that can be used to apply
+ * additional checks for tests.
+ */
+public class AssertingAtomicReader extends FilterAtomicReader {
+
+  public AssertingAtomicReader(AtomicReader in) {
+    super(in);
+    // check some basic reader sanity
+    assert in.maxDoc() >= 0;
+    assert in.numDocs() <= in.maxDoc();
+    assert in.numDeletedDocs() + in.numDocs() == in.maxDoc();
+    assert !in.hasDeletions() || in.numDeletedDocs() > 0 && in.numDocs() < in.maxDoc();
+  }
+
+  @Override
+  public Fields fields() throws IOException {
+    Fields fields = super.fields();
+    return fields == null ? null : new AssertingFields(fields);
+  }
+  
+  static class AssertingFields extends FilterFields {
+    public AssertingFields(Fields in) {
+      super(in);
+    }
+
+    @Override
+    public FieldsEnum iterator() throws IOException {
+      FieldsEnum fieldsEnum = super.iterator();
+      assert fieldsEnum != null;
+      return new AssertingFieldsEnum(fieldsEnum);
+    }
+
+    @Override
+    public Terms terms(String field) throws IOException {
+      Terms terms = super.terms(field);
+      return terms == null ? null : new AssertingTerms(terms);
+    }
+  }
+  
+  static class AssertingFieldsEnum extends FilterFieldsEnum {
+    public AssertingFieldsEnum(FieldsEnum in) {
+      super(in);
+    }
+
+    @Override
+    public Terms terms() throws IOException {
+      Terms terms = super.terms();
+      return terms == null ? null : new AssertingTerms(terms);
+    }
+  }
+  
+  static class AssertingTerms extends FilterTerms {
+    public AssertingTerms(Terms in) {
+      super(in);
+    }
+
+    @Override
+    public TermsEnum intersect(CompiledAutomaton automaton, BytesRef bytes) throws IOException {
+      TermsEnum termsEnum = super.intersect(automaton, bytes);
+      assert termsEnum != null;
+      return new AssertingTermsEnum(termsEnum);
+    }
+
+    @Override
+    public TermsEnum iterator(TermsEnum reuse) throws IOException {
+      // TODO: should we give this thing a random to be super-evil,
+      // and randomly *not* unwrap?
+      if (reuse instanceof AssertingTermsEnum) {
+        reuse = ((AssertingTermsEnum) reuse).in;
+      }
+      TermsEnum termsEnum = super.iterator(reuse);
+      assert termsEnum != null;
+      return new AssertingTermsEnum(termsEnum);
+    }
+  }
+  
+  static class AssertingTermsEnum extends FilterTermsEnum {
+    public AssertingTermsEnum(TermsEnum in) {
+      super(in);
+    }
+
+    @Override
+    public DocsEnum docs(Bits liveDocs, DocsEnum reuse, boolean needsFreqs) throws IOException {
+      // TODO: should we give this thing a random to be super-evil,
+      // and randomly *not* unwrap?
+      if (reuse instanceof AssertingDocsEnum) {
+        reuse = ((AssertingDocsEnum) reuse).in;
+      }
+      DocsEnum docs = super.docs(liveDocs, reuse, needsFreqs);
+      return docs == null ? null : new AssertingDocsEnum(docs);
+    }
+
+    @Override
+    public DocsAndPositionsEnum docsAndPositions(Bits liveDocs, DocsAndPositionsEnum reuse, boolean needsOffsets) throws IOException {
+      // TODO: should we give this thing a random to be super-evil,
+      // and randomly *not* unwrap?
+      if (reuse instanceof AssertingDocsAndPositionsEnum) {
+        reuse = ((AssertingDocsAndPositionsEnum) reuse).in;
+      }
+      DocsAndPositionsEnum docs = super.docsAndPositions(liveDocs, reuse, needsOffsets);
+      return docs == null ? null : new AssertingDocsAndPositionsEnum(docs);
+    }
+  }
+  
+  static class AssertingDocsEnum extends FilterDocsEnum {
+    public AssertingDocsEnum(DocsEnum in) {
+      super(in);
+    }
+  }
+  
+  static class AssertingDocsAndPositionsEnum extends FilterDocsAndPositionsEnum {
+    public AssertingDocsAndPositionsEnum(DocsAndPositionsEnum in) {
+      super(in);
+    }
+  }
+}

Property changes on: lucene/test-framework/src/java/org/apache/lucene/index/AssertingAtomicReader.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
Index: lucene/test-framework/src/java/org/apache/lucene/util/LuceneTestCase.java
===================================================================
--- lucene/test-framework/src/java/org/apache/lucene/util/LuceneTestCase.java	(revision 1360380)
+++ lucene/test-framework/src/java/org/apache/lucene/util/LuceneTestCase.java	(working copy)
@@ -1010,7 +1010,7 @@
       // TODO: remove this, and fix those tests to wrap before putting slow around:
       final boolean wasOriginallyAtomic = r instanceof AtomicReader;
       for (int i = 0, c = random.nextInt(6)+1; i < c; i++) {
-        switch(random.nextInt(4)) {
+        switch(random.nextInt(5)) {
           case 0:
             r = SlowCompositeReaderWrapper.wrap(r);
             break;
@@ -1041,6 +1041,12 @@
               new FieldFilterAtomicReader(ar, fields, true)
             );
             break;
+          case 4:
+            // TODO: we should make an AssertingCompositeReader too!
+            if (r instanceof AtomicReader) {
+              r = new AssertingAtomicReader((AtomicReader)r);
+            }
+            break;
           default:
             fail("should not get here");
         }
