Example #1
0
void testExtractFromWildcardQuery( CuTest * tc )
{
    Directory *     pIndex  = setUpIndex();
    IndexReader *   pReader = IndexReader::open( pIndex );
    TermSet         termSet;
    WildcardQuery * wildcard;
    Term *          t1;
    Query *         rewrite;


    t1 = _CLNEW Term( _T("data"), _T("aaaa?") );
    wildcard = _CLNEW WildcardQuery( t1 );
    rewrite = wildcard->rewrite( pReader );
    rewrite->extractTerms( &termSet );
    _CLLDECDELETE( t1 );

    assertEqualsMsg( _T( "wrong number of terms" ), 3, termSet.size() );
    for( TermSet::iterator itTerms = termSet.begin(); itTerms != termSet.end(); itTerms++ )
    {
        Term * pTerm = *itTerms;
        if(    0 != _tcscmp( _T( "aaaaa" ), pTerm->text()) 
            && 0 != _tcscmp( _T( "aaaab" ), pTerm->text())
            && 0 != _tcscmp( _T( "aaaac" ), pTerm->text()))
        {
            assertTrueMsg( _T( "wrong term" ), false );
        }
    }

    clearTermSet( termSet );
    if( rewrite != wildcard )
        _CLDELETE( rewrite );
    _CLDELETE( wildcard );
    

    t1 = _CLNEW Term( _T("data"), _T("aaa*") );
    wildcard = _CLNEW WildcardQuery( t1 );
    rewrite = wildcard->rewrite( pReader );
    rewrite->extractTerms( &termSet );
    _CLLDECDELETE( t1 );

    assertEqualsMsg( _T( "wrong number of terms" ), 5, termSet.size() );
    for( TermSet::iterator itTerms = termSet.begin(); itTerms != termSet.end(); itTerms++ )
    {
        Term * pTerm = *itTerms;
        assertTrueMsg( _T( "wrong term" ), ( 0 == _tcsncmp( _T( "aaa" ), pTerm->text(), 3 )));
    }

    clearTermSet( termSet );
    if( rewrite != wildcard )
        _CLDELETE( rewrite );
    _CLDELETE( wildcard );


    pReader->close();
    _CLDELETE( pReader );

    closeIndex( pIndex );
    pIndex = NULL;
}
    void testEqualScores() 
    {
        // NOTE: uses index build in *this* setUp
        
        IndexReader * pReader = IndexReader::open( m_pSmall );
	    IndexSearcher * pSearch = _CLNEW IndexSearcher( pReader );

	    Hits * pResult;

        // some hits match more terms then others, score should be the same
        Query * q = csrq( _T( "data" ), _T( "1" ), _T( "6" ), true, true );
        pResult = pSearch->search( q );
        size_t numHits = pResult->length();
        assertEqualsMsg( _T( "wrong number of results" ), 6, numHits );
        float_t score = pResult->score( 0 );
        for( size_t i = 1; i < numHits; i++ )
        {
            assertTrueMsg( _T( "score was not the same" ), score == pResult->score( i ));
        }
        _CLDELETE( pResult );
        _CLDELETE( q );

        pSearch->close();
        _CLDELETE( pSearch );

        pReader->close();
        _CLDELETE( pReader );
    }
    void testBooleanOrderUnAffected()
    {
        // NOTE: uses index build in *this* setUp

        IndexReader * pReader = IndexReader::open( m_pSmall );
	    IndexSearcher * pSearch = _CLNEW IndexSearcher( pReader );

        // first do a regular RangeQuery which uses term expansion so
        // docs with more terms in range get higher scores
        Term * pLower = _CLNEW Term( _T( "data" ), _T( "1" ));
        Term * pUpper = _CLNEW Term( _T( "data" ), _T( "4" ));
        Query * rq = _CLNEW RangeQuery( pLower, pUpper, true );
        _CLLDECDELETE( pUpper );
        _CLLDECDELETE( pLower );

        Hits * pExpected = pSearch->search( rq );
        size_t numHits = pExpected->length();
 
        // now do a boolean where which also contains a
        // ConstantScoreRangeQuery and make sure the order is the same
        
        BooleanQuery * q = _CLNEW BooleanQuery();
        q->add( rq, true, BooleanClause::MUST );
        q->add( csrq( _T( "data" ), _T( "1" ), _T( "6" ), true, true ), true, BooleanClause::MUST );
 
        Hits * pActual = pSearch->search( q );
        assertEqualsMsg( _T( "wrong number of hits" ), numHits, pActual->length() );
        for( size_t i = 0; i < numHits; i++ )
        {
            assertEqualsMsg( _T( "mismatch in docid for a hit" ), pExpected->id( i ), pActual->id( i ));
        }
        _CLDELETE( pActual );
        _CLDELETE( pExpected );
        _CLDELETE( q );

        pSearch->close();
        _CLDELETE( pSearch );

        pReader->close();
        _CLDELETE( pReader );
    }
Example #4
0
void testExtractFromTermQuery( CuTest * tc )
{
    Directory *     pIndex  = setUpIndex();
    IndexReader *   pReader = IndexReader::open( pIndex );
    TermSet         termSet;
 
    Term * t1 = _CLNEW Term( _T("data"), _T("aaaaa") );
    Term * t2 = _CLNEW Term( _T("data"), _T("bbbbb") );
    Query * q1 = _CLNEW TermQuery( t1 );
    Query * q2 = _CLNEW TermQuery( t2 );
    Query * rewrite1 = q1->rewrite( pReader );
    Query * rewrite2 = q2->rewrite( pReader );

    rewrite1->extractTerms( &termSet );
    assertEqualsMsg( _T( "wrong number of terms" ), 1, termSet.size() );
    assertEqualsMsg( _T( "wrong term" ), 0, t1->compareTo( *(termSet.begin())) );
    clearTermSet( termSet );

    rewrite2->extractTerms( &termSet );
    assertEqualsMsg( _T( "wrong number of terms" ), 1, termSet.size() );
    assertEqualsMsg( _T( "wrong term" ), 0, t2->compareTo( *(termSet.begin())) );
    clearTermSet( termSet );

    _CLLDECDELETE( t1 );
    _CLLDECDELETE( t2 );

    if( q1 != rewrite1 )
        _CLDELETE( rewrite1 );
    _CLDELETE( q1 );
    
    if( q2 != rewrite2 )
        _CLDELETE( rewrite2 );
    _CLDELETE( q2 );
    
    pReader->close();
    _CLDELETE( pReader );

    closeIndex( pIndex );
    pIndex = NULL;
}
Example #5
0
void testExtractFromFuzzyQuery( CuTest * tc )
{
    Directory *     pIndex  = setUpIndex();
    IndexReader *   pReader = IndexReader::open( pIndex );
    TermSet         termSet;
    FuzzyQuery *    fuzzy;
    Term *          t1;
    Query *         rewrite;


    t1 = _CLNEW Term( _T("data"), _T("aaaab") );
    fuzzy = _CLNEW FuzzyQuery( t1, 0.7f );
    rewrite = fuzzy->rewrite( pReader );
    rewrite->extractTerms( &termSet );
    _CLLDECDELETE( t1 );

    assertEqualsMsg( _T( "wrong number of terms" ), 4, termSet.size() );
    for( TermSet::iterator itTerms = termSet.begin(); itTerms != termSet.end(); itTerms++ )
    {
        Term * pTerm = *itTerms;
        if(    0 != _tcscmp( _T( "aaaaa" ), pTerm->text()) 
            && 0 != _tcscmp( _T( "aaaab" ), pTerm->text())
            && 0 != _tcscmp( _T( "aaabb" ), pTerm->text())
            && 0 != _tcscmp( _T( "aaaac" ), pTerm->text()))
        {
            assertTrueMsg( _T( "wrong term" ), false );
        }
    }

    clearTermSet( termSet );
    if( rewrite != fuzzy )
        _CLDELETE( rewrite );
    _CLDELETE( fuzzy );
    
    pReader->close();
    _CLDELETE( pReader );

    closeIndex( pIndex );
    pIndex = NULL;
}
Example #6
0
void testExtractFromBooleanQuery( CuTest * tc )
{
    Directory *     pIndex  = setUpIndex();
    IndexReader *   pReader = IndexReader::open( pIndex );
    TermSet         termSet;
 
    Term * t1 = _CLNEW Term( _T("data"), _T("aaaab") );
    Term * t2 = _CLNEW Term( _T("data"), _T("aaabb") );
    Term * t3 = _CLNEW Term( _T("data"), _T("aaabb") );
    BooleanQuery * bq = _CLNEW BooleanQuery();
    bq->add( _CLNEW TermQuery( t1 ), true, BooleanClause::SHOULD );
    bq->add( _CLNEW TermQuery( t2 ), true, BooleanClause::SHOULD );
    bq->add( _CLNEW TermQuery( t3 ), true, BooleanClause::SHOULD );

    Query * rewrite = bq->rewrite( pReader );

    rewrite->extractTerms( &termSet );
    assertEqualsMsg( _T( "wrong number of terms" ), 2, termSet.size() );
    for( TermSet::iterator itTerms = termSet.begin(); itTerms != termSet.end(); itTerms++ )
    {
        Term * pTerm = *itTerms;
        assertTrueMsg( _T( "wrong term" ), ( 0 == t1->compareTo( pTerm ) || 0 == t2->compareTo( pTerm )));
    }
    clearTermSet( termSet );

    _CLLDECDELETE( t1 );
    _CLLDECDELETE( t2 );
    _CLLDECDELETE( t3 );

    if( rewrite != bq )
        _CLDELETE( rewrite );
    _CLDELETE( bq );
    
    pReader->close();
    _CLDELETE( pReader );

    closeIndex( pIndex );
    pIndex = NULL;
}
    void testRangeFilterId() {

        IndexReader* reader = IndexReader::open(index);
        IndexSearcher* search = new IndexSearcher(reader);

        int medId = ((maxId - minId) / 2);

        std::tstring minIPstr = pad(minId);
        const TCHAR* minIP = minIPstr.c_str();

        std::tstring maxIPstr = pad(maxId);
        const TCHAR* maxIP = maxIPstr.c_str();

        std::tstring medIPstr = pad(medId);
        const TCHAR* medIP = medIPstr.c_str();

        size_t numDocs = static_cast<size_t>(reader->numDocs());

        assertEqualsMsg(_T("num of docs"), numDocs, static_cast<size_t>(1+ maxId - minId));

        Hits* result;
        Term* term = _CLNEW Term(_T("body"),_T("body"));
        Query* q = _CLNEW TermQuery(term);
        _CLDECDELETE(term);

        // test id, bounded on both ends

        Filter* f = _CLNEW RangeFilter(_T("id"),minIP,maxIP,T,T);
        result = search->search(q, f);
        assertEqualsMsg(_T("find all"), numDocs, result->length());
        _CLLDELETE(result);
        _CLLDELETE(f);

        f=_CLNEW RangeFilter(_T("id"),minIP,maxIP,T,F);
        result = search->search(q,f);
        assertEqualsMsg(_T("all but last"), numDocs-1, result->length());
        _CLLDELETE(result);
        _CLLDELETE(f);

        f =_CLNEW RangeFilter(_T("id"),minIP,maxIP,F,T);
        result = search->search(q,f);
        assertEqualsMsg(_T("all but first"), numDocs-1, result->length());
        _CLLDELETE(result);
        _CLLDELETE(f);

        f=_CLNEW RangeFilter(_T("id"),minIP,maxIP,F,F);
        result = search->search(q,f);
        assertEqualsMsg(_T("all but ends"), numDocs-2, result->length());
        _CLLDELETE(result);
        _CLLDELETE(f);

        f=_CLNEW RangeFilter(_T("id"),medIP,maxIP,T,T);
        result = search->search(q,f);
        assertEqualsMsg(_T("med and up"), 1+ maxId-medId, result->length());
        _CLLDELETE(result);
        _CLLDELETE(f);

        f=_CLNEW RangeFilter(_T("id"),minIP,medIP,T,T);
        result = search->search(q,f);
        assertEqualsMsg(_T("up to med"), 1+ medId-minId, result->length());
        _CLLDELETE(result);
        _CLLDELETE(f);

        // unbounded id

        f=_CLNEW RangeFilter(_T("id"),minIP,NULL,T,F);
        result = search->search(q,f);
        assertEqualsMsg(_T("min and up"), numDocs, result->length());
        _CLLDELETE(result);
        _CLLDELETE(f);

        f=_CLNEW RangeFilter(_T("id"),NULL,maxIP,F,T);
        result = search->search(q,f);
        assertEqualsMsg(_T("max and down"), numDocs, result->length());
        _CLLDELETE(result);
        _CLLDELETE(f);

        f=_CLNEW RangeFilter(_T("id"),minIP,NULL,F,F);
        result = search->search(q,f);
        assertEqualsMsg(_T("not min, but up"), numDocs-1, result->length());
        _CLLDELETE(result);
        _CLLDELETE(f);

        f=_CLNEW RangeFilter(_T("id"),NULL,maxIP,F,F);
        result = search->search(q,f);
        assertEqualsMsg(_T("not max, but down"), numDocs-1, result->length());
        _CLLDELETE(result);
        _CLLDELETE(f);

        f=_CLNEW RangeFilter(_T("id"),medIP,maxIP,T,F);
        result = search->search(q,f);
        assertEqualsMsg(_T("med and up, not max"), maxId-medId, result->length());
        _CLLDELETE(result);
        _CLLDELETE(f);

        f=_CLNEW RangeFilter(_T("id"),minIP,medIP,F,T);
        result = search->search(q,f);
        assertEqualsMsg(_T("not min, up to med"), medId-minId, result->length());
        _CLLDELETE(result);
        _CLLDELETE(f);

        // very small sets

        f=_CLNEW RangeFilter(_T("id"),minIP,minIP,F,F);
        result = search->search(q,f);
        assertEqualsMsg(_T("min,min,F,F"), 0, result->length());
        _CLLDELETE(result); _CLLDELETE(f);
        f=_CLNEW RangeFilter(_T("id"),medIP,medIP,F,F);
        result = search->search(q,f);
        assertEqualsMsg(_T("med,med,F,F"), 0, result->length());
        _CLLDELETE(result); _CLLDELETE(f);
        f=_CLNEW RangeFilter(_T("id"),maxIP,maxIP,F,F);
        result = search->search(q,f);
        assertEqualsMsg(_T("max,max,F,F"), 0, result->length());
        _CLLDELETE(result); _CLLDELETE(f);

        f=_CLNEW RangeFilter(_T("id"),minIP,minIP,T,T);
        result = search->search(q,f);
        assertEqualsMsg(_T("min,min,T,T"), 1, result->length());
        _CLLDELETE(result); _CLLDELETE(f);
        f=_CLNEW RangeFilter(_T("id"),NULL,minIP,F,T);
        result = search->search(q,f);
        assertEqualsMsg(_T("nul,min,F,T"), 1, result->length());
        _CLLDELETE(result); _CLLDELETE(f);

        f=_CLNEW RangeFilter(_T("id"),maxIP,maxIP,T,T);
        result = search->search(q,f);
        assertEqualsMsg(_T("max,max,T,T"), 1, result->length());
        _CLLDELETE(result); _CLLDELETE(f);
        f=_CLNEW RangeFilter(_T("id"),maxIP,NULL,T,F);
        result = search->search(q,f);
        assertEqualsMsg(_T("max,nul,T,T"), 1, result->length());
        _CLLDELETE(result); _CLLDELETE(f);

        f=_CLNEW RangeFilter(_T("id"),medIP,medIP,T,T);
        result = search->search(q,f);
        assertEqualsMsg(_T("med,med,T,T"), 1, result->length());
        _CLLDELETE(result); _CLLDELETE(f);

        search->close();
        _CLLDELETE(search);

        reader->close();
        _CLLDELETE(reader);

        _CLLDELETE(q);
    }
    void testRangeFilterRand()
    {
        IndexReader* reader = IndexReader::open(index);
        IndexSearcher* search = _CLNEW IndexSearcher(reader);

        std::tstring minRPstr = pad(minR);
        const TCHAR* minRP = minRPstr.c_str();
        
        std::tstring maxRPstr = pad(maxR);
        const TCHAR* maxRP = maxRPstr.c_str();

        size_t numDocs = static_cast<size_t>(reader->numDocs());

        assertEqualsMsg(_T("num of docs"), numDocs, 1+ maxId - minId);

        Hits* result;
        Term* term = _CLNEW Term(_T("body"),_T("body"));
        Query* q = _CLNEW TermQuery(term);
        _CLDECDELETE(term);

        // test extremes, bounded on both ends

        Filter* f = _CLNEW RangeFilter(_T("rand"),minRP,maxRP,T,T);
        result = search->search(q,f);
        assertEqualsMsg(_T("find all"), numDocs, result->length());
        _CLLDELETE(result); _CLLDELETE(f);

        f=_CLNEW RangeFilter(_T("rand"),minRP,maxRP,T,F);
        result = search->search(q,f);
        assertEqualsMsg(_T("all but biggest"), numDocs-1, result->length());
        _CLLDELETE(result); _CLLDELETE(f);

        f=_CLNEW RangeFilter(_T("rand"),minRP,maxRP,F,T);
        result = search->search(q,f);
        assertEqualsMsg(_T("all but smallest"), numDocs-1, result->length());
        _CLLDELETE(result); _CLLDELETE(f);

        f=_CLNEW RangeFilter(_T("rand"),minRP,maxRP,F,F);
        result = search->search(q,f);
        assertEqualsMsg(_T("all but extremes"), numDocs-2, result->length());
        _CLLDELETE(result); _CLLDELETE(f);

        // unbounded

        f=_CLNEW RangeFilter(_T("rand"),minRP,NULL,T,F);
        result = search->search(q,f);
        assertEqualsMsg(_T("smallest and up"), numDocs, result->length());
        _CLLDELETE(result); _CLLDELETE(f);

        f=_CLNEW RangeFilter(_T("rand"),NULL,maxRP,F,T);
        result = search->search(q,f);
        assertEqualsMsg(_T("biggest and down"), numDocs, result->length());
        _CLLDELETE(result); _CLLDELETE(f);

        f=_CLNEW RangeFilter(_T("rand"),minRP,NULL,F,F);
        result = search->search(q,f);
        assertEqualsMsg(_T("not smallest, but up"), numDocs-1, result->length());
        _CLLDELETE(result); _CLLDELETE(f);

        f=_CLNEW RangeFilter(_T("rand"),NULL,maxRP,F,F);
        result = search->search(q,f);
        assertEqualsMsg(_T("not biggest, but down"), numDocs-1, result->length());
        _CLLDELETE(result); _CLLDELETE(f);

        // very small sets

        f=_CLNEW RangeFilter(_T("rand"),minRP,minRP,F,F);
        result = search->search(q,f);
        assertEqualsMsg(_T("min,min,F,F"), 0, result->length());
        _CLLDELETE(result); _CLLDELETE(f);
        f=_CLNEW RangeFilter(_T("rand"),maxRP,maxRP,F,F);
        result = search->search(q,f);
        assertEqualsMsg(_T("max,max,F,F"), 0, result->length());
        _CLLDELETE(result); _CLLDELETE(f);

        f=_CLNEW RangeFilter(_T("rand"),minRP,minRP,T,T);
        result = search->search(q,f);
        assertEqualsMsg(_T("min,min,T,T"), 1, result->length());
        _CLLDELETE(result); _CLLDELETE(f);
        f=_CLNEW RangeFilter(_T("rand"),NULL,minRP,F,T);
        result = search->search(q,f);
        assertEqualsMsg(_T("nul,min,F,T"), 1, result->length());
        _CLLDELETE(result); _CLLDELETE(f);

        f=_CLNEW RangeFilter(_T("rand"),maxRP,maxRP,T,T);
        result = search->search(q,f);
        assertEqualsMsg(_T("max,max,T,T"), 1, result->length());
        _CLLDELETE(result); _CLLDELETE(f);
        f=_CLNEW RangeFilter(_T("rand"),maxRP,NULL,T,F);
        result = search->search(q,f);
        assertEqualsMsg(_T("max,nul,T,T"), 1, result->length());
        _CLLDELETE(result); _CLLDELETE(f);

        search->close();
        _CLLDELETE(search);

        reader->close();
        _CLLDELETE(reader);

        _CLLDELETE(q);
    }
    void testRangeQueryRand()
    {
        // NOTE: uses index build in *super* setUp

        IndexReader * pReader = IndexReader::open( index );
	    IndexSearcher * pSearch = _CLNEW IndexSearcher( pReader );

        std::tstring sMinRP = pad(minR);
        std::tstring sMaxRP = pad(maxR);
        const TCHAR* minRP = sMinRP.c_str();
        const TCHAR* maxRP = sMaxRP.c_str();
    
        size_t numDocs = static_cast<size_t>( pReader->numDocs() );
        assertEqualsMsg( _T("num of docs"), numDocs, static_cast<size_t>(1+ maxId - minId));
        
    	Hits * pResult;
        Query * q;

        // test extremes, bounded on both ends
        
        q = csrq( _T( "rand" ), minRP, maxRP, true, true );
	    pResult = pSearch->search( q );
        assertEqualsMsg( _T( "find all" ), numDocs, pResult->length());
        _CLDELETE( pResult ); _CLDELETE( q );

        q = csrq( _T( "rand" ), minRP, maxRP, true, false );
	    pResult = pSearch->search( q );
        assertEqualsMsg( _T( "all but biggest" ), numDocs-1, pResult->length());
        _CLDELETE( pResult ); _CLDELETE( q );

        q = csrq( _T( "rand" ), minRP, maxRP, false, true );
	    pResult = pSearch->search( q );
        assertEqualsMsg( _T( "all but smallest" ), numDocs-1, pResult->length());
        _CLDELETE( pResult ); _CLDELETE( q );

        q = csrq( _T( "rand" ), minRP, maxRP, false, false );
	    pResult = pSearch->search( q );
        assertEqualsMsg( _T( "all but extremes" ), numDocs-2, pResult->length());
        _CLDELETE( pResult ); _CLDELETE( q );
    
        // unbounded

        q = csrq( _T( "rand" ), minRP, NULL, true, false );
	    pResult = pSearch->search( q );
        assertEqualsMsg( _T( "smallest and up" ), numDocs, pResult->length());
        _CLDELETE( pResult ); _CLDELETE( q );

        q = csrq( _T( "rand" ), NULL, maxRP, false, true );
	    pResult = pSearch->search( q );
        assertEqualsMsg( _T( "biggest and down" ), numDocs, pResult->length());
        _CLDELETE( pResult ); _CLDELETE( q );

        q = csrq( _T( "rand" ), minRP, NULL, false, false );
	    pResult = pSearch->search( q );
        assertEqualsMsg( _T( "not smallest, but up" ), numDocs-1, pResult->length());
        _CLDELETE( pResult ); _CLDELETE( q );
            
        q = csrq( _T( "rand" ), NULL, maxRP, false, false );
	    pResult = pSearch->search( q );
        assertEqualsMsg( _T( "not biggest, but down" ), numDocs-1, pResult->length());
        _CLDELETE( pResult ); _CLDELETE( q );
        
        // very small sets

        q = csrq( _T( "rand" ), minRP, minRP, false, false );
	    pResult = pSearch->search( q );
        assertEqualsMsg( _T( "min,min,F,F" ), 0, pResult->length());
        _CLDELETE( pResult ); _CLDELETE( q );

        q = csrq( _T( "rand" ), maxRP, maxRP, false, false );
	    pResult = pSearch->search( q );
        assertEqualsMsg( _T( "max,max,F,F" ), 0, pResult->length());
        _CLDELETE( pResult ); _CLDELETE( q );
                         
        q = csrq( _T( "rand" ), minRP, minRP, true, true );
	    pResult = pSearch->search( q );
        assertEqualsMsg( _T( "min,min,T,T" ), 1, pResult->length());
        _CLDELETE( pResult ); _CLDELETE( q );

        q = csrq( _T( "rand" ), NULL, minRP, false, true );
	    pResult = pSearch->search( q );
        assertEqualsMsg( _T( "nul,min,F,T" ), 1, pResult->length());
        _CLDELETE( pResult ); _CLDELETE( q );

        q = csrq( _T( "rand" ), maxRP, maxRP, true, true );
	    pResult = pSearch->search( q );
        assertEqualsMsg( _T( "max,max,T,T" ), 1, pResult->length());
        _CLDELETE( pResult ); _CLDELETE( q );

        q = csrq( _T( "rand" ), maxRP, NULL, true, false );
	    pResult = pSearch->search( q );
        assertEqualsMsg( _T( "max,nul,T,T" ), 1, pResult->length());
        _CLDELETE( pResult ); _CLDELETE( q );

        pSearch->close();
        _CLDELETE( pSearch );

        pReader->close();
        _CLDELETE( pReader );
    }
    void testRangeQueryId()
    {
        // NOTE: uses index build in *super* setUp

        IndexReader * pReader = IndexReader::open( index );
	    IndexSearcher * pSearch = _CLNEW IndexSearcher( pReader );

        int32_t medId = ((maxId - minId) / 2);
        
        std::tstring sMinIP = pad(minId);
        std::tstring sMaxIP = pad(maxId);
        std::tstring sMedIP = pad(medId);
        const TCHAR* minIP = sMinIP.c_str();
        const TCHAR* maxIP = sMaxIP.c_str();
        const TCHAR* medIP = sMedIP.c_str();
    
        size_t numDocs = static_cast<size_t>( pReader->numDocs() );
        assertEqualsMsg( _T("num of docs"), numDocs, static_cast<size_t>(1+ maxId - minId));
        
	    Hits * pResult;
        Query * q;
        // test id, bounded on both ends
        
        q = csrq( _T( "id" ), minIP, maxIP, true, true );
	    pResult = pSearch->search( q );
	    assertEqualsMsg( _T( "find all" ), numDocs, pResult->length() );
        _CLDELETE( pResult ); _CLDELETE( q );

	    q = csrq( _T( "id" ), minIP, maxIP, true, false );
	    pResult = pSearch->search( q );
	    assertEqualsMsg( _T( "all but last" ), numDocs-1, pResult->length());
        _CLDELETE( pResult ); _CLDELETE( q );

	    q = csrq( _T( "id" ), minIP, maxIP, false, true );
	    pResult = pSearch->search( q );
	    assertEqualsMsg( _T( "all but first" ), numDocs-1, pResult->length());
        _CLDELETE( pResult ); _CLDELETE( q );
            
	    q = csrq( _T( "id" ), minIP, maxIP, false,false );
	    pResult = pSearch->search( q );
        assertEqualsMsg( _T( "all but ends" ), numDocs-2, pResult->length());
        _CLDELETE( pResult ); _CLDELETE( q );
    
        q = csrq( _T( "id" ), medIP, maxIP, true, true );
	    pResult = pSearch->search( q );
        assertEqualsMsg( _T( "med and up" ), 1+maxId-medId, pResult->length());
        _CLDELETE( pResult ); _CLDELETE( q );
        
        q = csrq( _T( "id" ), minIP, medIP, true, true );
	    pResult = pSearch->search( q );
        assertEqualsMsg( _T( "up to med" ), 1+medId-minId, pResult->length());
        _CLDELETE( pResult ); _CLDELETE( q );

        // unbounded id

	    q = csrq( _T( "id" ), minIP, NULL, true, false );
	    pResult = pSearch->search( q );
	    assertEqualsMsg( _T( "min and up" ), numDocs, pResult->length());
        _CLDELETE( pResult ); _CLDELETE( q );

	    q = csrq( _T( "id" ), NULL, maxIP, false, true );
	    pResult = pSearch->search( q );
	    assertEqualsMsg( _T( "max and down" ), numDocs, pResult->length());
        _CLDELETE( pResult ); _CLDELETE( q );

	    q = csrq( _T( "id" ), minIP, NULL, false, false );
	    pResult = pSearch->search( q );
	    assertEqualsMsg( _T( "not min, but up" ), numDocs-1, pResult->length());
        _CLDELETE( pResult ); _CLDELETE( q );
            
	    q = csrq( _T( "id" ), NULL, maxIP, false, false );
	    pResult = pSearch->search( q );
	    assertEqualsMsg( _T( "not max, but down" ), numDocs-1, pResult->length());
        _CLDELETE( pResult ); _CLDELETE( q );
            
        q = csrq( _T( "id" ), medIP, maxIP, true, false );
	    pResult = pSearch->search( q );
        assertEqualsMsg( _T( "med and up, not max" ), maxId-medId, pResult->length());
        _CLDELETE( pResult ); _CLDELETE( q );
        
        q = csrq( _T( "id" ), minIP, medIP, false,true );
	    pResult = pSearch->search( q );
        assertEqualsMsg( _T( "not min, up to med" ), medId-minId, pResult->length());
        _CLDELETE( pResult ); _CLDELETE( q );

        // very small sets

	    q = csrq( _T( "id" ), minIP, minIP, false, false );
	    pResult = pSearch->search( q );
	    assertEqualsMsg( _T( "min,min,F,F" ), 0, pResult->length());
        _CLDELETE( pResult ); _CLDELETE( q );

        q = csrq( _T( "id" ), medIP, medIP, false, false );
	    pResult = pSearch->search( q );
	    assertEqualsMsg( _T( "med,med,F,F" ), 0, pResult->length());
        _CLDELETE( pResult ); _CLDELETE( q );

        q = csrq( _T( "id") , maxIP, maxIP, false, false );
	    pResult = pSearch->search( q );
	    assertEqualsMsg( _T( "max,max,F,F" ), 0, pResult->length());
        _CLDELETE( pResult ); _CLDELETE( q );
                         
	    q = csrq( _T( "id" ), minIP, minIP, true, true );
	    pResult = pSearch->search( q );
	    assertEqualsMsg( _T( "min,min,T,T" ), 1, pResult->length());
        _CLDELETE( pResult ); _CLDELETE( q );

        q = csrq( _T( "id" ), NULL, minIP, false, true );
	    pResult = pSearch->search( q );
	    assertEqualsMsg( _T( "nul,min,F,T" ), 1, pResult->length());
        _CLDELETE( pResult ); _CLDELETE( q );

	    q = csrq( _T( "id" ), maxIP, maxIP, true, true );
	    pResult = pSearch->search( q );
	    assertEqualsMsg( _T( "max,max,T,T" ), 1, pResult->length());
        _CLDELETE( pResult ); _CLDELETE( q );

        q = csrq( _T( "id" ), maxIP, NULL, true, false );
	    pResult = pSearch->search( q );
	    assertEqualsMsg( _T( "max,nul,T,T" ), 1, pResult->length());
        _CLDELETE( pResult ); _CLDELETE( q );

	    q = csrq( _T( "id" ), medIP, medIP, true, true );
	    pResult = pSearch->search( q );
	    assertEqualsMsg( _T( "med,med,T,T" ), 1, pResult->length());
        _CLDELETE( pResult ); _CLDELETE( q );
            
        pSearch->close();
        _CLDELETE( pSearch );

        pReader->close();
        _CLDELETE( pReader );
    }