You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by mi...@apache.org on 2013/04/22 23:01:48 UTC

svn commit: r1470715 - in /lucene/dev/trunk/lucene: core/src/test/org/apache/lucene/search/ facet/src/java/org/apache/lucene/facet/search/ test-framework/src/java/org/apache/lucene/search/

Author: mikemccand
Date: Mon Apr 22 21:01:47 2013
New Revision: 1470715

URL: http://svn.apache.org/r1470715
Log:
factor out Asserting* from AssertingIndexSearcher

Added:
    lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/search/AssertingCollector.java   (with props)
    lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/search/AssertingScorer.java   (with props)
    lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/search/AssertingWeight.java   (with props)
Modified:
    lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/search/TestBooleanScorer.java
    lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/DrillSidewaysScorer.java
    lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/search/AssertingIndexSearcher.java

Modified: lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/search/TestBooleanScorer.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/search/TestBooleanScorer.java?rev=1470715&r1=1470714&r2=1470715&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/search/TestBooleanScorer.java (original)
+++ lucene/dev/trunk/lucene/core/src/test/org/apache/lucene/search/TestBooleanScorer.java Mon Apr 22 21:01:47 2013
@@ -28,7 +28,6 @@ import org.apache.lucene.index.AtomicRea
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.RandomIndexWriter;
 import org.apache.lucene.index.Term;
-import org.apache.lucene.search.AssertingIndexSearcher.AssertingScorer;
 import org.apache.lucene.search.BooleanQuery.BooleanWeight;
 import org.apache.lucene.store.Directory;
 import org.apache.lucene.util.LuceneTestCase;

Modified: lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/DrillSidewaysScorer.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/DrillSidewaysScorer.java?rev=1470715&r1=1470714&r2=1470715&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/DrillSidewaysScorer.java (original)
+++ lucene/dev/trunk/lucene/facet/src/java/org/apache/lucene/facet/search/DrillSidewaysScorer.java Mon Apr 22 21:01:47 2013
@@ -565,6 +565,9 @@ class DrillSidewaysScorer extends Scorer
       //  System.out.println("  now collect: " + filledCount + " hits");
       //}
       for(int i=0;i<filledCount;i++) {
+        // NOTE: This is actually in-order collection,
+        // because we only accept docs originally returned by
+        // the baseScorer (ie that Scorer is AND'd)
         int slot = filledSlots[i];
         collectDocID = docIDs[slot];
         collectScore = scores[slot];

Added: lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/search/AssertingCollector.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/search/AssertingCollector.java?rev=1470715&view=auto
==============================================================================
--- lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/search/AssertingCollector.java (added)
+++ lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/search/AssertingCollector.java Mon Apr 22 21:01:47 2013
@@ -0,0 +1,71 @@
+package org.apache.lucene.search;
+
+/*
+ * 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.index.AtomicReaderContext;
+
+/** Wraps another Collector and checks that
+ *  acceptsDocsOutOfOrder is respected. */
+
+public class AssertingCollector extends Collector {
+
+  public static Collector wrap(Random random, Collector other, boolean inOrder) {
+    return other instanceof AssertingCollector ? other : new AssertingCollector(random, other, inOrder);
+  }
+
+  final Random random;
+  final Collector in;
+  final boolean inOrder;
+  int lastCollected;
+
+  AssertingCollector(Random random, Collector in, boolean inOrder) {
+    this.random = random;
+    this.in = in;
+    this.inOrder = inOrder;
+    lastCollected = -1;
+  }
+
+  @Override
+  public void setScorer(Scorer scorer) throws IOException {
+    in.setScorer(AssertingScorer.getAssertingScorer(random, scorer));
+  }
+
+  @Override
+  public void collect(int doc) throws IOException {
+    if (inOrder || !acceptsDocsOutOfOrder()) {
+      assert doc > lastCollected : "Out of order : " + lastCollected + " " + doc;
+    }
+    in.collect(doc);
+    lastCollected = doc;
+  }
+
+  @Override
+  public void setNextReader(AtomicReaderContext context) throws IOException {
+    lastCollected = -1;
+  }
+
+  @Override
+  public boolean acceptsDocsOutOfOrder() {
+    return in.acceptsDocsOutOfOrder();
+  }
+
+}
+

Modified: lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/search/AssertingIndexSearcher.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/search/AssertingIndexSearcher.java?rev=1470715&r1=1470714&r2=1470715&view=diff
==============================================================================
--- lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/search/AssertingIndexSearcher.java (original)
+++ lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/search/AssertingIndexSearcher.java Mon Apr 22 21:01:47 2013
@@ -18,22 +18,13 @@ package org.apache.lucene.search;
  */
 
 import java.io.IOException;
-import java.lang.ref.WeakReference;
-import java.util.Collection;
-import java.util.Collections;
 import java.util.List;
-import java.util.Map;
 import java.util.Random;
-import java.util.WeakHashMap;
 import java.util.concurrent.ExecutorService;
 
-import org.apache.lucene.index.AssertingAtomicReader;
 import org.apache.lucene.index.AtomicReaderContext;
-import org.apache.lucene.index.DocsEnum;
 import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.index.IndexReaderContext;
-import org.apache.lucene.util.Bits;
-import org.apache.lucene.util.VirtualMethod;
 import org.apache.lucene.util._TestUtil;
 
 /**
@@ -102,255 +93,6 @@ public class AssertingIndexSearcher exte
     super.search(leaves, AssertingWeight.wrap(random, weight), collector);
   }
 
-  static class AssertingWeight extends Weight {
-
-    static Weight wrap(Random random, Weight other) {
-      return other instanceof AssertingWeight ? other : new AssertingWeight(random, other);
-    }
-
-    final Random random;
-    final Weight in;
-
-    AssertingWeight(Random random, Weight in) {
-      this.random = random;
-      this.in = in;
-    }
-
-    @Override
-    public Explanation explain(AtomicReaderContext context, int doc) throws IOException {
-      return in.explain(context, doc);
-    }
-
-    @Override
-    public Query getQuery() {
-      return in.getQuery();
-    }
-
-    @Override
-    public float getValueForNormalization() throws IOException {
-      return in.getValueForNormalization();
-    }
-
-    @Override
-    public void normalize(float norm, float topLevelBoost) {
-      in.normalize(norm, topLevelBoost);
-    }
-
-    @Override
-    public Scorer scorer(AtomicReaderContext context, boolean scoreDocsInOrder,
-        boolean topScorer, Bits acceptDocs) throws IOException {
-      // if the caller asks for in-order scoring or if the weight does not support
-      // out-of order scoring then collection will have to happen in-order.
-      final boolean inOrder = scoreDocsInOrder || !scoresDocsOutOfOrder();
-      final Scorer inScorer = in.scorer(context, scoreDocsInOrder, topScorer, acceptDocs);
-      return AssertingScorer.wrap(new Random(random.nextLong()), inScorer, topScorer, inOrder);
-    }
-
-    @Override
-    public boolean scoresDocsOutOfOrder() {
-      return in.scoresDocsOutOfOrder();
-    }
-
-  }
-
-  enum TopScorer {
-    YES, NO, UNKNOWN;
-  }
-
-  /** Wraps a Scorer with additional checks */
-  public static class AssertingScorer extends Scorer {
-
-    private static final VirtualMethod<Scorer> SCORE_COLLECTOR = new VirtualMethod<Scorer>(Scorer.class, "score", Collector.class);
-    private static final VirtualMethod<Scorer> SCORE_COLLECTOR_RANGE = new VirtualMethod<Scorer>(Scorer.class, "score", Collector.class, int.class, int.class);
-
-    // we need to track scorers using a weak hash map because otherwise we
-    // could loose references because of eg.
-    // AssertingScorer.score(Collector) which needs to delegate to work correctly
-    private static Map<Scorer, WeakReference<AssertingScorer>> ASSERTING_INSTANCES = Collections.synchronizedMap(new WeakHashMap<Scorer, WeakReference<AssertingScorer>>());
-
-    private static Scorer wrap(Random random, Scorer other, TopScorer topScorer, boolean inOrder) {
-      if (other == null || other instanceof AssertingScorer) {
-        return other;
-      }
-      final AssertingScorer assertScorer = new AssertingScorer(random, other, topScorer, inOrder);
-      ASSERTING_INSTANCES.put(other, new WeakReference<AssertingScorer>(assertScorer));
-      return assertScorer;
-    }
-
-    static Scorer wrap(Random random, Scorer other, boolean topScorer, boolean inOrder) {
-      return wrap(random, other, topScorer ? TopScorer.YES : TopScorer.NO, inOrder);
-    }
-
-    static Scorer getAssertingScorer(Random random, Scorer other) {
-      if (other == null || other instanceof AssertingScorer) {
-        return other;
-      }
-      final WeakReference<AssertingScorer> assertingScorerRef = ASSERTING_INSTANCES.get(other);
-      final AssertingScorer assertingScorer = assertingScorerRef == null ? null : assertingScorerRef.get();
-      if (assertingScorer == null) {
-        // can happen in case of memory pressure or if
-        // scorer1.score(collector) calls
-        // collector.setScorer(scorer2) with scorer1 != scorer2, such as
-        // BooleanScorer. In that case we can't enable all assertions
-        return new AssertingScorer(random, other, TopScorer.UNKNOWN, false);
-      } else {
-        return assertingScorer;
-      }
-    }
-
-    final Random random;
-    final Scorer in;
-    final AssertingAtomicReader.AssertingDocsEnum docsEnumIn;
-    final TopScorer topScorer;
-    final boolean inOrder;
-    final boolean canCallNextDoc;
-
-    private AssertingScorer(Random random, Scorer in, TopScorer topScorer, boolean inOrder) {
-      super(in.weight);
-      this.random = random;
-      this.in = in;
-      this.topScorer = topScorer;
-      this.inOrder = inOrder;
-      this.docsEnumIn = new AssertingAtomicReader.AssertingDocsEnum(in, topScorer == TopScorer.NO);
-      this.canCallNextDoc = topScorer != TopScorer.YES // not a top scorer
-          || !SCORE_COLLECTOR_RANGE.isOverriddenAsOf(in.getClass()) // the default impl relies upon nextDoc()
-          || !SCORE_COLLECTOR.isOverriddenAsOf(in.getClass()); // the default impl relies upon nextDoc()
-    }
-
-    public Scorer getIn() {
-      return in;
-    }
-
-    boolean iterating() {
-      switch (docID()) {
-        case -1:
-        case NO_MORE_DOCS:
-          return false;
-        default:
-          return true;
-      }
-    }
-
-    @Override
-    public float score() throws IOException {
-      assert iterating();
-      final float score = in.score();
-      assert !Float.isNaN(score);
-      assert !Float.isNaN(score);
-      return score;
-    }
-
-    @Override
-    public void score(Collector collector) throws IOException {
-      assert topScorer != TopScorer.NO;
-      if (SCORE_COLLECTOR.isOverriddenAsOf(this.in.getClass())) {
-        if (random.nextBoolean()) {
-          try {
-            final boolean remaining = in.score(collector, DocsEnum.NO_MORE_DOCS, in.nextDoc());
-            assert !remaining;
-          } catch (UnsupportedOperationException e) {
-            in.score(collector);
-          }
-        } else {
-          in.score(collector);
-        }
-      } else {
-        // score(Collector) has not been overridden, use the super method in
-        // order to benefit from all assertions
-        super.score(collector);
-      }
-    }
-
-    @Override
-    public boolean score(Collector collector, int max, int firstDocID) throws IOException {
-      assert topScorer != TopScorer.NO;
-      if (SCORE_COLLECTOR_RANGE.isOverriddenAsOf(this.in.getClass())) {
-        return in.score(collector, max, firstDocID);
-      } else {
-        // score(Collector,int,int) has not been overridden, use the super
-        // method in order to benefit from all assertions
-        return super.score(collector, max, firstDocID);
-      }
-    }
-
-    @Override
-    public Collection<ChildScorer> getChildren() {
-      return in.getChildren();
-    }
-
-    @Override
-    public int freq() throws IOException {
-      assert iterating();
-      return in.freq();
-    }
-
-    @Override
-    public int docID() {
-      return in.docID();
-    }
-
-    @Override
-    public int nextDoc() throws IOException {
-      assert canCallNextDoc : "top scorers should not call nextDoc()";
-      return docsEnumIn.nextDoc();
-    }
-
-    @Override
-    public int advance(int target) throws IOException {
-      assert canCallNextDoc : "top scorers should not call advance(target)";
-      return docsEnumIn.advance(target);
-    }
-
-    @Override
-    public long cost() {
-      return in.cost();
-    }
-  }
-
-  static class AssertingCollector extends Collector {
-
-    static Collector wrap(Random random, Collector other, boolean inOrder) {
-      return other instanceof AssertingCollector ? other : new AssertingCollector(random, other, inOrder);
-    }
-
-    final Random random;
-    final Collector in;
-    final boolean inOrder;
-    int lastCollected;
-
-    AssertingCollector(Random random, Collector in, boolean inOrder) {
-      this.random = random;
-      this.in = in;
-      this.inOrder = inOrder;
-      lastCollected = -1;
-    }
-
-    @Override
-    public void setScorer(Scorer scorer) throws IOException {
-      in.setScorer(AssertingScorer.getAssertingScorer(random, scorer));
-    }
-
-    @Override
-    public void collect(int doc) throws IOException {
-      if (inOrder || !acceptsDocsOutOfOrder()) {
-        assert doc > lastCollected : "Out of order : " + lastCollected + " " + doc;
-      }
-      in.collect(doc);
-      lastCollected = doc;
-    }
-
-    @Override
-    public void setNextReader(AtomicReaderContext context) throws IOException {
-      lastCollected = -1;
-    }
-
-    @Override
-    public boolean acceptsDocsOutOfOrder() {
-      return in.acceptsDocsOutOfOrder();
-    }
-
-  }
-
   @Override
   public String toString() {
     return "AssertingIndexSearcher(" + super.toString() + ")";

Added: lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/search/AssertingScorer.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/search/AssertingScorer.java?rev=1470715&view=auto
==============================================================================
--- lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/search/AssertingScorer.java (added)
+++ lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/search/AssertingScorer.java Mon Apr 22 21:01:47 2013
@@ -0,0 +1,185 @@
+package org.apache.lucene.search;
+
+/*
+ * 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.lang.ref.WeakReference;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Random;
+import java.util.WeakHashMap;
+
+import org.apache.lucene.index.AssertingAtomicReader;
+import org.apache.lucene.index.DocsEnum;
+import org.apache.lucene.util.VirtualMethod;
+
+/** Wraps a Scorer with additional checks */
+public class AssertingScorer extends Scorer {
+
+  enum TopScorer {
+    YES, NO, UNKNOWN;
+  }
+
+  private static final VirtualMethod<Scorer> SCORE_COLLECTOR = new VirtualMethod<Scorer>(Scorer.class, "score", Collector.class);
+  private static final VirtualMethod<Scorer> SCORE_COLLECTOR_RANGE = new VirtualMethod<Scorer>(Scorer.class, "score", Collector.class, int.class, int.class);
+
+  // we need to track scorers using a weak hash map because otherwise we
+  // could loose references because of eg.
+  // AssertingScorer.score(Collector) which needs to delegate to work correctly
+  private static Map<Scorer, WeakReference<AssertingScorer>> ASSERTING_INSTANCES = Collections.synchronizedMap(new WeakHashMap<Scorer, WeakReference<AssertingScorer>>());
+
+  private static Scorer wrap(Random random, Scorer other, TopScorer topScorer, boolean inOrder) {
+    if (other == null || other instanceof AssertingScorer) {
+      return other;
+    }
+    final AssertingScorer assertScorer = new AssertingScorer(random, other, topScorer, inOrder);
+    ASSERTING_INSTANCES.put(other, new WeakReference<AssertingScorer>(assertScorer));
+    return assertScorer;
+  }
+
+  static Scorer wrap(Random random, Scorer other, boolean topScorer, boolean inOrder) {
+    return wrap(random, other, topScorer ? TopScorer.YES : TopScorer.NO, inOrder);
+  }
+
+  static Scorer getAssertingScorer(Random random, Scorer other) {
+    if (other == null || other instanceof AssertingScorer) {
+      return other;
+    }
+    final WeakReference<AssertingScorer> assertingScorerRef = ASSERTING_INSTANCES.get(other);
+    final AssertingScorer assertingScorer = assertingScorerRef == null ? null : assertingScorerRef.get();
+    if (assertingScorer == null) {
+      // can happen in case of memory pressure or if
+      // scorer1.score(collector) calls
+      // collector.setScorer(scorer2) with scorer1 != scorer2, such as
+      // BooleanScorer. In that case we can't enable all assertions
+      return new AssertingScorer(random, other, TopScorer.UNKNOWN, false);
+    } else {
+      return assertingScorer;
+    }
+  }
+
+  final Random random;
+  final Scorer in;
+  final AssertingAtomicReader.AssertingDocsEnum docsEnumIn;
+  final TopScorer topScorer;
+  final boolean inOrder;
+  final boolean canCallNextDoc;
+
+  private AssertingScorer(Random random, Scorer in, TopScorer topScorer, boolean inOrder) {
+    super(in.weight);
+    this.random = random;
+    this.in = in;
+    this.topScorer = topScorer;
+    this.inOrder = inOrder;
+    this.docsEnumIn = new AssertingAtomicReader.AssertingDocsEnum(in, topScorer == TopScorer.NO);
+    this.canCallNextDoc = topScorer != TopScorer.YES // not a top scorer
+      || !SCORE_COLLECTOR_RANGE.isOverriddenAsOf(in.getClass()) // the default impl relies upon nextDoc()
+      || !SCORE_COLLECTOR.isOverriddenAsOf(in.getClass()); // the default impl relies upon nextDoc()
+  }
+
+  public Scorer getIn() {
+    return in;
+  }
+
+  boolean iterating() {
+    switch (docID()) {
+    case -1:
+    case NO_MORE_DOCS:
+      return false;
+    default:
+      return true;
+    }
+  }
+
+  @Override
+  public float score() throws IOException {
+    assert iterating();
+    final float score = in.score();
+    assert !Float.isNaN(score);
+    assert !Float.isNaN(score);
+    return score;
+  }
+
+  @Override
+  public void score(Collector collector) throws IOException {
+    assert topScorer != TopScorer.NO;
+    if (SCORE_COLLECTOR.isOverriddenAsOf(this.in.getClass())) {
+      if (random.nextBoolean()) {
+        try {
+          final boolean remaining = in.score(collector, DocsEnum.NO_MORE_DOCS, in.nextDoc());
+          assert !remaining;
+        } catch (UnsupportedOperationException e) {
+          in.score(collector);
+        }
+      } else {
+        in.score(collector);
+      }
+    } else {
+      // score(Collector) has not been overridden, use the super method in
+      // order to benefit from all assertions
+      super.score(collector);
+    }
+  }
+
+  @Override
+  public boolean score(Collector collector, int max, int firstDocID) throws IOException {
+    assert topScorer != TopScorer.NO;
+    if (SCORE_COLLECTOR_RANGE.isOverriddenAsOf(this.in.getClass())) {
+      return in.score(collector, max, firstDocID);
+    } else {
+      // score(Collector,int,int) has not been overridden, use the super
+      // method in order to benefit from all assertions
+      return super.score(collector, max, firstDocID);
+    }
+  }
+
+  @Override
+  public Collection<ChildScorer> getChildren() {
+    return in.getChildren();
+  }
+
+  @Override
+  public int freq() throws IOException {
+    assert iterating();
+    return in.freq();
+  }
+
+  @Override
+  public int docID() {
+    return in.docID();
+  }
+
+  @Override
+  public int nextDoc() throws IOException {
+    assert canCallNextDoc : "top scorers should not call nextDoc()";
+    return docsEnumIn.nextDoc();
+  }
+
+  @Override
+  public int advance(int target) throws IOException {
+    assert canCallNextDoc : "top scorers should not call advance(target)";
+    return docsEnumIn.advance(target);
+  }
+
+  @Override
+  public long cost() {
+    return in.cost();
+  }
+}
+

Added: lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/search/AssertingWeight.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/search/AssertingWeight.java?rev=1470715&view=auto
==============================================================================
--- lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/search/AssertingWeight.java (added)
+++ lucene/dev/trunk/lucene/test-framework/src/java/org/apache/lucene/search/AssertingWeight.java Mon Apr 22 21:01:47 2013
@@ -0,0 +1,76 @@
+package org.apache.lucene.search;
+
+/*
+ * 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.index.AtomicReaderContext;
+import org.apache.lucene.util.Bits;
+
+class AssertingWeight extends Weight {
+
+  static Weight wrap(Random random, Weight other) {
+    return other instanceof AssertingWeight ? other : new AssertingWeight(random, other);
+  }
+
+  final Random random;
+  final Weight in;
+
+  AssertingWeight(Random random, Weight in) {
+    this.random = random;
+    this.in = in;
+  }
+
+  @Override
+  public Explanation explain(AtomicReaderContext context, int doc) throws IOException {
+    return in.explain(context, doc);
+  }
+
+  @Override
+  public Query getQuery() {
+    return in.getQuery();
+  }
+
+  @Override
+  public float getValueForNormalization() throws IOException {
+    return in.getValueForNormalization();
+  }
+
+  @Override
+  public void normalize(float norm, float topLevelBoost) {
+    in.normalize(norm, topLevelBoost);
+  }
+
+  @Override
+  public Scorer scorer(AtomicReaderContext context, boolean scoreDocsInOrder,
+                       boolean topScorer, Bits acceptDocs) throws IOException {
+    // if the caller asks for in-order scoring or if the weight does not support
+    // out-of order scoring then collection will have to happen in-order.
+    final boolean inOrder = scoreDocsInOrder || !scoresDocsOutOfOrder();
+    final Scorer inScorer = in.scorer(context, scoreDocsInOrder, topScorer, acceptDocs);
+    return AssertingScorer.wrap(new Random(random.nextLong()), inScorer, topScorer, inOrder);
+  }
+
+  @Override
+  public boolean scoresDocsOutOfOrder() {
+    return in.scoresDocsOutOfOrder();
+  }
+
+}
+