/*
 * 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.
 */
package org.apache.lucene.search;

import java.io.IOException;
import java.util.Arrays;

import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.document.StringField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.store.Directory;
import org.apache.lucene.util.LuceneTestCase;
import org.apache.lucene.util.TestUtil;

public class TestWANDScorer extends LuceneTestCase {

  public void testScalingFactor() {
    doTestScalingFactor(1);
    doTestScalingFactor(2);
    doTestScalingFactor(Math.nextDown(1f));
    doTestScalingFactor(Math.nextUp(1f));
    doTestScalingFactor(Float.MIN_VALUE);
    doTestScalingFactor(Math.nextUp(Float.MIN_VALUE));
    doTestScalingFactor(Float.MAX_VALUE);
    doTestScalingFactor(Math.nextDown(Float.MAX_VALUE));
    assertEquals(WANDScorer.scalingFactor(Float.MIN_VALUE) - 1, WANDScorer.scalingFactor(0));
    assertEquals(WANDScorer.scalingFactor(Float.MAX_VALUE) + 1, WANDScorer.scalingFactor(Float.POSITIVE_INFINITY));
  }

  private void doTestScalingFactor(float f) {
    int scalingFactor = WANDScorer.scalingFactor(f);
    float scaled = Math.scalb(f, scalingFactor);
    assertTrue(""+scaled, scaled > 1 << 15);
    assertTrue(""+scaled, scaled <= 1 << 16);
  }

  private Query maybeWrap(Query query) {
    if (random().nextBoolean()) {
      query = new BlockScoreQueryWrapper(query, TestUtil.nextInt(random(), 2, 8));
      query = new AssertingQuery(random(), query);
    }
    return query;
  }

  public void testBasics() throws Exception {
    Directory dir = newDirectory();
    IndexWriter w = new IndexWriter(dir, newIndexWriterConfig().setMergePolicy(newLogMergePolicy()));
    for (String[] values : Arrays.asList(
        new String[]{ "A", "B" },       // 0
        new String[]{ "A" },            // 1
        new String[]{ },                // 2
        new String[]{ "A", "B", "C" },  // 3
        new String[]{ "B" },            // 4
        new String[]{ "B", "C" }        // 5
        )) {
      Document doc = new Document();
      for (String value : values) {
        doc.add(new StringField("foo", value, Store.NO));
      }
      w.addDocument(doc);
    }
    w.forceMerge(1);
    w.close();

    IndexReader reader = DirectoryReader.open(dir);
    IndexSearcher searcher = newSearcher(reader);

    Query query = new BooleanQuery.Builder()
        .add(new BoostQuery(new ConstantScoreQuery(new TermQuery(new Term("foo", "A"))), 2), Occur.SHOULD)
        .add(new ConstantScoreQuery(new TermQuery(new Term("foo", "B"))), Occur.SHOULD)
        .add(new BoostQuery(new ConstantScoreQuery(new TermQuery(new Term("foo", "C"))), 3), Occur.SHOULD)
        .build();

    Scorer scorer = searcher
        .createWeight(searcher.rewrite(query), ScoreMode.TOP_SCORES, 1)
        .scorer(searcher.getIndexReader().leaves().get(0));

    assertEquals(0, scorer.iterator().nextDoc());
    assertEquals(2 + 1, scorer.score(), 0);

    assertEquals(1, scorer.iterator().nextDoc());
    assertEquals(2, scorer.score(), 0);

    assertEquals(3, scorer.iterator().nextDoc());
    assertEquals(2 + 1 + 3, scorer.score(), 0);

    assertEquals(4, scorer.iterator().nextDoc());
    assertEquals(1, scorer.score(), 0);

    assertEquals(5, scorer.iterator().nextDoc());
    assertEquals(1 + 3, scorer.score(), 0);

    assertEquals(DocIdSetIterator.NO_MORE_DOCS, scorer.iterator().nextDoc());

    scorer = searcher
        .createWeight(searcher.rewrite(query), ScoreMode.TOP_SCORES, 1)
        .scorer(searcher.getIndexReader().leaves().get(0));
    scorer.setMinCompetitiveScore(4);

    assertEquals(3, scorer.iterator().nextDoc());
    assertEquals(2 + 1 + 3, scorer.score(), 0);

    assertEquals(5, scorer.iterator().nextDoc());
    assertEquals(1 + 3, scorer.score(), 0);

    assertEquals(DocIdSetIterator.NO_MORE_DOCS, scorer.iterator().nextDoc());

    scorer = searcher
        .createWeight(searcher.rewrite(query), ScoreMode.TOP_SCORES, 1)
        .scorer(searcher.getIndexReader().leaves().get(0));

    assertEquals(0, scorer.iterator().nextDoc());
    assertEquals(2 + 1, scorer.score(), 0);

    scorer.setMinCompetitiveScore(10);

    assertEquals(DocIdSetIterator.NO_MORE_DOCS, scorer.iterator().nextDoc());

    //  test a filtered disjunction
    query = new BooleanQuery.Builder()
        .add(
            new BooleanQuery.Builder()
            .add(new BoostQuery(new ConstantScoreQuery(new TermQuery(new Term("foo", "A"))), 2), Occur.SHOULD)
            .add(new ConstantScoreQuery(new TermQuery(new Term("foo", "B"))), Occur.SHOULD)
            .build(), Occur.MUST)
        .add(new TermQuery(new Term("foo", "C")), Occur.FILTER)
        .build();

    scorer = searcher
        .createWeight(searcher.rewrite(query), ScoreMode.TOP_SCORES, 1)
        .scorer(searcher.getIndexReader().leaves().get(0));

    assertEquals(3, scorer.iterator().nextDoc());
    assertEquals(2 + 1, scorer.score(), 0);

    assertEquals(5, scorer.iterator().nextDoc());
    assertEquals(1, scorer.score(), 0);

    assertEquals(DocIdSetIterator.NO_MORE_DOCS, scorer.iterator().nextDoc());

    scorer = searcher
        .createWeight(searcher.rewrite(query), ScoreMode.TOP_SCORES, 1)
        .scorer(searcher.getIndexReader().leaves().get(0));

    scorer.setMinCompetitiveScore(2);

    assertEquals(3, scorer.iterator().nextDoc());
    assertEquals(2 + 1, scorer.score(), 0);

    assertEquals(DocIdSetIterator.NO_MORE_DOCS, scorer.iterator().nextDoc());

    // Now test a filtered disjunction with a MUST_NOT
    query = new BooleanQuery.Builder()
        .add(new BoostQuery(new ConstantScoreQuery(new TermQuery(new Term("foo", "A"))), 2), Occur.SHOULD)
        .add(new ConstantScoreQuery(new TermQuery(new Term("foo", "B"))), Occur.SHOULD)
        .add(new TermQuery(new Term("foo", "C")), Occur.MUST_NOT)
        .build();

    scorer = searcher
        .createWeight(searcher.rewrite(query), ScoreMode.TOP_SCORES, 1)
        .scorer(searcher.getIndexReader().leaves().get(0));

    assertEquals(0, scorer.iterator().nextDoc());
    assertEquals(2 + 1, scorer.score(), 0);

    assertEquals(1, scorer.iterator().nextDoc());
    assertEquals(2, scorer.score(), 0);

    assertEquals(4, scorer.iterator().nextDoc());
    assertEquals(1, scorer.score(), 0);

    assertEquals(DocIdSetIterator.NO_MORE_DOCS, scorer.iterator().nextDoc());

    scorer = searcher
        .createWeight(searcher.rewrite(query), ScoreMode.TOP_SCORES, 1)
        .scorer(searcher.getIndexReader().leaves().get(0));

    scorer.setMinCompetitiveScore(3);

    assertEquals(0, scorer.iterator().nextDoc());
    assertEquals(2 + 1, scorer.score(), 0);

    assertEquals(DocIdSetIterator.NO_MORE_DOCS, scorer.iterator().nextDoc());

    reader.close();
    dir.close();
  }

  public void testBasicsWithDisjunctionAndMinShouldMatch() throws Exception {
    try (Directory dir = newDirectory()) {
      try (IndexWriter w =
          new IndexWriter(dir, newIndexWriterConfig().setMergePolicy(newLogMergePolicy()))) {
        for (String[] values :
            Arrays.asList(
                new String[] {"A", "B"}, // 0
                new String[] {"A"}, // 1
                new String[] {}, // 2
                new String[] {"A", "B", "C"}, // 3
                new String[] {"B"}, // 4
                new String[] {"B", "C"} // 5
                )) {
          Document doc = new Document();
          for (String value : values) {
            doc.add(new StringField("foo", value, Store.NO));
          }
          w.addDocument(doc);
        }

        w.forceMerge(1);
      }

      try (IndexReader reader = DirectoryReader.open(dir)) {
        IndexSearcher searcher = newSearcher(reader);

        Query query =
            new BooleanQuery.Builder()
                .add(
                    new BoostQuery(new ConstantScoreQuery(new TermQuery(new Term("foo", "A"))), 2),
                    Occur.SHOULD)
                .add(new ConstantScoreQuery(new TermQuery(new Term("foo", "B"))), Occur.SHOULD)
                .add(
                    new BoostQuery(new ConstantScoreQuery(new TermQuery(new Term("foo", "C"))), 3),
                    Occur.SHOULD)
                .setMinimumNumberShouldMatch(2)
                .build();

        Scorer scorer =
            searcher
                .createWeight(searcher.rewrite(query), ScoreMode.TOP_SCORES, 1)
                .scorer(searcher.getIndexReader().leaves().get(0));

        assertEquals(0, scorer.iterator().nextDoc());
        assertEquals(2 + 1, scorer.score(), 0);

        assertEquals(3, scorer.iterator().nextDoc());
        assertEquals(2 + 1 + 3, scorer.score(), 0);

        assertEquals(5, scorer.iterator().nextDoc());
        assertEquals(1 + 3, scorer.score(), 0);

        assertEquals(DocIdSetIterator.NO_MORE_DOCS, scorer.iterator().nextDoc());

        scorer =
            searcher
                .createWeight(searcher.rewrite(query), ScoreMode.TOP_SCORES, 1)
                .scorer(searcher.getIndexReader().leaves().get(0));
        scorer.setMinCompetitiveScore(4);

        assertEquals(3, scorer.iterator().nextDoc());
        assertEquals(2 + 1 + 3, scorer.score(), 0);

        assertEquals(5, scorer.iterator().nextDoc());
        assertEquals(1 + 3, scorer.score(), 0);

        assertEquals(DocIdSetIterator.NO_MORE_DOCS, scorer.iterator().nextDoc());

        scorer =
            searcher
                .createWeight(searcher.rewrite(query), ScoreMode.TOP_SCORES, 1)
                .scorer(searcher.getIndexReader().leaves().get(0));

        assertEquals(0, scorer.iterator().nextDoc());
        assertEquals(2 + 1, scorer.score(), 0);

        scorer.setMinCompetitiveScore(10);

        assertEquals(DocIdSetIterator.NO_MORE_DOCS, scorer.iterator().nextDoc());
      }
    }
  }

  public void testBasicsWithDisjunctionAndMinShouldMatchAndTailSizeCondition() throws Exception {
    try (Directory dir = newDirectory()) {
      try (IndexWriter w =
          new IndexWriter(dir, newIndexWriterConfig().setMergePolicy(newLogMergePolicy()))) {
        for (String[] values :
            Arrays.asList(
                new String[] {"A", "B"}, // 0
                new String[] {"A"}, // 1
                new String[] {}, // 2
                new String[] {"A", "B", "C"}, // 3
                // 2 "B"s here and the non constant score term query below forces the
                // tailMaxScore >= minCompetitiveScore && tailSize < minShouldMatch condition
                new String[] {"B", "B"}, // 4
                new String[] {"B", "C"} // 5
                )) {
          Document doc = new Document();
          for (String value : values) {
            doc.add(new StringField("foo", value, Store.NO));
          }
          w.addDocument(doc);
        }

        w.forceMerge(1);
      }

      try (IndexReader reader = DirectoryReader.open(dir)) {
        IndexSearcher searcher = newSearcher(reader);

        Query query =
            new BooleanQuery.Builder()
                .add(new TermQuery(new Term("foo", "A")), Occur.SHOULD)
                .add(new TermQuery(new Term("foo", "B")), Occur.SHOULD)
                .add(new TermQuery(new Term("foo", "C")), Occur.SHOULD)
                .setMinimumNumberShouldMatch(2)
                .build();

        Scorer scorer =
            searcher
                .createWeight(searcher.rewrite(query), ScoreMode.TOP_SCORES, 1)
                .scorer(searcher.getIndexReader().leaves().get(0));

        assertEquals(0, scorer.iterator().nextDoc());
        scorer.setMinCompetitiveScore(scorer.score());

        assertEquals(3, scorer.iterator().nextDoc());
      }
    }
  }

  public void testBasicsWithDisjunctionAndMinShouldMatchAndNonScoringMode() throws Exception {
    try (Directory dir = newDirectory()) {
      try (IndexWriter w =
          new IndexWriter(dir, newIndexWriterConfig().setMergePolicy(newLogMergePolicy()))) {
        for (String[] values :
            Arrays.asList(
                new String[] {"A", "B"}, // 0
                new String[] {"A"}, // 1
                new String[] {}, // 2
                new String[] {"A", "B", "C"}, // 3
                new String[] {"B"}, // 4
                new String[] {"B", "C"} // 5
                )) {
          Document doc = new Document();
          for (String value : values) {
            doc.add(new StringField("foo", value, Store.NO));
          }
          w.addDocument(doc);
        }

        w.forceMerge(1);
      }

      try (IndexReader reader = DirectoryReader.open(dir)) {
        IndexSearcher searcher = newSearcher(reader);

        Query query =
            new BooleanQuery.Builder()
                .add(
                    new BoostQuery(new ConstantScoreQuery(new TermQuery(new Term("foo", "A"))), 2),
                    Occur.SHOULD)
                .add(new ConstantScoreQuery(new TermQuery(new Term("foo", "B"))), Occur.SHOULD)
                .add(
                    new BoostQuery(new ConstantScoreQuery(new TermQuery(new Term("foo", "C"))), 3),
                    Occur.SHOULD)
                .setMinimumNumberShouldMatch(2)
                .build();

        Scorer scorer =
            searcher
                .createWeight(searcher.rewrite(query), ScoreMode.COMPLETE_NO_SCORES, 1)
                .scorer(searcher.getIndexReader().leaves().get(0));

        assertEquals(0, scorer.iterator().nextDoc());
        assertEquals(3, scorer.iterator().nextDoc());
        assertEquals(5, scorer.iterator().nextDoc());
        assertEquals(DocIdSetIterator.NO_MORE_DOCS, scorer.iterator().nextDoc());
      }
    }
  }

  public void testBasicsWithFilteredDisjunctionAndMinShouldMatch() throws Exception {
    try (Directory dir = newDirectory()) {
      try (IndexWriter w =
          new IndexWriter(dir, newIndexWriterConfig().setMergePolicy(newLogMergePolicy()))) {
        for (String[] values :
            Arrays.asList(
                new String[] {"A", "B"}, // 0
                new String[] {"A", "C", "D"}, // 1
                new String[] {}, // 2
                new String[] {"A", "B", "C", "D"}, // 3
                new String[] {"B"}, // 4
                new String[] {"C", "D"} // 5
                )) {
          Document doc = new Document();
          for (String value : values) {
            doc.add(new StringField("foo", value, Store.NO));
          }
          w.addDocument(doc);
        }

        w.forceMerge(1);
      }

      try (IndexReader reader = DirectoryReader.open(dir)) {
        IndexSearcher searcher = newSearcher(reader);

        Query query =
            new BooleanQuery.Builder()
                .add(
                    new BooleanQuery.Builder()
                        .add(
                            new BoostQuery(
                                new ConstantScoreQuery(new TermQuery(new Term("foo", "A"))), 2),
                            Occur.SHOULD)
                        .add(
                            new ConstantScoreQuery(new TermQuery(new Term("foo", "B"))),
                            Occur.SHOULD)
                        .add(
                            new BoostQuery(
                                new ConstantScoreQuery(new TermQuery(new Term("foo", "D"))), 4),
                            Occur.SHOULD)
                        .setMinimumNumberShouldMatch(2)
                        .build(),
                    Occur.MUST)
                .add(new TermQuery(new Term("foo", "C")), Occur.FILTER)
                .build();

        Scorer scorer =
            searcher
                .createWeight(searcher.rewrite(query), ScoreMode.TOP_SCORES, 1)
                .scorer(searcher.getIndexReader().leaves().get(0));

        assertEquals(1, scorer.iterator().nextDoc());
        assertEquals(2 + 4, scorer.score(), 0);

        assertEquals(3, scorer.iterator().nextDoc());
        assertEquals(2 + 1 + 4, scorer.score(), 0);

        assertEquals(DocIdSetIterator.NO_MORE_DOCS, scorer.iterator().nextDoc());

        scorer =
            searcher
                .createWeight(searcher.rewrite(query), ScoreMode.TOP_SCORES, 1)
                .scorer(searcher.getIndexReader().leaves().get(0));

        scorer.setMinCompetitiveScore(2 + 1 + 4);

        assertEquals(3, scorer.iterator().nextDoc());
        assertEquals(2 + 1 + 4, scorer.score(), 0);

        assertEquals(DocIdSetIterator.NO_MORE_DOCS, scorer.iterator().nextDoc());
      }
    }
  }

  public void testBasicsWithFilteredDisjunctionAndMinShouldMatchAndNonScoringMode()
      throws Exception {
    try (Directory dir = newDirectory()) {
      try (IndexWriter w =
          new IndexWriter(dir, newIndexWriterConfig().setMergePolicy(newLogMergePolicy()))) {
        for (String[] values :
            Arrays.asList(
                new String[] {"A", "B"}, // 0
                new String[] {"A", "C", "D"}, // 1
                new String[] {}, // 2
                new String[] {"A", "B", "C", "D"}, // 3
                new String[] {"B"}, // 4
                new String[] {"C", "D"} // 5
                )) {
          Document doc = new Document();
          for (String value : values) {
            doc.add(new StringField("foo", value, Store.NO));
          }
          w.addDocument(doc);
        }

        w.forceMerge(1);
      }

      try (IndexReader reader = DirectoryReader.open(dir)) {
        IndexSearcher searcher = newSearcher(reader);

        Query query =
            new BooleanQuery.Builder()
                .add(
                    new BooleanQuery.Builder()
                        .add(
                            new BoostQuery(
                                new ConstantScoreQuery(new TermQuery(new Term("foo", "A"))), 2),
                            Occur.SHOULD)
                        .add(
                            new ConstantScoreQuery(new TermQuery(new Term("foo", "B"))),
                            Occur.SHOULD)
                        .add(
                            new BoostQuery(
                                new ConstantScoreQuery(new TermQuery(new Term("foo", "D"))), 4),
                            Occur.SHOULD)
                        .setMinimumNumberShouldMatch(2)
                        .build(),
                    Occur.MUST)
                .add(new TermQuery(new Term("foo", "C")), Occur.FILTER)
                .build();

        Scorer scorer =
            searcher
                .createWeight(searcher.rewrite(query), ScoreMode.TOP_DOCS, 1)
                .scorer(searcher.getIndexReader().leaves().get(0));

        assertEquals(1, scorer.iterator().nextDoc());
        assertEquals(3, scorer.iterator().nextDoc());
        assertEquals(DocIdSetIterator.NO_MORE_DOCS, scorer.iterator().nextDoc());
      }
    }
  }

  public void testBasicsWithFilteredDisjunctionAndMustNotAndMinShouldMatch() throws Exception {
    try (Directory dir = newDirectory()) {
      try (IndexWriter w =
          new IndexWriter(dir, newIndexWriterConfig().setMergePolicy(newLogMergePolicy()))) {
        for (String[] values :
            Arrays.asList(
                new String[] {"A", "B"}, // 0
                new String[] {"A", "C", "D"}, // 1
                new String[] {}, // 2
                new String[] {"A", "B", "C", "D"}, // 3
                new String[] {"B", "D"}, // 4
                new String[] {"C", "D"} // 5
                )) {
          Document doc = new Document();
          for (String value : values) {
            doc.add(new StringField("foo", value, Store.NO));
          }
          w.addDocument(doc);
        }

        w.forceMerge(1);
      }

      try (IndexReader reader = DirectoryReader.open(dir)) {
        IndexSearcher searcher = newSearcher(reader);

        Query query =
            new BooleanQuery.Builder()
                .add(
                    new BoostQuery(new ConstantScoreQuery(new TermQuery(new Term("foo", "A"))), 2),
                    Occur.SHOULD)
                .add(new ConstantScoreQuery(new TermQuery(new Term("foo", "B"))), Occur.SHOULD)
                .add(new TermQuery(new Term("foo", "C")), Occur.MUST_NOT)
                .add(
                    new BoostQuery(new ConstantScoreQuery(new TermQuery(new Term("foo", "D"))), 4),
                    Occur.SHOULD)
                .setMinimumNumberShouldMatch(2)
                .build();

        Scorer scorer =
            searcher
                .createWeight(searcher.rewrite(query), ScoreMode.TOP_SCORES, 1)
                .scorer(searcher.getIndexReader().leaves().get(0));

        assertEquals(0, scorer.iterator().nextDoc());
        assertEquals(2 + 1, scorer.score(), 0);

        assertEquals(4, scorer.iterator().nextDoc());
        assertEquals(1 + 4, scorer.score(), 0);

        assertEquals(DocIdSetIterator.NO_MORE_DOCS, scorer.iterator().nextDoc());

        scorer =
            searcher
                .createWeight(searcher.rewrite(query), ScoreMode.TOP_SCORES, 1)
                .scorer(searcher.getIndexReader().leaves().get(0));

        scorer.setMinCompetitiveScore(4);

        assertEquals(4, scorer.iterator().nextDoc());
        assertEquals(1 + 4, scorer.score(), 0);

        assertEquals(DocIdSetIterator.NO_MORE_DOCS, scorer.iterator().nextDoc());
      }
    }
  }

  public void testBasicsWithFilteredDisjunctionAndMustNotAndMinShouldMatchAndNonScoringMode()
      throws Exception {
    try (Directory dir = newDirectory()) {
      try (IndexWriter w =
          new IndexWriter(dir, newIndexWriterConfig().setMergePolicy(newLogMergePolicy()))) {
        for (String[] values :
            Arrays.asList(
                new String[] {"A", "B"}, // 0
                new String[] {"A", "C", "D"}, // 1
                new String[] {}, // 2
                new String[] {"A", "B", "C", "D"}, // 3
                new String[] {"B", "D"}, // 4
                new String[] {"C", "D"} // 5
                )) {
          Document doc = new Document();
          for (String value : values) {
            doc.add(new StringField("foo", value, Store.NO));
          }
          w.addDocument(doc);
        }

        w.forceMerge(1);
      }

      try (IndexReader reader = DirectoryReader.open(dir)) {
        IndexSearcher searcher = newSearcher(reader);

        Query query =
            new BooleanQuery.Builder()
                .add(
                    new BoostQuery(new ConstantScoreQuery(new TermQuery(new Term("foo", "A"))), 2),
                    Occur.SHOULD)
                .add(new ConstantScoreQuery(new TermQuery(new Term("foo", "B"))), Occur.SHOULD)
                .add(new TermQuery(new Term("foo", "C")), Occur.MUST_NOT)
                .add(
                    new BoostQuery(new ConstantScoreQuery(new TermQuery(new Term("foo", "D"))), 4),
                    Occur.SHOULD)
                .setMinimumNumberShouldMatch(2)
                .build();

        Scorer scorer =
            searcher
                .createWeight(searcher.rewrite(query), ScoreMode.COMPLETE_NO_SCORES, 1)
                .scorer(searcher.getIndexReader().leaves().get(0));

        assertEquals(0, scorer.iterator().nextDoc());
        assertEquals(4, scorer.iterator().nextDoc());
        assertEquals(DocIdSetIterator.NO_MORE_DOCS, scorer.iterator().nextDoc());
      }
    }
  }

  public void testRandom() throws IOException {
    Directory dir = newDirectory();
    IndexWriter w = new IndexWriter(dir, newIndexWriterConfig());
    int numDocs = atLeast(1000);
    for (int i = 0; i < numDocs; ++i) {
      Document doc = new Document();
      int numValues = random().nextInt(1 << random().nextInt(5));
      int start = random().nextInt(10);
      for (int j = 0; j < numValues; ++j) {
        doc.add(new StringField("foo", Integer.toString(start + j), Store.NO));
      }
      w.addDocument(doc);
    }
    IndexReader reader = DirectoryReader.open(w);
    w.close();
    IndexSearcher searcher = newSearcher(reader);

    for (int iter = 0; iter < 100; ++iter) {
      int start = random().nextInt(10);
      int numClauses = random().nextInt(1 << random().nextInt(5));
      BooleanQuery.Builder builder = new BooleanQuery.Builder();
      for (int i = 0; i < numClauses; ++i) {
        builder.add(maybeWrap(new TermQuery(new Term("foo", Integer.toString(start + i)))), Occur.SHOULD);
      }
      Query query = builder.build();

      CheckHits.checkTopScores(random(), query, searcher);

      int filterTerm = random().nextInt(30);
      Query filteredQuery = new BooleanQuery.Builder()
          .add(query, Occur.MUST)
          .add(new TermQuery(new Term("foo", Integer.toString(filterTerm))), Occur.FILTER)
          .build();

      CheckHits.checkTopScores(random(), filteredQuery, searcher);
    }
    reader.close();
    dir.close();
  }

  public void testRandomWithInfiniteMaxScore() throws IOException {
    Directory dir = newDirectory();
    IndexWriter w = new IndexWriter(dir, newIndexWriterConfig());
    int numDocs = atLeast(1000);
    for (int i = 0; i < numDocs; ++i) {
      Document doc = new Document();
      int numValues = random().nextInt(1 << random().nextInt(5));
      int start = random().nextInt(10);
      for (int j = 0; j < numValues; ++j) {
        doc.add(new StringField("foo", Integer.toString(start + j), Store.NO));
      }
      w.addDocument(doc);
    }
    IndexReader reader = DirectoryReader.open(w);
    w.close();
    IndexSearcher searcher = newSearcher(reader);

    for (int iter = 0; iter < 100; ++iter) {
      int start = random().nextInt(10);
      int numClauses = random().nextInt(1 << random().nextInt(5));
      BooleanQuery.Builder builder = new BooleanQuery.Builder();
      for (int i = 0; i < numClauses; ++i) {
        Query query = new TermQuery(new Term("foo", Integer.toString(start + i)));
        if (random().nextBoolean()) {
          query = new InfiniteMaxScoreWrapperQuery(query, numDocs / TestUtil.nextInt(random(), 1, 100));
        }
        builder.add(query, Occur.SHOULD);
      }
      Query query = builder.build();

      CheckHits.checkTopScores(random(), query, searcher);

      int filterTerm = random().nextInt(30);
      Query filteredQuery = new BooleanQuery.Builder()
          .add(query, Occur.MUST)
          .add(new TermQuery(new Term("foo", Integer.toString(filterTerm))), Occur.FILTER)
          .build();

      CheckHits.checkTopScores(random(), filteredQuery, searcher);
    }
    reader.close();
    dir.close();
  }

  private static class InfiniteMaxScoreWrapperScorer extends FilterScorer {

    private final int maxRange;
    private int lastShallowTarget = -1;

    InfiniteMaxScoreWrapperScorer(Scorer scorer, int maxRange) {
      super(scorer);
      this.maxRange = maxRange;
    }

    @Override
    public int advanceShallow(int target) throws IOException {
      lastShallowTarget = target;
      return in.advanceShallow(target);
    }

    @Override
    public float getMaxScore(int upTo) throws IOException {
      if (upTo - Math.max(docID(), lastShallowTarget) >= maxRange) {
        return Float.POSITIVE_INFINITY;
      }
      return in.getMaxScore(upTo);
    }

  }

  private static class InfiniteMaxScoreWrapperQuery extends Query {

    private final Query query;
    private final int maxRange;
    
    /**
     * If asked for the maximum score over a range of doc IDs that is greater
     * than or equal to maxRange, this query will return a maximum score of +Infty
     */
    InfiniteMaxScoreWrapperQuery(Query query, int maxRange) {
      this.query = query;
      this.maxRange = maxRange;
    }
    
    @Override
    public String toString(String field) {
      return query.toString(field);
    }

    @Override
    public boolean equals(Object obj) {
      return sameClassAs(obj) && query.equals(((InfiniteMaxScoreWrapperQuery) obj).query);
    }

    @Override
    public int hashCode() {
      return 31 * classHash() + query.hashCode();
    }

    @Override
    public Query rewrite(IndexReader reader) throws IOException {
      Query rewritten = query.rewrite(reader);
      if (rewritten != query) {
        return new InfiniteMaxScoreWrapperQuery(rewritten, maxRange);
      }
      return super.rewrite(reader);
    }

    @Override
    public void visit(QueryVisitor visitor) {

    }

    @Override
    public Weight createWeight(IndexSearcher searcher, ScoreMode scoreMode, float boost) throws IOException {
      return new FilterWeight(query.createWeight(searcher, scoreMode, boost)) {
        @Override
        public Scorer scorer(LeafReaderContext context) throws IOException {
          Scorer scorer = super.scorer(context);
          if (scorer == null) {
            return null;
          } else {
            return new InfiniteMaxScoreWrapperScorer(scorer, maxRange);
          }
        }

        @Override
        public ScorerSupplier scorerSupplier(LeafReaderContext context) throws IOException {
          ScorerSupplier supplier = super.scorerSupplier(context);
          if (supplier == null) {
            return null;
          } else {
            return new ScorerSupplier() {
              
              @Override
              public Scorer get(long leadCost) throws IOException {
                return new InfiniteMaxScoreWrapperScorer(supplier.get(leadCost), maxRange);
              }
              
              @Override
              public long cost() {
                return supplier.cost();
              }
            };
          }
        }
      };
    }
  }

}
