LCOV - code coverage report
Current view: top level - home/olly/git/atia-xapian/xapian-core/tests - api_anydb.cc (source / functions) Hit Total Coverage
Test: Test Coverage for xapian-core r Lines: 1349 1383 97.5 %
Date: 2011-08-21 Functions: 83 86 96.5 %
Branches: 560 1713 32.7 %

           Branch data     Line data    Source code
       1                 :            : /* api_anydb.cc: tests which work with any backend
       2                 :            :  *
       3                 :            :  * Copyright 1999,2000,2001 BrightStation PLC
       4                 :            :  * Copyright 2002 Ananova Ltd
       5                 :            :  * Copyright 2002,2003,2004,2005,2006,2007,2008,2009,2010,2011 Olly Betts
       6                 :            :  * Copyright 2006,2008 Lemur Consulting Ltd
       7                 :            :  * Copyright 2011 Action Without Borders
       8                 :            :  *
       9                 :            :  * This program is free software; you can redistribute it and/or
      10                 :            :  * modify it under the terms of the GNU General Public License as
      11                 :            :  * published by the Free Software Foundation; either version 2 of the
      12                 :            :  * License, or (at your option) any later version.
      13                 :            :  *
      14                 :            :  * This program is distributed in the hope that it will be useful,
      15                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      16                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17                 :            :  * GNU General Public License for more details.
      18                 :            :  *
      19                 :            :  * You should have received a copy of the GNU General Public License
      20                 :            :  * along with this program; if not, write to the Free Software
      21                 :            :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
      22                 :            :  * USA
      23                 :            :  */
      24                 :            : 
      25                 :            : #include <config.h>
      26                 :            : 
      27                 :            : #include "api_anydb.h"
      28                 :            : 
      29                 :            : #include <algorithm>
      30                 :            : #include <string>
      31                 :            : 
      32                 :            : #include <xapian.h>
      33                 :            : #include "backendmanager_local.h"
      34                 :            : #include "testsuite.h"
      35                 :            : #include "testutils.h"
      36                 :            : #include "utils.h"
      37                 :            : 
      38                 :            : #include "apitest.h"
      39                 :            : 
      40                 :            : #include <list>
      41                 :            : 
      42                 :            : using namespace std;
      43                 :            : 
      44                 :            : static void
      45                 :          0 : print_mset_weights(const Xapian::MSet &mset)
      46                 :            : {
      47                 :          0 :     Xapian::MSetIterator i = mset.begin();
      48         [ #  # ]:          0 :     for ( ; i != mset.end(); ++i) {
      49                 :          0 :         tout << " " << i.get_weight();
      50                 :          0 :     }
      51                 :          0 : }
      52                 :            : 
      53                 :            : static void
      54                 :          0 : print_mset_percentages(const Xapian::MSet &mset)
      55                 :            : {
      56                 :          0 :     Xapian::MSetIterator i = mset.begin();
      57         [ #  # ]:          0 :     for ( ; i != mset.end(); ++i) {
      58                 :          0 :         tout << " " << mset.convert_to_percent(i);
      59                 :          0 :     }
      60                 :          0 : }
      61                 :            : 
      62                 :            : static Xapian::Query
      63                 :        247 : query(Xapian::Query::op op,
      64                 :            :       const string & t1 = string(), const string & t2 = string(),
      65                 :            :       const string & t3 = string(), const string & t4 = string(),
      66                 :            :       const string & t5 = string(), const string & t6 = string(),
      67                 :            :       const string & t7 = string(), const string & t8 = string(),
      68                 :            :       const string & t9 = string(), const string & t10 = string())
      69                 :            : {
      70                 :        247 :     vector<string> v;
      71                 :        247 :     Xapian::Stem stemmer("english");
      72         [ +  - ]:        247 :     if (!t1.empty()) v.push_back(stemmer(t1));
      73         [ +  + ]:        247 :     if (!t2.empty()) v.push_back(stemmer(t2));
      74         [ +  + ]:        247 :     if (!t3.empty()) v.push_back(stemmer(t3));
      75         [ +  + ]:        247 :     if (!t4.empty()) v.push_back(stemmer(t4));
      76         [ -  + ]:        247 :     if (!t5.empty()) v.push_back(stemmer(t5));
      77         [ -  + ]:        247 :     if (!t6.empty()) v.push_back(stemmer(t6));
      78         [ -  + ]:        247 :     if (!t7.empty()) v.push_back(stemmer(t7));
      79         [ -  + ]:        247 :     if (!t8.empty()) v.push_back(stemmer(t8));
      80         [ -  + ]:        247 :     if (!t9.empty()) v.push_back(stemmer(t9));
      81         [ -  + ]:        247 :     if (!t10.empty()) v.push_back(stemmer(t10));
      82                 :        247 :     return Xapian::Query(op, v.begin(), v.end());
      83                 :            : }
      84                 :            : 
      85                 :            : static Xapian::Query
      86                 :         20 : query(Xapian::Query::op op, Xapian::termcount parameter,
      87                 :            :       const string & t1 = string(), const string & t2 = string(),
      88                 :            :       const string & t3 = string(), const string & t4 = string(),
      89                 :            :       const string & t5 = string(), const string & t6 = string(),
      90                 :            :       const string & t7 = string(), const string & t8 = string(),
      91                 :            :       const string & t9 = string(), const string & t10 = string())
      92                 :            : {
      93                 :         20 :     vector<string> v;
      94                 :         20 :     Xapian::Stem stemmer("english");
      95         [ +  - ]:         20 :     if (!t1.empty()) v.push_back(stemmer(t1));
      96         [ +  - ]:         20 :     if (!t2.empty()) v.push_back(stemmer(t2));
      97         [ +  + ]:         20 :     if (!t3.empty()) v.push_back(stemmer(t3));
      98         [ -  + ]:         20 :     if (!t4.empty()) v.push_back(stemmer(t4));
      99         [ -  + ]:         20 :     if (!t5.empty()) v.push_back(stemmer(t5));
     100         [ -  + ]:         20 :     if (!t6.empty()) v.push_back(stemmer(t6));
     101         [ -  + ]:         20 :     if (!t7.empty()) v.push_back(stemmer(t7));
     102         [ -  + ]:         20 :     if (!t8.empty()) v.push_back(stemmer(t8));
     103         [ -  + ]:         20 :     if (!t9.empty()) v.push_back(stemmer(t9));
     104         [ -  + ]:         20 :     if (!t10.empty()) v.push_back(stemmer(t10));
     105                 :         20 :     return Xapian::Query(op, v.begin(), v.end(), parameter);
     106                 :            : }
     107                 :            : 
     108                 :            : static Xapian::Query
     109                 :        152 : query(const string &t)
     110                 :            : {
     111                 :        152 :     return Xapian::Query(Xapian::Stem("english")(t));
     112                 :            : }
     113                 :            : 
     114                 :            : // #######################################################################
     115                 :            : // # Tests start here
     116                 :            : 
     117                 :            : // tests that the backend doesn't return zero docids
     118                 :         13 : DEFINE_TESTCASE(zerodocid1, backend) {
     119                 :            :     // open the database (in this case a simple text file
     120                 :            :     // we prepared earlier)
     121                 :            : 
     122                 :         13 :     Xapian::Database mydb(get_database("apitest_onedoc"));
     123                 :            : 
     124                 :         13 :     Xapian::Enquire enquire(mydb);
     125                 :            : 
     126                 :            :     // make a simple query, with one word in it - "word".
     127                 :         13 :     enquire.set_query(Xapian::Query("word"));
     128                 :            : 
     129                 :            :     // retrieve the top ten results (we only expect one)
     130                 :         13 :     Xapian::MSet mymset = enquire.get_mset(0, 10);
     131                 :            : 
     132                 :            :     // We've done the query, now check that the result is what
     133                 :            :     // we expect (1 document, with non-zero docid)
     134   [ -  +  #  # ]:         13 :     TEST_MSET_SIZE(mymset, 1);
     135                 :            : 
     136 [ -  + ][ #  # ]:         13 :     TEST_AND_EXPLAIN(*(mymset.begin()) != 0,
     137                 :            :                      "A query on a database returned a zero docid");
     138                 :            : 
     139                 :         13 :     return true;
     140                 :            : }
     141                 :            : 
     142                 :            : // tests that an empty query returns no matches
     143                 :         13 : DEFINE_TESTCASE(emptyquery1, backend) {
     144                 :         13 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
     145                 :            : 
     146                 :         13 :     enquire.set_query(Xapian::Query());
     147                 :         13 :     Xapian::MSet mymset = enquire.get_mset(0, 10);
     148   [ -  +  #  # ]:         13 :     TEST_MSET_SIZE(mymset, 0);
     149 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_matches_lower_bound(), 0);
     150 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_matches_upper_bound(), 0);
     151 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_matches_estimated(), 0);
     152 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_uncollapsed_matches_lower_bound(), 0);
     153 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_uncollapsed_matches_upper_bound(), 0);
     154 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_uncollapsed_matches_estimated(), 0);
     155                 :            : 
     156                 :         13 :     vector<Xapian::Query> v;
     157                 :         13 :     enquire.set_query(Xapian::Query(Xapian::Query::OP_AND, v.begin(), v.end()));
     158                 :         13 :     mymset = enquire.get_mset(0, 10);
     159   [ -  +  #  # ]:         13 :     TEST_MSET_SIZE(mymset, 0);
     160 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_matches_lower_bound(), 0);
     161 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_matches_upper_bound(), 0);
     162 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_matches_estimated(), 0);
     163 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_uncollapsed_matches_lower_bound(), 0);
     164 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_uncollapsed_matches_upper_bound(), 0);
     165 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_uncollapsed_matches_estimated(), 0);
     166                 :            : 
     167                 :         13 :     return true;
     168                 :            : }
     169                 :            : 
     170                 :            : // tests the document count for a simple query
     171                 :         13 : DEFINE_TESTCASE(simplequery1, backend) {
     172                 :         13 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
     173                 :         13 :     enquire.set_query(Xapian::Query("word"));
     174                 :         13 :     Xapian::MSet mymset = enquire.get_mset(0, 10);
     175   [ -  +  #  # ]:         13 :     TEST_MSET_SIZE(mymset, 2);
     176                 :         13 :     return true;
     177                 :            : }
     178                 :            : 
     179                 :            : // tests for the right documents and weights returned with simple query
     180                 :         13 : DEFINE_TESTCASE(simplequery2, backend) {
     181                 :            :     // open the database (in this case a simple text file
     182                 :            :     // we prepared earlier)
     183                 :         13 :     Xapian::Database db = get_database("apitest_simpledata");
     184                 :         13 :     Xapian::Enquire enquire(db);
     185                 :         13 :     enquire.set_query(Xapian::Query("word"));
     186                 :            : 
     187                 :            :     // retrieve the top results
     188                 :         13 :     Xapian::MSet mymset = enquire.get_mset(0, 10);
     189                 :            : 
     190                 :            :     // We've done the query, now check that the result is what
     191                 :            :     // we expect (documents 2 and 4)
     192                 :         13 :     mset_expect_order(mymset, 2, 4);
     193                 :            : 
     194                 :            :     // Check the weights
     195                 :         13 :     Xapian::MSetIterator i = mymset.begin();
     196                 :            :     // These weights are for BM25Weight(1,0,1,0.5,0.5)
     197   [ -  +  #  # ]:         13 :     TEST_EQUAL_DOUBLE(i.get_weight(), 1.04648168717725);
     198                 :         13 :     i++;
     199   [ -  +  #  # ]:         13 :     TEST_EQUAL_DOUBLE(i.get_weight(), 0.640987686595914);
     200                 :            : 
     201                 :         13 :     return true;
     202                 :            : }
     203                 :            : 
     204                 :            : // tests for the right document count for another simple query
     205                 :         13 : DEFINE_TESTCASE(simplequery3, backend) {
     206                 :         13 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
     207                 :         13 :     enquire.set_query(query("this"));
     208                 :         13 :     Xapian::MSet mymset = enquire.get_mset(0, 10);
     209                 :            : 
     210                 :            :     // Check that 6 documents were returned.
     211   [ -  +  #  # ]:         13 :     TEST_MSET_SIZE(mymset, 6);
     212                 :            : 
     213                 :         13 :     return true;
     214                 :            : }
     215                 :            : 
     216                 :            : // tests for the right document count for a wildcard query
     217                 :            : // FIXME: move this to querytest (and just use an InMemory DB).
     218                 :         13 : DEFINE_TESTCASE(wildquery1, backend) {
     219                 :         13 :     Xapian::QueryParser queryparser;
     220                 :            :     unsigned flags = Xapian::QueryParser::FLAG_WILDCARD |
     221                 :         13 :                      Xapian::QueryParser::FLAG_LOVEHATE;
     222                 :         13 :     queryparser.set_stemmer(Xapian::Stem("english"));
     223                 :         13 :     queryparser.set_stemming_strategy(Xapian::QueryParser::STEM_ALL);
     224                 :         13 :     Xapian::Database db = get_database("apitest_simpledata");
     225                 :         13 :     queryparser.set_database(db);
     226                 :         13 :     Xapian::Enquire enquire(db);
     227                 :            : 
     228                 :         13 :     Xapian::Query qobj = queryparser.parse_query("th*", flags);
     229                 :         13 :     tout << qobj.get_description() << endl;
     230                 :         13 :     enquire.set_query(qobj);
     231                 :         13 :     Xapian::MSet mymset = enquire.get_mset(0, 10);
     232                 :            :     // Check that 6 documents were returned.
     233   [ -  +  #  # ]:         13 :     TEST_MSET_SIZE(mymset, 6);
     234                 :            : 
     235                 :         13 :     qobj = queryparser.parse_query("notindb* \"this\"", flags);
     236                 :         13 :     tout << qobj.get_description() << endl;
     237                 :         13 :     enquire.set_query(qobj);
     238                 :         13 :     mymset = enquire.get_mset(0, 10);
     239                 :            :     // Check that 6 documents were returned.
     240   [ -  +  #  # ]:         13 :     TEST_MSET_SIZE(mymset, 6);
     241                 :            : 
     242                 :         13 :     qobj = queryparser.parse_query("+notindb* \"this\"", flags);
     243                 :         13 :     tout << qobj.get_description() << endl;
     244                 :         13 :     enquire.set_query(qobj);
     245                 :         13 :     mymset = enquire.get_mset(0, 10);
     246                 :            :     // Check that 0 documents were returned.
     247   [ -  +  #  # ]:         13 :     TEST_MSET_SIZE(mymset, 0);
     248                 :            : 
     249                 :         13 :     return true;
     250                 :            : }
     251                 :            : 
     252                 :            : // tests a query across multiple databases
     253                 :         13 : DEFINE_TESTCASE(multidb1, backend) {
     254                 :         13 :     Xapian::Database mydb1(get_database("apitest_simpledata", "apitest_simpledata2"));
     255                 :         13 :     Xapian::Enquire enquire1(mydb1);
     256                 :            : 
     257                 :         13 :     Xapian::Database mydb2(get_database("apitest_simpledata"));
     258                 :         13 :     mydb2.add_database(get_database("apitest_simpledata2"));
     259                 :         13 :     Xapian::Enquire enquire2(mydb2);
     260                 :            : 
     261                 :            :     // make a simple query, with one word in it - "word".
     262                 :         13 :     Xapian::Query myquery("word");
     263                 :         13 :     enquire1.set_query(myquery);
     264                 :         13 :     enquire2.set_query(myquery);
     265                 :            : 
     266                 :            :     // retrieve the top ten results from each method of accessing
     267                 :            :     // multiple text files
     268                 :         13 :     Xapian::MSet mymset1 = enquire1.get_mset(0, 10);
     269                 :         13 :     Xapian::MSet mymset2 = enquire2.get_mset(0, 10);
     270                 :            : 
     271   [ -  +  #  # ]:         13 :     TEST_EQUAL(mymset1.size(), mymset2.size());
     272 [ -  + ][ #  # ]:         13 :     TEST(mset_range_is_same_weights(mymset1, 0, mymset2, 0, mymset1.size()));
     273                 :         13 :     return true;
     274                 :            : }
     275                 :            : 
     276                 :            : // tests a query across multiple databases with terms only
     277                 :            : // in one of the two databases
     278                 :         10 : DEFINE_TESTCASE(multidb2, backend && !multi) {
     279                 :            :     Xapian::Database mydb1(get_database("apitest_simpledata",
     280                 :         10 :                                   "apitest_simpledata2"));
     281                 :         10 :     Xapian::Enquire enquire1(mydb1);
     282                 :            : 
     283                 :         10 :     Xapian::Database mydb2(get_database("apitest_simpledata"));
     284                 :         10 :     mydb2.add_database(get_database("apitest_simpledata2"));
     285                 :         10 :     Xapian::Enquire enquire2(mydb2);
     286                 :            : 
     287                 :            :     // make a simple query
     288                 :         10 :     Xapian::Query myquery = query(Xapian::Query::OP_OR, "inmemory", "word");
     289                 :         10 :     enquire1.set_query(myquery);
     290                 :         10 :     enquire2.set_query(myquery);
     291                 :            : 
     292                 :            :     // retrieve the top ten results from each method of accessing
     293                 :            :     // multiple text files
     294                 :         10 :     Xapian::MSet mymset1 = enquire1.get_mset(0, 10);
     295                 :         10 :     Xapian::MSet mymset2 = enquire2.get_mset(0, 10);
     296                 :            : 
     297   [ -  +  #  # ]:         10 :     TEST_EQUAL(mymset1.size(), mymset2.size());
     298 [ -  + ][ #  # ]:         10 :     TEST(mset_range_is_same_weights(mymset1, 0, mymset2, 0, mymset1.size()));
     299                 :         10 :     return true;
     300                 :            : }
     301                 :            : 
     302                 :            : // test that a multidb with 2 dbs query returns correct docids
     303                 :         10 : DEFINE_TESTCASE(multidb3, backend && !multi) {
     304                 :         10 :     Xapian::Database mydb2(get_database("apitest_simpledata"));
     305                 :         10 :     mydb2.add_database(get_database("apitest_simpledata2"));
     306                 :         10 :     Xapian::Enquire enquire(mydb2);
     307                 :            : 
     308                 :            :     // make a query
     309                 :         10 :     Xapian::Query myquery = query(Xapian::Query::OP_OR, "inmemory", "word");
     310                 :         10 :     enquire.set_weighting_scheme(Xapian::BoolWeight());
     311                 :         10 :     enquire.set_query(myquery);
     312                 :            : 
     313                 :            :     // retrieve the top ten results
     314                 :         10 :     Xapian::MSet mymset = enquire.get_mset(0, 10);
     315                 :         10 :     mset_expect_order(mymset, 2, 3, 7);
     316                 :            : 
     317                 :         10 :     return true;
     318                 :            : }
     319                 :            : 
     320                 :            : // test that a multidb with 3 dbs query returns correct docids
     321                 :         10 : DEFINE_TESTCASE(multidb4, backend && !multi) {
     322                 :         10 :     Xapian::Database mydb2(get_database("apitest_simpledata"));
     323                 :         10 :     mydb2.add_database(get_database("apitest_simpledata2"));
     324                 :         10 :     mydb2.add_database(get_database("apitest_termorder"));
     325                 :         10 :     Xapian::Enquire enquire(mydb2);
     326                 :            : 
     327                 :            :     // make a query
     328                 :         10 :     Xapian::Query myquery = query(Xapian::Query::OP_OR, "inmemory", "word");
     329                 :         10 :     enquire.set_weighting_scheme(Xapian::BoolWeight());
     330                 :         10 :     enquire.set_query(myquery);
     331                 :            : 
     332                 :            :     // retrieve the top ten results
     333                 :         10 :     Xapian::MSet mymset = enquire.get_mset(0, 10);
     334                 :         10 :     mset_expect_order(mymset, 2, 3, 4, 10);
     335                 :            : 
     336                 :         10 :     return true;
     337                 :            : }
     338                 :            : 
     339                 :            : // tests MultiPostList::skip_to().
     340                 :         10 : DEFINE_TESTCASE(multidb5, backend && !multi) {
     341                 :         10 :     Xapian::Database mydb2(get_database("apitest_simpledata"));
     342                 :         10 :     mydb2.add_database(get_database("apitest_simpledata2"));
     343                 :         10 :     Xapian::Enquire enquire(mydb2);
     344                 :            : 
     345                 :            :     // make a query
     346                 :         10 :     Xapian::Query myquery = query(Xapian::Query::OP_AND, "inmemory", "word");
     347                 :         10 :     enquire.set_weighting_scheme(Xapian::BoolWeight());
     348                 :         10 :     enquire.set_query(myquery);
     349                 :            : 
     350                 :            :     // retrieve the top ten results
     351                 :         10 :     Xapian::MSet mymset = enquire.get_mset(0, 10);
     352                 :         10 :     mset_expect_order(mymset, 2);
     353                 :            : 
     354                 :         10 :     return true;
     355                 :            : }
     356                 :            : 
     357                 :            : // tests that when specifying maxitems to get_mset, no more than
     358                 :            : // that are returned.
     359                 :         13 : DEFINE_TESTCASE(msetmaxitems1, backend) {
     360                 :         13 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
     361                 :         13 :     enquire.set_query(query("this"));
     362                 :         13 :     Xapian::MSet mymset = enquire.get_mset(0, 1);
     363   [ -  +  #  # ]:         13 :     TEST_MSET_SIZE(mymset, 1);
     364                 :            : 
     365                 :         13 :     mymset = enquire.get_mset(0, 5);
     366   [ -  +  #  # ]:         13 :     TEST_MSET_SIZE(mymset, 5);
     367                 :            : 
     368                 :         13 :     return true;
     369                 :            : }
     370                 :            : 
     371                 :            : // tests the returned weights are as expected (regression test for remote
     372                 :            : // backend which was using the average weight rather than the actual document
     373                 :            : // weight for computing weights - fixed in 1.0.0).
     374                 :         13 : DEFINE_TESTCASE(expandweights1, backend) {
     375                 :         13 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
     376                 :         13 :     enquire.set_query(Xapian::Query("this"));
     377                 :            : 
     378                 :         13 :     Xapian::MSet mymset = enquire.get_mset(0, 10);
     379                 :            : 
     380                 :         13 :     Xapian::RSet myrset;
     381                 :         13 :     Xapian::MSetIterator i = mymset.begin();
     382                 :         13 :     myrset.add_document(*i);
     383                 :         13 :     myrset.add_document(*(++i));
     384                 :            : 
     385                 :         13 :     Xapian::ESet eset = enquire.get_eset(3, myrset, enquire.USE_EXACT_TERMFREQ);
     386   [ -  +  #  # ]:         13 :     TEST_EQUAL(eset.size(), 3);
     387 [ -  + ][ #  # ]:         13 :     TEST_EQUAL_DOUBLE(eset[0].get_weight(), 6.08904001099445);
     388 [ -  + ][ #  # ]:         13 :     TEST_EQUAL_DOUBLE(eset[1].get_weight(), 6.08904001099445);
     389 [ -  + ][ #  # ]:         13 :     TEST_EQUAL_DOUBLE(eset[2].get_weight(), 4.73383620844021);
     390                 :            : 
     391                 :         13 :     return true;
     392                 :            : }
     393                 :            : 
     394                 :            : // Just like test_expandweights1 but without USE_EXACT_TERMFREQ.
     395                 :         13 : DEFINE_TESTCASE(expandweights2, backend) {
     396                 :         13 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
     397                 :         13 :     enquire.set_query(Xapian::Query("this"));
     398                 :            : 
     399                 :         13 :     Xapian::MSet mymset = enquire.get_mset(0, 10);
     400                 :            : 
     401                 :         13 :     Xapian::RSet myrset;
     402                 :         13 :     Xapian::MSetIterator i = mymset.begin();
     403                 :         13 :     myrset.add_document(*i);
     404                 :         13 :     myrset.add_document(*(++i));
     405                 :            : 
     406                 :         13 :     Xapian::ESet eset = enquire.get_eset(3, myrset);
     407   [ -  +  #  # ]:         13 :     TEST_EQUAL(eset.size(), 3);
     408         [ +  + ]:         13 :     if (!startswith(get_dbtype(), "multi")) {
     409                 :            :         // For a single database, the weights should be the same with or
     410                 :            :         // without USE_EXACT_TERMFREQ.
     411 [ -  + ][ #  # ]:         10 :         TEST_EQUAL_DOUBLE(eset[0].get_weight(), 6.08904001099445);
     412 [ -  + ][ #  # ]:         10 :         TEST_EQUAL_DOUBLE(eset[1].get_weight(), 6.08904001099445);
     413 [ -  + ][ #  # ]:         10 :         TEST_EQUAL_DOUBLE(eset[2].get_weight(), 4.73383620844021);
     414                 :            :     } else {
     415                 :            :         // For multiple databases, we expect that using USE_EXACT_TERMFREQ
     416                 :            :         // will result in different weights in some cases.
     417 [ -  + ][ #  # ]:          3 :         TEST_NOT_EQUAL_DOUBLE(eset[0].get_weight(), 6.08904001099445);
     418 [ -  + ][ #  # ]:          3 :         TEST_EQUAL_DOUBLE(eset[1].get_weight(), 6.08904001099445);
     419 [ -  + ][ #  # ]:          3 :         TEST_NOT_EQUAL_DOUBLE(eset[2].get_weight(), 4.73383620844021);
     420                 :            :     }
     421                 :            : 
     422                 :         13 :     return true;
     423                 :            : }
     424                 :            : 
     425                 :         13 : DEFINE_TESTCASE(expandweights3, backend) {
     426                 :         13 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
     427                 :         13 :     enquire.set_query(Xapian::Query("this"));
     428                 :            : 
     429                 :         13 :     Xapian::MSet mymset = enquire.get_mset(0, 10);
     430                 :            : 
     431                 :         13 :     Xapian::RSet myrset;
     432                 :         13 :     Xapian::MSetIterator i = mymset.begin();
     433                 :         13 :     myrset.add_document(*i);
     434                 :         13 :     myrset.add_document(*(++i));
     435                 :            : 
     436                 :            :     // Set min_wt to 0
     437                 :         13 :     Xapian::ESet eset = enquire.get_eset(50, myrset, 0, 1.0, 0, 0);
     438         [ +  + ]:         13 :     if (!startswith(get_dbtype(), "multi")) {
     439                 :            :         // For a single database, the weights should be the same with or
     440                 :            :         // without USE_EXACT_TERMFREQ.
     441 [ -  + ][ #  # ]:         10 :         TEST_EQUAL_DOUBLE(eset[0].get_weight(), 6.08904001099445);
     442 [ -  + ][ #  # ]:         10 :         TEST_EQUAL_DOUBLE(eset[1].get_weight(), 6.08904001099445);
     443 [ -  + ][ #  # ]:         10 :         TEST_EQUAL_DOUBLE(eset[2].get_weight(), 4.73383620844021);
     444                 :            :     } else {
     445                 :            :         // For multiple databases, we expect that using USE_EXACT_TERMFREQ
     446                 :            :         // will result in different weights in some cases.
     447 [ -  + ][ #  # ]:          3 :         TEST_NOT_EQUAL_DOUBLE(eset[0].get_weight(), 6.08904001099445);
     448 [ -  + ][ #  # ]:          3 :         TEST_EQUAL_DOUBLE(eset[1].get_weight(), 6.08904001099445);
     449 [ -  + ][ #  # ]:          3 :         TEST_NOT_EQUAL_DOUBLE(eset[2].get_weight(), 4.73383620844021);
     450                 :            :     }
     451 [ -  + ][ #  # ]:         13 :     TEST_REL(eset.back().get_weight(),>=,0);
     452                 :            : 
     453                 :         13 :     return true;
     454                 :            : }
     455                 :            : 
     456                 :            : 
     457                 :            : // tests that negative weights are returned
     458                 :         13 : DEFINE_TESTCASE(expandweights4, backend) {
     459                 :         13 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
     460                 :         13 :     enquire.set_query(Xapian::Query("paragraph"));
     461                 :            : 
     462                 :         13 :     Xapian::MSet mymset = enquire.get_mset(0, 10);
     463                 :            : 
     464                 :         13 :     Xapian::RSet myrset;
     465                 :         13 :     Xapian::MSetIterator i = mymset.begin();
     466                 :         13 :     myrset.add_document(*i);
     467                 :         13 :     myrset.add_document(*(++i));
     468                 :            : 
     469                 :         13 :     Xapian::ESet eset = enquire.get_eset(37, myrset, 0, 1.0, 0, -100);
     470                 :            :     // Now include negative weights
     471   [ -  +  #  # ]:         13 :     TEST_EQUAL(eset.size(), 37);
     472 [ -  + ][ #  # ]:         13 :     TEST_REL(eset[36].get_weight(),<,0);
     473 [ -  + ][ #  # ]:         13 :     TEST_REL(eset[36].get_weight(),>=,-100);
     474                 :            : 
     475                 :         13 :     return true;
     476                 :            : }
     477                 :            : 
     478                 :            : 
     479                 :            : // tests that when specifying maxitems to get_eset, no more than
     480                 :            : // that are returned.
     481                 :         13 : DEFINE_TESTCASE(expandmaxitems1, backend) {
     482                 :         13 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
     483                 :         13 :     enquire.set_query(Xapian::Query("this"));
     484                 :            : 
     485                 :         13 :     Xapian::MSet mymset = enquire.get_mset(0, 10);
     486                 :         13 :     tout << "mymset.size() = " << mymset.size() << endl;
     487   [ -  +  #  # ]:         13 :     TEST(mymset.size() >= 2);
     488                 :            : 
     489                 :         13 :     Xapian::RSet myrset;
     490                 :         13 :     Xapian::MSetIterator i = mymset.begin();
     491                 :         13 :     myrset.add_document(*i);
     492                 :         13 :     myrset.add_document(*(++i));
     493                 :            : 
     494                 :         13 :     Xapian::ESet myeset = enquire.get_eset(1, myrset);
     495   [ -  +  #  # ]:         13 :     TEST_EQUAL(myeset.size(), 1);
     496                 :            : 
     497                 :         13 :     return true;
     498                 :            : }
     499                 :            : 
     500                 :            : // tests that a pure boolean query has all weights set to 0
     501                 :         13 : DEFINE_TESTCASE(boolquery1, backend) {
     502                 :         13 :     Xapian::Query myboolquery(query("this"));
     503                 :            : 
     504                 :            :     // open the database (in this case a simple text file
     505                 :            :     // we prepared earlier)
     506                 :         13 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
     507                 :         13 :     enquire.set_query(myboolquery);
     508                 :         13 :     enquire.set_weighting_scheme(Xapian::BoolWeight());
     509                 :            : 
     510                 :            :     // retrieve the top results
     511                 :         13 :     Xapian::MSet mymset = enquire.get_mset(0, 10);
     512                 :            : 
     513   [ -  +  #  # ]:         13 :     TEST_NOT_EQUAL(mymset.size(), 0);
     514 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_max_possible(), 0);
     515         [ +  + ]:         91 :     for (Xapian::MSetIterator i = mymset.begin(); i != mymset.end(); ++i) {
     516 [ -  + ][ #  # ]:         78 :         TEST_EQUAL(i.get_weight(), 0);
     517                 :         13 :     }
     518                 :         13 :     return true;
     519                 :            : }
     520                 :            : 
     521                 :            : // tests that get_mset() specifying "this" works as expected
     522                 :         13 : DEFINE_TESTCASE(msetfirst1, backend) {
     523                 :         13 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
     524                 :         13 :     enquire.set_query(query("this"));
     525                 :         13 :     Xapian::MSet mymset1 = enquire.get_mset(0, 6);
     526                 :         13 :     Xapian::MSet mymset2 = enquire.get_mset(3, 3);
     527   [ -  +  #  # ]:         13 :     TEST(mset_range_is_same(mymset1, 3, mymset2, 0, 3));
     528                 :            : 
     529                 :            :     // Regression test - we weren't adjusting the index into items[] by
     530                 :            :     // firstitem in api/omenquire.cc.
     531 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset1[5].get_document().get_data(),
     532                 :            :                mymset2[2].get_document().get_data());
     533                 :         13 :     return true;
     534                 :            : }
     535                 :            : 
     536                 :            : // tests the converting-to-percent functions
     537                 :         13 : DEFINE_TESTCASE(topercent1, backend) {
     538                 :         13 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
     539                 :         13 :     enquire.set_query(query("this"));
     540                 :         13 :     Xapian::MSet mymset = enquire.get_mset(0, 20);
     541                 :            : 
     542                 :         13 :     int last_pct = 100;
     543                 :         13 :     Xapian::MSetIterator i = mymset.begin();
     544         [ +  + ]:         91 :     for ( ; i != mymset.end(); ++i) {
     545                 :         78 :         int pct = mymset.convert_to_percent(i);
     546   [ -  +  #  # ]:         78 :         TEST_AND_EXPLAIN(pct == i.get_percent(),
     547                 :            :                          "convert_to_%(msetitor) != convert_to_%(wt)");
     548 [ -  + ][ #  # ]:         78 :         TEST_AND_EXPLAIN(pct == mymset.convert_to_percent(i.get_weight()),
     549                 :            :                          "convert_to_%(msetitor) != convert_to_%(wt)");
     550 [ +  - ][ -  + ]:         78 :         TEST_AND_EXPLAIN(pct >= 0 && pct <= 100,
                 [ #  # ]
     551                 :            :                          "percentage out of range: " << pct);
     552 [ -  + ][ #  # ]:         78 :         TEST_AND_EXPLAIN(pct <= last_pct, "percentage increased down mset");
     553                 :         78 :         last_pct = pct;
     554                 :            :     }
     555                 :         13 :     return true;
     556                 :            : }
     557                 :            : 
     558                 :            : // tests the percentage values returned
     559                 :         14 : DEFINE_TESTCASE(topercent2, backend) {
     560                 :         14 :     BackendManagerLocal local_manager;
     561                 :         14 :     local_manager.set_datadir(test_driver::get_srcdir() + "/testdata/");
     562                 :         14 :     Xapian::Enquire localenq(local_manager.get_database("apitest_simpledata"));
     563                 :         14 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
     564                 :            : 
     565                 :            :     int pct;
     566                 :            : 
     567                 :            :     // First, test a search in which the top document scores 100%.
     568                 :         14 :     enquire.set_query(query("this"));
     569                 :         14 :     localenq.set_query(query("this"));
     570                 :         14 :     Xapian::MSet mymset = enquire.get_mset(0, 20);
     571                 :         14 :     Xapian::MSet localmset = localenq.get_mset(0, 20);
     572                 :            : 
     573                 :         14 :     Xapian::MSetIterator i = mymset.begin();
     574 [ -  + ][ #  # ]:         14 :     TEST(i != mymset.end());
     575                 :         14 :     pct = mymset.convert_to_percent(i);
     576   [ -  +  #  # ]:         14 :     TEST_EQUAL(pct, 100);
     577                 :            : 
     578 [ -  + ][ #  # ]:         14 :     TEST_EQUAL(mymset.get_matches_lower_bound(), localmset.get_matches_lower_bound());
     579 [ -  + ][ #  # ]:         14 :     TEST_EQUAL(mymset.get_matches_upper_bound(), localmset.get_matches_upper_bound());
     580 [ -  + ][ #  # ]:         14 :     TEST_EQUAL(mymset.get_matches_estimated(), localmset.get_matches_estimated());
     581 [ -  + ][ #  # ]:         14 :     TEST_EQUAL_DOUBLE(mymset.get_max_attained(), localmset.get_max_attained());
     582 [ -  + ][ #  # ]:         14 :     TEST_EQUAL(mymset.size(), localmset.size());
     583 [ -  + ][ #  # ]:         14 :     TEST(mset_range_is_same(mymset, 0, localmset, 0, mymset.size()));
     584                 :            : 
     585                 :            :     // A search in which the top document doesn't have 100%
     586                 :            :     Xapian::Query q = query(Xapian::Query::OP_OR,
     587                 :         14 :                             "this", "line", "paragraph", "rubbish");
     588                 :         14 :     enquire.set_query(q);
     589                 :         14 :     localenq.set_query(q);
     590                 :         14 :     mymset = enquire.get_mset(0, 20);
     591                 :         14 :     localmset = localenq.get_mset(0, 20);
     592                 :            : 
     593                 :         14 :     i = mymset.begin();
     594 [ -  + ][ #  # ]:         14 :     TEST(i != mymset.end());
     595                 :         14 :     pct = mymset.convert_to_percent(i);
     596   [ -  +  #  # ]:         14 :     TEST_REL(pct,>,60);
     597 [ -  + ][ #  # ]:         14 :     TEST_REL(pct,<,76);
     598                 :            : 
     599                 :         14 :     ++i;
     600                 :            : 
     601 [ -  + ][ #  # ]:         14 :     TEST(i != mymset.end());
     602                 :         14 :     pct = mymset.convert_to_percent(i);
     603   [ -  +  #  # ]:         14 :     TEST_REL(pct,>,40);
     604 [ -  + ][ #  # ]:         14 :     TEST_REL(pct,<,50);
     605                 :            : 
     606 [ -  + ][ #  # ]:         14 :     TEST_EQUAL(mymset.get_matches_lower_bound(), localmset.get_matches_lower_bound());
     607 [ -  + ][ #  # ]:         14 :     TEST_EQUAL(mymset.get_matches_upper_bound(), localmset.get_matches_upper_bound());
     608 [ -  + ][ #  # ]:         14 :     TEST_EQUAL(mymset.get_matches_estimated(), localmset.get_matches_estimated());
     609 [ -  + ][ #  # ]:         14 :     TEST_EQUAL_DOUBLE(mymset.get_max_attained(), localmset.get_max_attained());
     610 [ -  + ][ #  # ]:         14 :     TEST_EQUAL(mymset.size(), localmset.size());
     611 [ -  + ][ #  # ]:         14 :     TEST(mset_range_is_same(mymset, 0, localmset, 0, mymset.size()));
     612                 :            : 
     613                 :         14 :     return true;
     614                 :            : }
     615                 :            : 
     616 [ #  # ][ -  + ]:         26 : class myExpandFunctor : public Xapian::ExpandDecider {
     617                 :            :     public:
     618                 :       2429 :         bool operator()(const string & tname) const {
     619                 :       2429 :             unsigned long sum = 0;
     620         [ +  + ]:      12363 :             for (string::const_iterator i=tname.begin(); i!=tname.end(); ++i) {
     621                 :       9934 :                 sum += *i;
     622                 :            :             }
     623                 :            : //          if (verbose) {
     624                 :            : //              tout << tname << "==> " << sum << "\n";
     625                 :            : //          }
     626                 :       2429 :             return (sum % 2) == 0;
     627                 :            :         }
     628                 :            : };
     629                 :            : 
     630                 :            : // tests the expand decision functor
     631                 :         13 : DEFINE_TESTCASE(expandfunctor1, backend) {
     632                 :         13 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
     633                 :         13 :     enquire.set_query(Xapian::Query("this"));
     634                 :            : 
     635                 :         13 :     Xapian::MSet mymset = enquire.get_mset(0, 10);
     636   [ -  +  #  # ]:         13 :     TEST(mymset.size() >= 2);
     637                 :            : 
     638                 :         13 :     Xapian::RSet myrset;
     639                 :         13 :     Xapian::MSetIterator i = mymset.begin();
     640                 :         13 :     myrset.add_document(*i);
     641                 :         13 :     myrset.add_document(*(++i));
     642                 :            : 
     643                 :         13 :     myExpandFunctor myfunctor;
     644                 :            : 
     645                 :         13 :     Xapian::ESet myeset_orig = enquire.get_eset(1000, myrset);
     646                 :         13 :     unsigned int neweset_size = 0;
     647                 :         13 :     Xapian::ESetIterator j = myeset_orig.begin();
     648         [ +  + ]:        792 :     for ( ; j != myeset_orig.end(); ++j) {
     649         [ +  + ]:        779 :         if (myfunctor(*j)) neweset_size++;
     650                 :            :     }
     651                 :         13 :     Xapian::ESet myeset = enquire.get_eset(neweset_size, myrset, &myfunctor);
     652                 :            : 
     653                 :            : #if 0
     654                 :            :     // Compare myeset with the hand-filtered version of myeset_orig.
     655                 :            :     if (verbose) {
     656                 :            :         tout << "orig_eset: ";
     657                 :            :         copy(myeset_orig.begin(), myeset_orig.end(),
     658                 :            :              ostream_iterator<Xapian::ESetItem>(tout, " "));
     659                 :            :         tout << "\n";
     660                 :            : 
     661                 :            :         tout << "new_eset: ";
     662                 :            :         copy(myeset.begin(), myeset.end(),
     663                 :            :              ostream_iterator<Xapian::ESetItem>(tout, " "));
     664                 :            :         tout << "\n";
     665                 :            :     }
     666                 :            : #endif
     667                 :         13 :     Xapian::ESetIterator orig = myeset_orig.begin();
     668                 :         13 :     Xapian::ESetIterator filt = myeset.begin();
     669 [ +  - ][ +  + ]:        336 :     for (; orig != myeset_orig.end() && filt != myeset.end(); ++orig, ++filt) {
         [ +  - ][ #  # ]
         [ #  # ][ +  - ]
                 [ +  + ]
     670                 :            :         // skip over items that shouldn't be in myeset
     671 [ +  - ][ +  + ]:        753 :         while (orig != myeset_orig.end() && !myfunctor(*orig)) {
         [ +  - ][ #  # ]
                 [ +  + ]
     672                 :        430 :             ++orig;
     673                 :            :         }
     674                 :            : 
     675 [ +  - ][ -  + ]:        323 :         TEST_AND_EXPLAIN(*orig == *filt &&
         [ -  + ][ #  # ]
     676                 :            :                          orig.get_weight() == filt.get_weight(),
     677                 :            :                          "Mismatch in items " << *orig << " vs. " << *filt
     678                 :            :                          << " after filtering");
     679                 :            :     }
     680                 :            : 
     681 [ +  + ][ +  - ]:         39 :     while (orig != myeset_orig.end() && !myfunctor(*orig)) {
         [ +  - ][ #  # ]
                 [ +  + ]
     682                 :         26 :         ++orig;
     683                 :            :     }
     684                 :            : 
     685 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(orig, myeset_orig.end());
     686 [ -  + ][ #  # ]:         13 :     TEST_AND_EXPLAIN(filt == myeset.end(),
     687                 :            :                      "Extra items in the filtered eset.");
     688                 :         13 :     return true;
     689                 :            : }
     690                 :            : 
     691                 :            : // tests the percent cutoff option
     692                 :         13 : DEFINE_TESTCASE(pctcutoff1, backend) {
     693                 :         13 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
     694                 :            :     enquire.set_query(query(Xapian::Query::OP_OR,
     695                 :         13 :                             "this", "line", "paragraph", "rubbish"));
     696                 :         13 :     Xapian::MSet mymset1 = enquire.get_mset(0, 100);
     697                 :            : 
     698         [ -  + ]:         13 :     if (verbose) {
     699                 :          0 :         tout << "Original mset pcts:";
     700                 :          0 :         print_mset_percentages(mymset1);
     701                 :          0 :         tout << "\n";
     702                 :            :     }
     703                 :            : 
     704                 :         13 :     unsigned int num_items = 0;
     705                 :         13 :     int my_pct = 100;
     706                 :         13 :     int changes = 0;
     707                 :         13 :     Xapian::MSetIterator i = mymset1.begin();
     708                 :         13 :     int c = 0;
     709         [ +  - ]:         52 :     for ( ; i != mymset1.end(); ++i, ++c) {
     710                 :         52 :         int new_pct = mymset1.convert_to_percent(i);
     711         [ +  - ]:         52 :         if (new_pct != my_pct) {
     712                 :         52 :             changes++;
     713         [ +  + ]:         52 :             if (changes > 3) break;
     714                 :         39 :             num_items = c;
     715                 :         39 :             my_pct = new_pct;
     716                 :            :         }
     717                 :            :     }
     718                 :            : 
     719 [ -  + ][ #  # ]:         13 :     TEST_AND_EXPLAIN(changes > 3, "MSet not varied enough to test");
     720         [ -  + ]:         13 :     if (verbose) {
     721                 :          0 :         tout << "Cutoff percent: " << my_pct << "\n";
     722                 :            :     }
     723                 :            : 
     724                 :         13 :     enquire.set_cutoff(my_pct);
     725                 :         13 :     Xapian::MSet mymset2 = enquire.get_mset(0, 100);
     726                 :            : 
     727         [ -  + ]:         13 :     if (verbose) {
     728                 :          0 :         tout << "Percentages after cutoff:";
     729                 :          0 :         print_mset_percentages(mymset2);
     730                 :          0 :         tout << "\n";
     731                 :            :     }
     732                 :            : 
     733 [ -  + ][ #  # ]:         13 :     TEST_AND_EXPLAIN(mymset2.size() >= num_items,
     734                 :            :                      "Match with % cutoff lost too many items");
     735                 :            : 
     736 [ +  - ][ +  - ]:         13 :     TEST_AND_EXPLAIN(mymset2.size() == num_items ||
         [ -  + ][ +  - ]
         [ #  # ][ #  # ]
         [ +  - ][ -  + ]
                 [ #  # ]
     737                 :            :                      (mymset2.convert_to_percent(mymset2[num_items]) == my_pct &&
     738                 :            :                       mymset2.convert_to_percent(mymset2.back()) == my_pct),
     739                 :            :                      "Match with % cutoff returned too many items");
     740                 :            : 
     741                 :         13 :     return true;
     742                 :            : }
     743                 :            : 
     744                 :            : // Tests the percent cutoff option combined with collapsing
     745                 :         13 : DEFINE_TESTCASE(pctcutoff2, backend) {
     746                 :         13 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
     747                 :         13 :     enquire.set_query(Xapian::Query("this"));
     748                 :         13 :     enquire.set_query(Xapian::Query(Xapian::Query::OP_AND_NOT, Xapian::Query("this"), Xapian::Query("banana")));
     749                 :         13 :     Xapian::MSet mset = enquire.get_mset(0, 100);
     750                 :            : 
     751         [ -  + ]:         13 :     if (verbose) {
     752                 :          0 :         tout << "Original mset pcts:";
     753                 :          0 :         print_mset_percentages(mset);
     754                 :          0 :         tout << "\n";
     755                 :            :     }
     756                 :            : 
     757 [ -  + ][ #  # ]:         13 :     TEST(mset.size() >= 2);
     758 [ -  + ][ #  # ]:         13 :     TEST(mset[0].get_percent() - mset[1].get_percent() >= 2);
     759                 :            : 
     760                 :         13 :     Xapian::percent cutoff = mset[0].get_percent() + mset[1].get_percent();
     761                 :         13 :     cutoff /= 2;
     762                 :            : 
     763                 :         13 :     enquire.set_cutoff(cutoff);
     764                 :         13 :     enquire.set_collapse_key(1234); // Value which is always empty.
     765                 :            : 
     766                 :         13 :     Xapian::MSet mset2 = enquire.get_mset(0, 1);
     767   [ -  +  #  # ]:         13 :     TEST_EQUAL(mset2.size(), 1);
     768 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mset2.get_matches_lower_bound(), 1);
     769 [ -  + ][ #  # ]:         13 :     TEST_REL(mset2.get_uncollapsed_matches_lower_bound(),>=,1);
     770 [ -  + ][ #  # ]:         13 :     TEST_REL(mset2.get_uncollapsed_matches_lower_bound(),<=,mset.size());
     771 [ -  + ][ #  # ]:         13 :     TEST_REL(mset2.get_uncollapsed_matches_upper_bound(),>=,mset.size());
     772 [ -  + ][ #  # ]:         13 :     TEST_REL(mset2.get_uncollapsed_matches_lower_bound(),<=,mset2.get_uncollapsed_matches_estimated());
     773 [ -  + ][ #  # ]:         13 :     TEST_REL(mset2.get_uncollapsed_matches_upper_bound(),>=,mset2.get_uncollapsed_matches_estimated());
     774                 :            : 
     775                 :         13 :     return true;
     776                 :            : }
     777                 :            : 
     778                 :            : // Test that the percent cutoff option returns all the answers it should.
     779                 :         13 : DEFINE_TESTCASE(pctcutoff3, backend) {
     780                 :         13 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
     781                 :         13 :     enquire.set_query(Xapian::Query("this"));
     782                 :         13 :     Xapian::MSet mset1 = enquire.get_mset(0, 10);
     783                 :            : 
     784         [ -  + ]:         13 :     if (verbose) {
     785                 :          0 :         tout << "Original mset pcts:";
     786                 :          0 :         print_mset_percentages(mset1);
     787                 :          0 :         tout << "\n";
     788                 :            :     }
     789                 :            : 
     790                 :         13 :     int percent = 100;
     791         [ +  + ]:         91 :     for (Xapian::MSetIterator i = mset1.begin(); i != mset1.end(); ++i) {
     792                 :         78 :         int new_percent = mset1.convert_to_percent(i);
     793         [ +  + ]:         78 :         if (new_percent != percent) {
     794                 :         39 :             enquire.set_cutoff(percent);
     795                 :         39 :             Xapian::MSet mset2 = enquire.get_mset(0, 10);
     796   [ -  +  #  # ]:         39 :             TEST_EQUAL(mset2.size(), i.get_rank());
     797                 :         39 :             percent = new_percent;
     798                 :            :         }
     799                 :         13 :     }
     800                 :            : 
     801                 :         13 :     return true;
     802                 :            : }
     803                 :            : 
     804                 :            : // tests the cutoff option
     805                 :         13 : DEFINE_TESTCASE(cutoff1, backend) {
     806                 :         13 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
     807                 :            :     enquire.set_query(query(Xapian::Query::OP_OR,
     808                 :         13 :                             "this", "line", "paragraph", "rubbish"));
     809                 :         13 :     Xapian::MSet mymset1 = enquire.get_mset(0, 100);
     810                 :            : 
     811         [ -  + ]:         13 :     if (verbose) {
     812                 :          0 :         tout << "Original mset weights:";
     813                 :          0 :         print_mset_weights(mymset1);
     814                 :          0 :         tout << "\n";
     815                 :            :     }
     816                 :            : 
     817                 :         13 :     unsigned int num_items = 0;
     818                 :         13 :     Xapian::weight my_wt = -100;
     819                 :         13 :     int changes = 0;
     820                 :         13 :     Xapian::MSetIterator i = mymset1.begin();
     821                 :         13 :     int c = 0;
     822         [ +  - ]:         52 :     for ( ; i != mymset1.end(); ++i, ++c) {
     823                 :         52 :         Xapian::weight new_wt = i.get_weight();
     824         [ +  - ]:         52 :         if (new_wt != my_wt) {
     825                 :         52 :             changes++;
     826         [ +  + ]:         52 :             if (changes > 3) break;
     827                 :         39 :             num_items = c;
     828                 :         39 :             my_wt = new_wt;
     829                 :            :         }
     830                 :            :     }
     831                 :            : 
     832 [ -  + ][ #  # ]:         13 :     TEST_AND_EXPLAIN(changes > 3, "MSet not varied enough to test");
     833         [ -  + ]:         13 :     if (verbose) {
     834                 :          0 :         tout << "Cutoff weight: " << my_wt << "\n";
     835                 :            :     }
     836                 :            : 
     837                 :         13 :     enquire.set_cutoff(0, my_wt);
     838                 :         13 :     Xapian::MSet mymset2 = enquire.get_mset(0, 100);
     839                 :            : 
     840         [ -  + ]:         13 :     if (verbose) {
     841                 :          0 :         tout << "Weights after cutoff:";
     842                 :          0 :         print_mset_weights(mymset2);
     843                 :          0 :         tout << "\n";
     844                 :            :     }
     845                 :            : 
     846 [ -  + ][ #  # ]:         13 :     TEST_AND_EXPLAIN(mymset2.size() >= num_items,
     847                 :            :                      "Match with cutoff lost too many items");
     848                 :            : 
     849 [ +  - ][ +  - ]:         13 :     TEST_AND_EXPLAIN(mymset2.size() == num_items ||
         [ -  + ][ +  - ]
         [ #  # ][ #  # ]
         [ +  - ][ -  + ]
                 [ #  # ]
     850                 :            :                      (mymset2[num_items].get_weight() == my_wt &&
     851                 :            :                       mymset2.back().get_weight() == my_wt),
     852                 :            :                      "Match with cutoff returned too many items");
     853                 :            : 
     854                 :         13 :     return true;
     855                 :            : }
     856                 :            : 
     857                 :            : // tests the allow query terms expand option
     858                 :         13 : DEFINE_TESTCASE(allowqterms1, backend) {
     859                 :         13 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
     860                 :         13 :     string term = "paragraph";
     861                 :         13 :     enquire.set_query(Xapian::Query(term));
     862                 :            : 
     863                 :         13 :     Xapian::MSet mymset = enquire.get_mset(0, 10);
     864   [ -  +  #  # ]:         13 :     TEST(mymset.size() >= 2);
     865                 :            : 
     866                 :         13 :     Xapian::RSet myrset;
     867                 :         13 :     Xapian::MSetIterator i = mymset.begin();
     868                 :         13 :     myrset.add_document(*i);
     869                 :         13 :     myrset.add_document(*(++i));
     870                 :            : 
     871                 :         13 :     Xapian::ESet myeset = enquire.get_eset(1000, myrset);
     872                 :         13 :     Xapian::ESetIterator j = myeset.begin();
     873         [ +  + ]:        398 :     for ( ; j != myeset.end(); ++j) {
     874 [ -  + ][ #  # ]:        385 :         TEST_NOT_EQUAL(*j, term);
     875                 :            :     }
     876                 :            : 
     877                 :         13 :     Xapian::ESet myeset2 = enquire.get_eset(1000, myrset, Xapian::Enquire::INCLUDE_QUERY_TERMS);
     878                 :         13 :     j = myeset2.begin();
     879         [ +  - ]:        261 :     for ( ; j != myeset2.end(); ++j) {
     880         [ +  + ]:        261 :         if (*j == term) break;
     881                 :            :     }
     882 [ -  + ][ #  # ]:         13 :     TEST(j != myeset2.end());
     883                 :         13 :     return true;
     884                 :            : }
     885                 :            : 
     886                 :            : // tests that the MSet max_attained works
     887                 :         13 : DEFINE_TESTCASE(maxattain1, backend) {
     888                 :         13 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
     889                 :         13 :     enquire.set_query(query("this"));
     890                 :         13 :     Xapian::MSet mymset = enquire.get_mset(0, 100);
     891                 :            : 
     892                 :         13 :     Xapian::weight mymax = 0;
     893                 :         13 :     Xapian::MSetIterator i = mymset.begin();
     894         [ +  + ]:         91 :     for ( ; i != mymset.end(); ++i) {
     895         [ +  + ]:         78 :         if (i.get_weight() > mymax) mymax = i.get_weight();
     896                 :            :     }
     897 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymax, mymset.get_max_attained());
     898                 :            : 
     899                 :         13 :     return true;
     900                 :            : }
     901                 :            : 
     902                 :            : // tests a reversed boolean query
     903                 :         13 : DEFINE_TESTCASE(reversebool1, backend) {
     904                 :         13 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
     905                 :         13 :     enquire.set_query(Xapian::Query("this"));
     906                 :         13 :     enquire.set_weighting_scheme(Xapian::BoolWeight());
     907                 :            : 
     908                 :         13 :     Xapian::MSet mymset1 = enquire.get_mset(0, 100);
     909   [ -  +  #  # ]:         13 :     TEST_AND_EXPLAIN(mymset1.size() > 1,
     910                 :            :                      "Mset was too small to test properly");
     911                 :            : 
     912                 :         13 :     enquire.set_docid_order(Xapian::Enquire::ASCENDING);
     913                 :         13 :     Xapian::MSet mymset2 = enquire.get_mset(0, 100);
     914                 :         13 :     enquire.set_docid_order(Xapian::Enquire::DESCENDING);
     915                 :         13 :     Xapian::MSet mymset3 = enquire.get_mset(0, 100);
     916                 :            : 
     917                 :            :     // mymset1 and mymset2 should be identical
     918   [ -  +  #  # ]:         13 :     TEST_EQUAL(mymset1.size(), mymset2.size());
     919                 :            : 
     920                 :            :     {
     921                 :         13 :         Xapian::MSetIterator i = mymset1.begin();
     922                 :         13 :         Xapian::MSetIterator j = mymset2.begin();
     923         [ +  + ]:         91 :         for ( ; i != mymset1.end(), j != mymset2.end(); ++i, j++) {
     924                 :            :             // if this fails, then setting match_sort_forward=true was not
     925                 :            :             // the same as the default.
     926 [ -  + ][ #  # ]:         78 :             TEST_EQUAL(*i, *j);
     927                 :         13 :         }
     928                 :            :     }
     929                 :            : 
     930                 :            :     // mymset1 and mymset3 should be same but reversed
     931   [ -  +  #  # ]:         13 :     TEST_EQUAL(mymset1.size(), mymset3.size());
     932                 :            : 
     933                 :            :     {
     934                 :         13 :         Xapian::MSetIterator i = mymset1.begin();
     935                 :         13 :         vector<Xapian::docid> rev(mymset3.begin(), mymset3.end());
     936                 :            :         // Next iterator not const because of compiler brokenness (egcs 1.1.2)
     937                 :         13 :         vector<Xapian::docid>::reverse_iterator j = rev.rbegin();
     938         [ +  + ]:         91 :         for ( ; i != mymset1.end(); ++i, j++) {
     939                 :            :             // if this fails, then setting match_sort_forward=false didn't
     940                 :            :             // reverse the results.
     941 [ -  + ][ #  # ]:         78 :             TEST_EQUAL(*i, *j);
     942                 :         13 :         }
     943                 :            :     }
     944                 :            : 
     945                 :         13 :     return true;
     946                 :            : }
     947                 :            : 
     948                 :            : // tests a reversed boolean query, where the full mset isn't returned
     949                 :         13 : DEFINE_TESTCASE(reversebool2, backend) {
     950                 :         13 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
     951                 :         13 :     enquire.set_query(Xapian::Query("this"));
     952                 :         13 :     enquire.set_weighting_scheme(Xapian::BoolWeight());
     953                 :            : 
     954                 :         13 :     Xapian::MSet mymset1 = enquire.get_mset(0, 100);
     955                 :            : 
     956   [ -  +  #  # ]:         13 :     TEST_AND_EXPLAIN(mymset1.size() > 1,
     957                 :            :                      "Mset was too small to test properly");
     958                 :            : 
     959                 :         13 :     enquire.set_docid_order(Xapian::Enquire::ASCENDING);
     960                 :         13 :     Xapian::doccount msize = mymset1.size() / 2;
     961                 :         13 :     Xapian::MSet mymset2 = enquire.get_mset(0, msize);
     962                 :         13 :     enquire.set_docid_order(Xapian::Enquire::DESCENDING);
     963                 :         13 :     Xapian::MSet mymset3 = enquire.get_mset(0, msize);
     964                 :            : 
     965                 :            :     // mymset2 should be first msize items of mymset1
     966   [ -  +  #  # ]:         13 :     TEST_EQUAL(msize, mymset2.size());
     967                 :            :     {
     968                 :         13 :         Xapian::MSetIterator i = mymset1.begin();
     969                 :         13 :         Xapian::MSetIterator j = mymset2.begin();
     970         [ +  + ]:         52 :         for ( ; i != mymset1.end(), j != mymset2.end(); ++i, j++) {
     971                 :            :             // if this fails, then setting match_sort_forward=true was not
     972                 :            :             // the same as the default.
     973 [ -  + ][ #  # ]:         39 :             TEST_EQUAL(*i, *j);
     974                 :         13 :         }
     975                 :            :     }
     976                 :            : 
     977                 :            :     // mymset3 should be last msize items of mymset1, in reverse order
     978   [ -  +  #  # ]:         13 :     TEST_EQUAL(msize, mymset3.size());
     979                 :            :     {
     980                 :         13 :         vector<Xapian::docid> rev(mymset1.begin(), mymset1.end());
     981                 :            :         // Next iterator not const because of compiler brokenness (egcs 1.1.2)
     982                 :         13 :         vector<Xapian::docid>::reverse_iterator i = rev.rbegin();
     983                 :         13 :         Xapian::MSetIterator j = mymset3.begin();
     984         [ +  + ]:         52 :         for ( ; j != mymset3.end(); ++i, j++) {
     985                 :            :             // if this fails, then setting match_sort_forward=false didn't
     986                 :            :             // reverse the results.
     987 [ -  + ][ #  # ]:         39 :             TEST_EQUAL(*i, *j);
     988                 :         13 :         }
     989                 :            :     }
     990                 :            : 
     991                 :         13 :     return true;
     992                 :            : }
     993                 :            : 
     994                 :            : // tests that get_matching_terms() returns the terms in the right order
     995                 :         13 : DEFINE_TESTCASE(getmterms1, backend) {
     996                 :         13 :     list<string> answers_list;
     997                 :         13 :     answers_list.push_back("one");
     998                 :         13 :     answers_list.push_back("two");
     999                 :         13 :     answers_list.push_back("three");
    1000                 :         13 :     answers_list.push_back("four");
    1001                 :            : 
    1002                 :         13 :     Xapian::Database mydb(get_database("apitest_termorder"));
    1003                 :         13 :     Xapian::Enquire enquire(mydb);
    1004                 :            : 
    1005                 :            :     Xapian::Query myquery(Xapian::Query::OP_OR,
    1006                 :            :             Xapian::Query(Xapian::Query::OP_AND,
    1007                 :            :                     Xapian::Query("one", 1, 1),
    1008                 :            :                     Xapian::Query("three", 1, 3)),
    1009                 :            :             Xapian::Query(Xapian::Query::OP_OR,
    1010                 :            :                     Xapian::Query("four", 1, 4),
    1011                 :         13 :                     Xapian::Query("two", 1, 2)));
    1012                 :            : 
    1013                 :         13 :     enquire.set_query(myquery);
    1014                 :            : 
    1015                 :         13 :     Xapian::MSet mymset = enquire.get_mset(0, 10);
    1016                 :            : 
    1017   [ -  +  #  # ]:         13 :     TEST_MSET_SIZE(mymset, 1);
    1018                 :            :     list<string> list(enquire.get_matching_terms_begin(mymset.begin()),
    1019                 :         13 :                           enquire.get_matching_terms_end(mymset.begin()));
    1020   [ -  +  #  # ]:         13 :     TEST(list == answers_list);
    1021                 :            : 
    1022                 :         13 :     return true;
    1023                 :            : }
    1024                 :            : 
    1025                 :            : // tests that get_matching_terms() returns the terms only once
    1026                 :         13 : DEFINE_TESTCASE(getmterms2, backend) {
    1027                 :         13 :     list<string> answers_list;
    1028                 :         13 :     answers_list.push_back("one");
    1029                 :         13 :     answers_list.push_back("two");
    1030                 :         13 :     answers_list.push_back("three");
    1031                 :            : 
    1032                 :         13 :     Xapian::Database mydb(get_database("apitest_termorder"));
    1033                 :         13 :     Xapian::Enquire enquire(mydb);
    1034                 :            : 
    1035                 :            :     Xapian::Query myquery(Xapian::Query::OP_OR,
    1036                 :            :             Xapian::Query(Xapian::Query::OP_AND,
    1037                 :            :                     Xapian::Query("one", 1, 1),
    1038                 :            :                     Xapian::Query("three", 1, 3)),
    1039                 :            :             Xapian::Query(Xapian::Query::OP_OR,
    1040                 :            :                     Xapian::Query("one", 1, 4),
    1041                 :         13 :                     Xapian::Query("two", 1, 2)));
    1042                 :            : 
    1043                 :         13 :     enquire.set_query(myquery);
    1044                 :            : 
    1045                 :         13 :     Xapian::MSet mymset = enquire.get_mset(0, 10);
    1046                 :            : 
    1047   [ -  +  #  # ]:         13 :     TEST_MSET_SIZE(mymset, 1);
    1048                 :            :     list<string> list(enquire.get_matching_terms_begin(mymset.begin()),
    1049                 :         13 :                           enquire.get_matching_terms_end(mymset.begin()));
    1050   [ -  +  #  # ]:         13 :     TEST(list == answers_list);
    1051                 :            : 
    1052                 :         13 :     return true;
    1053                 :            : }
    1054                 :            : 
    1055                 :            : // tests that the collapsing on termpos optimisation works
    1056                 :         13 : DEFINE_TESTCASE(poscollapse1, backend) {
    1057                 :            :     Xapian::Query myquery1(Xapian::Query::OP_OR,
    1058                 :            :                      Xapian::Query("this", 1, 1),
    1059                 :         13 :                      Xapian::Query("this", 1, 1));
    1060                 :         13 :     Xapian::Query myquery2("this", 2, 1);
    1061                 :            : 
    1062         [ -  + ]:         13 :     if (verbose) {
    1063                 :          0 :         tout << myquery1.get_description() << "\n";
    1064                 :          0 :         tout << myquery2.get_description() << "\n";
    1065                 :            :     }
    1066                 :            : 
    1067                 :         13 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
    1068                 :         13 :     enquire.set_query(myquery1);
    1069                 :         13 :     Xapian::MSet mymset1 = enquire.get_mset(0, 10);
    1070                 :            : 
    1071                 :         13 :     enquire.set_query(myquery2);
    1072                 :         13 :     Xapian::MSet mymset2 = enquire.get_mset(0, 10);
    1073                 :            : 
    1074   [ -  +  #  # ]:         13 :     TEST_EQUAL(mymset1, mymset2);
    1075                 :            : 
    1076                 :         13 :     return true;
    1077                 :            : }
    1078                 :            : 
    1079                 :            : // test that running a query twice returns the same results
    1080                 :         13 : DEFINE_TESTCASE(repeatquery1, backend) {
    1081                 :         13 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
    1082                 :         13 :     enquire.set_query(Xapian::Query("this"));
    1083                 :            : 
    1084                 :         13 :     enquire.set_query(query(Xapian::Query::OP_OR, "this", "word"));
    1085                 :            : 
    1086                 :         13 :     Xapian::MSet mymset1 = enquire.get_mset(0, 10);
    1087                 :         13 :     Xapian::MSet mymset2 = enquire.get_mset(0, 10);
    1088   [ -  +  #  # ]:         13 :     TEST_EQUAL(mymset1, mymset2);
    1089                 :            : 
    1090                 :         13 :     return true;
    1091                 :            : }
    1092                 :            : 
    1093                 :            : // test that prefetching documents works (at least, gives same results)
    1094                 :         13 : DEFINE_TESTCASE(fetchdocs1, backend) {
    1095                 :         13 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
    1096                 :         13 :     enquire.set_query(Xapian::Query("this"));
    1097                 :            : 
    1098                 :         13 :     enquire.set_query(query(Xapian::Query::OP_OR, "this", "word"));
    1099                 :            : 
    1100                 :         13 :     Xapian::MSet mymset1 = enquire.get_mset(0, 10);
    1101                 :         13 :     Xapian::MSet mymset2 = enquire.get_mset(0, 10);
    1102   [ -  +  #  # ]:         13 :     TEST_EQUAL(mymset1, mymset2);
    1103                 :         13 :     mymset2.fetch(mymset2[0], mymset2[mymset2.size() - 1]);
    1104                 :         13 :     mymset2.fetch(mymset2.begin(), mymset2.end());
    1105                 :         13 :     mymset2.fetch(mymset2.begin());
    1106                 :         13 :     mymset2.fetch();
    1107                 :            : 
    1108                 :         13 :     Xapian::MSetIterator it1 = mymset1.begin();
    1109                 :         13 :     Xapian::MSetIterator it2 = mymset2.begin();
    1110                 :            : 
    1111 [ +  + ][ +  - ]:         91 :     while (it1 != mymset1.end() && it2 != mymset2.end()) {
         [ +  + ][ #  # ]
         [ #  # ][ +  - ]
                 [ +  + ]
    1112 [ -  + ][ #  # ]:         78 :         TEST_EQUAL(it1.get_document().get_data(),
    1113                 :            :                    it2.get_document().get_data());
    1114 [ -  + ][ #  # ]:         78 :         TEST_NOT_EQUAL(it1.get_document().get_data(), "");
    1115 [ -  + ][ #  # ]:         78 :         TEST_NOT_EQUAL(it2.get_document().get_data(), "");
    1116                 :         78 :         it1++;
    1117                 :         78 :         it2++;
    1118                 :            :     }
    1119 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(it1, mymset1.end());
    1120 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(it1, mymset2.end());
    1121                 :            : 
    1122                 :         13 :     return true;
    1123                 :            : }
    1124                 :            : 
    1125                 :            : // test that searching for a term not in the database fails nicely
    1126                 :         13 : DEFINE_TESTCASE(absentterm1, backend) {
    1127                 :         13 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
    1128                 :         13 :     enquire.set_weighting_scheme(Xapian::BoolWeight());
    1129                 :         13 :     enquire.set_query(Xapian::Query("frink"));
    1130                 :            : 
    1131                 :         13 :     Xapian::MSet mymset = enquire.get_mset(0, 10);
    1132                 :         13 :     mset_expect_order(mymset);
    1133                 :            : 
    1134                 :         13 :     return true;
    1135                 :            : }
    1136                 :            : 
    1137                 :            : // as absentterm1, but setting query from a vector of terms
    1138                 :         13 : DEFINE_TESTCASE(absentterm2, backend) {
    1139                 :         13 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
    1140                 :         13 :     vector<string> terms;
    1141                 :         13 :     terms.push_back("frink");
    1142                 :            : 
    1143                 :         13 :     Xapian::Query query(Xapian::Query::OP_OR, terms.begin(), terms.end());
    1144                 :         13 :     enquire.set_query(query);
    1145                 :            : 
    1146                 :         13 :     Xapian::MSet mymset = enquire.get_mset(0, 10);
    1147                 :         13 :     mset_expect_order(mymset);
    1148                 :            : 
    1149                 :         13 :     return true;
    1150                 :            : }
    1151                 :            : 
    1152                 :            : // test that rsets do sensible things
    1153                 :         13 : DEFINE_TESTCASE(rset1, backend) {
    1154                 :         13 :     Xapian::Database mydb(get_database("apitest_rset"));
    1155                 :         13 :     Xapian::Enquire enquire(mydb);
    1156                 :         13 :     Xapian::Query myquery = query(Xapian::Query::OP_OR, "giraffe", "tiger");
    1157                 :         13 :     enquire.set_query(myquery);
    1158                 :            : 
    1159                 :         13 :     Xapian::MSet mymset1 = enquire.get_mset(0, 10);
    1160                 :            : 
    1161                 :         13 :     Xapian::RSet myrset;
    1162                 :         13 :     myrset.add_document(1);
    1163                 :            : 
    1164                 :         13 :     Xapian::MSet mymset2 = enquire.get_mset(0, 10, &myrset);
    1165                 :            : 
    1166                 :            :     // We should have the same documents turn up, but 1 and 3 should
    1167                 :            :     // have higher weights with the RSet.
    1168   [ -  +  #  # ]:         13 :     TEST_MSET_SIZE(mymset1, 3);
    1169 [ -  + ][ #  # ]:         13 :     TEST_MSET_SIZE(mymset2, 3);
    1170                 :            : 
    1171                 :         13 :     return true;
    1172                 :            : }
    1173                 :            : 
    1174                 :            : // test that rsets do more sensible things
    1175                 :         13 : DEFINE_TESTCASE(rset2, backend) {
    1176                 :         13 :     Xapian::Database mydb(get_database("apitest_rset"));
    1177                 :         13 :     Xapian::Enquire enquire(mydb);
    1178                 :         13 :     Xapian::Query myquery = query(Xapian::Query::OP_OR, "cuddly", "people");
    1179                 :         13 :     enquire.set_query(myquery);
    1180                 :            : 
    1181                 :         13 :     Xapian::MSet mymset1 = enquire.get_mset(0, 10);
    1182                 :            : 
    1183                 :         13 :     Xapian::RSet myrset;
    1184                 :         13 :     myrset.add_document(2);
    1185                 :            : 
    1186                 :         13 :     Xapian::MSet mymset2 = enquire.get_mset(0, 10, &myrset);
    1187                 :            : 
    1188                 :         13 :     mset_expect_order(mymset1, 1, 2);
    1189                 :         13 :     mset_expect_order(mymset2, 2, 1);
    1190                 :            : 
    1191                 :         13 :     return true;
    1192                 :            : }
    1193                 :            : 
    1194                 :            : // test that rsets behave correctly with multiDBs
    1195                 :         10 : DEFINE_TESTCASE(rsetmultidb1, backend && !multi) {
    1196                 :         10 :     Xapian::Database mydb1(get_database("apitest_rset", "apitest_simpledata2"));
    1197                 :         10 :     Xapian::Database mydb2(get_database("apitest_rset"));
    1198                 :         10 :     mydb2.add_database(get_database("apitest_simpledata2"));
    1199                 :            : 
    1200                 :         10 :     Xapian::Enquire enquire1(mydb1);
    1201                 :         10 :     Xapian::Enquire enquire2(mydb2);
    1202                 :            : 
    1203                 :         10 :     Xapian::Query myquery = query(Xapian::Query::OP_OR, "cuddly", "multiple");
    1204                 :            : 
    1205                 :         10 :     enquire1.set_query(myquery);
    1206                 :         10 :     enquire2.set_query(myquery);
    1207                 :            : 
    1208                 :         10 :     Xapian::RSet myrset1;
    1209                 :         10 :     Xapian::RSet myrset2;
    1210                 :         10 :     myrset1.add_document(4);
    1211                 :         10 :     myrset2.add_document(2);
    1212                 :            : 
    1213                 :         10 :     Xapian::MSet mymset1a = enquire1.get_mset(0, 10);
    1214                 :         10 :     Xapian::MSet mymset1b = enquire1.get_mset(0, 10, &myrset1);
    1215                 :         10 :     Xapian::MSet mymset2a = enquire2.get_mset(0, 10);
    1216                 :         10 :     Xapian::MSet mymset2b = enquire2.get_mset(0, 10, &myrset2);
    1217                 :            : 
    1218                 :         10 :     mset_expect_order(mymset1a, 1, 4);
    1219                 :         10 :     mset_expect_order(mymset1b, 4, 1);
    1220                 :         10 :     mset_expect_order(mymset2a, 1, 2);
    1221                 :         10 :     mset_expect_order(mymset2b, 2, 1);
    1222                 :            : 
    1223   [ -  +  #  # ]:         10 :     TEST(mset_range_is_same_weights(mymset1a, 0, mymset2a, 0, 2));
    1224 [ -  + ][ #  # ]:         10 :     TEST(mset_range_is_same_weights(mymset1b, 0, mymset2b, 0, 2));
    1225 [ -  + ][ #  # ]:         10 :     TEST_NOT_EQUAL(mymset1a, mymset1b);
    1226 [ -  + ][ #  # ]:         10 :     TEST_NOT_EQUAL(mymset2a, mymset2b);
    1227                 :            : 
    1228                 :         10 :     return true;
    1229                 :            : }
    1230                 :            : 
    1231                 :            : // regression tests - used to cause assertion in stats.h to fail
    1232                 :            : // Doesn't actually fail for multi but it doesn't make sense to run there.
    1233                 :         10 : DEFINE_TESTCASE(rsetmultidb3, backend && !multi) {
    1234                 :         10 :     Xapian::Enquire enquire(get_database("apitest_simpledata2"));
    1235                 :         10 :     enquire.set_query(query(Xapian::Query::OP_OR, "cuddly", "people"));
    1236                 :         10 :     Xapian::MSet mset = enquire.get_mset(0, 10); // used to fail assertion
    1237                 :         10 :     return true;
    1238                 :            : }
    1239                 :            : 
    1240                 :            : /// Simple test of the elite set operator.
    1241                 :         13 : DEFINE_TESTCASE(eliteset1, backend) {
    1242                 :            :     // FIXME: OP_ELITE_SET erroneously picks the best N terms separately in
    1243                 :            :     // each sub-database!
    1244                 :         19 :     SKIP_TEST_FOR_BACKEND("multi");
    1245                 :            : 
    1246                 :         10 :     Xapian::Database mydb(get_database("apitest_simpledata"));
    1247                 :         10 :     Xapian::Enquire enquire(mydb);
    1248                 :            : 
    1249                 :         10 :     Xapian::Query myquery1 = query(Xapian::Query::OP_OR, "word");
    1250                 :            : 
    1251                 :            :     Xapian::Query myquery2 = query(Xapian::Query::OP_ELITE_SET, 1,
    1252                 :         10 :                                    "simple", "word");
    1253                 :            : 
    1254                 :         10 :     enquire.set_query(myquery1, 2); // So the query lengths are the same.
    1255                 :         10 :     Xapian::MSet mymset1 = enquire.get_mset(0, 10);
    1256                 :            : 
    1257                 :         10 :     enquire.set_query(myquery2);
    1258                 :         10 :     Xapian::MSet mymset2 = enquire.get_mset(0, 10);
    1259                 :            : 
    1260   [ -  +  #  # ]:         10 :     TEST_EQUAL(mymset1, mymset2);
    1261                 :         10 :     return true;
    1262                 :            : }
    1263                 :            : 
    1264                 :            : /// Test that the elite set operator works if the set contains
    1265                 :            : /// sub-expressions (regression test)
    1266                 :         13 : DEFINE_TESTCASE(eliteset2, backend) {
    1267                 :            :     // FIXME: OP_ELITE_SET erroneously picks the best N terms separately in
    1268                 :            :     // each sub-database!
    1269                 :         19 :     SKIP_TEST_FOR_BACKEND("multi");
    1270                 :            : 
    1271                 :         10 :     Xapian::Database mydb(get_database("apitest_simpledata"));
    1272                 :         10 :     Xapian::Enquire enquire(mydb);
    1273                 :            : 
    1274                 :         10 :     Xapian::Query myquery1 = query(Xapian::Query::OP_AND, "word", "search");
    1275                 :            : 
    1276                 :         10 :     vector<Xapian::Query> qs;
    1277                 :         10 :     qs.push_back(query("this"));
    1278                 :         10 :     qs.push_back(query(Xapian::Query::OP_AND, "word", "search"));
    1279                 :            :     Xapian::Query myquery2(Xapian::Query::OP_ELITE_SET,
    1280                 :         10 :                            qs.begin(), qs.end(), 1);
    1281                 :            : 
    1282                 :         10 :     enquire.set_query(myquery1);
    1283                 :         10 :     Xapian::MSet mymset1 = enquire.get_mset(0, 10);
    1284                 :            : 
    1285                 :         10 :     enquire.set_query(myquery2);
    1286                 :         10 :     Xapian::MSet mymset2 = enquire.get_mset(0, 10);
    1287                 :            : 
    1288   [ -  +  #  # ]:         10 :     TEST_EQUAL(mymset1, mymset2);
    1289                 :            :     // query lengths differ so mset weights not the same (with some weighting
    1290                 :            :     // parameters)
    1291                 :            :     //test_mset_order_equal(mymset1, mymset2);
    1292                 :            : 
    1293                 :         10 :     return true;
    1294                 :            : }
    1295                 :            : 
    1296                 :            : /// Test that elite set doesn't affect query results if we have fewer
    1297                 :            : /// terms than the threshold
    1298                 :         13 : DEFINE_TESTCASE(eliteset3, backend) {
    1299                 :         13 :     Xapian::Database mydb1(get_database("apitest_simpledata"));
    1300                 :         13 :     Xapian::Enquire enquire1(mydb1);
    1301                 :            : 
    1302                 :         13 :     Xapian::Database mydb2(get_database("apitest_simpledata"));
    1303                 :         13 :     Xapian::Enquire enquire2(mydb2);
    1304                 :            : 
    1305                 :            :     // make a query
    1306                 :         13 :     Xapian::Stem stemmer("english");
    1307                 :            : 
    1308                 :         13 :     string term1 = stemmer("word");
    1309                 :         13 :     string term2 = stemmer("rubbish");
    1310                 :         13 :     string term3 = stemmer("banana");
    1311                 :            : 
    1312                 :         13 :     vector<string> terms;
    1313                 :         13 :     terms.push_back(term1);
    1314                 :         13 :     terms.push_back(term2);
    1315                 :         13 :     terms.push_back(term3);
    1316                 :            : 
    1317                 :         13 :     Xapian::Query myquery1(Xapian::Query::OP_OR, terms.begin(), terms.end());
    1318                 :         13 :     enquire1.set_query(myquery1);
    1319                 :            : 
    1320                 :         13 :     Xapian::Query myquery2(Xapian::Query::OP_ELITE_SET, terms.begin(), terms.end(), 3);
    1321                 :         13 :     enquire2.set_query(myquery2);
    1322                 :            : 
    1323                 :            :     // retrieve the results
    1324                 :         13 :     Xapian::MSet mymset1 = enquire1.get_mset(0, 10);
    1325                 :         13 :     Xapian::MSet mymset2 = enquire2.get_mset(0, 10);
    1326                 :            : 
    1327   [ -  +  #  # ]:         13 :     TEST_EQUAL(mymset1.get_termfreq(term1),
    1328                 :            :                mymset2.get_termfreq(term1));
    1329 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset1.get_termweight(term1),
    1330                 :            :                mymset2.get_termweight(term1));
    1331 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset1.get_termfreq(term2),
    1332                 :            :                mymset2.get_termfreq(term2));
    1333 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset1.get_termweight(term2),
    1334                 :            :                mymset2.get_termweight(term2));
    1335 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset1.get_termfreq(term3),
    1336                 :            :                mymset2.get_termfreq(term3));
    1337 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset1.get_termweight(term3),
    1338                 :            :                mymset2.get_termweight(term3));
    1339                 :            : //    TEST_EQUAL(mymset1, mymset2);
    1340                 :            : 
    1341                 :         13 :     return true;
    1342                 :            : }
    1343                 :            : 
    1344                 :            : /// Test that elite set doesn't pick terms with 0 frequency
    1345                 :         13 : DEFINE_TESTCASE(eliteset4, backend) {
    1346                 :            :     // FIXME: OP_ELITE_SET erroneously picks the best N terms separately in
    1347                 :            :     // each sub-database!
    1348                 :         19 :     SKIP_TEST_FOR_BACKEND("multi");
    1349                 :            : 
    1350                 :         10 :     Xapian::Database mydb1(get_database("apitest_simpledata"));
    1351                 :         10 :     Xapian::Enquire enquire1(mydb1);
    1352                 :            : 
    1353                 :         10 :     Xapian::Database mydb2(get_database("apitest_simpledata"));
    1354                 :         10 :     Xapian::Enquire enquire2(mydb2);
    1355                 :            : 
    1356                 :         10 :     Xapian::Query myquery1 = query("rubbish");
    1357                 :            :     Xapian::Query myquery2 = query(Xapian::Query::OP_ELITE_SET, 1,
    1358                 :         10 :                                    "word", "rubbish", "fibble");
    1359                 :         10 :     enquire1.set_query(myquery1);
    1360                 :         10 :     enquire2.set_query(myquery2);
    1361                 :            : 
    1362                 :            :     // retrieve the results
    1363                 :         10 :     Xapian::MSet mymset1 = enquire1.get_mset(0, 10);
    1364                 :         10 :     Xapian::MSet mymset2 = enquire2.get_mset(0, 10);
    1365                 :            : 
    1366   [ -  +  #  # ]:         10 :     TEST_NOT_EQUAL(mymset2.size(), 0);
    1367 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(mymset1, mymset2);
    1368                 :            : //    TEST_EQUAL(mymset1, mymset2);
    1369                 :            : 
    1370                 :         10 :     return true;
    1371                 :            : }
    1372                 :            : 
    1373                 :            : /// Regression test for problem with excess precision.
    1374                 :         13 : DEFINE_TESTCASE(eliteset5, backend) {
    1375                 :         19 :     SKIP_TEST_FOR_BACKEND("multi");
    1376                 :            : 
    1377                 :         10 :     Xapian::Database mydb1(get_database("apitest_simpledata"));
    1378                 :         10 :     Xapian::Enquire enquire1(mydb1);
    1379                 :            : 
    1380                 :         10 :     vector<string> v;
    1381         [ +  + ]:         40 :     for (int i = 0; i != 3; ++i) {
    1382                 :         30 :         v.push_back("simpl");
    1383                 :         30 :         v.push_back("queri");
    1384                 :            : 
    1385                 :         30 :         v.push_back("rubbish");
    1386                 :         30 :         v.push_back("rubbish");
    1387                 :         30 :         v.push_back("rubbish");
    1388                 :         30 :         v.push_back("word");
    1389                 :         30 :         v.push_back("word");
    1390                 :         30 :         v.push_back("word");
    1391                 :            :     }
    1392                 :            : 
    1393                 :            :     Xapian::Query myquery1 = Xapian::Query(Xapian::Query::OP_ELITE_SET,
    1394                 :         10 :                                            v.begin(), v.end(), 1);
    1395                 :            :     myquery1 = Xapian::Query(Xapian::Query::OP_SCALE_WEIGHT,
    1396                 :            :                              myquery1,
    1397                 :         10 :                              0.004);
    1398                 :            : 
    1399                 :         10 :     enquire1.set_query(myquery1);
    1400                 :            :     // On architectures with excess precision (or, at least, on x86), the
    1401                 :            :     // following call used to result in a segfault.
    1402                 :         10 :     enquire1.get_mset(0, 10);
    1403                 :            : 
    1404                 :         10 :     return true;
    1405                 :            : }
    1406                 :            : 
    1407                 :            : /// Test that the termfreq returned by termlists is correct.
    1408                 :         13 : DEFINE_TESTCASE(termlisttermfreq1, backend) {
    1409                 :         13 :     Xapian::Database mydb(get_database("apitest_simpledata"));
    1410                 :         13 :     Xapian::Enquire enquire(mydb);
    1411                 :         13 :     Xapian::Stem stemmer("english");
    1412                 :         13 :     Xapian::RSet rset1;
    1413                 :         13 :     Xapian::RSet rset2;
    1414                 :         13 :     rset1.add_document(5);
    1415                 :         13 :     rset2.add_document(6);
    1416                 :            : 
    1417                 :         13 :     Xapian::ESet eset1 = enquire.get_eset(1000, rset1);
    1418                 :         13 :     Xapian::ESet eset2 = enquire.get_eset(1000, rset2);
    1419                 :            : 
    1420                 :            :     // search for weight of term 'another'
    1421                 :         13 :     string theterm = stemmer("another");
    1422                 :            : 
    1423                 :         13 :     Xapian::weight wt1 = 0;
    1424                 :         13 :     Xapian::weight wt2 = 0;
    1425                 :            :     {
    1426                 :         13 :         Xapian::ESetIterator i = eset1.begin();
    1427         [ +  - ]:         97 :         for ( ; i != eset1.end(); i++) {
    1428         [ +  + ]:         97 :             if (*i == theterm) {
    1429                 :         13 :                 wt1 = i.get_weight();
    1430                 :         13 :                 break;
    1431                 :            :             }
    1432                 :         13 :         }
    1433                 :            :     }
    1434                 :            :     {
    1435                 :         13 :         Xapian::ESetIterator i = eset2.begin();
    1436         [ +  - ]:        147 :         for ( ; i != eset2.end(); i++) {
    1437         [ +  + ]:        147 :             if (*i == theterm) {
    1438                 :         13 :                 wt2 = i.get_weight();
    1439                 :         13 :                 break;
    1440                 :            :             }
    1441                 :         13 :         }
    1442                 :            :     }
    1443                 :            : 
    1444   [ -  +  #  # ]:         13 :     TEST_NOT_EQUAL(wt1, 0);
    1445 [ -  + ][ #  # ]:         13 :     TEST_NOT_EQUAL(wt2, 0);
    1446 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(wt1, wt2);
    1447                 :            : 
    1448                 :         13 :     return true;
    1449                 :            : }
    1450                 :            : 
    1451                 :            : /// Test the termfrequency and termweight info returned for query terms
    1452                 :         13 : DEFINE_TESTCASE(qterminfo1, backend) {
    1453                 :         13 :     Xapian::Database mydb1(get_database("apitest_simpledata", "apitest_simpledata2"));
    1454                 :         13 :     Xapian::Enquire enquire1(mydb1);
    1455                 :            : 
    1456                 :         13 :     Xapian::Database mydb2(get_database("apitest_simpledata"));
    1457                 :         13 :     mydb2.add_database(get_database("apitest_simpledata2"));
    1458                 :         13 :     Xapian::Enquire enquire2(mydb2);
    1459                 :            : 
    1460                 :            :     // make a query
    1461                 :         13 :     Xapian::Stem stemmer("english");
    1462                 :            : 
    1463                 :         13 :     string term1 = stemmer("word");
    1464                 :         13 :     string term2 = stemmer("inmemory");
    1465                 :         13 :     string term3 = stemmer("flibble");
    1466                 :            : 
    1467                 :            :     Xapian::Query myquery(Xapian::Query::OP_OR,
    1468                 :            :                     Xapian::Query(term1),
    1469                 :            :                     Xapian::Query(Xapian::Query::OP_OR,
    1470                 :            :                             Xapian::Query(term2),
    1471                 :         13 :                             Xapian::Query(term3)));
    1472                 :         13 :     enquire1.set_query(myquery);
    1473                 :         13 :     enquire2.set_query(myquery);
    1474                 :            : 
    1475                 :            :     // retrieve the results
    1476                 :         13 :     Xapian::MSet mymset1a = enquire1.get_mset(0, 0);
    1477                 :         13 :     Xapian::MSet mymset2a = enquire2.get_mset(0, 0);
    1478                 :            : 
    1479   [ -  +  #  # ]:         13 :     TEST_EQUAL(mymset1a.get_termfreq(term1),
    1480                 :            :                mymset2a.get_termfreq(term1));
    1481 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset1a.get_termfreq(term2),
    1482                 :            :                mymset2a.get_termfreq(term2));
    1483 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset1a.get_termfreq(term3),
    1484                 :            :                mymset2a.get_termfreq(term3));
    1485                 :            : 
    1486 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset1a.get_termfreq(term1), 3);
    1487 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset1a.get_termfreq(term2), 1);
    1488 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset1a.get_termfreq(term3), 0);
    1489                 :            : 
    1490 [ -  + ][ #  # ]:         13 :     TEST_NOT_EQUAL(mymset1a.get_termweight(term1), 0);
    1491 [ -  + ][ #  # ]:         13 :     TEST_NOT_EQUAL(mymset1a.get_termweight(term2), 0);
    1492                 :            :     // non-existent terms should have 0 weight.
    1493 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset1a.get_termweight(term3), 0);
    1494                 :            : 
    1495 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset1a.get_termfreq(stemmer("banana")), 1);
    1496 [ +  - ][ -  + ]:         65 :     TEST_EXCEPTION(Xapian::InvalidArgumentError,
         [ #  # ][ -  + ]
    1497                 :            :                    mymset1a.get_termweight(stemmer("banana")));
    1498                 :            : 
    1499 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset1a.get_termfreq("sponge"), 0);
    1500 [ +  - ][ -  + ]:         52 :     TEST_EXCEPTION(Xapian::InvalidArgumentError,
         [ #  # ][ -  + ]
    1501                 :            :                    mymset1a.get_termweight("sponge"));
    1502                 :            : 
    1503                 :         13 :     return true;
    1504                 :            : }
    1505                 :            : 
    1506                 :            : /// Regression test for bug #37.
    1507                 :         13 : DEFINE_TESTCASE(qterminfo2, backend) {
    1508                 :         13 :     Xapian::Database db(get_database("apitest_simpledata"));
    1509                 :         13 :     Xapian::Enquire enquire(db);
    1510                 :            : 
    1511                 :            :     // make a query
    1512                 :         13 :     Xapian::Stem stemmer("english");
    1513                 :            : 
    1514                 :         13 :     string term1 = stemmer("paragraph");
    1515                 :         13 :     string term2 = stemmer("another");
    1516                 :            : 
    1517                 :            :     Xapian::Query query(Xapian::Query::OP_AND_NOT, term1,
    1518                 :         13 :             Xapian::Query(Xapian::Query::OP_AND, term1, term2));
    1519                 :         13 :     enquire.set_query(query);
    1520                 :            : 
    1521                 :            :     // retrieve the results
    1522                 :            :     // Note: get_mset() used to throw "AssertionError" in debug builds
    1523                 :         13 :     Xapian::MSet mset = enquire.get_mset(0, 10);
    1524                 :            : 
    1525 [ -  + ][ #  # ]:         13 :     TEST_NOT_EQUAL(mset.get_termweight("paragraph"), 0);
    1526                 :            : 
    1527                 :         13 :     return true;
    1528                 :            : }
    1529                 :            : 
    1530                 :            : // tests that when specifying that no items are to be returned, those
    1531                 :            : // statistics which should be the same are.
    1532                 :         13 : DEFINE_TESTCASE(msetzeroitems1, backend) {
    1533                 :         13 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
    1534                 :         13 :     enquire.set_query(query("this"));
    1535                 :         13 :     Xapian::MSet mymset1 = enquire.get_mset(0, 0);
    1536                 :            : 
    1537                 :         13 :     Xapian::MSet mymset2 = enquire.get_mset(0, 1);
    1538                 :            : 
    1539   [ -  +  #  # ]:         13 :     TEST_EQUAL(mymset1.get_max_possible(), mymset2.get_max_possible());
    1540                 :            : 
    1541                 :         13 :     return true;
    1542                 :            : }
    1543                 :            : 
    1544                 :            : // test that the matches_* of a simple query are as expected
    1545                 :         13 : DEFINE_TESTCASE(matches1, backend) {
    1546                 :         13 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
    1547                 :         13 :     Xapian::Query myquery;
    1548                 :         13 :     Xapian::MSet mymset;
    1549                 :            : 
    1550                 :         13 :     myquery = query("word");
    1551                 :         13 :     enquire.set_query(myquery);
    1552                 :         13 :     mymset = enquire.get_mset(0, 10);
    1553   [ -  +  #  # ]:         13 :     TEST_EQUAL(mymset.get_matches_lower_bound(), 2);
    1554 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_matches_estimated(), 2);
    1555 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_matches_upper_bound(), 2);
    1556 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_uncollapsed_matches_lower_bound(), 2);
    1557 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_uncollapsed_matches_estimated(), 2);
    1558 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_uncollapsed_matches_upper_bound(), 2);
    1559                 :            : 
    1560                 :         13 :     myquery = query(Xapian::Query::OP_OR, "inmemory", "word");
    1561                 :         13 :     enquire.set_query(myquery);
    1562                 :         13 :     mymset = enquire.get_mset(0, 10);
    1563   [ -  +  #  # ]:         13 :     TEST_EQUAL(mymset.get_matches_lower_bound(), 2);
    1564 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_matches_estimated(), 2);
    1565 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_matches_upper_bound(), 2);
    1566 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_uncollapsed_matches_lower_bound(), 2);
    1567 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_uncollapsed_matches_estimated(), 2);
    1568 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_uncollapsed_matches_upper_bound(), 2);
    1569                 :            : 
    1570                 :         13 :     myquery = query(Xapian::Query::OP_AND, "inmemory", "word");
    1571                 :         13 :     enquire.set_query(myquery);
    1572                 :         13 :     mymset = enquire.get_mset(0, 10);
    1573   [ -  +  #  # ]:         13 :     TEST_EQUAL(mymset.get_matches_lower_bound(), 0);
    1574 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_matches_estimated(), 0);
    1575 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_matches_upper_bound(), 0);
    1576 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_uncollapsed_matches_lower_bound(), 0);
    1577 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_uncollapsed_matches_estimated(), 0);
    1578 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_uncollapsed_matches_upper_bound(), 0);
    1579                 :            : 
    1580                 :         13 :     myquery = query(Xapian::Query::OP_AND, "simple", "word");
    1581                 :         13 :     enquire.set_query(myquery);
    1582                 :         13 :     mymset = enquire.get_mset(0, 10);
    1583   [ -  +  #  # ]:         13 :     TEST_EQUAL(mymset.get_matches_lower_bound(), 2);
    1584 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_matches_estimated(), 2);
    1585 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_matches_upper_bound(), 2);
    1586 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_uncollapsed_matches_lower_bound(), 2);
    1587 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_uncollapsed_matches_estimated(), 2);
    1588 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_uncollapsed_matches_upper_bound(), 2);
    1589                 :            : 
    1590                 :         13 :     myquery = query(Xapian::Query::OP_AND, "simple", "word");
    1591                 :         13 :     enquire.set_query(myquery);
    1592                 :         13 :     mymset = enquire.get_mset(0, 0);
    1593                 :            :     // For a single database, this is true, but not for "multi" (since there
    1594                 :            :     // one sub-database has 3 documents and simple and word both have termfreq
    1595                 :            :     // of 2, so the matcher can tell at least one document must match!)
    1596                 :            :     // TEST_EQUAL(mymset.get_matches_lower_bound(), 0);
    1597   [ -  +  #  # ]:         13 :     TEST_REL(mymset.get_matches_lower_bound(),<=,mymset.get_matches_estimated());
    1598 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_matches_estimated(), 1);
    1599 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_matches_upper_bound(), 2);
    1600 [ -  + ][ #  # ]:         13 :     TEST_REL(mymset.get_uncollapsed_matches_lower_bound(),<=,mymset.get_uncollapsed_matches_estimated());
    1601 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_uncollapsed_matches_estimated(), 1);
    1602 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_uncollapsed_matches_upper_bound(), 2);
    1603                 :            : 
    1604                 :         13 :     mymset = enquire.get_mset(0, 1);
    1605   [ -  +  #  # ]:         13 :     TEST_EQUAL(mymset.get_matches_lower_bound(), 2);
    1606 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_matches_estimated(), 2);
    1607 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_matches_upper_bound(), 2);
    1608 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_uncollapsed_matches_lower_bound(), 2);
    1609 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_uncollapsed_matches_estimated(), 2);
    1610 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_uncollapsed_matches_upper_bound(), 2);
    1611                 :            : 
    1612                 :         13 :     mymset = enquire.get_mset(0, 2);
    1613   [ -  +  #  # ]:         13 :     TEST_EQUAL(mymset.get_matches_lower_bound(), 2);
    1614 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_matches_estimated(), 2);
    1615 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_matches_upper_bound(), 2);
    1616 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_uncollapsed_matches_lower_bound(), 2);
    1617 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_uncollapsed_matches_estimated(), 2);
    1618 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_uncollapsed_matches_upper_bound(), 2);
    1619                 :            : 
    1620                 :         13 :     myquery = query(Xapian::Query::OP_AND, "paragraph", "another");
    1621                 :         13 :     enquire.set_query(myquery);
    1622                 :         13 :     mymset = enquire.get_mset(0, 0);
    1623   [ -  +  #  # ]:         13 :     TEST_EQUAL(mymset.get_matches_lower_bound(), 1);
    1624 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_matches_estimated(), 2);
    1625 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_matches_upper_bound(), 2);
    1626 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_uncollapsed_matches_lower_bound(), 1);
    1627 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_uncollapsed_matches_estimated(), 2);
    1628 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_uncollapsed_matches_upper_bound(), 2);
    1629                 :            : 
    1630                 :         13 :     mymset = enquire.get_mset(0, 1);
    1631   [ -  +  #  # ]:         13 :     TEST_EQUAL(mymset.get_matches_lower_bound(), 1);
    1632 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_matches_estimated(), 2);
    1633 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_matches_upper_bound(), 2);
    1634 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_uncollapsed_matches_lower_bound(), 1);
    1635 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_uncollapsed_matches_estimated(), 2);
    1636 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_uncollapsed_matches_upper_bound(), 2);
    1637                 :            : 
    1638                 :         13 :     mymset = enquire.get_mset(0, 2);
    1639   [ -  +  #  # ]:         13 :     TEST_EQUAL(mymset.get_matches_lower_bound(), 1);
    1640 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_matches_estimated(), 1);
    1641 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_matches_upper_bound(), 1);
    1642 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_uncollapsed_matches_lower_bound(), 1);
    1643 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_uncollapsed_matches_estimated(), 1);
    1644 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_uncollapsed_matches_upper_bound(), 1);
    1645                 :            : 
    1646                 :         13 :     mymset = enquire.get_mset(1, 20);
    1647   [ -  +  #  # ]:         13 :     TEST_EQUAL(mymset.get_matches_lower_bound(), 1);
    1648 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_matches_estimated(), 1);
    1649 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_matches_upper_bound(), 1);
    1650 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_uncollapsed_matches_lower_bound(), 1);
    1651 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_uncollapsed_matches_estimated(), 1);
    1652 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_uncollapsed_matches_upper_bound(), 1);
    1653                 :            : 
    1654                 :         13 :     return true;
    1655                 :            : }
    1656                 :            : 
    1657                 :            : // tests that wqf affects the document weights
    1658                 :         13 : DEFINE_TESTCASE(wqf1, backend) {
    1659                 :            :     // Both queries have length 2; in q1 word has wqf=2, in q2 word has wqf=1
    1660                 :         13 :     Xapian::Query q1("word", 2);
    1661                 :         13 :     Xapian::Query q2("word");
    1662                 :         13 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
    1663                 :         13 :     enquire.set_query(q1);
    1664                 :         13 :     Xapian::MSet mset1 = enquire.get_mset(0, 10);
    1665                 :         13 :     enquire.set_query(q2);
    1666                 :         13 :     Xapian::MSet mset2 = enquire.get_mset(0, 2);
    1667                 :            :     // Check the weights
    1668 [ -  + ][ #  # ]:         13 :     TEST(mset1.begin().get_weight() > mset2.begin().get_weight());
    1669                 :         13 :     return true;
    1670                 :            : }
    1671                 :            : 
    1672                 :            : // tests that query length affects the document weights
    1673                 :         13 : DEFINE_TESTCASE(qlen1, backend) {
    1674                 :         13 :     Xapian::Query q1("word");
    1675                 :         13 :     Xapian::Query q2("word");
    1676                 :         13 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
    1677                 :         13 :     enquire.set_query(q1);
    1678                 :         13 :     Xapian::MSet mset1 = enquire.get_mset(0, 10);
    1679                 :         13 :     enquire.set_query(q2);
    1680                 :         13 :     Xapian::MSet mset2 = enquire.get_mset(0, 2);
    1681                 :            :     // Check the weights
    1682                 :            :     //TEST(mset1.begin().get_weight() < mset2.begin().get_weight());
    1683 [ -  + ][ #  # ]:         13 :     TEST(mset1.begin().get_weight() == mset2.begin().get_weight());
    1684                 :         13 :     return true;
    1685                 :            : }
    1686                 :            : 
    1687                 :            : // tests that opening a non-existent termlist throws the correct exception
    1688                 :         13 : DEFINE_TESTCASE(termlist1, backend) {
    1689                 :         13 :     Xapian::Database db(get_database("apitest_onedoc"));
    1690 [ +  - ][ -  + ]:         26 :     TEST_EXCEPTION(Xapian::InvalidArgumentError,
         [ #  # ][ -  + ]
    1691                 :            :                    Xapian::TermIterator t = db.termlist_begin(0));
    1692 [ +  - ][ -  + ]:         26 :     TEST_EXCEPTION(Xapian::DocNotFoundError,
         [ #  # ][ -  + ]
    1693                 :            :                    Xapian::TermIterator t = db.termlist_begin(2));
    1694                 :            :     /* Cause the database to be used properly, showing up problems
    1695                 :            :      * with the link being in a bad state.  CME */
    1696                 :         13 :     Xapian::TermIterator temp = db.termlist_begin(1);
    1697 [ +  - ][ -  + ]:         26 :     TEST_EXCEPTION(Xapian::DocNotFoundError,
         [ #  # ][ -  + ]
    1698                 :            :                    Xapian::TermIterator t = db.termlist_begin(999999999));
    1699                 :         13 :     return true;
    1700                 :            : }
    1701                 :            : 
    1702                 :            : // tests that a Xapian::TermIterator works as an STL iterator
    1703                 :         13 : DEFINE_TESTCASE(termlist2, backend) {
    1704                 :         13 :     Xapian::Database db(get_database("apitest_onedoc"));
    1705                 :         13 :     Xapian::TermIterator t = db.termlist_begin(1);
    1706                 :         13 :     Xapian::TermIterator tend = db.termlist_end(1);
    1707                 :            : 
    1708                 :            :     // test operator= creates a copy which compares equal
    1709                 :         13 :     Xapian::TermIterator t_copy = t;
    1710   [ -  +  #  # ]:         13 :     TEST_EQUAL(t, t_copy);
    1711                 :            : 
    1712                 :            :     // test copy constructor creates a copy which compares equal
    1713                 :         13 :     Xapian::TermIterator t_clone(t);
    1714   [ -  +  #  # ]:         13 :     TEST_EQUAL(t, t_clone);
    1715                 :            : 
    1716                 :         13 :     vector<string> v(t, tend);
    1717                 :            : 
    1718                 :         13 :     t = db.termlist_begin(1);
    1719                 :         13 :     tend = db.termlist_end(1);
    1720                 :         13 :     vector<string>::const_iterator i;
    1721         [ +  + ]:        130 :     for (i = v.begin(); i != v.end(); i++) {
    1722 [ -  + ][ #  # ]:        117 :         TEST_NOT_EQUAL(t, tend);
    1723 [ -  + ][ #  # ]:        117 :         TEST_EQUAL(*i, *t);
    1724                 :        117 :         t++;
    1725                 :            :     }
    1726 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(t, tend);
    1727                 :         13 :     return true;
    1728                 :            : }
    1729                 :            : 
    1730                 :            : static Xapian::TermIterator
    1731                 :         13 : test_termlist3_helper()
    1732                 :            : {
    1733                 :         13 :     Xapian::Database db(get_database("apitest_onedoc"));
    1734                 :         13 :     return db.termlist_begin(1);
    1735                 :            : }
    1736                 :            : 
    1737                 :            : // tests that a Xapian::TermIterator still works when the DB is deleted
    1738                 :         13 : DEFINE_TESTCASE(termlist3, backend) {
    1739                 :         13 :     Xapian::TermIterator u = test_termlist3_helper();
    1740                 :         13 :     Xapian::Database db(get_database("apitest_onedoc"));
    1741                 :         13 :     Xapian::TermIterator t = db.termlist_begin(1);
    1742                 :         13 :     Xapian::TermIterator tend = db.termlist_end(1);
    1743                 :            : 
    1744         [ +  + ]:        130 :     while (t != tend) {
    1745 [ -  + ][ #  # ]:        117 :         TEST_EQUAL(*t, *u);
    1746                 :        117 :         t++;
    1747                 :        117 :         u++;
    1748                 :            :     }
    1749                 :         13 :     return true;
    1750                 :            : }
    1751                 :            : 
    1752                 :            : // tests skip_to
    1753                 :         13 : DEFINE_TESTCASE(termlist4, backend) {
    1754                 :         13 :     Xapian::Database db(get_database("apitest_onedoc"));
    1755                 :         13 :     Xapian::TermIterator i = db.termlist_begin(1);
    1756                 :         13 :     i.skip_to("");
    1757                 :         13 :     i.skip_to("\xff");
    1758                 :         13 :     return true;
    1759                 :            : }
    1760                 :            : 
    1761                 :            : // tests punctuation is OK in terms (particularly in remote queries)
    1762                 :         13 : DEFINE_TESTCASE(puncterms1, backend) {
    1763                 :         13 :     Xapian::Database db(get_database("apitest_punc"));
    1764                 :         13 :     Xapian::Enquire enquire(db);
    1765                 :            : 
    1766                 :         13 :     Xapian::Query q1("semi;colon");
    1767                 :         13 :     enquire.set_query(q1);
    1768                 :         13 :     Xapian::MSet m1 = enquire.get_mset(0, 10);
    1769                 :            : 
    1770                 :         13 :     Xapian::Query q2("col:on");
    1771                 :         13 :     enquire.set_query(q2);
    1772                 :         13 :     Xapian::MSet m2 = enquire.get_mset(0, 10);
    1773                 :            : 
    1774                 :         13 :     Xapian::Query q3("com,ma");
    1775                 :         13 :     enquire.set_query(q3);
    1776                 :         13 :     Xapian::MSet m3 = enquire.get_mset(0, 10);
    1777                 :            : 
    1778                 :         13 :     return true;
    1779                 :            : }
    1780                 :            : 
    1781                 :            : // test that searching for a term with a space or backslash in it works
    1782                 :         13 : DEFINE_TESTCASE(spaceterms1, backend) {
    1783                 :         13 :     Xapian::Enquire enquire(get_database("apitest_space"));
    1784                 :         13 :     Xapian::MSet mymset;
    1785                 :            :     Xapian::doccount count;
    1786                 :         13 :     Xapian::MSetIterator m;
    1787                 :         13 :     Xapian::Stem stemmer("english");
    1788                 :            : 
    1789                 :         13 :     enquire.set_query(stemmer("space man"));
    1790                 :         13 :     mymset = enquire.get_mset(0, 10);
    1791   [ -  +  #  # ]:         13 :     TEST_MSET_SIZE(mymset, 1);
    1792                 :         13 :     count = 0;
    1793         [ +  + ]:         26 :     for (m = mymset.begin(); m != mymset.end(); ++m) ++count;
    1794 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(count, 1);
    1795                 :            : 
    1796         [ +  + ]:         91 :     for (Xapian::valueno value_no = 1; value_no < 7; ++value_no) {
    1797 [ -  + ][ #  # ]:         78 :         TEST_NOT_EQUAL(mymset.begin().get_document().get_data(), "");
    1798 [ -  + ][ #  # ]:         78 :         TEST_NOT_EQUAL(mymset.begin().get_document().get_value(value_no), "");
    1799                 :            :     }
    1800                 :            : 
    1801                 :         13 :     enquire.set_query(stemmer("tab\tby"));
    1802                 :         13 :     mymset = enquire.get_mset(0, 10);
    1803   [ -  +  #  # ]:         13 :     TEST_MSET_SIZE(mymset, 1);
    1804                 :         13 :     count = 0;
    1805         [ +  + ]:         26 :     for (m = mymset.begin(); m != mymset.end(); ++m) ++count;
    1806 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(count, 1);
    1807                 :            : 
    1808         [ +  + ]:        104 :     for (Xapian::valueno value_no = 0; value_no < 7; ++value_no) {
    1809                 :         91 :         string value = mymset.begin().get_document().get_value(value_no);
    1810   [ -  +  #  # ]:         91 :         TEST_NOT_EQUAL(value, "");
    1811         [ +  + ]:         91 :         if (value_no == 0) {
    1812 [ -  + ][ #  # ]:         13 :             TEST(value.size() > 262);
    1813 [ -  + ][ #  # ]:         13 :             TEST_EQUAL(static_cast<unsigned char>(value[262]), 255);
    1814                 :            :         }
    1815                 :            :     }
    1816                 :            : 
    1817                 :         13 :     enquire.set_query(stemmer("back\\slash"));
    1818                 :         13 :     mymset = enquire.get_mset(0, 10);
    1819   [ -  +  #  # ]:         13 :     TEST_MSET_SIZE(mymset, 1);
    1820                 :         13 :     count = 0;
    1821         [ +  + ]:         26 :     for (m = mymset.begin(); m != mymset.end(); ++m) ++count;
    1822 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(count, 1);
    1823                 :            : 
    1824                 :         13 :     return true;
    1825                 :            : }
    1826                 :            : 
    1827                 :            : // test that XOR queries work
    1828                 :         13 : DEFINE_TESTCASE(xor1, backend) {
    1829                 :         13 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
    1830                 :         13 :     Xapian::Stem stemmer("english");
    1831                 :            : 
    1832                 :         13 :     vector<string> terms;
    1833                 :         13 :     terms.push_back(stemmer("this"));
    1834                 :         13 :     terms.push_back(stemmer("word"));
    1835                 :         13 :     terms.push_back(stemmer("of"));
    1836                 :            : 
    1837                 :         13 :     Xapian::Query query(Xapian::Query::OP_XOR, terms.begin(), terms.end());
    1838                 :         13 :     enquire.set_weighting_scheme(Xapian::BoolWeight());
    1839                 :         13 :     enquire.set_query(query);
    1840                 :            : 
    1841                 :         13 :     Xapian::MSet mymset = enquire.get_mset(0, 10);
    1842                 :            :     //  Docid   this    word    of      Match?
    1843                 :            :     //  1       *                       *
    1844                 :            :     //  2       *       *       *       *
    1845                 :            :     //  3       *               *
    1846                 :            :     //  4       *       *
    1847                 :            :     //  5       *                       *
    1848                 :            :     //  6       *                       *
    1849                 :         13 :     mset_expect_order(mymset, 1, 2, 5, 6);
    1850                 :            : 
    1851                 :         13 :     return true;
    1852                 :            : }
    1853                 :            : 
    1854                 :            : /// Test that weighted XOR queries work (bug fixed in 1.2.1 and 1.0.21).
    1855                 :         13 : DEFINE_TESTCASE(xor2, backend) {
    1856                 :         13 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
    1857                 :         13 :     Xapian::Stem stemmer("english");
    1858                 :            : 
    1859                 :         13 :     vector<string> terms;
    1860                 :         13 :     terms.push_back(stemmer("this"));
    1861                 :         13 :     terms.push_back(stemmer("word"));
    1862                 :         13 :     terms.push_back(stemmer("of"));
    1863                 :            : 
    1864                 :         13 :     Xapian::Query query(Xapian::Query::OP_XOR, terms.begin(), terms.end());
    1865                 :         13 :     enquire.set_query(query);
    1866                 :            : 
    1867                 :         13 :     Xapian::MSet mymset = enquire.get_mset(0, 10);
    1868                 :            :     //  Docid   LEN     this    word    of      Match?
    1869                 :            :     //  1       28      2                       *
    1870                 :            :     //  2       81      5       8       1       *
    1871                 :            :     //  3       15      1               2
    1872                 :            :     //  4       31      1       1
    1873                 :            :     //  5       15      1                       *
    1874                 :            :     //  6       15      1                       *
    1875                 :         13 :     mset_expect_order(mymset, 2, 1, 5, 6);
    1876                 :            : 
    1877                 :         13 :     return true;
    1878                 :            : }
    1879                 :            : 
    1880                 :            : // test Xapian::Database::get_document()
    1881                 :         13 : DEFINE_TESTCASE(getdoc1, backend) {
    1882                 :         13 :     Xapian::Database db(get_database("apitest_onedoc"));
    1883                 :         13 :     Xapian::Document doc(db.get_document(1));
    1884 [ +  - ][ -  + ]:         26 :     TEST_EXCEPTION(Xapian::InvalidArgumentError, db.get_document(0));
         [ #  # ][ -  + ]
    1885 [ +  - ][ -  + ]:         26 :     TEST_EXCEPTION(Xapian::DocNotFoundError, db.get_document(999999999));
         [ #  # ][ -  + ]
    1886 [ +  - ][ -  + ]:         26 :     TEST_EXCEPTION(Xapian::DocNotFoundError, db.get_document(123456789));
         [ #  # ][ -  + ]
    1887 [ +  - ][ -  + ]:         26 :     TEST_EXCEPTION(Xapian::DocNotFoundError, db.get_document(3));
         [ #  # ][ -  + ]
    1888 [ +  - ][ -  + ]:         26 :     TEST_EXCEPTION(Xapian::DocNotFoundError, db.get_document(2));
         [ #  # ][ -  + ]
    1889                 :            :     // Check that Document works as a handle on modification
    1890                 :            :     // (this was broken for the first try at Xapian::Document prior to 0.7).
    1891                 :         13 :     Xapian::Document doc2 = doc;
    1892                 :         13 :     doc.set_data("modified!");
    1893 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(doc.get_data(), "modified!");
    1894 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(doc.get_data(), doc2.get_data());
    1895                 :         13 :     return true;
    1896                 :            : }
    1897                 :            : 
    1898                 :            : // test whether operators with no elements work as a null query
    1899                 :         13 : DEFINE_TESTCASE(emptyop1, backend) {
    1900                 :         13 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
    1901                 :         13 :     vector<Xapian::Query> nullvec;
    1902                 :            : 
    1903                 :         13 :     Xapian::Query query1(Xapian::Query::OP_XOR, nullvec.begin(), nullvec.end());
    1904                 :            : 
    1905                 :         13 :     enquire.set_query(query1);
    1906                 :         13 :     Xapian::MSet mymset = enquire.get_mset(0, 10);
    1907   [ -  +  #  # ]:         13 :     TEST_MSET_SIZE(mymset, 0);
    1908 [ +  - ][ -  + ]:         26 :     TEST_EXCEPTION(Xapian::InvalidArgumentError, enquire.get_matching_terms_begin(1));
         [ #  # ][ -  + ]
    1909                 :            : 
    1910                 :         13 :     return true;
    1911                 :            : }
    1912                 :            : 
    1913                 :            : // Regression test for check_at_least SEGV when there are no matches.
    1914                 :         13 : DEFINE_TESTCASE(checkatleast1, backend) {
    1915                 :         13 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
    1916                 :         13 :     enquire.set_query(Xapian::Query("thom"));
    1917                 :         13 :     Xapian::MSet mymset = enquire.get_mset(0, 10, 11);
    1918   [ -  +  #  # ]:         13 :     TEST_EQUAL(0, mymset.size());
    1919                 :            : 
    1920                 :         13 :     return true;
    1921                 :            : }
    1922                 :            : 
    1923                 :            : // Regression test - if check_at_least was set we returned (check_at_least - 1)
    1924                 :            : // results, rather than the requested msize.  Fixed in 1.0.2.
    1925                 :         13 : DEFINE_TESTCASE(checkatleast2, backend) {
    1926                 :         13 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
    1927                 :         13 :     enquire.set_query(Xapian::Query("paragraph"));
    1928                 :            : 
    1929                 :         13 :     Xapian::MSet mymset = enquire.get_mset(0, 3, 10);
    1930   [ -  +  #  # ]:         13 :     TEST_MSET_SIZE(mymset, 3);
    1931 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_matches_lower_bound(), 5);
    1932 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mymset.get_uncollapsed_matches_lower_bound(), 5);
    1933                 :            : 
    1934                 :         13 :     mymset = enquire.get_mset(0, 2, 4);
    1935   [ -  +  #  # ]:         13 :     TEST_MSET_SIZE(mymset, 2);
    1936 [ -  + ][ #  # ]:         13 :     TEST_REL(mymset.get_matches_lower_bound(),>=,4);
    1937 [ -  + ][ #  # ]:         13 :     TEST_REL(mymset.get_matches_lower_bound(),>=,4);
    1938 [ -  + ][ #  # ]:         13 :     TEST_REL(mymset.get_uncollapsed_matches_lower_bound(),>=,4);
    1939 [ -  + ][ #  # ]:         13 :     TEST_REL(mymset.get_uncollapsed_matches_lower_bound(),>=,4);
    1940                 :            : 
    1941                 :         13 :     return true;
    1942                 :            : }
    1943                 :            : 
    1944                 :            : // Feature tests - check_at_least with various sorting options.
    1945                 :         13 : DEFINE_TESTCASE(checkatleast3, backend) {
    1946                 :         13 :     Xapian::Enquire enquire(get_database("etext"));
    1947                 :         13 :     enquire.set_query(Xapian::Query("prussian")); // 60 matches.
    1948                 :            : 
    1949         [ +  + ]:         52 :     for (int order = 0; order < 3; ++order) {
    1950   [ +  +  +  - ]:         39 :         switch (order) {
    1951                 :            :             case 0:
    1952                 :         13 :                 enquire.set_docid_order(Xapian::Enquire::ASCENDING);
    1953                 :         13 :                 break;
    1954                 :            :             case 1:
    1955                 :         13 :                 enquire.set_docid_order(Xapian::Enquire::DESCENDING);
    1956                 :         13 :                 break;
    1957                 :            :             case 2:
    1958                 :         13 :                 enquire.set_docid_order(Xapian::Enquire::DONT_CARE);
    1959                 :            :                 break;
    1960                 :            :         }
    1961                 :            : 
    1962         [ +  + ]:        312 :         for (int sort = 0; sort < 7; ++sort) {
    1963                 :        273 :             bool reverse = (sort & 1);
    1964   [ +  +  +  +  :        273 :             switch (sort) {
                      - ]
    1965                 :            :                 case 0:
    1966                 :         39 :                     enquire.set_sort_by_relevance();
    1967                 :         39 :                     break;
    1968                 :            :                 case 1: case 2:
    1969                 :         78 :                     enquire.set_sort_by_value(0, reverse);
    1970                 :         78 :                     break;
    1971                 :            :                 case 3: case 4:
    1972                 :         78 :                     enquire.set_sort_by_value_then_relevance(0, reverse);
    1973                 :         78 :                     break;
    1974                 :            :                 case 5: case 6:
    1975                 :         78 :                     enquire.set_sort_by_relevance_then_value(0, reverse);
    1976                 :            :                     break;
    1977                 :            :             }
    1978                 :            : 
    1979                 :        273 :             Xapian::MSet mset = enquire.get_mset(0, 100, 500);
    1980   [ -  +  #  # ]:        273 :             TEST_MSET_SIZE(mset, 60);
    1981 [ -  + ][ #  # ]:        273 :             TEST_EQUAL(mset.get_matches_lower_bound(), 60);
    1982 [ -  + ][ #  # ]:        273 :             TEST_EQUAL(mset.get_matches_estimated(), 60);
    1983 [ -  + ][ #  # ]:        273 :             TEST_EQUAL(mset.get_matches_upper_bound(), 60);
    1984 [ -  + ][ #  # ]:        273 :             TEST_EQUAL(mset.get_uncollapsed_matches_lower_bound(), 60);
    1985 [ -  + ][ #  # ]:        273 :             TEST_EQUAL(mset.get_uncollapsed_matches_estimated(), 60);
    1986 [ -  + ][ #  # ]:        273 :             TEST_EQUAL(mset.get_uncollapsed_matches_upper_bound(), 60);
    1987                 :            : 
    1988                 :        273 :             mset = enquire.get_mset(0, 50, 100);
    1989   [ -  +  #  # ]:        273 :             TEST_MSET_SIZE(mset, 50);
    1990 [ -  + ][ #  # ]:        273 :             TEST_EQUAL(mset.get_matches_lower_bound(), 60);
    1991 [ -  + ][ #  # ]:        273 :             TEST_EQUAL(mset.get_matches_estimated(), 60);
    1992 [ -  + ][ #  # ]:        273 :             TEST_EQUAL(mset.get_matches_upper_bound(), 60);
    1993 [ -  + ][ #  # ]:        273 :             TEST_EQUAL(mset.get_uncollapsed_matches_lower_bound(), 60);
    1994 [ -  + ][ #  # ]:        273 :             TEST_EQUAL(mset.get_uncollapsed_matches_estimated(), 60);
    1995 [ -  + ][ #  # ]:        273 :             TEST_EQUAL(mset.get_uncollapsed_matches_upper_bound(), 60);
    1996                 :            : 
    1997                 :        273 :             mset = enquire.get_mset(0, 10, 50);
    1998   [ -  +  #  # ]:        273 :             TEST_MSET_SIZE(mset, 10);
    1999 [ -  + ][ #  # ]:        273 :             TEST_REL(mset.get_matches_lower_bound(),>=,50);
    2000 [ -  + ][ #  # ]:        273 :             TEST_REL(mset.get_uncollapsed_matches_lower_bound(),>=,50);
    2001                 :        273 :         }
    2002                 :            :     }
    2003                 :            : 
    2004                 :         13 :     return true;
    2005                 :            : }
    2006                 :            : 
    2007                 :            : // tests all document postlists
    2008                 :         13 : DEFINE_TESTCASE(allpostlist1, backend) {
    2009                 :         13 :     Xapian::Database db(get_database("apitest_manydocs"));
    2010                 :         13 :     Xapian::PostingIterator i = db.postlist_begin("");
    2011                 :         13 :     unsigned int j = 1;
    2012         [ +  + ]:       6669 :     while (i != db.postlist_end("")) {
    2013 [ -  + ][ #  # ]:       6656 :         TEST_EQUAL(*i, j);
    2014                 :       6656 :         i++;
    2015                 :       6656 :         j++;
    2016                 :            :     }
    2017 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(j, 513);
    2018                 :            : 
    2019                 :         13 :     i = db.postlist_begin("");
    2020                 :         13 :     j = 1;
    2021         [ +  + ]:       6539 :     while (i != db.postlist_end("")) {
    2022 [ -  + ][ #  # ]:       6526 :         TEST_EQUAL(*i, j);
    2023                 :       6526 :         i++;
    2024                 :       6526 :         j++;
    2025         [ +  + ]:       6526 :         if (j == 50) {
    2026                 :         13 :             j += 10;
    2027                 :         13 :             i.skip_to(j);
    2028                 :            :         }
    2029                 :            :     }
    2030 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(j, 513);
    2031                 :            : 
    2032                 :         13 :     return true;
    2033                 :            : }
    2034                 :            : 
    2035                 :         39 : static void test_emptyterm1_helper(Xapian::Database & db)
    2036                 :            : {
    2037                 :            :     // Don't bother with postlist_begin() because allpostlist tests cover that.
    2038 [ +  - ][ -  + ]:        156 :     TEST_EXCEPTION(Xapian::InvalidArgumentError, db.positionlist_begin(1, ""));
         [ #  # ][ -  + ]
    2039 [ -  + ][ #  # ]:         39 :     TEST_EQUAL(db.get_doccount(), db.get_termfreq(""));
    2040 [ -  + ][ #  # ]:         39 :     TEST_EQUAL(db.get_doccount() != 0, db.term_exists(""));
    2041 [ -  + ][ #  # ]:         39 :     TEST_EQUAL(db.get_doccount(), db.get_collection_freq(""));
    2042                 :         39 : }
    2043                 :            : 
    2044                 :            : // tests results of passing an empty term to various methods
    2045                 :         13 : DEFINE_TESTCASE(emptyterm1, backend) {
    2046                 :         13 :     Xapian::Database db(get_database("apitest_manydocs"));
    2047   [ -  +  #  # ]:         13 :     TEST_EQUAL(db.get_doccount(), 512);
    2048                 :         13 :     test_emptyterm1_helper(db);
    2049                 :            : 
    2050                 :         13 :     db = get_database("apitest_onedoc");
    2051   [ -  +  #  # ]:         13 :     TEST_EQUAL(db.get_doccount(), 1);
    2052                 :         13 :     test_emptyterm1_helper(db);
    2053                 :            : 
    2054                 :         13 :     db = get_database("");
    2055   [ -  +  #  # ]:         13 :     TEST_EQUAL(db.get_doccount(), 0);
    2056                 :         13 :     test_emptyterm1_helper(db);
    2057                 :            : 
    2058                 :         13 :     return true;
    2059                 :            : }
    2060                 :            : 
    2061                 :            : // Test for alldocs postlist with a sparse database.
    2062                 :         10 : DEFINE_TESTCASE(alldocspl1, writable) {
    2063                 :         10 :     Xapian::WritableDatabase db = get_writable_database();
    2064                 :         10 :     Xapian::Document doc;
    2065                 :         10 :     doc.set_data("5");
    2066                 :         10 :     doc.add_value(0, "5");
    2067                 :         10 :     db.replace_document(5, doc);
    2068                 :            : 
    2069                 :         10 :     Xapian::PostingIterator i = db.postlist_begin("");
    2070 [ -  + ][ #  # ]:         10 :     TEST(i != db.postlist_end(""));
    2071 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*i, 5);
    2072 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(i.get_doclength(), 0);
    2073 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(i.get_wdf(), 1);
    2074                 :         10 :     ++i;
    2075 [ -  + ][ #  # ]:         10 :     TEST(i == db.postlist_end(""));
    2076                 :            : 
    2077                 :         10 :     return true;
    2078                 :            : }
    2079                 :            : 
    2080                 :            : // Test reading and writing a modified alldocspostlist.
    2081                 :         10 : DEFINE_TESTCASE(alldocspl2, writable) {
    2082                 :         10 :     Xapian::PostingIterator i, end;
    2083                 :            :     {
    2084                 :         10 :         Xapian::WritableDatabase db = get_writable_database();
    2085                 :         10 :         Xapian::Document doc;
    2086                 :         10 :         doc.set_data("5");
    2087                 :         10 :         doc.add_value(0, "5");
    2088                 :         10 :         db.replace_document(5, doc);
    2089                 :            : 
    2090                 :            :         // Test iterating before committing the changes.
    2091                 :         10 :         i = db.postlist_begin("");
    2092                 :         10 :         end = db.postlist_end("");
    2093   [ -  +  #  # ]:         10 :         TEST(i != end);
    2094 [ -  + ][ #  # ]:         10 :         TEST_EQUAL(*i, 5);
    2095 [ -  + ][ #  # ]:         10 :         TEST_EQUAL(i.get_doclength(), 0);
    2096 [ -  + ][ #  # ]:         10 :         TEST_EQUAL(i.get_wdf(), 1);
    2097                 :         10 :         ++i;
    2098   [ -  +  #  # ]:         10 :         TEST(i == end);
    2099                 :            : 
    2100                 :         10 :         db.commit();
    2101                 :            : 
    2102                 :            :         // Test iterating after committing the changes.
    2103                 :         10 :         i = db.postlist_begin("");
    2104                 :         10 :         end = db.postlist_end("");
    2105   [ -  +  #  # ]:         10 :         TEST(i != end);
    2106 [ -  + ][ #  # ]:         10 :         TEST_EQUAL(*i, 5);
    2107 [ -  + ][ #  # ]:         10 :         TEST_EQUAL(i.get_doclength(), 0);
    2108 [ -  + ][ #  # ]:         10 :         TEST_EQUAL(i.get_wdf(), 1);
    2109                 :         10 :         ++i;
    2110   [ -  +  #  # ]:         10 :         TEST(i == end);
    2111                 :            : 
    2112                 :            :         // Add another document.
    2113                 :         10 :         doc = Xapian::Document();
    2114                 :         10 :         doc.set_data("5");
    2115                 :         10 :         doc.add_value(0, "7");
    2116                 :         10 :         db.replace_document(7, doc);
    2117                 :            : 
    2118                 :            :         // Test iterating through before committing the changes.
    2119                 :         10 :         i = db.postlist_begin("");
    2120                 :         10 :         end = db.postlist_end("");
    2121   [ -  +  #  # ]:         10 :         TEST(i != end);
    2122 [ -  + ][ #  # ]:         10 :         TEST_EQUAL(*i, 5);
    2123 [ -  + ][ #  # ]:         10 :         TEST_EQUAL(i.get_doclength(), 0);
    2124 [ -  + ][ #  # ]:         10 :         TEST_EQUAL(i.get_wdf(), 1);
    2125                 :         10 :         ++i;
    2126   [ -  +  #  # ]:         10 :         TEST(i != end);
    2127 [ -  + ][ #  # ]:         10 :         TEST_EQUAL(*i, 7);
    2128 [ -  + ][ #  # ]:         10 :         TEST_EQUAL(i.get_doclength(), 0);
    2129 [ -  + ][ #  # ]:         10 :         TEST_EQUAL(i.get_wdf(), 1);
    2130                 :         10 :         ++i;
    2131   [ -  +  #  # ]:         10 :         TEST(i == end);
    2132                 :            : 
    2133                 :            :         // Delete the first document.
    2134                 :         10 :         db.delete_document(5);
    2135                 :            : 
    2136                 :            :         // Test iterating through before committing the changes.
    2137                 :         10 :         i = db.postlist_begin("");
    2138                 :         10 :         end = db.postlist_end("");
    2139   [ -  +  #  # ]:         10 :         TEST(i != end);
    2140 [ -  + ][ #  # ]:         10 :         TEST_EQUAL(*i, 7);
    2141 [ -  + ][ #  # ]:         10 :         TEST_EQUAL(i.get_doclength(), 0);
    2142 [ -  + ][ #  # ]:         10 :         TEST_EQUAL(i.get_wdf(), 1);
    2143                 :         10 :         ++i;
    2144   [ -  +  #  # ]:         10 :         TEST(i == end);
    2145                 :            : 
    2146                 :            :         // Test iterating through after committing the changes, and dropping the
    2147                 :            :         // reference to the main DB.
    2148                 :         10 :         db.commit();
    2149                 :         10 :         i = db.postlist_begin("");
    2150                 :         10 :         end = db.postlist_end("");
    2151                 :            :     }
    2152                 :            : 
    2153   [ -  +  #  # ]:         10 :     TEST(i != end);
    2154 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*i, 7);
    2155 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(i.get_doclength(), 0);
    2156 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(i.get_wdf(), 1);
    2157                 :         10 :     ++i;
    2158   [ -  +  #  # ]:         10 :     TEST(i == end);
    2159                 :            : 
    2160                 :         10 :     return true;
    2161                 :            : }
    2162                 :            : 
    2163                 :            : // Feature test for Query::OP_SCALE_WEIGHT.
    2164                 :         13 : DEFINE_TESTCASE(scaleweight1, backend) {
    2165                 :         13 :     Xapian::Database db(get_database("apitest_phrase"));
    2166                 :         13 :     Xapian::Enquire enq(db);
    2167                 :         13 :     Xapian::QueryParser qp;
    2168                 :            : 
    2169                 :            :     static const char * queries[] = {
    2170                 :            :         "pad",
    2171                 :            :         "milk fridge",
    2172                 :            :         "leave milk on fridge",
    2173                 :            :         "ordered milk operator",
    2174                 :            :         "ordered phrase operator",
    2175                 :            :         "leave \"milk on fridge\"",
    2176                 :            :         "notpresent",
    2177                 :            :         "leave \"milk notpresent\"",
    2178                 :            :         NULL
    2179                 :            :     };
    2180                 :            :     static const double multipliers[] = {
    2181                 :            :         -1000000, -2.5, -1, -0.5, 0, 0.5, 1, 2.5, 1000000,
    2182                 :            :         0, 0
    2183                 :            :     };
    2184                 :            : 
    2185         [ +  + ]:        117 :     for (const char **qstr = queries; *qstr; ++qstr) {
    2186                 :        104 :         tout.str(string());
    2187                 :        104 :         Xapian::Query query1 = qp.parse_query(*qstr);
    2188                 :        104 :         tout << "query1: " << query1.get_description() << endl;
    2189         [ +  + ]:       1040 :         for (const double *multp = multipliers; multp[0] != multp[1]; ++multp) {
    2190                 :        936 :             double mult = *multp;
    2191         [ +  + ]:        936 :             if (mult < 0) {
    2192 [ +  - ][ -  + ]:       1248 :                 TEST_EXCEPTION(Xapian::InvalidArgumentError,
         [ #  # ][ -  + ]
    2193                 :            :                                Xapian::Query(Xapian::Query::OP_SCALE_WEIGHT,
    2194                 :            :                                              query1, mult));
    2195                 :        416 :                 continue;
    2196                 :            :             }
    2197                 :        520 :             Xapian::Query query2(Xapian::Query::OP_SCALE_WEIGHT, query1, mult);
    2198                 :        520 :             tout << "query2: " << query2.get_description() << endl;
    2199                 :            : 
    2200                 :        520 :             enq.set_query(query1);
    2201                 :        520 :             Xapian::MSet mset1 = enq.get_mset(0, 20);
    2202                 :        520 :             enq.set_query(query2);
    2203                 :        520 :             Xapian::MSet mset2 = enq.get_mset(0, 20);
    2204                 :            : 
    2205   [ -  +  #  # ]:        520 :             TEST_EQUAL(mset1.size(), mset2.size());
    2206                 :            : 
    2207                 :        520 :             Xapian::MSetIterator i1, i2;
    2208         [ +  + ]:        520 :             if (mult > 0) {
    2209 [ +  + ][ +  - ]:       2652 :                 for (i1 = mset1.begin(), i2 = mset2.begin();
         [ +  + ][ #  # ]
         [ #  # ][ +  - ]
                 [ +  + ]
    2210                 :            :                      i1 != mset1.end() && i2 != mset2.end(); ++i1, ++i2) {
    2211 [ -  + ][ #  # ]:       2236 :                     TEST_EQUAL_DOUBLE(i1.get_weight() * mult, i2.get_weight());
    2212 [ -  + ][ #  # ]:       2236 :                     TEST_EQUAL(*i1, *i2);
    2213                 :            :                 }
    2214                 :            :             } else {
    2215                 :            :                 // Weights in mset2 are 0; so it should be sorted by docid.
    2216                 :        104 :                 vector<Xapian::docid> ids1;
    2217                 :        104 :                 vector<Xapian::docid> ids2;
    2218 [ +  + ][ +  - ]:        663 :                 for (i1 = mset1.begin(), i2 = mset2.begin();
         [ +  + ][ #  # ]
         [ #  # ][ +  - ]
                 [ +  + ]
    2219                 :            :                      i1 != mset1.end() && i2 != mset2.end(); ++i1, ++i2) {
    2220 [ -  + ][ #  # ]:        559 :                     TEST_NOT_EQUAL_DOUBLE(i1.get_weight(), 0);
    2221 [ -  + ][ #  # ]:        559 :                     TEST_EQUAL_DOUBLE(i2.get_weight(), 0);
    2222                 :        559 :                     ids1.push_back(*i1);
    2223                 :        559 :                     ids2.push_back(*i2);
    2224                 :            :                 }
    2225                 :        104 :                 sort(ids1.begin(), ids1.end());
    2226   [ -  +  #  # ]:        104 :                 TEST_EQUAL(ids1, ids2);
    2227                 :            :             }
    2228                 :            :         }
    2229                 :            :     }
    2230                 :         13 :     return true;
    2231                 :            : }
    2232                 :            : 
    2233                 :            : // Test Query::OP_SCALE_WEIGHT being used to multiply some of the weights of a
    2234                 :            : // search by zero.
    2235                 :         13 : DEFINE_TESTCASE(scaleweight2, backend) {
    2236                 :         13 :     Xapian::Database db(get_database("apitest_phrase"));
    2237                 :         13 :     Xapian::Enquire enq(db);
    2238                 :         13 :     Xapian::MSetIterator i;
    2239                 :            : 
    2240                 :         13 :     Xapian::Query query1("fridg");
    2241                 :         13 :     Xapian::Query query2(Xapian::Query::OP_SCALE_WEIGHT, query1, 2.5);
    2242                 :         13 :     Xapian::Query query3("milk");
    2243                 :         13 :     Xapian::Query query4(Xapian::Query::OP_SCALE_WEIGHT, query3, 0);
    2244                 :         13 :     Xapian::Query query5(Xapian::Query::OP_OR, query2, query4);
    2245                 :            : 
    2246                 :            :     // query5 should first return the same results as query1, in the same
    2247                 :            :     // order, and then return the results of query3 which aren't also results
    2248                 :            :     // of query1, in ascending docid order.  We test that this happens.
    2249                 :            : 
    2250                 :            :     // First, build a vector of docids matching the first part of the query,
    2251                 :            :     // and append the non-duplicate docids matching the second part of the
    2252                 :            :     // query.
    2253                 :         13 :     vector<Xapian::docid> ids1;
    2254                 :         13 :     set<Xapian::docid> idsin1;
    2255                 :         13 :     vector<Xapian::docid> ids3;
    2256                 :            : 
    2257                 :         13 :     enq.set_query(query1);
    2258                 :         13 :     Xapian::MSet mset1 = enq.get_mset(0, 20);
    2259                 :         13 :     enq.set_query(query3);
    2260                 :         13 :     Xapian::MSet mset3 = enq.get_mset(0, 20);
    2261   [ -  +  #  # ]:         13 :     TEST_NOT_EQUAL(mset1.size(), 0);
    2262         [ +  + ]:        156 :     for (i = mset1.begin(); i != mset1.end(); ++i) {
    2263                 :        143 :         ids1.push_back(*i);
    2264                 :        143 :         idsin1.insert(*i);
    2265                 :            :     }
    2266 [ -  + ][ #  # ]:         13 :     TEST_NOT_EQUAL(mset3.size(), 0);
    2267         [ +  + ]:        104 :     for (i = mset3.begin(); i != mset3.end(); ++i) {
    2268         [ +  + ]:         91 :         if (idsin1.find(*i) != idsin1.end())
    2269                 :         65 :             continue;
    2270                 :         26 :         ids3.push_back(*i);
    2271                 :            :     }
    2272                 :         13 :     sort(ids3.begin(), ids3.end());
    2273                 :         13 :     ids1.insert(ids1.end(), ids3.begin(), ids3.end());
    2274                 :            : 
    2275                 :            :     // Now, run the combined query and build a vector of the matching docids.
    2276                 :         13 :     vector<Xapian::docid> ids5;
    2277                 :         13 :     enq.set_query(query5);
    2278                 :         13 :     Xapian::MSet mset5 = enq.get_mset(0, 20);
    2279         [ +  + ]:        182 :     for (i = mset5.begin(); i != mset5.end(); ++i) {
    2280                 :        169 :         ids5.push_back(*i);
    2281                 :            :     }
    2282                 :            : 
    2283 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(ids1, ids5);
    2284                 :         13 :     return true;
    2285                 :            : }
    2286                 :            : 
    2287                 :            : // Regression test for bug fixed in 1.0.5 - this test would failed under
    2288                 :            : // valgrind because it used an uninitialised value.
    2289                 :         13 : DEFINE_TESTCASE(bm25weight1, backend) {
    2290                 :         13 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
    2291                 :         13 :     enquire.set_weighting_scheme(Xapian::BM25Weight(1, 25, 1, 0.01, 0.5));
    2292                 :         13 :     enquire.set_query(Xapian::Query("word") );
    2293                 :            : 
    2294                 :         13 :     Xapian::MSet mset = enquire.get_mset(0, 25);
    2295                 :            : 
    2296                 :         13 :     return true;
    2297                 :            : }
    2298                 :            : 
    2299                 :            : // Feature test for TradWeight.
    2300                 :         13 : DEFINE_TESTCASE(tradweight1, backend) {
    2301                 :         13 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
    2302                 :         13 :     enquire.set_weighting_scheme(Xapian::TradWeight());
    2303                 :         13 :     enquire.set_query(Xapian::Query("word") );
    2304                 :            : 
    2305                 :         13 :     Xapian::MSet mset = enquire.get_mset(0, 25);
    2306                 :            : 
    2307                 :         13 :     enquire.set_weighting_scheme(Xapian::TradWeight(0));
    2308                 :         13 :     enquire.set_query(Xapian::Query("word") );
    2309                 :            : 
    2310                 :         13 :     mset = enquire.get_mset(0, 25);
    2311                 :            :     // FIXME: should check that TradWeight(0) means wdf and doc length really
    2312                 :            :     // don't affect the weights as stated in the documentation.
    2313                 :            : 
    2314                 :         13 :     return true;
    2315                 :            : }
    2316                 :            : 
    2317                 :            : // Feature test for Database::get_uuid().
    2318                 :         10 : DEFINE_TESTCASE(uuid1, backend && !multi) {
    2319                 :         12 :     SKIP_TEST_FOR_BACKEND("inmemory");
    2320                 :          9 :     Xapian::Database db = get_database("apitest_simpledata");
    2321                 :          9 :     string uuid1 = db.get_uuid();
    2322   [ -  +  #  # ]:          9 :     TEST_EQUAL(uuid1.size(), 36);
    2323                 :            : 
    2324                 :            :     // A database with no sub-databases has an empty UUID.
    2325                 :          9 :     Xapian::Database db2;
    2326 [ -  + ][ #  # ]:          9 :     TEST(db2.get_uuid().empty());
    2327                 :            : 
    2328                 :          9 :     db2.add_database(db);
    2329 [ -  + ][ #  # ]:          9 :     TEST_EQUAL(uuid1, db2.get_uuid());
    2330                 :            : 
    2331                 :            :     // Multi-database has multiple UUIDs (we don't define the format exactly
    2332                 :            :     // so this assumes something about the implementation).
    2333                 :          9 :     db2.add_database(db);
    2334 [ -  + ][ #  # ]:          9 :     TEST_EQUAL(uuid1 + ":" + uuid1, db2.get_uuid());
    2335                 :            : 
    2336                 :            : #ifdef XAPIAN_HAS_INMEMORY_BACKEND
    2337                 :            :     // This relies on InMemory databases not supporting uuids.
    2338                 :            :     // A multi-database containing a database with no uuid has no uuid.
    2339                 :          9 :     db2.add_database(Xapian::InMemory::open());
    2340 [ -  + ][ #  # ]:          9 :     TEST(db2.get_uuid().empty());
    2341                 :            : #endif
    2342                 :            : 
    2343                 :          9 :     return true;
    2344                 :            : }

Generated by: LCOV version 1.8