diff --git a/lucene/core/src/test/org/apache/lucene/search/TestBooleanScorer.java b/lucene/core/src/test/org/apache/lucene/search/TestBooleanScorer.java index e6ed13aa21c..f1ed5bcb667 100644 --- a/lucene/core/src/test/org/apache/lucene/search/TestBooleanScorer.java +++ b/lucene/core/src/test/org/apache/lucene/search/TestBooleanScorer.java @@ -138,7 +138,8 @@ public class TestBooleanScorer extends LuceneTestCase { w.addDocument(doc); final IndexReader r = w.getReader(); w.close(); - final IndexSearcher s = newSearcher(r); + // we don't wrap with AssertingIndexSearcher in order to have the original scorer in setScorer. + final IndexSearcher s = newSearcher(r, true, false); final BooleanQuery q = new BooleanQuery(); for(int term=0;term<33;term++) { @@ -154,7 +155,7 @@ public class TestBooleanScorer extends LuceneTestCase { @Override public void setScorer(Scorer scorer) { // Make sure we got BooleanScorer: - final Class clazz = scorer instanceof AssertingScorer ? ((AssertingScorer) scorer).getIn().getClass() : scorer.getClass(); + final Class clazz = scorer.getClass(); assertEquals("Scorer is implemented by wrong class", FakeScorer.class.getName(), clazz.getName()); } diff --git a/lucene/core/src/test/org/apache/lucene/search/TestConstantScoreQuery.java b/lucene/core/src/test/org/apache/lucene/search/TestConstantScoreQuery.java index 93d5a1da4ab..741934fdd9d 100644 --- a/lucene/core/src/test/org/apache/lucene/search/TestConstantScoreQuery.java +++ b/lucene/core/src/test/org/apache/lucene/search/TestConstantScoreQuery.java @@ -91,7 +91,8 @@ public class TestConstantScoreQuery extends LuceneTestCase { reader = writer.getReader(); writer.close(); - searcher = newSearcher(reader); + // we don't wrap with AssertingIndexSearcher in order to have the original scorer in setScorer. + searcher = newSearcher(reader, true, false); // set a similarity that does not normalize our boost away searcher.setSimilarity(new DefaultSimilarity() { diff --git a/lucene/test-framework/src/java/org/apache/lucene/search/AssertingBulkOutOfOrderScorer.java b/lucene/test-framework/src/java/org/apache/lucene/search/AssertingBulkOutOfOrderScorer.java index 39aa3c68b50..26a0a4f545d 100644 --- a/lucene/test-framework/src/java/org/apache/lucene/search/AssertingBulkOutOfOrderScorer.java +++ b/lucene/test-framework/src/java/org/apache/lucene/search/AssertingBulkOutOfOrderScorer.java @@ -18,93 +18,37 @@ 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.Map; import java.util.Random; -import java.util.WeakHashMap; -import org.apache.lucene.index.DocsEnum; -import org.apache.lucene.util.VirtualMethod; - -/** A crazy {@link BulkScorer} that wraps a {@link Scorer} +/** A crazy {@link BulkScorer} that wraps another {@link BulkScorer} * but shuffles the order of the collected documents. */ public class AssertingBulkOutOfOrderScorer extends BulkScorer { + final BulkScorer in; final Random random; - final Scorer scorer; - public AssertingBulkOutOfOrderScorer(Random random, Scorer scorer) { + public AssertingBulkOutOfOrderScorer(Random random, BulkScorer in) { + this.in = in; this.random = random; - this.scorer = scorer; - } - - private void shuffle(int[] docIDs, float[] scores, int[] freqs, int size) { - for (int i = size - 1; i > 0; --i) { - final int other = random.nextInt(i + 1); - - final int tmpDoc = docIDs[i]; - docIDs[i] = docIDs[other]; - docIDs[other] = tmpDoc; - - final float tmpScore = scores[i]; - scores[i] = scores[other]; - scores[other] = tmpScore; - - final int tmpFreq = freqs[i]; - freqs[i] = freqs[other]; - freqs[other] = tmpFreq; - } - } - - private static void flush(int[] docIDs, float[] scores, int[] freqs, int size, - FakeScorer scorer, LeafCollector collector) throws IOException { - for (int i = 0; i < size; ++i) { - scorer.doc = docIDs[i]; - scorer.freq = freqs[i]; - scorer.score = scores[i]; - collector.collect(scorer.doc); - } } @Override public boolean score(LeafCollector collector, int max) throws IOException { - if (scorer.docID() == -1) { - scorer.nextDoc(); - } + final RandomOrderCollector randomCollector = new RandomOrderCollector(random, collector); + final boolean remaining = in.score(randomCollector, max); + randomCollector.flush(); + return remaining; + } - FakeScorer fake = new FakeScorer(); - collector.setScorer(fake); - - final int bufferSize = 1 + random.nextInt(100); - final int[] docIDs = new int[bufferSize]; - final float[] scores = new float[bufferSize]; - final int[] freqs = new int[bufferSize]; - - int buffered = 0; - int doc = scorer.docID(); - while (doc < max) { - docIDs[buffered] = doc; - scores[buffered] = scorer.score(); - freqs[buffered] = scorer.freq(); - - if (++buffered == bufferSize) { - shuffle(docIDs, scores, freqs, buffered); - flush(docIDs, scores, freqs, buffered, fake, collector); - buffered = 0; - } - doc = scorer.nextDoc(); - } - - shuffle(docIDs, scores, freqs, buffered); - flush(docIDs, scores, freqs, buffered, fake, collector); - - return doc != Scorer.NO_MORE_DOCS; + @Override + public void score(LeafCollector collector) throws IOException { + final RandomOrderCollector randomCollector = new RandomOrderCollector(random, collector); + in.score(randomCollector); + randomCollector.flush(); } @Override public String toString() { - return "AssertingBulkOutOfOrderScorer(" + scorer + ")"; + return "AssertingBulkOutOfOrderScorer(" + in + ")"; } } diff --git a/lucene/test-framework/src/java/org/apache/lucene/search/AssertingWeight.java b/lucene/test-framework/src/java/org/apache/lucene/search/AssertingWeight.java index 793b396ab7c..b0752473b86 100644 --- a/lucene/test-framework/src/java/org/apache/lucene/search/AssertingWeight.java +++ b/lucene/test-framework/src/java/org/apache/lucene/search/AssertingWeight.java @@ -79,22 +79,20 @@ class AssertingWeight extends Weight { if (AssertingBulkScorer.shouldWrap(inScorer)) { // The incoming scorer already has a specialized // implementation for BulkScorer, so we should use it: - return AssertingBulkScorer.wrap(new Random(random.nextLong()), inScorer); - } else if (scoreDocsInOrder == false && random.nextBoolean()) { + inScorer = AssertingBulkScorer.wrap(new Random(random.nextLong()), inScorer); + } else if (random.nextBoolean()) { + // Let super wrap this.scorer instead, so we use + // AssertingScorer: + inScorer = super.bulkScorer(context, scoreDocsInOrder, acceptDocs); + } + + if (scoreDocsInOrder == false && random.nextBoolean()) { // The caller claims it can handle out-of-order // docs; let's confirm that by pulling docs and // randomly shuffling them before collection: - //Scorer scorer = in.scorer(context, acceptDocs); - Scorer scorer = scorer(context, acceptDocs); - - // Scorer should not be null if bulkScorer wasn't: - assert scorer != null; - return new AssertingBulkOutOfOrderScorer(new Random(random.nextLong()), scorer); - } else { - // Let super wrap this.scorer instead, so we use - // AssertingScorer: - return super.bulkScorer(context, scoreDocsInOrder, acceptDocs); + inScorer = new AssertingBulkOutOfOrderScorer(new Random(random.nextLong()), inScorer); } + return inScorer; } @Override diff --git a/lucene/test-framework/src/java/org/apache/lucene/search/RandomOrderCollector.java b/lucene/test-framework/src/java/org/apache/lucene/search/RandomOrderCollector.java new file mode 100644 index 00000000000..c91835bbe7d --- /dev/null +++ b/lucene/test-framework/src/java/org/apache/lucene/search/RandomOrderCollector.java @@ -0,0 +1,106 @@ +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; + +/** Randomize collection order. Don't forget to call {@link #flush()} when + * collection is finished to collect buffered documents. */ +final class RandomOrderCollector extends FilterLeafCollector { + + final Random random; + Scorer scorer; + FakeScorer fakeScorer; + + int buffered; + final int bufferSize; + final int[] docIDs; + final float[] scores; + final int[] freqs; + + RandomOrderCollector(Random random, LeafCollector in) { + super(in); + if (!in.acceptsDocsOutOfOrder()) { + throw new IllegalArgumentException(); + } + this.random = random; + bufferSize = 1 + random.nextInt(100); + docIDs = new int[bufferSize]; + scores = new float[bufferSize]; + freqs = new int[bufferSize]; + buffered = 0; + } + + @Override + public void setScorer(Scorer scorer) throws IOException { + this.scorer = scorer; + fakeScorer = new FakeScorer(); + in.setScorer(fakeScorer); + } + + private void shuffle() { + for (int i = buffered - 1; i > 0; --i) { + final int other = random.nextInt(i + 1); + + final int tmpDoc = docIDs[i]; + docIDs[i] = docIDs[other]; + docIDs[other] = tmpDoc; + + final float tmpScore = scores[i]; + scores[i] = scores[other]; + scores[other] = tmpScore; + + final int tmpFreq = freqs[i]; + freqs[i] = freqs[other]; + freqs[other] = tmpFreq; + } + } + + public void flush() throws IOException { + shuffle(); + for (int i = 0; i < buffered; ++i) { + fakeScorer.doc = docIDs[i]; + fakeScorer.freq = freqs[i]; + fakeScorer.score = scores[i]; + in.collect(fakeScorer.doc); + } + buffered = 0; + } + + @Override + public void collect(int doc) throws IOException { + docIDs[buffered] = doc; + scores[buffered] = scorer.score(); + try { + freqs[buffered] = scorer.freq(); + } catch (UnsupportedOperationException e) { + freqs[buffered] = -1; + } + if (++buffered == bufferSize) { + flush(); + } + } + + @Override + public boolean acceptsDocsOutOfOrder() { + return in.acceptsDocsOutOfOrder(); + } + +} + diff --git a/lucene/test-framework/src/java/org/apache/lucene/util/LuceneTestCase.java b/lucene/test-framework/src/java/org/apache/lucene/util/LuceneTestCase.java index 0bfc5e64960..9bd0579ea9e 100644 --- a/lucene/test-framework/src/java/org/apache/lucene/util/LuceneTestCase.java +++ b/lucene/test-framework/src/java/org/apache/lucene/util/LuceneTestCase.java @@ -1287,13 +1287,23 @@ public abstract class LuceneTestCase extends Assert { public static IndexSearcher newSearcher(IndexReader r) { return newSearcher(r, true); } - + + /** + * Create a new searcher over the reader. This searcher might randomly use + * threads. + */ + public static IndexSearcher newSearcher(IndexReader r, boolean maybeWrap) { + return newSearcher(r, maybeWrap, true); + } + /** * Create a new searcher over the reader. This searcher might randomly use * threads. if maybeWrap is true, this searcher might wrap the - * reader with one that returns null for getSequentialSubReaders. + * reader with one that returns null for getSequentialSubReaders. If + * wrapWithAssertions is true, this searcher might be an + * {@link AssertingIndexSearcher} instance. */ - public static IndexSearcher newSearcher(IndexReader r, boolean maybeWrap) { + public static IndexSearcher newSearcher(IndexReader r, boolean maybeWrap, boolean wrapWithAssertions) { Random random = random(); if (usually()) { if (maybeWrap) { @@ -1314,7 +1324,12 @@ public abstract class LuceneTestCase extends Assert { throw new AssertionError(e); } } - IndexSearcher ret = random.nextBoolean() ? new AssertingIndexSearcher(random, r) : new AssertingIndexSearcher(random, r.getContext()); + final IndexSearcher ret; + if (wrapWithAssertions) { + ret = random.nextBoolean() ? new AssertingIndexSearcher(random, r) : new AssertingIndexSearcher(random, r.getContext()); + } else { + ret = random.nextBoolean() ? new IndexSearcher(r) : new IndexSearcher(r.getContext()); + } ret.setSimilarity(classEnvRule.similarity); return ret; } else { @@ -1341,9 +1356,16 @@ public abstract class LuceneTestCase extends Assert { } }); } - IndexSearcher ret = random.nextBoolean() - ? new AssertingIndexSearcher(random, r, ex) - : new AssertingIndexSearcher(random, r.getContext(), ex); + IndexSearcher ret; + if (wrapWithAssertions) { + ret = random.nextBoolean() + ? new AssertingIndexSearcher(random, r, ex) + : new AssertingIndexSearcher(random, r.getContext(), ex); + } else { + ret = random.nextBoolean() + ? new IndexSearcher(r, ex) + : new IndexSearcher(r.getContext(), ex); + } ret.setSimilarity(classEnvRule.similarity); return ret; }