void testSorting(int32_t precisionStep) {
     RandomPtr rnd = newLucene<Random>();
     String field = L"field" + StringUtils::toString(precisionStep);
     // 10 random tests, the index order is ascending, so using a reverse sort field should return descending documents
     for (int32_t i = 0; i < 10; ++i) {
         int32_t lower = (int32_t)(rnd->nextDouble() * noDocs * distance) + startOffset;
         int32_t upper = (int32_t)(rnd->nextDouble() * noDocs * distance) + startOffset;
         if (lower > upper) {
             std::swap(lower, upper);
         }
         QueryPtr tq = NumericRangeQuery::newIntRange(field, precisionStep, lower, upper, true, true);
         TopDocsPtr topDocs = searcher->search(tq, FilterPtr(), noDocs, newLucene<Sort>(newLucene<SortField>(field, SortField::INT, true)));
         if (topDocs->totalHits == 0) {
             continue;
         }
         Collection<ScoreDocPtr> sd = topDocs->scoreDocs;
         EXPECT_TRUE(sd);
         int32_t last = StringUtils::toInt(searcher->doc(sd[0]->doc)->get(field));
         for (int32_t j = 1; j < sd.size(); ++j) {
             int32_t act = StringUtils::toInt(searcher->doc(sd[j]->doc)->get(field));
             EXPECT_TRUE(last > act);
             last = act;
         }
     }
 }
 void testRightOpenRange(int32_t precisionStep) {
     String field = L"field" + StringUtils::toString(precisionStep);
     int32_t count = 3000;
     int32_t lower = (count - 1) * distance + (distance / 3) + startOffset;
     NumericRangeQueryPtr q = NumericRangeQuery::newIntRange(field, precisionStep, lower, INT_MAX, true, true);
     TopDocsPtr topDocs = searcher->search(q, FilterPtr(), noDocs, Sort::INDEXORDER());
     Collection<ScoreDocPtr> sd = topDocs->scoreDocs;
     EXPECT_TRUE(sd);
     EXPECT_EQ(noDocs - count, sd.size());
     DocumentPtr doc = searcher->doc(sd[0]->doc);
     EXPECT_EQ(StringUtils::toString(count * distance + startOffset), doc->get(field));
     doc = searcher->doc(sd[sd.size() - 1]->doc);
     EXPECT_EQ(StringUtils::toString((noDocs - 1) * distance + startOffset), doc->get(field));
 }
    /// test for both constant score and boolean query, the other tests only use the constant score mode
    void testRange(int32_t precisionStep) {
        String field = L"field" + StringUtils::toString(precisionStep);
        int32_t count = 3000;
        int32_t lower = (distance * 3 / 2) + startOffset;
        int32_t upper = lower + count * distance + (distance / 3);

        NumericRangeQueryPtr q = NumericRangeQuery::newIntRange(field, precisionStep, lower, upper, true, true);
        NumericRangeFilterPtr f = NumericRangeFilter::newIntRange(field, precisionStep, lower, upper, true, true);
        int32_t lastTerms = 0;
        for (uint8_t i = 0; i < 3; ++i) {
            TopDocsPtr topDocs;
            int32_t terms;
            String type;
            q->clearTotalNumberOfTerms();
            f->clearTotalNumberOfTerms();
            switch (i) {
            case 0:
                type = L" (constant score filter rewrite)";
                q->setRewriteMethod(MultiTermQuery::CONSTANT_SCORE_FILTER_REWRITE());
                topDocs = searcher->search(q, FilterPtr(), noDocs, Sort::INDEXORDER());
                terms = q->getTotalNumberOfTerms();
                break;
            case 1:
                type = L" (constant score boolean rewrite)";
                q->setRewriteMethod(MultiTermQuery::CONSTANT_SCORE_BOOLEAN_QUERY_REWRITE());
                topDocs = searcher->search(q, FilterPtr(), noDocs, Sort::INDEXORDER());
                terms = q->getTotalNumberOfTerms();
                break;
            case 2:
                type = L" (filter)";
                topDocs = searcher->search(newLucene<MatchAllDocsQuery>(), f, noDocs, Sort::INDEXORDER());
                terms = f->getTotalNumberOfTerms();
                break;
            default:
                return;
            }
            // std::cout << "Found " << terms << " distinct terms in range for field '" << field << "'" << type << ".";
            Collection<ScoreDocPtr> sd = topDocs->scoreDocs;
            EXPECT_TRUE(sd);
            EXPECT_EQ(count, sd.size());
            DocumentPtr doc = searcher->doc(sd[0]->doc);
            EXPECT_EQ(StringUtils::toString(2 * distance + startOffset), doc->get(field));
            doc = searcher->doc(sd[sd.size() - 1]->doc);
            EXPECT_EQ(StringUtils::toString((1 + count) * distance + startOffset), doc->get(field));
            if (i > 0) {
                EXPECT_EQ(lastTerms, terms);
            }
            lastTerms = terms;
        }
    }
TEST_F(DateSortTest, testReverseDateSort) {
    IndexSearcherPtr searcher = newLucene<IndexSearcher>(directory, true);

    SortPtr sort = newLucene<Sort>(newLucene<SortField>(DATE_TIME_FIELD, SortField::STRING, true));

    QueryParserPtr queryParser = newLucene<QueryParser>(LuceneVersion::LUCENE_CURRENT, TEXT_FIELD, newLucene<WhitespaceAnalyzer>());
    QueryPtr query = queryParser->parse(L"Document");

    // Execute the search and process the search results.
    Collection<String> actualOrder = Collection<String>::newInstance(5);
    Collection<ScoreDocPtr>hits = searcher->search(query, FilterPtr(), 1000, sort)->scoreDocs;
    for (int32_t i = 0; i < hits.size(); ++i) {
        DocumentPtr document = searcher->doc(hits[i]->doc);
        String text = document->get(TEXT_FIELD);
        actualOrder[i] = text;
    }
    searcher->close();

    // Set up the expected order (ie. Document 5, 4, 3, 2, 1).
    Collection<String> expectedOrder = Collection<String>::newInstance(5);
    expectedOrder[0] = L"Document 5";
    expectedOrder[1] = L"Document 4";
    expectedOrder[2] = L"Document 3";
    expectedOrder[3] = L"Document 2";
    expectedOrder[4] = L"Document 1";

    EXPECT_TRUE(expectedOrder.equals(actualOrder));
}
    /// Test that FieldScoreQuery returns docs in expected order.
    void doTestRank(const String& field, FieldScoreQuery::Type tp) {
        IndexSearcherPtr s = newLucene<IndexSearcher>(dir, true);
        QueryPtr q = newLucene<FieldScoreQuery>(field,tp);

        QueryUtils::check(q, s);
        Collection<ScoreDocPtr> h = s->search(q, FilterPtr(), 1000)->scoreDocs;
        EXPECT_EQ(N_DOCS, h.size());
        String prevID = L"ID" + StringUtils::toString(N_DOCS + 1); // greater than all ids of docs in this test
        for (int32_t i = 0; i < h.size(); ++i) {
            String resID = s->doc(h[i]->doc)->get(ID_FIELD);
            EXPECT_TRUE(resID.compare(prevID) < 0);
            prevID = resID;
        }
    }