LCOV - code coverage report
Current view: top level - home/olly/git/atia-xapian/xapian-core/tests - api_db.cc (source / functions) Hit Total Coverage
Test: Test Coverage for xapian-core r Lines: 1081 1099 98.4 %
Date: 2011-08-21 Functions: 66 72 91.7 %
Branches: 553 1810 30.6 %

           Branch data     Line data    Source code
       1                 :            : /* api_db.cc: tests which need a backend
       2                 :            :  *
       3                 :            :  * Copyright 1999,2000,2001 BrightStation PLC
       4                 :            :  * Copyright 2002 Ananova Ltd
       5                 :            :  * Copyright 2002,2003,2004,2005,2006,2007,2008,2009 Olly Betts
       6                 :            :  * Copyright 2006,2007,2008,2009 Lemur Consulting Ltd
       7                 :            :  *
       8                 :            :  * This program is free software; you can redistribute it and/or
       9                 :            :  * modify it under the terms of the GNU General Public License as
      10                 :            :  * published by the Free Software Foundation; either version 2 of the
      11                 :            :  * License, or (at your option) any later version.
      12                 :            :  *
      13                 :            :  * This program is distributed in the hope that it will be useful,
      14                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      15                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16                 :            :  * GNU General Public License for more details.
      17                 :            :  *
      18                 :            :  * You should have received a copy of the GNU General Public License
      19                 :            :  * along with this program; if not, write to the Free Software
      20                 :            :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
      21                 :            :  * USA
      22                 :            :  */
      23                 :            : 
      24                 :            : #include <config.h>
      25                 :            : 
      26                 :            : #include "api_db.h"
      27                 :            : 
      28                 :            : #include <algorithm>
      29                 :            : #include <fstream>
      30                 :            : #include <map>
      31                 :            : #include <string>
      32                 :            : #include <vector>
      33                 :            : 
      34                 :            : #include <xapian.h>
      35                 :            : 
      36                 :            : #include "backendmanager.h"
      37                 :            : #include "backendmanager_local.h"
      38                 :            : #include "testsuite.h"
      39                 :            : #include "testutils.h"
      40                 :            : #include "unixcmds.h"
      41                 :            : #include "utils.h"
      42                 :            : 
      43                 :            : #include "apitest.h"
      44                 :            : 
      45                 :            : using namespace std;
      46                 :            : 
      47                 :            : static Xapian::Query
      48                 :         10 : query(const string &t)
      49                 :            : {
      50                 :         10 :     return Xapian::Query(Xapian::Stem("english")(t));
      51                 :            : }
      52                 :            : 
      53                 :            : // #######################################################################
      54                 :            : // # Tests start here
      55                 :            : 
      56                 :            : // tests Xapian::Database::get_termfreq() and Xapian::Database::term_exists()
      57                 :         13 : DEFINE_TESTCASE(termstats, backend) {
      58                 :         13 :     Xapian::Database db(get_database("apitest_simpledata"));
      59                 :            : 
      60 [ -  + ][ #  # ]:         13 :     TEST(!db.term_exists("corn"));
      61 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(db.get_termfreq("corn"), 0);
      62 [ -  + ][ #  # ]:         13 :     TEST(db.term_exists("banana"));
      63 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(db.get_termfreq("banana"), 1);
      64 [ -  + ][ #  # ]:         13 :     TEST(db.term_exists("paragraph"));
      65 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(db.get_termfreq("paragraph"), 5);
      66                 :            : 
      67                 :         13 :     return true;
      68                 :            : }
      69                 :            : 
      70                 :            : // Check that stub databases work.
      71                 :          6 : DEFINE_TESTCASE(stubdb1, backend && !inmemory && !remote) {
      72                 :            :     // Only works for backends which have a path.
      73                 :          6 :     mkdir(".stub", 0755);
      74                 :          6 :     const char * dbpath = ".stub/stubdb1";
      75                 :          6 :     ofstream out(dbpath);
      76   [ -  +  #  # ]:          6 :     TEST(out.is_open());
      77                 :          6 :     out << "auto ../" << get_database_path("apitest_simpledata") << endl;
      78                 :          6 :     out.close();
      79                 :            : 
      80                 :            :     {
      81                 :          6 :         Xapian::Database db = Xapian::Auto::open_stub(dbpath);
      82                 :          6 :         Xapian::Enquire enquire(db);
      83                 :          6 :         enquire.set_query(Xapian::Query("word"));
      84                 :          6 :         enquire.get_mset(0, 10);
      85                 :            :     }
      86                 :            :     {
      87                 :          6 :         Xapian::Database db(dbpath);
      88                 :          6 :         Xapian::Enquire enquire(db);
      89                 :          6 :         enquire.set_query(Xapian::Query("word"));
      90                 :          6 :         enquire.get_mset(0, 10);
      91                 :            :     }
      92                 :            : 
      93                 :          6 :     return true;
      94                 :            : }
      95                 :            : 
      96                 :            : // Check that stub databases work remotely.
      97                 :          6 : DEFINE_TESTCASE(stubdb2, backend && !inmemory && !remote) {
      98                 :            :     // Only works for backends which have a path.
      99                 :          6 :     mkdir(".stub", 0755);
     100                 :          6 :     const char * dbpath = ".stub/stubdb2";
     101                 :          6 :     ofstream out(dbpath);
     102   [ -  +  #  # ]:          6 :     TEST(out.is_open());
     103                 :            :     out << "remote :" << BackendManager::get_xapian_progsrv_command()
     104                 :          6 :         << ' ' << get_database_path("apitest_simpledata") << endl;
     105                 :          6 :     out.close();
     106                 :            : 
     107                 :            :     {
     108                 :          6 :         Xapian::Database db = Xapian::Auto::open_stub(dbpath);
     109                 :          6 :         Xapian::Enquire enquire(db);
     110                 :          6 :         enquire.set_query(Xapian::Query("word"));
     111                 :          6 :         enquire.get_mset(0, 10);
     112                 :            :     }
     113                 :            :     {
     114                 :          6 :         Xapian::Database db(dbpath);
     115                 :          6 :         Xapian::Enquire enquire(db);
     116                 :          6 :         enquire.set_query(Xapian::Query("word"));
     117                 :          6 :         enquire.get_mset(0, 10);
     118                 :            :     }
     119                 :            : 
     120                 :          6 :     return true;
     121                 :            : }
     122                 :            : 
     123                 :            : // Regression test - bad entries were ignored after a good entry prior to 1.0.8.
     124                 :          6 : DEFINE_TESTCASE(stubdb3, backend && !inmemory && !remote) {
     125                 :            :     // Only works for backends which have a path.
     126                 :          6 :     mkdir(".stub", 0755);
     127                 :          6 :     const char * dbpath = ".stub/stubdb3";
     128                 :          6 :     ofstream out(dbpath);
     129   [ -  +  #  # ]:          6 :     TEST(out.is_open());
     130                 :            :     out << "auto ../" << get_database_path("apitest_simpledata") << "\n"
     131                 :          6 :            "bad line here\n";
     132                 :          6 :     out.close();
     133                 :            : 
     134 [ +  - ][ -  + ]:         24 :     TEST_EXCEPTION(Xapian::DatabaseOpeningError,
         [ #  # ][ -  + ]
     135                 :            :         Xapian::Database db = Xapian::Auto::open_stub(dbpath));
     136                 :            : 
     137 [ +  - ][ -  + ]:         24 :     TEST_EXCEPTION(Xapian::DatabaseOpeningError,
         [ #  # ][ -  + ]
     138                 :            :         Xapian::Database db(dbpath));
     139                 :            : 
     140                 :          6 :     return true;
     141                 :            : }
     142                 :            : 
     143                 :            : // Test a stub database with just a bad entry.
     144                 :          6 : DEFINE_TESTCASE(stubdb4, backend && !inmemory && !remote) {
     145                 :            :     // Only works for backends which have a path.
     146                 :          6 :     mkdir(".stub", 0755);
     147                 :          6 :     const char * dbpath = ".stub/stubdb4";
     148                 :          6 :     ofstream out(dbpath);
     149   [ -  +  #  # ]:          6 :     TEST(out.is_open());
     150                 :          6 :     out << "bad line here\n";
     151                 :          6 :     out.close();
     152                 :            : 
     153 [ +  - ][ -  + ]:         24 :     TEST_EXCEPTION(Xapian::DatabaseOpeningError,
         [ #  # ][ -  + ]
     154                 :            :         Xapian::Database db = Xapian::Auto::open_stub(dbpath));
     155                 :            : 
     156 [ +  - ][ -  + ]:         24 :     TEST_EXCEPTION(Xapian::DatabaseOpeningError,
         [ #  # ][ -  + ]
     157                 :            :         Xapian::Database db(dbpath));
     158                 :            : 
     159                 :          6 :     return true;
     160                 :            : }
     161                 :            : 
     162                 :            : // Test a stub database with a bad entry with no spaces (prior to 1.1.0 this
     163                 :            : // was deliberately allowed, though not documented.
     164                 :          6 : DEFINE_TESTCASE(stubdb5, backend && !inmemory && !remote) {
     165                 :            :     // Only works for backends which have a path.
     166                 :          6 :     mkdir(".stub", 0755);
     167                 :          6 :     const char * dbpath = ".stub/stubdb5";
     168                 :          6 :     ofstream out(dbpath);
     169   [ -  +  #  # ]:          6 :     TEST(out.is_open());
     170                 :            :     out << "bad\n"
     171                 :          6 :            "auto ../" << get_database_path("apitest_simpledata") << endl;
     172                 :          6 :     out.close();
     173                 :            : 
     174 [ +  - ][ -  + ]:         24 :     TEST_EXCEPTION(Xapian::DatabaseOpeningError,
         [ #  # ][ -  + ]
     175                 :            :         Xapian::Database db = Xapian::Auto::open_stub(dbpath));
     176                 :            : 
     177 [ +  - ][ -  + ]:         24 :     TEST_EXCEPTION(Xapian::DatabaseOpeningError,
         [ #  # ][ -  + ]
     178                 :            :         Xapian::Database db(dbpath));
     179                 :            : 
     180                 :          6 :     return true;
     181                 :            : }
     182                 :            : 
     183                 :            : // Test a stub database with an inmemory database (new feature in 1.1.0).
     184                 :          1 : DEFINE_TESTCASE(stubdb6, inmemory) {
     185                 :          1 :     mkdir(".stub", 0755);
     186                 :          1 :     const char * dbpath = ".stub/stubdb6";
     187                 :          1 :     ofstream out(dbpath);
     188   [ -  +  #  # ]:          1 :     TEST(out.is_open());
     189                 :          1 :     out << "inmemory\n";
     190                 :          1 :     out.close();
     191                 :            : 
     192                 :            :     // Read-only tests:
     193                 :            :     {
     194                 :          1 :         Xapian::Database db = Xapian::Auto::open_stub(dbpath);
     195   [ -  +  #  # ]:          1 :         TEST_EQUAL(db.get_doccount(), 0);
     196                 :          1 :         Xapian::Enquire enquire(db);
     197                 :          1 :         enquire.set_query(Xapian::Query("word"));
     198                 :          1 :         Xapian::MSet mset = enquire.get_mset(0, 10);
     199   [ -  +  #  # ]:          1 :         TEST(mset.empty());
     200                 :            :     }
     201                 :            :     {
     202                 :          1 :         Xapian::Database db(dbpath);
     203   [ -  +  #  # ]:          1 :         TEST_EQUAL(db.get_doccount(), 0);
     204                 :          1 :         Xapian::Enquire enquire(db);
     205                 :          1 :         enquire.set_query(Xapian::Query("word"));
     206                 :          1 :         Xapian::MSet mset = enquire.get_mset(0, 10);
     207   [ -  +  #  # ]:          1 :         TEST(mset.empty());
     208                 :            :     }
     209                 :            : 
     210                 :            :     // Writable tests:
     211                 :            :     {
     212                 :          1 :         Xapian::WritableDatabase db;
     213                 :          1 :         db = Xapian::Auto::open_stub(dbpath, Xapian::DB_OPEN);
     214   [ -  +  #  # ]:          1 :         TEST_EQUAL(db.get_doccount(), 0);
     215                 :          1 :         db.add_document(Xapian::Document());
     216   [ -  +  #  # ]:          1 :         TEST_EQUAL(db.get_doccount(), 1);
     217                 :            :     }
     218                 :            :     {
     219                 :          1 :         Xapian::WritableDatabase db(dbpath, Xapian::DB_OPEN);
     220   [ -  +  #  # ]:          1 :         TEST_EQUAL(db.get_doccount(), 0);
     221                 :          1 :         db.add_document(Xapian::Document());
     222   [ -  +  #  # ]:          1 :         TEST_EQUAL(db.get_doccount(), 1);
     223                 :            :     }
     224                 :            :  
     225                 :          1 :     return true;
     226                 :            : }
     227                 :            : 
     228                 :            : #if 0 // the "force error" mechanism is no longer in place...
     229                 :            : class MyErrorHandler : public Xapian::ErrorHandler {
     230                 :            :     public:
     231                 :            :         int count;
     232                 :            : 
     233                 :            :         bool handle_error(Xapian::Error & error) {
     234                 :            :             ++count;
     235                 :            :             tout << "Error handling caught: " << error.get_description()
     236                 :            :                  << ", count is now " << count << "\n";
     237                 :            :             return true;
     238                 :            :         }
     239                 :            : 
     240                 :            :         MyErrorHandler() : count (0) {}
     241                 :            : };
     242                 :            : 
     243                 :            : // tests error handler in multimatch().
     244                 :            : //DEFINE_TESTCASE(multierrhandler1, backend) {
     245                 :            :     MyErrorHandler myhandler;
     246                 :            : 
     247                 :            :     Xapian::Database mydb2(get_database("apitest_simpledata"));
     248                 :            :     Xapian::Database mydb3(get_database("apitest_simpledata2"));
     249                 :            :     int errcount = 1;
     250                 :            :     for (int testcount = 0; testcount < 14; testcount ++) {
     251                 :            :         tout << "testcount=" << testcount << "\n";
     252                 :            :         Xapian::Database mydb4(get_database("-e", "apitest_termorder"));
     253                 :            :         Xapian::Database mydb5(get_network_database("apitest_termorder", 1));
     254                 :            :         Xapian::Database mydb6(get_database("-e2", "apitest_termorder"));
     255                 :            :         Xapian::Database mydb7(get_database("-e3", "apitest_simpledata"));
     256                 :            : 
     257                 :            :         Xapian::Database dbs;
     258                 :            :         switch (testcount) {
     259                 :            :             case 0:
     260                 :            :                 dbs.add_database(mydb2);
     261                 :            :                 dbs.add_database(mydb3);
     262                 :            :                 dbs.add_database(mydb4);
     263                 :            :                 break;
     264                 :            :             case 1:
     265                 :            :                 dbs.add_database(mydb4);
     266                 :            :                 dbs.add_database(mydb2);
     267                 :            :                 dbs.add_database(mydb3);
     268                 :            :                 break;
     269                 :            :             case 2:
     270                 :            :                 dbs.add_database(mydb3);
     271                 :            :                 dbs.add_database(mydb4);
     272                 :            :                 dbs.add_database(mydb2);
     273                 :            :                 break;
     274                 :            :             case 3:
     275                 :            :                 dbs.add_database(mydb2);
     276                 :            :                 dbs.add_database(mydb3);
     277                 :            :                 dbs.add_database(mydb5);
     278                 :            :                 sleep(1);
     279                 :            :                 break;
     280                 :            :             case 4:
     281                 :            :                 dbs.add_database(mydb5);
     282                 :            :                 dbs.add_database(mydb2);
     283                 :            :                 dbs.add_database(mydb3);
     284                 :            :                 sleep(1);
     285                 :            :                 break;
     286                 :            :             case 5:
     287                 :            :                 dbs.add_database(mydb3);
     288                 :            :                 dbs.add_database(mydb5);
     289                 :            :                 dbs.add_database(mydb2);
     290                 :            :                 sleep(1);
     291                 :            :                 break;
     292                 :            :             case 6:
     293                 :            :                 dbs.add_database(mydb2);
     294                 :            :                 dbs.add_database(mydb3);
     295                 :            :                 dbs.add_database(mydb6);
     296                 :            :                 break;
     297                 :            :             case 7:
     298                 :            :                 dbs.add_database(mydb6);
     299                 :            :                 dbs.add_database(mydb2);
     300                 :            :                 dbs.add_database(mydb3);
     301                 :            :                 break;
     302                 :            :             case 8:
     303                 :            :                 dbs.add_database(mydb3);
     304                 :            :                 dbs.add_database(mydb6);
     305                 :            :                 dbs.add_database(mydb2);
     306                 :            :                 break;
     307                 :            :             case 9:
     308                 :            :                 dbs.add_database(mydb2);
     309                 :            :                 dbs.add_database(mydb3);
     310                 :            :                 dbs.add_database(mydb7);
     311                 :            :                 break;
     312                 :            :             case 10:
     313                 :            :                 dbs.add_database(mydb7);
     314                 :            :                 dbs.add_database(mydb2);
     315                 :            :                 dbs.add_database(mydb3);
     316                 :            :                 break;
     317                 :            :             case 11:
     318                 :            :                 dbs.add_database(mydb3);
     319                 :            :                 dbs.add_database(mydb7);
     320                 :            :                 dbs.add_database(mydb2);
     321                 :            :                 break;
     322                 :            :             case 12:
     323                 :            :                 dbs.add_database(mydb2);
     324                 :            :                 dbs.add_database(mydb6);
     325                 :            :                 dbs.add_database(mydb7);
     326                 :            :                 break;
     327                 :            :             case 13:
     328                 :            :                 dbs.add_database(mydb2);
     329                 :            :                 dbs.add_database(mydb7);
     330                 :            :                 dbs.add_database(mydb6);
     331                 :            :                 break;
     332                 :            :         }
     333                 :            :         tout << "db=" << dbs << "\n";
     334                 :            :         Xapian::Enquire enquire(dbs, &myhandler);
     335                 :            : 
     336                 :            :         // make a query
     337                 :            :         Xapian::Query myquery = query(Xapian::Query::OP_OR, "inmemory", "word");
     338                 :            :         enquire.set_weighting_scheme(Xapian::BoolWeight());
     339                 :            :         enquire.set_query(myquery);
     340                 :            : 
     341                 :            :         tout << "query=" << myquery << "\n";
     342                 :            :         // retrieve the top ten results
     343                 :            :         Xapian::MSet mymset = enquire.get_mset(0, 10);
     344                 :            : 
     345                 :            :         switch (testcount) {
     346                 :            :             case 0: case 3: case 6: case 9:
     347                 :            :                 mset_expect_order(mymset, 2, 4, 10);
     348                 :            :                 break;
     349                 :            :             case 1: case 4: case 7: case 10:
     350                 :            :                 mset_expect_order(mymset, 3, 5, 11);
     351                 :            :                 break;
     352                 :            :             case 2: case 5: case 8: case 11:
     353                 :            :                 mset_expect_order(mymset, 1, 6, 12);
     354                 :            :                 break;
     355                 :            :             case 12:
     356                 :            :             case 13:
     357                 :            :                 mset_expect_order(mymset, 4, 10);
     358                 :            :                 errcount += 1;
     359                 :            :                 break;
     360                 :            :         }
     361                 :            :         TEST_EQUAL(myhandler.count, errcount);
     362                 :            :         errcount += 1;
     363                 :            :     }
     364                 :            : 
     365                 :            :     return true;
     366                 :            : }
     367                 :            : #endif
     368                 :            : 
     369 [ #  # ][ -  + ]:         28 : class myMatchDecider : public Xapian::MatchDecider {
     370                 :            :     public:
     371                 :        266 :         bool operator()(const Xapian::Document &doc) const {
     372                 :            :             // Note that this is not recommended usage of get_data()
     373                 :        266 :             return doc.get_data().find("This is") != string::npos;
     374                 :            :         }
     375                 :            : };
     376                 :            : 
     377                 :            : // Test Xapian::MatchDecider functor.
     378                 :          7 : DEFINE_TESTCASE(matchdecider1, backend && !remote) {
     379                 :          7 :     Xapian::Database db(get_database("apitest_simpledata"));
     380                 :          7 :     Xapian::Enquire enquire(db);
     381                 :          7 :     enquire.set_query(Xapian::Query("this"));
     382                 :            : 
     383                 :          7 :     myMatchDecider myfunctor;
     384                 :            : 
     385                 :          7 :     Xapian::MSet mymset = enquire.get_mset(0, 100, 0, &myfunctor);
     386                 :            : 
     387                 :          7 :     vector<bool> docid_checked(db.get_lastdocid());
     388                 :            : 
     389                 :            :     // Check that we get the expected number of matches, and that they
     390                 :            :     // satisfy the condition.
     391                 :          7 :     Xapian::MSetIterator i = mymset.begin();
     392 [ -  + ][ #  # ]:          7 :     TEST(i != mymset.end());
     393 [ -  + ][ #  # ]:          7 :     TEST_EQUAL(mymset.size(), 3);
     394 [ -  + ][ #  # ]:          7 :     TEST_EQUAL(mymset.get_matches_lower_bound(), 3);
     395 [ -  + ][ #  # ]:          7 :     TEST_EQUAL(mymset.get_matches_upper_bound(), 3);
     396 [ -  + ][ #  # ]:          7 :     TEST_EQUAL(mymset.get_matches_estimated(), 3);
     397 [ -  + ][ #  # ]:          7 :     TEST_EQUAL(mymset.get_uncollapsed_matches_lower_bound(), 3);
     398 [ -  + ][ #  # ]:          7 :     TEST_EQUAL(mymset.get_uncollapsed_matches_upper_bound(), 3);
     399 [ -  + ][ #  # ]:          7 :     TEST_EQUAL(mymset.get_uncollapsed_matches_estimated(), 3);
     400         [ +  + ]:         28 :     for ( ; i != mymset.end(); ++i) {
     401                 :         21 :         const Xapian::Document doc(i.get_document());
     402   [ -  +  #  # ]:         21 :         TEST(myfunctor(doc));
     403                 :         21 :         docid_checked[*i] = true;
     404                 :            :     }
     405                 :            : 
     406                 :            :     // Check that there are some documents which aren't accepted by the match
     407                 :            :     // decider.
     408                 :          7 :     mymset = enquire.get_mset(0, 100);
     409   [ -  +  #  # ]:          7 :     TEST(mymset.size() > 3);
     410                 :            : 
     411                 :            :     // Check that the bounds are appropriate even if we don't ask for any
     412                 :            :     // actual matches.
     413                 :          7 :     mymset = enquire.get_mset(0, 0, 0, &myfunctor);
     414   [ -  +  #  # ]:          7 :     TEST_EQUAL(mymset.size(), 0);
     415 [ -  + ][ #  # ]:          7 :     TEST_EQUAL(mymset.get_matches_lower_bound(), 0);
     416 [ -  + ][ #  # ]:          7 :     TEST_EQUAL(mymset.get_matches_upper_bound(), 6);
     417 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_matches_estimated(),>,0);
     418 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_matches_estimated(),<=,6);
     419 [ -  + ][ #  # ]:          7 :     TEST_EQUAL(mymset.get_uncollapsed_matches_lower_bound(), 0);
     420 [ -  + ][ #  # ]:          7 :     TEST_EQUAL(mymset.get_uncollapsed_matches_upper_bound(), 6);
     421 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_uncollapsed_matches_estimated(),>,0);
     422 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_uncollapsed_matches_estimated(),<=,6);
     423                 :            : 
     424                 :            :     // Check that the bounds are appropriate if we ask for only one hit.
     425                 :            :     // (Regression test - until SVN 10256, we didn't reduce the lower_bound
     426                 :            :     // appropriately, and returned 6 here.)
     427                 :          7 :     mymset = enquire.get_mset(0, 1, 0, &myfunctor);
     428   [ -  +  #  # ]:          7 :     TEST_EQUAL(mymset.size(), 1);
     429 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_matches_lower_bound(),>=,1);
     430 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_matches_lower_bound(),<=,3);
     431 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_matches_upper_bound(),>=,3);
     432 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_matches_upper_bound(),<=,6);
     433 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_matches_estimated(),>,0);
     434 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_matches_estimated(),<=,6);
     435 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_uncollapsed_matches_lower_bound(),>=,1);
     436 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_uncollapsed_matches_lower_bound(),<=,3);
     437 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_uncollapsed_matches_upper_bound(),>=,3);
     438 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_uncollapsed_matches_upper_bound(),<=,6);
     439 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_uncollapsed_matches_estimated(),>,0);
     440 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_uncollapsed_matches_estimated(),<=,6);
     441                 :            : 
     442                 :            :     // Check that the other documents don't satisfy the condition.
     443         [ +  + ]:         42 :     for (Xapian::docid did = 1; did < docid_checked.size(); ++did) {
     444         [ +  + ]:         35 :         if (!docid_checked[did]) {
     445 [ -  + ][ #  # ]:         14 :             TEST(!myfunctor(db.get_document(did)));
     446                 :            :         }
     447                 :            :     }
     448                 :            : 
     449                 :            :     // Check that the bounds are appropriate if a collapse key is used.
     450                 :            :     // Use a value which is never set so we don't actually discard anything.
     451                 :          7 :     enquire.set_collapse_key(99);
     452                 :          7 :     mymset = enquire.get_mset(0, 1, 0, &myfunctor);
     453   [ -  +  #  # ]:          7 :     TEST_EQUAL(mymset.size(), 1);
     454 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_matches_lower_bound(),>=,1);
     455 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_matches_lower_bound(),<=,3);
     456 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_matches_upper_bound(),>=,3);
     457 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_matches_upper_bound(),<=,6);
     458 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_matches_estimated(),>,0);
     459 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_matches_estimated(),<=,6);
     460 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_uncollapsed_matches_lower_bound(),>=,1);
     461 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_uncollapsed_matches_lower_bound(),<=,3);
     462 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_uncollapsed_matches_upper_bound(),>=,3);
     463 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_uncollapsed_matches_upper_bound(),<=,6);
     464 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_uncollapsed_matches_estimated(),>,0);
     465 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_uncollapsed_matches_estimated(),<=,6);
     466                 :            : 
     467                 :            :     // Check that the bounds are appropriate if a percentage cutoff is in
     468                 :            :     // use.  Set a 1% threshold so we don't actually discard anything.
     469                 :          7 :     enquire.set_collapse_key(Xapian::BAD_VALUENO);
     470                 :          7 :     enquire.set_cutoff(1);
     471                 :          7 :     mymset = enquire.get_mset(0, 1, 0, &myfunctor);
     472   [ -  +  #  # ]:          7 :     TEST_EQUAL(mymset.size(), 1);
     473 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_matches_lower_bound(),>=,1);
     474 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_matches_lower_bound(),<=,3);
     475 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_matches_upper_bound(),>=,3);
     476 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_matches_upper_bound(),<=,6);
     477 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_matches_estimated(),>,0);
     478 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_matches_estimated(),<=,6);
     479 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_uncollapsed_matches_lower_bound(),>=,1);
     480 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_uncollapsed_matches_lower_bound(),<=,3);
     481 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_uncollapsed_matches_upper_bound(),>=,3);
     482 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_uncollapsed_matches_upper_bound(),<=,6);
     483 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_uncollapsed_matches_estimated(),>,0);
     484 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_uncollapsed_matches_estimated(),<=,6);
     485                 :            : 
     486                 :            :     // And now with both a collapse key and percentage cutoff.
     487                 :          7 :     enquire.set_collapse_key(99);
     488                 :          7 :     mymset = enquire.get_mset(0, 1, 0, &myfunctor);
     489   [ -  +  #  # ]:          7 :     TEST_EQUAL(mymset.size(), 1);
     490 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_matches_lower_bound(),>=,1);
     491 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_matches_lower_bound(),<=,3);
     492 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_matches_upper_bound(),>=,3);
     493 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_matches_upper_bound(),<=,6);
     494 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_matches_estimated(),>,0);
     495 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_matches_estimated(),<=,6);
     496 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_uncollapsed_matches_lower_bound(),>=,1);
     497 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_uncollapsed_matches_lower_bound(),<=,3);
     498 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_uncollapsed_matches_upper_bound(),>=,3);
     499 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_uncollapsed_matches_upper_bound(),<=,6);
     500 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_uncollapsed_matches_estimated(),>,0);
     501 [ -  + ][ #  # ]:          7 :     TEST_REL(mymset.get_uncollapsed_matches_estimated(),<=,6);
     502                 :            : 
     503                 :          7 :     return true;
     504                 :            : }
     505                 :            : 
     506                 :            : // Test Xapian::MatchDecider functor used as a match spy.
     507                 :          7 : DEFINE_TESTCASE(matchdecider2, backend && !remote) {
     508                 :          7 :     Xapian::Database db(get_database("apitest_simpledata"));
     509                 :          7 :     Xapian::Enquire enquire(db);
     510                 :          7 :     enquire.set_query(Xapian::Query("this"));
     511                 :            : 
     512                 :          7 :     myMatchDecider myfunctor;
     513                 :            : 
     514                 :          7 :     Xapian::MSet mymset = enquire.get_mset(0, 100, 0, NULL, &myfunctor);
     515                 :            : 
     516                 :          7 :     vector<bool> docid_checked(db.get_lastdocid());
     517                 :            : 
     518                 :            :     // Check that we get the expected number of matches, and that they
     519                 :            :     // satisfy the condition.
     520                 :          7 :     Xapian::MSetIterator i = mymset.begin();
     521 [ -  + ][ #  # ]:          7 :     TEST(i != mymset.end());
     522 [ -  + ][ #  # ]:          7 :     TEST_EQUAL(mymset.size(), 3);
     523         [ +  + ]:         28 :     for ( ; i != mymset.end(); ++i) {
     524                 :         21 :         const Xapian::Document doc(i.get_document());
     525   [ -  +  #  # ]:         21 :         TEST(myfunctor(doc));
     526                 :         21 :         docid_checked[*i] = true;
     527                 :            :     }
     528                 :            : 
     529                 :            :     // Check that the other documents don't satisfy the condition.
     530         [ +  + ]:         42 :     for (Xapian::docid did = 1; did < docid_checked.size(); ++did) {
     531         [ +  + ]:         35 :         if (!docid_checked[did]) {
     532 [ -  + ][ #  # ]:         14 :             TEST(!myfunctor(db.get_document(did)));
     533                 :            :         }
     534                 :            :     }
     535                 :            : 
     536                 :          7 :     return true;
     537                 :            : }
     538                 :            : 
     539 [ #  # ][ -  + ]:         14 : class myMatchDecider2 : public Xapian::MatchDecider {
     540                 :            :     public:
     541                 :       4116 :         bool operator()(const Xapian::Document &doc) const {
     542                 :            :             // Note that this is not recommended usage of get_data()
     543                 :       4116 :             return doc.get_data().find("We produce") == string::npos;
     544                 :            :         }
     545                 :            : };
     546                 :            : 
     547                 :            : 
     548                 :            : // Regression test for lower bound using functor, sorting and collapsing.
     549                 :          7 : DEFINE_TESTCASE(matchdecider3, backend && !remote) {
     550                 :          7 :     Xapian::Database db(get_database("etext"));
     551                 :          7 :     Xapian::Enquire enquire(db);
     552                 :          7 :     enquire.set_query(Xapian::Query(""));
     553                 :          7 :     enquire.set_collapse_key(12);
     554                 :          7 :     enquire.set_sort_by_value(11, true);
     555                 :            : 
     556                 :          7 :     myMatchDecider2 myfunctor;
     557                 :            : 
     558                 :          7 :     Xapian::MSet mset1 = enquire.get_mset(0, 2, 0, NULL, &myfunctor);
     559                 :          7 :     Xapian::MSet mset2 = enquire.get_mset(0, 1000, 0, NULL, &myfunctor);
     560                 :            : 
     561                 :            :     // mset2 should contain all the hits, so the statistics should be exact.
     562   [ -  +  #  # ]:          7 :     TEST_EQUAL(mset2.get_matches_estimated(), mset2.size());
     563 [ -  + ][ #  # ]:          7 :     TEST_EQUAL(mset2.get_matches_lower_bound(), mset2.get_matches_estimated());
     564 [ -  + ][ #  # ]:          7 :     TEST_EQUAL(mset2.get_matches_estimated(), mset2.get_matches_upper_bound());
     565                 :            : 
     566 [ -  + ][ #  # ]:          7 :     TEST_REL(mset2.get_uncollapsed_matches_lower_bound(),<=,mset2.get_uncollapsed_matches_estimated());
     567 [ -  + ][ #  # ]:          7 :     TEST_REL(mset2.get_uncollapsed_matches_estimated(),<=,mset2.get_uncollapsed_matches_upper_bound());
     568                 :            : 
     569                 :            :     // Check that the lower bound in mset1 is not greater than the known
     570                 :            :     // number of hits.  This failed until revision 10811.
     571 [ -  + ][ #  # ]:          7 :     TEST_REL(mset1.get_matches_lower_bound(),<=,mset2.size());
     572                 :            : 
     573                 :            :     // Check that the bounds for mset1 make sense.
     574 [ -  + ][ #  # ]:          7 :     TEST_REL(mset1.get_matches_lower_bound(),<=,mset1.get_matches_estimated());
     575 [ -  + ][ #  # ]:          7 :     TEST_REL(mset1.get_matches_estimated(),<=,mset1.get_matches_upper_bound());
     576 [ -  + ][ #  # ]:          7 :     TEST_REL(mset1.size(),<=,mset1.get_matches_upper_bound());
     577                 :            : 
     578 [ -  + ][ #  # ]:          7 :     TEST_REL(mset1.get_uncollapsed_matches_lower_bound(),<=,mset1.get_uncollapsed_matches_estimated());
     579 [ -  + ][ #  # ]:          7 :     TEST_REL(mset1.get_uncollapsed_matches_estimated(),<=,mset1.get_uncollapsed_matches_upper_bound());
     580                 :            : 
     581                 :            :     // The uncollapsed match would match all documents but the one the
     582                 :            :     // matchdecider rejects.
     583 [ -  + ][ #  # ]:          7 :     TEST_REL(mset1.get_uncollapsed_matches_upper_bound(),>=,db.get_doccount() - 1);
     584 [ -  + ][ #  # ]:          7 :     TEST_REL(mset1.get_uncollapsed_matches_upper_bound(),<=,db.get_doccount());
     585 [ -  + ][ #  # ]:          7 :     TEST_REL(mset2.get_uncollapsed_matches_upper_bound(),>=,db.get_doccount() - 1);
     586 [ -  + ][ #  # ]:          7 :     TEST_REL(mset2.get_uncollapsed_matches_upper_bound(),<=,db.get_doccount());
     587                 :            : 
     588                 :          7 :     return true;
     589                 :            : }
     590                 :            : 
     591                 :            : // tests that mset iterators on msets compare correctly.
     592                 :         13 : DEFINE_TESTCASE(msetiterator1, backend) {
     593                 :         13 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
     594                 :         13 :     enquire.set_query(Xapian::Query("this"));
     595                 :         13 :     Xapian::MSet mymset = enquire.get_mset(0, 2);
     596                 :            : 
     597                 :         13 :     Xapian::MSetIterator j;
     598                 :         13 :     j = mymset.begin();
     599                 :         13 :     Xapian::MSetIterator k = mymset.end();
     600                 :         13 :     Xapian::MSetIterator l(j);
     601                 :         13 :     Xapian::MSetIterator m(k);
     602                 :         13 :     Xapian::MSetIterator n = mymset.begin();
     603                 :         13 :     Xapian::MSetIterator o = mymset.begin();
     604   [ -  +  #  # ]:         13 :     TEST_NOT_EQUAL(j, k);
     605 [ -  + ][ #  # ]:         13 :     TEST_NOT_EQUAL(l, m);
     606 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(k, m);
     607 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(j, l);
     608 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(j, j);
     609 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(k, k);
     610                 :            : 
     611                 :         13 :     k = j;
     612   [ -  +  #  # ]:         13 :     TEST_EQUAL(j, k);
     613 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(j, o);
     614                 :         13 :     k++;
     615   [ -  +  #  # ]:         13 :     TEST_NOT_EQUAL(j, k);
     616 [ -  + ][ #  # ]:         13 :     TEST_NOT_EQUAL(k, l);
     617 [ -  + ][ #  # ]:         13 :     TEST_NOT_EQUAL(k, m);
     618 [ -  + ][ #  # ]:         13 :     TEST_NOT_EQUAL(k, o);
     619                 :         13 :     o++;
     620   [ -  +  #  # ]:         13 :     TEST_EQUAL(k, o);
     621                 :         13 :     k++;
     622   [ -  +  #  # ]:         13 :     TEST_NOT_EQUAL(j, k);
     623 [ -  + ][ #  # ]:         13 :     TEST_NOT_EQUAL(k, l);
     624 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(k, m);
     625 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(n, l);
     626                 :            : 
     627                 :         13 :     n = m;
     628   [ -  +  #  # ]:         13 :     TEST_NOT_EQUAL(n, l);
     629 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(n, m);
     630 [ -  + ][ #  # ]:         13 :     TEST_NOT_EQUAL(n, mymset.begin());
     631 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(n, mymset.end());
     632                 :            : 
     633                 :         13 :     return true;
     634                 :            : }
     635                 :            : 
     636                 :            : // tests that mset iterators on empty msets compare equal.
     637                 :         13 : DEFINE_TESTCASE(msetiterator2, backend) {
     638                 :         13 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
     639                 :         13 :     enquire.set_query(Xapian::Query("this"));
     640                 :         13 :     Xapian::MSet mymset = enquire.get_mset(0, 0);
     641                 :            : 
     642                 :         13 :     Xapian::MSetIterator j = mymset.begin();
     643                 :         13 :     Xapian::MSetIterator k = mymset.end();
     644                 :         13 :     Xapian::MSetIterator l(j);
     645                 :         13 :     Xapian::MSetIterator m(k);
     646   [ -  +  #  # ]:         13 :     TEST_EQUAL(j, k);
     647 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(l, m);
     648 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(k, m);
     649 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(j, l);
     650 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(j, j);
     651 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(k, k);
     652                 :            : 
     653                 :         13 :     return true;
     654                 :            : }
     655                 :            : 
     656                 :            : // tests that begin().get_document() works when first != 0
     657                 :         13 : DEFINE_TESTCASE(msetiterator3, backend) {
     658                 :         13 :     Xapian::Database mydb(get_database("apitest_simpledata"));
     659                 :         13 :     Xapian::Enquire enquire(mydb);
     660                 :         13 :     enquire.set_query(Xapian::Query("this"));
     661                 :            : 
     662                 :         13 :     Xapian::MSet mymset = enquire.get_mset(2, 10);
     663                 :            : 
     664   [ -  +  #  # ]:         13 :     TEST(!mymset.empty());
     665                 :         13 :     Xapian::Document doc(mymset.begin().get_document());
     666 [ -  + ][ #  # ]:         13 :     TEST(!doc.get_data().empty());
     667                 :            : 
     668                 :         13 :     return true;
     669                 :            : }
     670                 :            : 
     671                 :            : // tests that eset iterators on empty esets compare equal.
     672                 :         13 : DEFINE_TESTCASE(esetiterator1, backend) {
     673                 :         13 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
     674                 :         13 :     enquire.set_query(Xapian::Query("this"));
     675                 :            : 
     676                 :         13 :     Xapian::MSet mymset = enquire.get_mset(0, 10);
     677   [ -  +  #  # ]:         13 :     TEST(mymset.size() >= 2);
     678                 :            : 
     679                 :         13 :     Xapian::RSet myrset;
     680                 :         13 :     Xapian::MSetIterator i = mymset.begin();
     681                 :         13 :     myrset.add_document(*i);
     682                 :         13 :     myrset.add_document(*(++i));
     683                 :            : 
     684                 :         13 :     Xapian::ESet myeset = enquire.get_eset(2, myrset);
     685                 :         13 :     Xapian::ESetIterator j;
     686                 :         13 :     j = myeset.begin();
     687                 :         13 :     Xapian::ESetIterator k = myeset.end();
     688                 :         13 :     Xapian::ESetIterator l(j);
     689                 :         13 :     Xapian::ESetIterator m(k);
     690                 :         13 :     Xapian::ESetIterator n = myeset.begin();
     691                 :            : 
     692   [ -  +  #  # ]:         13 :     TEST_NOT_EQUAL(j, k);
     693 [ -  + ][ #  # ]:         13 :     TEST_NOT_EQUAL(l, m);
     694 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(k, m);
     695 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(j, l);
     696 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(j, j);
     697 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(k, k);
     698                 :            : 
     699                 :         13 :     k = j;
     700   [ -  +  #  # ]:         13 :     TEST_EQUAL(j, k);
     701                 :         13 :     k++;
     702   [ -  +  #  # ]:         13 :     TEST_NOT_EQUAL(j, k);
     703 [ -  + ][ #  # ]:         13 :     TEST_NOT_EQUAL(k, l);
     704 [ -  + ][ #  # ]:         13 :     TEST_NOT_EQUAL(k, m);
     705                 :         13 :     k++;
     706   [ -  +  #  # ]:         13 :     TEST_NOT_EQUAL(j, k);
     707 [ -  + ][ #  # ]:         13 :     TEST_NOT_EQUAL(k, l);
     708 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(k, m);
     709 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(n, l);
     710                 :            : 
     711                 :         13 :     n = m;
     712   [ -  +  #  # ]:         13 :     TEST_NOT_EQUAL(n, l);
     713 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(n, m);
     714 [ -  + ][ #  # ]:         13 :     TEST_NOT_EQUAL(n, myeset.begin());
     715 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(n, myeset.end());
     716                 :            : 
     717                 :         13 :     return true;
     718                 :            : }
     719                 :            : 
     720                 :            : // tests that eset iterators on empty esets compare equal.
     721                 :         13 : DEFINE_TESTCASE(esetiterator2, backend) {
     722                 :         13 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
     723                 :         13 :     enquire.set_query(Xapian::Query("this"));
     724                 :            : 
     725                 :         13 :     Xapian::MSet mymset = enquire.get_mset(0, 10);
     726   [ -  +  #  # ]:         13 :     TEST(mymset.size() >= 2);
     727                 :            : 
     728                 :         13 :     Xapian::RSet myrset;
     729                 :         13 :     Xapian::MSetIterator i = mymset.begin();
     730                 :         13 :     myrset.add_document(*i);
     731                 :         13 :     myrset.add_document(*(++i));
     732                 :            : 
     733                 :         13 :     Xapian::ESet myeset = enquire.get_eset(0, myrset);
     734                 :         13 :     Xapian::ESetIterator j = myeset.begin();
     735                 :         13 :     Xapian::ESetIterator k = myeset.end();
     736                 :         13 :     Xapian::ESetIterator l(j);
     737                 :         13 :     Xapian::ESetIterator m(k);
     738   [ -  +  #  # ]:         13 :     TEST_EQUAL(j, k);
     739 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(l, m);
     740 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(k, m);
     741 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(j, l);
     742 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(j, j);
     743 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(k, k);
     744                 :            : 
     745                 :         13 :     return true;
     746                 :            : }
     747                 :            : 
     748                 :            : // tests the collapse-on-key
     749                 :         13 : DEFINE_TESTCASE(collapsekey1, backend) {
     750                 :         13 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
     751                 :         13 :     enquire.set_query(Xapian::Query("this"));
     752                 :            : 
     753                 :         13 :     Xapian::MSet mymset1 = enquire.get_mset(0, 100);
     754                 :         13 :     Xapian::doccount mymsize1 = mymset1.size();
     755                 :            : 
     756         [ +  + ]:         91 :     for (Xapian::valueno value_no = 1; value_no < 7; ++value_no) {
     757                 :         78 :         enquire.set_collapse_key(value_no);
     758                 :         78 :         Xapian::MSet mymset = enquire.get_mset(0, 100);
     759                 :            : 
     760   [ -  +  #  # ]:         78 :         TEST_AND_EXPLAIN(mymsize1 > mymset.size(),
     761                 :            :                          "Had no fewer items when performing collapse: don't know whether it worked.");
     762                 :            : 
     763                 :         78 :         map<string, Xapian::docid> values;
     764                 :         78 :         Xapian::MSetIterator i = mymset.begin();
     765         [ +  + ]:        286 :         for ( ; i != mymset.end(); ++i) {
     766                 :        208 :             string value = i.get_document().get_value(value_no);
     767   [ -  +  #  # ]:        208 :             TEST(values[value] == 0 || value.empty());
         [ -  + ][ #  # ]
     768                 :        208 :             values[value] = *i;
     769                 :            :         }
     770                 :            :     }
     771                 :            : 
     772                 :         13 :     return true;
     773                 :            : }
     774                 :            : 
     775                 :            : // tests that collapse-on-key modifies the predicted bounds for the number of
     776                 :            : // matches appropriately.
     777                 :         13 : DEFINE_TESTCASE(collapsekey2, backend) {
     778         [ -  + ]:         13 :     SKIP_TEST("Don't have a suitable database currently");
     779                 :            :     // FIXME: this needs an appropriate database creating, but that's quite
     780                 :            :     // subtle to do it seems.
     781                 :            :     Xapian::Enquire enquire(get_database("apitest_simpledata2"));
     782                 :            :     enquire.set_query(Xapian::Query("this"));
     783                 :            : 
     784                 :            :     Xapian::MSet mset1 = enquire.get_mset(0, 1);
     785                 :            : 
     786                 :            :     // Test that if no duplicates are found, then the upper bound remains
     787                 :            :     // unchanged and the lower bound drops.
     788                 :            :     {
     789                 :            :         enquire.set_query(Xapian::Query("this"));
     790                 :            :         Xapian::valueno value_no = 3;
     791                 :            :         enquire.set_collapse_key(value_no);
     792                 :            :         Xapian::MSet mset = enquire.get_mset(0, 1);
     793                 :            : 
     794                 :            :         TEST_REL(mset.get_matches_lower_bound(),<,mset1.get_matches_lower_bound());
     795                 :            :         TEST_EQUAL(mset.get_matches_upper_bound(), mset1.get_matches_upper_bound());
     796                 :            :     }
     797                 :            : 
     798                 :            :     return true;
     799                 :            : }
     800                 :            : 
     801                 :            : // tests that collapse-on-key modifies the predicted bounds for the number of
     802                 :            : // matches appropriately.
     803                 :         13 : DEFINE_TESTCASE(collapsekey3, backend) {
     804                 :         13 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
     805                 :         13 :     enquire.set_query(Xapian::Query("this"));
     806                 :            : 
     807                 :         13 :     Xapian::MSet mymset1 = enquire.get_mset(0, 3);
     808                 :            : 
     809         [ +  + ]:         91 :     for (Xapian::valueno value_no = 1; value_no < 7; ++value_no) {
     810                 :         78 :         enquire.set_collapse_key(value_no);
     811                 :         78 :         Xapian::MSet mymset = enquire.get_mset(0, 3);
     812                 :            : 
     813   [ -  +  #  # ]:         78 :         TEST_AND_EXPLAIN(mymset1.get_matches_lower_bound() > mymset.get_matches_lower_bound(),
     814                 :            :                          "Lower bound was not lower when performing collapse: don't know whether it worked.");
     815 [ -  + ][ #  # ]:         78 :         TEST_AND_EXPLAIN(mymset1.get_matches_upper_bound() > mymset.get_matches_upper_bound(),
     816                 :            :                          "Upper bound was not lower when performing collapse: don't know whether it worked.");
     817                 :            : 
     818                 :         78 :         map<string, Xapian::docid> values;
     819                 :         78 :         Xapian::MSetIterator i = mymset.begin();
     820         [ +  + ]:        260 :         for ( ; i != mymset.end(); ++i) {
     821                 :        182 :             string value = i.get_document().get_value(value_no);
     822   [ -  +  #  # ]:        182 :             TEST(values[value] == 0 || value.empty());
         [ -  + ][ #  # ]
     823                 :        182 :             values[value] = *i;
     824                 :            :         }
     825                 :            :     }
     826                 :            : 
     827                 :            :     // Test that if the collapse value is always empty, then the upper bound
     828                 :            :     // remains unchanged, and the lower bound is the same or lower (it can be
     829                 :            :     // lower because the matcher counts the number of documents with empty
     830                 :            :     // collapse keys, but may have rejected a document because its weight is
     831                 :            :     // too low for the proto-MSet before it even looks at its collapse key).
     832                 :            :     {
     833                 :         13 :         Xapian::valueno value_no = 1000;
     834                 :         13 :         enquire.set_collapse_key(value_no);
     835                 :         13 :         Xapian::MSet mymset = enquire.get_mset(0, 3);
     836                 :            : 
     837   [ -  +  #  # ]:         13 :         TEST(mymset.get_matches_lower_bound() <= mymset1.get_matches_lower_bound());
     838 [ -  + ][ #  # ]:         13 :         TEST_EQUAL(mymset.get_matches_upper_bound(), mymset1.get_matches_upper_bound());
     839                 :            : 
     840                 :         13 :         map<string, Xapian::docid> values;
     841                 :         13 :         Xapian::MSetIterator i = mymset.begin();
     842         [ +  + ]:         52 :         for ( ; i != mymset.end(); ++i) {
     843                 :         39 :             string value = i.get_document().get_value(value_no);
     844   [ +  +  -  + ]:         39 :             TEST(values[value] == 0 || value.empty());
         [ -  + ][ #  # ]
     845                 :         39 :             values[value] = *i;
     846                 :         13 :         }
     847                 :            :     }
     848                 :            : 
     849                 :         13 :     return true;
     850                 :            : }
     851                 :            : 
     852                 :            : // tests that collapse-on-key modifies the predicted bounds for the number of
     853                 :            : // matches appropriately even when no results are requested.
     854                 :         13 : DEFINE_TESTCASE(collapsekey4, backend) {
     855                 :         13 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
     856                 :         13 :     enquire.set_query(Xapian::Query("this"));
     857                 :            : 
     858                 :         13 :     Xapian::MSet mymset1 = enquire.get_mset(0, 0);
     859                 :            : 
     860         [ +  + ]:         91 :     for (Xapian::valueno value_no = 1; value_no < 7; ++value_no) {
     861                 :         78 :         enquire.set_collapse_key(value_no);
     862                 :         78 :         Xapian::MSet mymset = enquire.get_mset(0, 0);
     863                 :            : 
     864   [ -  +  #  # ]:         78 :         TEST_AND_EXPLAIN(mymset.get_matches_lower_bound() == 1,
     865                 :            :                          "Lower bound was not 1 when performing collapse but not asking for any results.");
     866 [ -  + ][ #  # ]:         78 :         TEST_AND_EXPLAIN(mymset1.get_matches_upper_bound() == mymset.get_matches_upper_bound(),
     867                 :            :                          "Upper bound was changed when performing collapse but not asking for any results.");
     868                 :            : 
     869                 :         78 :         map<string, Xapian::docid> values;
     870                 :         78 :         Xapian::MSetIterator i = mymset.begin();
     871         [ -  + ]:         78 :         for ( ; i != mymset.end(); ++i) {
     872                 :          0 :             string value = i.get_document().get_value(value_no);
     873   [ #  #  #  # ]:          0 :             TEST(values[value] == 0 || value.empty());
         [ #  # ][ #  # ]
     874                 :          0 :             values[value] = *i;
     875                 :            :         }
     876                 :            :     }
     877                 :            : 
     878                 :         13 :     return true;
     879                 :            : }
     880                 :            : 
     881                 :            : // test for keepalives
     882                 :          6 : DEFINE_TESTCASE(keepalive1, remote) {
     883                 :          6 :     Xapian::Database db(get_remote_database("apitest_simpledata", 5000));
     884                 :            : 
     885                 :            :     /* Test that keep-alives work */
     886         [ +  + ]:         66 :     for (int i = 0; i < 10; ++i) {
     887                 :         60 :         sleep(2);
     888                 :         60 :         db.keep_alive();
     889                 :            :     }
     890                 :          6 :     Xapian::Enquire enquire(db);
     891                 :          6 :     enquire.set_query(Xapian::Query("word"));
     892                 :          6 :     enquire.get_mset(0, 10);
     893                 :            : 
     894                 :            :     /* Test that things break without keepalives */
     895                 :          6 :     sleep(10);
     896                 :          6 :     enquire.set_query(Xapian::Query("word"));
     897 [ +  - ][ -  + ]:         12 :     TEST_EXCEPTION(Xapian::NetworkError,
         [ #  # ][ -  + ]
     898                 :            :                    enquire.get_mset(0, 10));
     899                 :            : 
     900                 :          6 :     return true;
     901                 :            : }
     902                 :            : 
     903                 :            : // test that iterating through all terms in a database works.
     904                 :         13 : DEFINE_TESTCASE(allterms1, backend) {
     905                 :         13 :     Xapian::Database db(get_database("apitest_allterms"));
     906                 :         13 :     Xapian::TermIterator ati = db.allterms_begin();
     907 [ -  + ][ #  # ]:         13 :     TEST(ati != db.allterms_end());
     908 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(*ati, "one");
     909 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(ati.get_termfreq(), 1);
     910                 :            : 
     911                 :         13 :     Xapian::TermIterator ati2 = ati;
     912                 :            : 
     913                 :         13 :     ati++;
     914 [ -  + ][ #  # ]:         13 :     TEST(ati != db.allterms_end());
     915         [ -  + ]:         13 :     if (verbose) {
     916                 :          0 :         tout << "*ati = `" << *ati << "'\n";
     917                 :          0 :         tout << "*ati.length = `" << (*ati).length() << "'\n";
     918                 :          0 :         tout << "*ati == \"one\" = " << (*ati == "one") << "\n";
     919                 :          0 :         tout << "*ati[3] = " << ((*ati)[3]) << "\n";
     920                 :          0 :         tout << "*ati = `" << *ati << "'\n";
     921                 :            :     }
     922 [ -  + ][ #  # ]:         13 :     TEST(*ati == "three");
     923 [ -  + ][ #  # ]:         13 :     TEST(ati.get_termfreq() == 3);
     924                 :            : 
     925                 :            : #if 0
     926                 :            :     TEST(ati2 != db.allterms_end());
     927                 :            :     TEST(*ati2 == "one");
     928                 :            :     TEST(ati2.get_termfreq() == 1);
     929                 :            : #endif
     930                 :            : 
     931                 :         13 :     ++ati;
     932                 :            : #if 0
     933                 :            :     ++ati2;
     934                 :            : #endif
     935 [ -  + ][ #  # ]:         13 :     TEST(ati != db.allterms_end());
     936 [ -  + ][ #  # ]:         13 :     TEST(*ati == "two");
     937 [ -  + ][ #  # ]:         13 :     TEST(ati.get_termfreq() == 2);
     938                 :            : 
     939                 :            : #if 0
     940                 :            :     TEST(ati2 != db.allterms_end());
     941                 :            :     TEST(*ati2 == "three");
     942                 :            :     TEST(ati2.get_termfreq() == 3);
     943                 :            : #endif
     944                 :            : 
     945                 :         13 :     ati++;
     946 [ -  + ][ #  # ]:         13 :     TEST(ati == db.allterms_end());
     947                 :            : 
     948                 :         13 :     return true;
     949                 :            : }
     950                 :            : 
     951                 :            : // test that iterating through all terms in two databases works.
     952                 :         13 : DEFINE_TESTCASE(allterms2, backend) {
     953                 :         13 :     Xapian::Database db;
     954                 :         13 :     db.add_database(get_database("apitest_allterms"));
     955                 :         13 :     db.add_database(get_database("apitest_allterms2"));
     956                 :         13 :     Xapian::TermIterator ati = db.allterms_begin();
     957                 :            : 
     958 [ -  + ][ #  # ]:         13 :     TEST(ati != db.allterms_end());
     959 [ -  + ][ #  # ]:         13 :     TEST(*ati == "five");
     960 [ -  + ][ #  # ]:         13 :     TEST(ati.get_termfreq() == 2);
     961                 :         13 :     ati++;
     962                 :            : 
     963 [ -  + ][ #  # ]:         13 :     TEST(ati != db.allterms_end());
     964 [ -  + ][ #  # ]:         13 :     TEST(*ati == "four");
     965 [ -  + ][ #  # ]:         13 :     TEST(ati.get_termfreq() == 1);
     966                 :            : 
     967                 :         13 :     ati++;
     968 [ -  + ][ #  # ]:         13 :     TEST(ati != db.allterms_end());
     969 [ -  + ][ #  # ]:         13 :     TEST(*ati == "one");
     970 [ -  + ][ #  # ]:         13 :     TEST(ati.get_termfreq() == 1);
     971                 :            : 
     972                 :         13 :     ++ati;
     973 [ -  + ][ #  # ]:         13 :     TEST(ati != db.allterms_end());
     974 [ -  + ][ #  # ]:         13 :     TEST(*ati == "six");
     975 [ -  + ][ #  # ]:         13 :     TEST(ati.get_termfreq() == 3);
     976                 :            : 
     977                 :         13 :     ati++;
     978 [ -  + ][ #  # ]:         13 :     TEST(ati != db.allterms_end());
     979 [ -  + ][ #  # ]:         13 :     TEST(*ati == "three");
     980 [ -  + ][ #  # ]:         13 :     TEST(ati.get_termfreq() == 3);
     981                 :            : 
     982                 :         13 :     ati++;
     983 [ -  + ][ #  # ]:         13 :     TEST(ati != db.allterms_end());
     984 [ -  + ][ #  # ]:         13 :     TEST(*ati == "two");
     985 [ -  + ][ #  # ]:         13 :     TEST(ati.get_termfreq() == 2);
     986                 :            : 
     987                 :         13 :     ati++;
     988 [ -  + ][ #  # ]:         13 :     TEST(ati == db.allterms_end());
     989                 :            : 
     990                 :         13 :     return true;
     991                 :            : }
     992                 :            : 
     993                 :            : // test that skip_to sets at_end (regression test)
     994                 :         13 : DEFINE_TESTCASE(allterms3, backend) {
     995                 :         13 :     Xapian::Database db;
     996                 :         13 :     db.add_database(get_database("apitest_allterms"));
     997                 :         13 :     Xapian::TermIterator ati = db.allterms_begin();
     998                 :            : 
     999                 :         13 :     ati.skip_to(string("zzzzzz"));
    1000 [ -  + ][ #  # ]:         13 :     TEST(ati == db.allterms_end());
    1001                 :            : 
    1002                 :         13 :     return true;
    1003                 :            : }
    1004                 :            : 
    1005                 :            : // test that next ignores extra entries due to long posting lists being
    1006                 :            : // chunked (regression test for quartz)
    1007                 :         13 : DEFINE_TESTCASE(allterms4, backend) {
    1008                 :            :     // apitest_allterms4 contains 682 documents each containing just the word
    1009                 :            :     // "foo".  682 was the magic number which started to cause Quartz problems.
    1010                 :         13 :     Xapian::Database db = get_database("apitest_allterms4");
    1011                 :            : 
    1012                 :         13 :     Xapian::TermIterator i = db.allterms_begin();
    1013 [ -  + ][ #  # ]:         13 :     TEST(i != db.allterms_end());
    1014 [ -  + ][ #  # ]:         13 :     TEST(*i == "foo");
    1015 [ -  + ][ #  # ]:         13 :     TEST(i.get_termfreq() == 682);
    1016                 :         13 :     ++i;
    1017 [ -  + ][ #  # ]:         13 :     TEST(i == db.allterms_end());
    1018                 :            : 
    1019                 :         13 :     return true;
    1020                 :            : }
    1021                 :            : 
    1022                 :            : // test that skip_to with an exact match sets the current term (regression test
    1023                 :            : // for quartz)
    1024                 :         13 : DEFINE_TESTCASE(allterms5, backend) {
    1025                 :         13 :     Xapian::Database db;
    1026                 :         13 :     db.add_database(get_database("apitest_allterms"));
    1027                 :         13 :     Xapian::TermIterator ati = db.allterms_begin();
    1028                 :         13 :     ati.skip_to("three");
    1029 [ -  + ][ #  # ]:         13 :     TEST(ati != db.allterms_end());
    1030 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(*ati, "three");
    1031                 :            : 
    1032                 :         13 :     return true;
    1033                 :            : }
    1034                 :            : 
    1035                 :            : // test allterms iterators with prefixes
    1036                 :         13 : DEFINE_TESTCASE(allterms6, backend) {
    1037                 :         13 :     Xapian::Database db;
    1038                 :         13 :     db.add_database(get_database("apitest_allterms"));
    1039                 :         13 :     db.add_database(get_database("apitest_allterms2"));
    1040                 :            : 
    1041                 :         13 :     Xapian::TermIterator ati = db.allterms_begin("three");
    1042 [ -  + ][ #  # ]:         13 :     TEST(ati != db.allterms_end("three"));
    1043 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(*ati, "three");
    1044                 :         13 :     ati.skip_to("three");
    1045 [ -  + ][ #  # ]:         13 :     TEST(ati != db.allterms_end("three"));
    1046 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(*ati, "three");
    1047                 :         13 :     ati++;
    1048 [ -  + ][ #  # ]:         13 :     TEST(ati == db.allterms_end("three"));
    1049                 :            : 
    1050                 :         13 :     ati = db.allterms_begin("thre");
    1051 [ -  + ][ #  # ]:         13 :     TEST(ati != db.allterms_end("thre"));
    1052 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(*ati, "three");
    1053                 :         13 :     ati.skip_to("three");
    1054 [ -  + ][ #  # ]:         13 :     TEST(ati != db.allterms_end("thre"));
    1055 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(*ati, "three");
    1056                 :         13 :     ati++;
    1057 [ -  + ][ #  # ]:         13 :     TEST(ati == db.allterms_end("thre"));
    1058                 :            : 
    1059                 :         13 :     ati = db.allterms_begin("f");
    1060 [ -  + ][ #  # ]:         13 :     TEST(ati != db.allterms_end("f"));
    1061 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(*ati, "five");
    1062 [ -  + ][ #  # ]:         13 :     TEST(ati != db.allterms_end("f"));
    1063                 :         13 :     ati.skip_to("three");
    1064 [ -  + ][ #  # ]:         13 :     TEST(ati == db.allterms_end("f"));
    1065                 :            : 
    1066                 :         13 :     ati = db.allterms_begin("f");
    1067 [ -  + ][ #  # ]:         13 :     TEST(ati != db.allterms_end("f"));
    1068 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(*ati, "five");
    1069                 :         13 :     ati++;
    1070 [ -  + ][ #  # ]:         13 :     TEST(ati != db.allterms_end("f"));
    1071 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(*ati, "four");
    1072                 :         13 :     ati++;
    1073 [ -  + ][ #  # ]:         13 :     TEST(ati == db.allterms_end("f"));
    1074                 :            : 
    1075                 :         13 :     ati = db.allterms_begin("absent");
    1076 [ -  + ][ #  # ]:         13 :     TEST(ati == db.allterms_end("absent"));
    1077                 :            : 
    1078                 :         13 :     return true;
    1079                 :            : }
    1080                 :            : 
    1081                 :            : // test that searching for a term with a special characters in it works
    1082                 :         13 : DEFINE_TESTCASE(specialterms1, backend) {
    1083                 :         13 :     Xapian::Enquire enquire(get_database("apitest_space"));
    1084                 :         13 :     Xapian::MSet mymset;
    1085                 :            :     Xapian::doccount count;
    1086                 :         13 :     Xapian::MSetIterator m;
    1087                 :         13 :     Xapian::Stem stemmer("english");
    1088                 :            : 
    1089                 :         13 :     enquire.set_query(stemmer("new\nline"));
    1090                 :         13 :     mymset = enquire.get_mset(0, 10);
    1091   [ -  +  #  # ]:         13 :     TEST_MSET_SIZE(mymset, 1);
    1092                 :         13 :     count = 0;
    1093         [ +  + ]:         26 :     for (m = mymset.begin(); m != mymset.end(); ++m) ++count;
    1094 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(count, 1);
    1095                 :            : 
    1096         [ +  + ]:        104 :     for (Xapian::valueno value_no = 0; value_no < 7; ++value_no) {
    1097                 :         91 :         string value = mymset.begin().get_document().get_value(value_no);
    1098   [ -  +  #  # ]:         91 :         TEST_NOT_EQUAL(value, "");
    1099         [ +  + ]:         91 :         if (value_no == 0) {
    1100 [ -  + ][ #  # ]:         13 :             TEST(value.size() > 263);
    1101 [ -  + ][ #  # ]:         13 :             TEST_EQUAL(static_cast<unsigned char>(value[262]), 255);
    1102         [ +  + ]:       3341 :             for (int k = 0; k < 256; k++) {
    1103 [ -  + ][ #  # ]:       3328 :                 TEST_EQUAL(static_cast<unsigned char>(value[k+7]), k);
    1104                 :            :             }
    1105                 :            :         }
    1106                 :            :     }
    1107                 :            : 
    1108                 :         13 :     enquire.set_query(stemmer(string("big\0zero", 8)));
    1109                 :         13 :     mymset = enquire.get_mset(0, 10);
    1110   [ -  +  #  # ]:         13 :     TEST_MSET_SIZE(mymset, 1);
    1111                 :         13 :     count = 0;
    1112         [ +  + ]:         26 :     for (m = mymset.begin(); m != mymset.end(); ++m) ++count;
    1113 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(count, 1);
    1114                 :            : 
    1115                 :         13 :     return true;
    1116                 :            : }
    1117                 :            : 
    1118                 :            : // test that terms with a special characters in appear correctly when iterating
    1119                 :            : // allterms
    1120                 :         13 : DEFINE_TESTCASE(specialterms2, backend) {
    1121                 :         13 :     Xapian::Database db(get_database("apitest_space"));
    1122                 :            : 
    1123                 :            :     // Check the terms are all as expected (after stemming) and that allterms
    1124                 :            :     // copes with iterating over them.
    1125                 :         13 :     Xapian::TermIterator t;
    1126                 :         13 :     t = db.allterms_begin();
    1127 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(*t, "back\\slash"); ++t; TEST_NOT_EQUAL(t, db.allterms_end());
         [ -  + ][ #  # ]
    1128 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(*t, string("big\0zero", 8)); ++t; TEST_NOT_EQUAL(t, db.allterms_end());
         [ -  + ][ #  # ]
    1129 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(*t, "new\nlin"); ++t; TEST_NOT_EQUAL(t, db.allterms_end());
         [ -  + ][ #  # ]
    1130 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(*t, "one\x01on"); ++t; TEST_NOT_EQUAL(t, db.allterms_end());
         [ -  + ][ #  # ]
    1131 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(*t, "space man"); ++t; TEST_NOT_EQUAL(t, db.allterms_end());
         [ -  + ][ #  # ]
    1132 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(*t, "tab\tbi"); ++t; TEST_NOT_EQUAL(t, db.allterms_end());
         [ -  + ][ #  # ]
    1133 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(*t, "tu\x02tu"); ++t; TEST_EQUAL(t, db.allterms_end());
         [ -  + ][ #  # ]
    1134                 :            : 
    1135                 :            :     // Now check that skip_to exactly a term containing a zero byte works.
    1136                 :            :     // This is a regression test for flint and quartz - an Assert() used to
    1137                 :            :     // fire in debug builds (the Assert was wrong - the actual code handled
    1138                 :            :     // this OK).
    1139                 :         13 :     t = db.allterms_begin();
    1140                 :         13 :     t.skip_to(string("big\0zero", 8));
    1141 [ -  + ][ #  # ]:         13 :     TEST_NOT_EQUAL(t, db.allterms_end());
    1142 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(*t, string("big\0zero", 8));
    1143                 :            : 
    1144                 :         13 :     return true;
    1145                 :            : }
    1146                 :            : 
    1147                 :            : // test that rsets behave correctly with multiDBs
    1148                 :         10 : DEFINE_TESTCASE(rsetmultidb2, backend && !multi) {
    1149                 :         10 :     Xapian::Database mydb1(get_database("apitest_rset", "apitest_simpledata2"));
    1150                 :         10 :     Xapian::Database mydb2(get_database("apitest_rset"));
    1151                 :         10 :     mydb2.add_database(get_database("apitest_simpledata2"));
    1152                 :            : 
    1153                 :         10 :     Xapian::Enquire enquire1(mydb1);
    1154                 :         10 :     Xapian::Enquire enquire2(mydb2);
    1155                 :            : 
    1156                 :         10 :     Xapian::Query myquery = query("is");
    1157                 :            : 
    1158                 :         10 :     enquire1.set_query(myquery);
    1159                 :         10 :     enquire2.set_query(myquery);
    1160                 :            : 
    1161                 :         10 :     Xapian::RSet myrset1;
    1162                 :         10 :     Xapian::RSet myrset2;
    1163                 :         10 :     myrset1.add_document(4);
    1164                 :         10 :     myrset2.add_document(2);
    1165                 :            : 
    1166                 :         10 :     Xapian::MSet mymset1a = enquire1.get_mset(0, 10);
    1167                 :         10 :     Xapian::MSet mymset1b = enquire1.get_mset(0, 10, &myrset1);
    1168                 :         10 :     Xapian::MSet mymset2a = enquire2.get_mset(0, 10);
    1169                 :         10 :     Xapian::MSet mymset2b = enquire2.get_mset(0, 10, &myrset2);
    1170                 :            : 
    1171                 :         10 :     mset_expect_order(mymset1a, 4, 3);
    1172                 :         10 :     mset_expect_order(mymset1b, 4, 3);
    1173                 :         10 :     mset_expect_order(mymset2a, 2, 5);
    1174                 :         10 :     mset_expect_order(mymset2b, 2, 5);
    1175                 :            : 
    1176   [ -  +  #  # ]:         10 :     TEST(mset_range_is_same_weights(mymset1a, 0, mymset2a, 0, 2));
    1177 [ -  + ][ #  # ]:         10 :     TEST(mset_range_is_same_weights(mymset1b, 0, mymset2b, 0, 2));
    1178 [ -  + ][ #  # ]:         10 :     TEST_NOT_EQUAL(mymset1a, mymset1b);
    1179 [ -  + ][ #  # ]:         10 :     TEST_NOT_EQUAL(mymset2a, mymset2b);
    1180                 :            : 
    1181                 :         10 :     return true;
    1182                 :            : }
    1183                 :            : 
    1184                 :            : // tests an expand across multiple databases
    1185                 :         10 : DEFINE_TESTCASE(multiexpand1, backend && !multi) {
    1186                 :         10 :     Xapian::Database mydb1(get_database("apitest_simpledata", "apitest_simpledata2"));
    1187                 :         10 :     Xapian::Enquire enquire1(mydb1);
    1188                 :            : 
    1189                 :         10 :     Xapian::Database mydb2(get_database("apitest_simpledata"));
    1190                 :         10 :     mydb2.add_database(get_database("apitest_simpledata2"));
    1191                 :         10 :     Xapian::Enquire enquire2(mydb2);
    1192                 :            : 
    1193                 :            :     // make simple equivalent rsets, with a document from each database in each.
    1194                 :         10 :     Xapian::RSet rset1;
    1195                 :         10 :     Xapian::RSet rset2;
    1196                 :         10 :     rset1.add_document(1);
    1197                 :         10 :     rset1.add_document(7);
    1198                 :         10 :     rset2.add_document(1);
    1199                 :         10 :     rset2.add_document(2);
    1200                 :            : 
    1201                 :            :     // Retrieve all the ESet results in each of the three setups:
    1202                 :            : 
    1203                 :            :     // This is the single database one.
    1204                 :         10 :     Xapian::ESet eset1 = enquire1.get_eset(1000, rset1);
    1205                 :            : 
    1206                 :            :     // This is the multi database with approximation
    1207                 :         10 :     Xapian::ESet eset2 = enquire2.get_eset(1000, rset2);
    1208                 :            : 
    1209                 :            :     // This is the multi database without approximation
    1210                 :         10 :     Xapian::ESet eset3 = enquire2.get_eset(1000, rset2, Xapian::Enquire::USE_EXACT_TERMFREQ);
    1211                 :            : 
    1212   [ -  +  #  # ]:         10 :     TEST_EQUAL(eset1.size(), eset3.size());
    1213                 :            : 
    1214                 :         10 :     Xapian::ESetIterator i = eset1.begin();
    1215                 :         10 :     Xapian::ESetIterator j = eset3.begin();
    1216 [ +  + ][ +  - ]:        370 :     while (i != eset1.end() && j != eset3.end()) {
         [ +  + ][ #  # ]
         [ #  # ][ +  - ]
                 [ +  + ]
    1217 [ -  + ][ #  # ]:        360 :         TEST_EQUAL(*i, *j);
    1218 [ -  + ][ #  # ]:        360 :         TEST_EQUAL(i.get_weight(), j.get_weight());
    1219                 :        360 :         ++i;
    1220                 :        360 :         ++j;
    1221                 :            :     }
    1222 [ -  + ][ #  # ]:         10 :     TEST(i == eset1.end());
    1223 [ -  + ][ #  # ]:         10 :     TEST(j == eset3.end());
    1224                 :            : 
    1225                 :         10 :     bool eset1_eq_eset2 = true;
    1226                 :         10 :     i = eset1.begin();
    1227                 :         10 :     j = eset2.begin();
    1228 [ +  - ][ +  - ]:         10 :     while (i != eset1.end() && j != eset2.end()) {
         [ +  - ][ #  # ]
         [ #  # ][ +  - ]
                 [ +  - ]
    1229         [ +  - ]:         10 :         if (i.get_weight() != j.get_weight()) {
    1230                 :         10 :             eset1_eq_eset2 = false;
    1231                 :         10 :             break;
    1232                 :            :         }
    1233                 :          0 :         ++i;
    1234                 :          0 :         ++j;
    1235                 :            :     }
    1236 [ -  + ][ #  # ]:         10 :     TEST(!eset1_eq_eset2);
    1237                 :            : 
    1238                 :         10 :     return true;
    1239                 :            : }
    1240                 :            : 
    1241                 :            : // tests that opening a non-existent postlist returns an empty list
    1242                 :         13 : DEFINE_TESTCASE(postlist1, backend) {
    1243                 :         13 :     Xapian::Database db(get_database("apitest_simpledata"));
    1244                 :            : 
    1245 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(db.postlist_begin("rosebud"), db.postlist_end("rosebud"));
    1246                 :            : 
    1247                 :         13 :     string s = "let_us_see_if_we_can_break_it_with_a_really_really_long_term.";
    1248         [ +  + ]:        117 :     for (int i = 0; i < 8; ++i) {
    1249                 :        104 :         s += s;
    1250 [ -  + ][ #  # ]:        104 :         TEST_EQUAL(db.postlist_begin(s), db.postlist_end(s));
    1251                 :            :     }
    1252                 :            : 
    1253                 :            :     // A regression test (no, really!)
    1254 [ -  + ][ #  # ]:         13 :     TEST_NOT_EQUAL(db.postlist_begin("a"), db.postlist_end("a"));
    1255                 :            : 
    1256                 :         13 :     return true;
    1257                 :            : }
    1258                 :            : 
    1259                 :            : // tests that a Xapian::PostingIterator works as an STL iterator
    1260                 :         13 : DEFINE_TESTCASE(postlist2, backend) {
    1261                 :         13 :     Xapian::Database db(get_database("apitest_simpledata"));
    1262                 :         13 :     Xapian::PostingIterator p;
    1263                 :         13 :     p = db.postlist_begin("this");
    1264                 :         13 :     Xapian::PostingIterator pend = db.postlist_end("this");
    1265                 :            : 
    1266 [ -  + ][ #  # ]:         13 :     TEST(p.get_description() != "Xapian::PostingIterator(pos=END)");
    1267                 :            : 
    1268                 :            :     // test operator= creates a copy which compares equal
    1269                 :         13 :     Xapian::PostingIterator p_copy = p;
    1270   [ -  +  #  # ]:         13 :     TEST_EQUAL(p, p_copy);
    1271                 :            : 
    1272 [ -  + ][ #  # ]:         13 :     TEST(p_copy.get_description() != "Xapian::PostingIterator(pos=END)");
    1273                 :            : 
    1274                 :            :     // test copy constructor creates a copy which compares equal
    1275                 :         13 :     Xapian::PostingIterator p_clone(p);
    1276   [ -  +  #  # ]:         13 :     TEST_EQUAL(p, p_clone);
    1277                 :            : 
    1278 [ -  + ][ #  # ]:         13 :     TEST(p_clone.get_description() != "Xapian::PostingIterator(pos=END)");
    1279                 :            : 
    1280                 :         13 :     vector<Xapian::docid> v(p, pend);
    1281                 :            : 
    1282                 :         13 :     p = db.postlist_begin("this");
    1283                 :         13 :     pend = db.postlist_end("this");
    1284                 :         13 :     vector<Xapian::docid>::const_iterator i;
    1285         [ +  + ]:         91 :     for (i = v.begin(); i != v.end(); i++) {
    1286 [ -  + ][ #  # ]:         78 :         TEST_NOT_EQUAL(p, pend);
    1287 [ -  + ][ #  # ]:         78 :         TEST_EQUAL(*i, *p);
    1288                 :         78 :         p++;
    1289                 :            :     }
    1290 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(p, pend);
    1291                 :            : 
    1292 [ -  + ][ #  # ]:         13 :     TEST_STRINGS_EQUAL(p.get_description(),
    1293                 :            :                        "Xapian::PostingIterator(pos=END)");
    1294 [ -  + ][ #  # ]:         13 :     TEST_STRINGS_EQUAL(pend.get_description(),
    1295                 :            :                        "Xapian::PostingIterator(pos=END)");
    1296                 :            : 
    1297                 :         13 :     return true;
    1298                 :            : }
    1299                 :            : 
    1300                 :            : // tests that a Xapian::PostingIterator still works when the DB is deleted
    1301                 :         13 : DEFINE_TESTCASE(postlist3, backend) {
    1302                 :         13 :     Xapian::PostingIterator u;
    1303                 :            :     {
    1304                 :         13 :         Xapian::Database db_temp(get_database("apitest_simpledata"));
    1305                 :         13 :         u = db_temp.postlist_begin("this");
    1306                 :            :     }
    1307                 :            : 
    1308                 :         13 :     Xapian::Database db(get_database("apitest_simpledata"));
    1309                 :         13 :     Xapian::PostingIterator p = db.postlist_begin("this");
    1310                 :         13 :     Xapian::PostingIterator pend = db.postlist_end("this");
    1311                 :            : 
    1312         [ +  + ]:         91 :     while (p != pend) {
    1313 [ -  + ][ #  # ]:         78 :         TEST_EQUAL(*p, *u);
    1314                 :         78 :         p++;
    1315                 :         78 :         u++;
    1316                 :            :     }
    1317                 :         13 :     return true;
    1318                 :            : }
    1319                 :            : 
    1320                 :            : // tests skip_to
    1321                 :         13 : DEFINE_TESTCASE(postlist4, backend) {
    1322                 :         13 :     Xapian::Database db(get_database("apitest_simpledata"));
    1323                 :         13 :     Xapian::PostingIterator i = db.postlist_begin("this");
    1324                 :         13 :     i.skip_to(1);
    1325                 :         13 :     i.skip_to(999999999);
    1326 [ -  + ][ #  # ]:         13 :     TEST(i == db.postlist_end("this"));
    1327                 :         13 :     return true;
    1328                 :            : }
    1329                 :            : 
    1330                 :            : // tests long postlists
    1331                 :         13 : DEFINE_TESTCASE(postlist5, backend) {
    1332                 :         13 :     Xapian::Database db(get_database("apitest_manydocs"));
    1333                 :            :     // Allow for databases which don't support length
    1334         [ +  - ]:         13 :     if (db.get_avlength() != 1)
    1335 [ -  + ][ #  # ]:         13 :         TEST_EQUAL_DOUBLE(db.get_avlength(), 4);
    1336                 :         13 :     Xapian::PostingIterator i = db.postlist_begin("this");
    1337                 :         13 :     unsigned int j = 1;
    1338         [ +  + ]:       6669 :     while (i != db.postlist_end("this")) {
    1339 [ -  + ][ #  # ]:       6656 :         TEST_EQUAL(*i, j);
    1340                 :       6656 :         i++;
    1341                 :       6656 :         j++;
    1342                 :            :     }
    1343 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(j, 513);
    1344                 :         13 :     return true;
    1345                 :            : }
    1346                 :            : 
    1347                 :            : // tests document length in postlists
    1348                 :         13 : DEFINE_TESTCASE(postlist6, backend) {
    1349                 :         13 :     Xapian::Database db(get_database("apitest_simpledata"));
    1350                 :         13 :     Xapian::PostingIterator i = db.postlist_begin("this");
    1351 [ -  + ][ #  # ]:         13 :     TEST(i != db.postlist_end("this"));
    1352         [ +  + ]:         91 :     while (i != db.postlist_end("this")) {
    1353 [ -  + ][ #  # ]:         78 :         TEST_EQUAL(i.get_doclength(), db.get_doclength(*i));
    1354 [ -  + ][ #  # ]:         78 :         TEST_REL(i.get_wdf(),<=,i.get_doclength());
    1355                 :         78 :         ++i;
    1356                 :            :     }
    1357                 :         13 :     return true;
    1358                 :            : }
    1359                 :            : 
    1360                 :            : // tests collection frequency
    1361                 :         13 : DEFINE_TESTCASE(collfreq1, backend) {
    1362                 :         13 :     Xapian::Database db(get_database("apitest_simpledata"));
    1363                 :            : 
    1364 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(db.get_collection_freq("this"), 11);
    1365 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(db.get_collection_freq("first"), 1);
    1366 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(db.get_collection_freq("last"), 0);
    1367 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(db.get_collection_freq("word"), 9);
    1368                 :            : 
    1369                 :         13 :     Xapian::Database db1(get_database("apitest_simpledata", "apitest_simpledata2"));
    1370                 :         13 :     Xapian::Database db2(get_database("apitest_simpledata"));
    1371                 :         13 :     db2.add_database(get_database("apitest_simpledata2"));
    1372                 :            : 
    1373 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(db1.get_collection_freq("this"), 15);
    1374 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(db1.get_collection_freq("first"), 1);
    1375 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(db1.get_collection_freq("last"), 0);
    1376 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(db1.get_collection_freq("word"), 11);
    1377 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(db2.get_collection_freq("this"), 15);
    1378 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(db2.get_collection_freq("first"), 1);
    1379 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(db2.get_collection_freq("last"), 0);
    1380 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(db2.get_collection_freq("word"), 11);
    1381                 :            : 
    1382                 :         13 :     return true;
    1383                 :            : }
    1384                 :            : 
    1385                 :            : // Regression test for split msets being incorrect when sorting
    1386                 :         13 : DEFINE_TESTCASE(sortvalue1, backend) {
    1387                 :         13 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
    1388                 :         13 :     enquire.set_query(Xapian::Query("this"));
    1389                 :            : 
    1390         [ +  + ]:         39 :     for (int pass = 1; pass <= 2; ++pass) {
    1391         [ +  + ]:        182 :         for (Xapian::valueno value_no = 1; value_no < 7; ++value_no) {
    1392                 :        156 :             tout << "Sorting on value " << value_no << endl;
    1393                 :        156 :             enquire.set_sort_by_value(value_no, true);
    1394                 :        156 :             Xapian::MSet allbset = enquire.get_mset(0, 100);
    1395                 :        156 :             Xapian::MSet partbset1 = enquire.get_mset(0, 3);
    1396                 :        156 :             Xapian::MSet partbset2 = enquire.get_mset(3, 97);
    1397   [ -  +  #  # ]:        156 :             TEST_EQUAL(allbset.size(), partbset1.size() + partbset2.size());
    1398                 :            : 
    1399                 :        156 :             bool ok = true;
    1400                 :        156 :             int n = 0;
    1401                 :        156 :             Xapian::MSetIterator i, j;
    1402                 :        156 :             j = allbset.begin();
    1403         [ +  + ]:        624 :             for (i = partbset1.begin(); i != partbset1.end(); ++i) {
    1404                 :        468 :                 tout << "Entry " << n << ": " << *i << " | " << *j << endl;
    1405 [ -  + ][ #  # ]:        468 :                 TEST(j != allbset.end());
    1406         [ -  + ]:        468 :                 if (*i != *j) ok = false;
    1407                 :        468 :                 ++j;
    1408                 :        468 :                 ++n;
    1409                 :            :             }
    1410                 :        156 :             tout << "===\n";
    1411         [ +  + ]:        624 :             for (i = partbset2.begin(); i != partbset2.end(); ++i) {
    1412                 :        468 :                 tout << "Entry " << n << ": " << *i << " | " << *j << endl;
    1413 [ -  + ][ #  # ]:        468 :                 TEST(j != allbset.end());
    1414         [ -  + ]:        468 :                 if (*i != *j) ok = false;
    1415                 :        468 :                 ++j;
    1416                 :        468 :                 ++n;
    1417                 :            :             }
    1418 [ -  + ][ #  # ]:        156 :             TEST(j == allbset.end());
    1419         [ -  + ]:        156 :             if (!ok)
    1420         [ #  # ]:          0 :                 FAIL_TEST("Split msets aren't consistent with unsplit");
    1421                 :            :         }
    1422                 :         26 :         enquire.set_docid_order(Xapian::Enquire::DESCENDING);
    1423                 :            :     }
    1424                 :            : 
    1425                 :         13 :     return true;
    1426                 :            : }
    1427                 :            : 
    1428                 :            : // consistency check match - vary mset size and check results agree.
    1429                 :            : // consistency1 will run on the remote backend, but it's particularly slow
    1430                 :            : // with that, and testing it there doesn't actually improve the test
    1431                 :            : // coverage really.
    1432                 :          7 : DEFINE_TESTCASE(consistency1, backend && !remote) {
    1433                 :          7 :     Xapian::Database db(get_database("etext"));
    1434                 :          7 :     Xapian::Enquire enquire(db);
    1435                 :          7 :     enquire.set_query(Xapian::Query(Xapian::Query::OP_OR, Xapian::Query("the"), Xapian::Query("sky")));
    1436                 :          7 :     Xapian::doccount lots = 214;
    1437                 :          7 :     Xapian::MSet bigmset = enquire.get_mset(0, lots);
    1438   [ -  +  #  # ]:          7 :     TEST_EQUAL(bigmset.size(), lots);
    1439                 :            :     try {
    1440         [ +  + ]:       1505 :         for (Xapian::doccount start = 0; start < lots; ++start) {
    1441         [ +  + ]:     162533 :             for (Xapian::doccount size = 0; size < lots - start; ++size) {
    1442                 :     161035 :                 Xapian::MSet mset = enquire.get_mset(start, size);
    1443         [ +  + ]:     161035 :                 if (mset.size()) {
    1444 [ -  + ][ #  # ]:     159537 :                     TEST_EQUAL(start + mset.size(),
    1445                 :            :                                min(start + size, bigmset.size()));
    1446         [ -  + ]:       1498 :                 } else if (size) {
    1447                 :            : //              tout << start << mset.size() << bigmset.size() << endl;
    1448 [ #  # ][ #  # ]:          0 :                     TEST(start >= bigmset.size());
    1449                 :            :                 }
    1450         [ +  + ]:   11594520 :                 for (Xapian::doccount i = 0; i < mset.size(); ++i) {
    1451 [ -  + ][ #  # ]:   11433485 :                     TEST_EQUAL(*mset[i], *bigmset[start + i]);
    1452 [ -  + ][ #  # ]:   11433485 :                     TEST_EQUAL_DOUBLE(mset[i].get_weight(),
    1453                 :            :                                       bigmset[start + i].get_weight());
    1454                 :            :                 }
    1455                 :            :             }
    1456                 :            :         }
    1457                 :            :     }
    1458                 :          0 :     catch (const Xapian::NetworkTimeoutError &) {
    1459                 :            :         // consistency1 is a long test - may timeout with the remote backend...
    1460         [ #  # ]:          0 :         SKIP_TEST("Test taking too long");
    1461                 :            :     }
    1462                 :          7 :     return true;
    1463                 :            : }
    1464                 :            : 
    1465                 :            : // tests that specifying a nonexistent input file throws an exception.
    1466                 :          1 : DEFINE_TESTCASE(flintdatabaseopeningerror1, flint) {
    1467                 :            : #ifdef XAPIAN_HAS_FLINT_BACKEND
    1468                 :          1 :     mkdir(".flint", 0755);
    1469                 :            : 
    1470 [ +  - ][ -  + ]:          4 :     TEST_EXCEPTION(Xapian::DatabaseOpeningError,
         [ #  # ][ -  + ]
    1471                 :            :                    Xapian::Flint::open(".flint/nosuchdirectory"));
    1472 [ +  - ][ -  + ]:          4 :     TEST_EXCEPTION(Xapian::DatabaseOpeningError,
         [ #  # ][ -  + ]
    1473                 :            :                    Xapian::Flint::open(".flint/nosuchdirectory", Xapian::DB_OPEN));
    1474                 :            : 
    1475                 :          1 :     mkdir(".flint/emptydirectory", 0700);
    1476 [ +  - ][ -  + ]:          4 :     TEST_EXCEPTION(Xapian::DatabaseOpeningError,
         [ #  # ][ -  + ]
    1477                 :            :                    Xapian::Flint::open(".flint/emptydirectory"));
    1478                 :            : 
    1479                 :          1 :     touch(".flint/somefile");
    1480 [ +  - ][ -  + ]:          4 :     TEST_EXCEPTION(Xapian::DatabaseOpeningError,
         [ #  # ][ -  + ]
    1481                 :            :                    Xapian::Flint::open(".flint/somefile"));
    1482 [ +  - ][ -  + ]:          4 :     TEST_EXCEPTION(Xapian::DatabaseOpeningError,
         [ #  # ][ -  + ]
    1483                 :            :                    Xapian::Flint::open(".flint/somefile", Xapian::DB_OPEN));
    1484 [ +  - ][ -  + ]:          4 :     TEST_EXCEPTION(Xapian::DatabaseCreateError,
         [ #  # ][ -  + ]
    1485                 :            :                    Xapian::Flint::open(".flint/somefile", Xapian::DB_CREATE));
    1486 [ +  - ][ -  + ]:          4 :     TEST_EXCEPTION(Xapian::DatabaseCreateError,
         [ #  # ][ -  + ]
    1487                 :            :                    Xapian::Flint::open(".flint/somefile", Xapian::DB_CREATE_OR_OPEN));
    1488 [ +  - ][ -  + ]:          4 :     TEST_EXCEPTION(Xapian::DatabaseCreateError,
         [ #  # ][ -  + ]
    1489                 :            :                    Xapian::Flint::open(".flint/somefile", Xapian::DB_CREATE_OR_OVERWRITE));
    1490                 :            : #endif
    1491                 :            : 
    1492                 :          1 :     return true;
    1493                 :            : }
    1494                 :            : 
    1495                 :            : /// Tests that appropriate error is thrown for database format change.
    1496                 :          1 : DEFINE_TESTCASE(flintdatabaseformaterror1, flint) {
    1497                 :            : #ifdef XAPIAN_HAS_FLINT_BACKEND
    1498                 :          1 :     string dbdir = test_driver::get_srcdir();
    1499                 :          1 :     dbdir += "/testdata/flint-0.9.9";
    1500                 :            : 
    1501                 :            :     // We should get a version error when we try and open the database for
    1502                 :            :     // reading now.
    1503 [ +  - ][ -  + ]:          2 :     TEST_EXCEPTION(Xapian::DatabaseVersionError,
         [ #  # ][ -  + ]
    1504                 :            :                    Xapian::Database db(dbdir));
    1505                 :            : 
    1506                 :            :     // Also test when explicitly opening as a flint database.
    1507 [ +  - ][ -  + ]:          2 :     TEST_EXCEPTION(Xapian::DatabaseVersionError,
         [ #  # ][ -  + ]
    1508                 :            :                    (void)Xapian::Flint::open(dbdir));
    1509                 :            : 
    1510                 :            :     // Clean up the "flintlock" file that we will have created while trying
    1511                 :            :     // to open the database.
    1512                 :          1 :     unlink((dbdir + "/flintlock").c_str());
    1513                 :            : #endif
    1514                 :            : 
    1515                 :          1 :     return true;
    1516                 :            : }
    1517                 :            : 
    1518                 :            : /// Test that an old database can be successfully overwritten when using
    1519                 :            : // Xapian::DB_CREATE_OR_OVERWRITE.
    1520                 :          1 : DEFINE_TESTCASE(flintdatabaseformaterror2, flint) {
    1521                 :            : #ifdef XAPIAN_HAS_FLINT_BACKEND
    1522                 :          1 :     string flint099 = test_driver::get_srcdir();
    1523                 :          1 :     flint099 += "/testdata/flint-0.9.9";
    1524                 :            : 
    1525                 :          1 :     mkdir(".flint", 0755);
    1526                 :          1 :     string dbdir = ".flint/test_flintdatabaseformaterror2";
    1527                 :            : 
    1528                 :          1 :     rm_rf(dbdir);
    1529                 :          1 :     cp_R(flint099, dbdir);
    1530                 :            : 
    1531                 :          1 :     (void)Xapian::WritableDatabase(dbdir, Xapian::DB_CREATE_OR_OVERWRITE);
    1532                 :            : 
    1533                 :          1 :     rm_rf(dbdir);
    1534                 :          1 :     cp_R(flint099, dbdir);
    1535                 :            : 
    1536                 :            :     // Also test when explicitly opening as a flint database.
    1537                 :          1 :     (void)Xapian::Flint::open(dbdir, Xapian::DB_CREATE_OR_OVERWRITE);
    1538                 :            : #endif
    1539                 :            : 
    1540                 :          1 :     return true;
    1541                 :            : }
    1542                 :            : 
    1543                 :            : // regression test for not releasing lock on error.
    1544                 :          1 : DEFINE_TESTCASE(flintdatabaseformaterror3, flint) {
    1545                 :            : #ifdef XAPIAN_HAS_FLINT_BACKEND
    1546                 :          1 :     string flint099 = test_driver::get_srcdir();
    1547                 :          1 :     flint099 += "/testdata/flint-0.9.9";
    1548                 :            : 
    1549                 :          1 :     mkdir(".flint", 0755);
    1550                 :          1 :     string dbdir = ".flint/test_flintdatabaseformaterror3";
    1551                 :            : 
    1552                 :          1 :     rm_rf(dbdir);
    1553                 :          1 :     cp_R(flint099, dbdir);
    1554                 :            : 
    1555 [ +  - ][ -  + ]:          2 :     TEST_EXCEPTION(Xapian::DatabaseVersionError,
         [ #  # ][ -  + ]
    1556                 :            :                    Xapian::WritableDatabase(dbdir, Xapian::DB_CREATE_OR_OPEN));
    1557                 :            : 
    1558                 :            :     // This used to throw a DatabaseLockError: "Unable to acquire database
    1559                 :            :     // write lock on .flint/formatdb: already locked"
    1560                 :          1 :     Xapian::WritableDatabase(dbdir, Xapian::DB_CREATE_OR_OVERWRITE);
    1561                 :            : #endif
    1562                 :            : 
    1563                 :          1 :     return true;
    1564                 :            : }
    1565                 :            : 
    1566                 :            : // Test that 1.0.2 and later can open 1.0.1 databases.
    1567                 :          1 : DEFINE_TESTCASE(flintbackwardcompat1, flint) {
    1568                 :            : #ifdef XAPIAN_HAS_FLINT_BACKEND
    1569                 :          1 :     string flint101 = test_driver::get_srcdir();
    1570                 :          1 :     flint101 += "/testdata/flint-1.0.1";
    1571                 :            : 
    1572                 :          1 :     mkdir(".flint", 0755);
    1573                 :          1 :     string dbdir = ".flint/test_flintbackwardcompat1";
    1574                 :            : 
    1575                 :          1 :     rm_rf(dbdir);
    1576                 :          1 :     cp_R(flint101, dbdir);
    1577                 :            : 
    1578                 :            :     // Check we can open the older format for reading.
    1579                 :            :     {
    1580                 :          1 :         Xapian::Database db(dbdir);
    1581   [ -  +  #  # ]:          1 :         TEST_EQUAL(db.get_doccount(), 0);
    1582                 :            :     }
    1583                 :            : 
    1584                 :            :     // Check we can open the older format for update.
    1585                 :            :     {
    1586                 :          1 :         Xapian::WritableDatabase db(dbdir, Xapian::DB_OPEN);
    1587   [ -  +  #  # ]:          1 :         TEST_EQUAL(db.get_doccount(), 0);
    1588                 :            :     }
    1589                 :            : #endif
    1590                 :            : 
    1591                 :          1 :     return true;
    1592                 :            : }
    1593                 :            : 
    1594                 :            : // Test that 1.0.3 and later can open 1.0.2 databases.
    1595                 :          1 : DEFINE_TESTCASE(flintbackwardcompat2, flint) {
    1596                 :            : #ifdef XAPIAN_HAS_FLINT_BACKEND
    1597                 :          1 :     string flint102 = test_driver::get_srcdir();
    1598                 :          1 :     flint102 += "/testdata/flint-1.0.2";
    1599                 :            : 
    1600                 :          1 :     mkdir(".flint", 0755);
    1601                 :          1 :     string dbdir = ".flint/test_flintbackwardcompat2";
    1602                 :            : 
    1603                 :          1 :     rm_rf(dbdir);
    1604                 :          1 :     cp_R(flint102, dbdir);
    1605                 :            : 
    1606                 :            :     // Check we can open the older format for reading.
    1607                 :            :     {
    1608                 :          1 :         Xapian::Database db(dbdir);
    1609   [ -  +  #  # ]:          1 :         TEST_EQUAL(db.get_doccount(), 0);
    1610                 :            :     }
    1611                 :            : 
    1612                 :            :     // Check we can open the older format for update.
    1613                 :            :     {
    1614                 :          1 :         Xapian::WritableDatabase db(dbdir, Xapian::DB_OPEN);
    1615   [ -  +  #  # ]:          1 :         TEST_EQUAL(db.get_doccount(), 0);
    1616                 :            :     }
    1617                 :            : #endif
    1618                 :            : 
    1619                 :          1 :     return true;
    1620                 :            : }
    1621                 :            : 
    1622                 :            : /// Test opening of a flint database
    1623                 :          1 : DEFINE_TESTCASE(flintdatabaseopen1, flint) {
    1624                 :            : #ifdef XAPIAN_HAS_FLINT_BACKEND
    1625                 :          1 :     const string dbdir = ".flint/test_flintdatabaseopen1";
    1626                 :          1 :     mkdir(".flint", 0755);
    1627                 :            : 
    1628                 :            :     {
    1629                 :          1 :         rm_rf(dbdir);
    1630                 :            :         Xapian::WritableDatabase wdb =
    1631                 :          1 :             Xapian::Flint::open(dbdir, Xapian::DB_CREATE);
    1632 [ +  - ][ -  + ]:          2 :         TEST_EXCEPTION(Xapian::DatabaseLockError,
         [ #  # ][ -  + ]
    1633                 :            :             Xapian::Flint::open(dbdir, Xapian::DB_OPEN));
    1634                 :          1 :         Xapian::Flint::open(dbdir);
    1635                 :            :     }
    1636                 :            : 
    1637                 :            :     {
    1638                 :          1 :         rm_rf(dbdir);
    1639                 :            :         Xapian::WritableDatabase wdb =
    1640                 :          1 :             Xapian::Flint::open(dbdir, Xapian::DB_CREATE_OR_OPEN);
    1641 [ +  - ][ -  + ]:          2 :         TEST_EXCEPTION(Xapian::DatabaseLockError,
         [ #  # ][ -  + ]
    1642                 :            :             Xapian::Flint::open(dbdir, Xapian::DB_CREATE_OR_OVERWRITE));
    1643                 :          1 :         Xapian::Flint::open(dbdir);
    1644                 :            :     }
    1645                 :            : 
    1646                 :            :     {
    1647                 :          1 :         rm_rf(dbdir);
    1648                 :            :         Xapian::WritableDatabase wdb =
    1649                 :          1 :             Xapian::Flint::open(dbdir, Xapian::DB_CREATE_OR_OVERWRITE);
    1650 [ +  - ][ -  + ]:          2 :         TEST_EXCEPTION(Xapian::DatabaseLockError,
         [ #  # ][ -  + ]
    1651                 :            :             Xapian::Flint::open(dbdir, Xapian::DB_CREATE_OR_OPEN));
    1652                 :          1 :         Xapian::Flint::open(dbdir);
    1653                 :            :     }
    1654                 :            : 
    1655                 :            :     {
    1656 [ +  - ][ -  + ]:          2 :         TEST_EXCEPTION(Xapian::DatabaseCreateError,
         [ #  # ][ -  + ]
    1657                 :            :             Xapian::Flint::open(dbdir, Xapian::DB_CREATE));
    1658                 :            :         Xapian::WritableDatabase wdb =
    1659                 :          1 :             Xapian::Flint::open(dbdir, Xapian::DB_CREATE_OR_OVERWRITE);
    1660                 :          1 :         Xapian::Flint::open(dbdir);
    1661                 :            :     }
    1662                 :            : 
    1663                 :            :     {
    1664                 :            :         Xapian::WritableDatabase wdb =
    1665                 :          1 :             Xapian::Flint::open(dbdir, Xapian::DB_CREATE_OR_OPEN);
    1666                 :          1 :         Xapian::Flint::open(dbdir);
    1667                 :            :     }
    1668                 :            : 
    1669                 :            :     {
    1670                 :            :         Xapian::WritableDatabase wdb =
    1671                 :          1 :             Xapian::Flint::open(dbdir, Xapian::DB_OPEN);
    1672                 :          1 :         Xapian::Flint::open(dbdir);
    1673                 :            :     }
    1674                 :            : #endif
    1675                 :            : 
    1676                 :          1 :     return true;
    1677                 :            : }
    1678                 :            : 
    1679                 :            : // feature test for Enquire:
    1680                 :            : // set_sort_by_value
    1681                 :            : // set_sort_by_value_then_relevance
    1682                 :            : // set_sort_by_relevance_then_value
    1683                 :         13 : DEFINE_TESTCASE(sortrel1, backend) {
    1684                 :         13 :     Xapian::Enquire enquire(get_database("apitest_sortrel"));
    1685                 :         13 :     enquire.set_sort_by_value(1, true);
    1686                 :         13 :     enquire.set_query(Xapian::Query("woman"));
    1687                 :            : 
    1688                 :         13 :     const Xapian::docid order1[] = { 1,2,3,4,5,6,7,8,9 };
    1689                 :         13 :     const Xapian::docid order2[] = { 2,1,3,6,5,4,7,9,8 };
    1690                 :         13 :     const Xapian::docid order3[] = { 3,2,1,6,5,4,9,8,7 };
    1691                 :         13 :     const Xapian::docid order4[] = { 7,8,9,4,5,6,1,2,3 };
    1692                 :         13 :     const Xapian::docid order5[] = { 9,8,7,6,5,4,3,2,1 };
    1693                 :         13 :     const Xapian::docid order6[] = { 7,9,8,6,5,4,2,1,3 };
    1694                 :         13 :     const Xapian::docid order7[] = { 7,9,8,6,5,4,2,1,3 };
    1695                 :         13 :     const Xapian::docid order8[] = { 7,6,2,9,5,1,8,4,3 };
    1696                 :         13 :     const Xapian::docid order9[] = { 2,6,7,1,5,9,3,4,8 };
    1697                 :            : 
    1698                 :         13 :     Xapian::MSet mset;
    1699                 :            :     size_t i;
    1700                 :            : 
    1701                 :         13 :     mset = enquire.get_mset(0, 10);
    1702   [ -  +  #  # ]:         13 :     TEST_EQUAL(mset.size(), sizeof(order1) / sizeof(Xapian::docid));
    1703         [ +  + ]:        130 :     for (i = 0; i < sizeof(order1) / sizeof(Xapian::docid); ++i) {
    1704 [ -  + ][ #  # ]:        117 :         TEST_EQUAL(*mset[i], order1[i]);
    1705                 :            :     }
    1706                 :            : 
    1707                 :         13 :     enquire.set_sort_by_value_then_relevance(1, true);
    1708                 :            : 
    1709                 :         13 :     mset = enquire.get_mset(0, 10);
    1710   [ -  +  #  # ]:         13 :     TEST_EQUAL(mset.size(), sizeof(order2) / sizeof(Xapian::docid));
    1711         [ +  + ]:        130 :     for (i = 0; i < sizeof(order2) / sizeof(Xapian::docid); ++i) {
    1712 [ -  + ][ #  # ]:        117 :         TEST_EQUAL(*mset[i], order2[i]);
    1713                 :            :     }
    1714                 :            : 
    1715                 :         13 :     enquire.set_sort_by_value(1, true);
    1716                 :            : 
    1717                 :         13 :     mset = enquire.get_mset(0, 10);
    1718   [ -  +  #  # ]:         13 :     TEST_EQUAL(mset.size(), sizeof(order1) / sizeof(Xapian::docid));
    1719         [ +  + ]:        130 :     for (i = 0; i < sizeof(order1) / sizeof(Xapian::docid); ++i) {
    1720 [ -  + ][ #  # ]:        117 :         TEST_EQUAL(*mset[i], order1[i]);
    1721                 :            :     }
    1722                 :            : 
    1723                 :         13 :     enquire.set_sort_by_value_then_relevance(1, true);
    1724                 :         13 :     enquire.set_docid_order(Xapian::Enquire::DESCENDING);
    1725                 :            : 
    1726                 :         13 :     mset = enquire.get_mset(0, 10);
    1727   [ -  +  #  # ]:         13 :     TEST_EQUAL(mset.size(), sizeof(order2) / sizeof(Xapian::docid));
    1728         [ +  + ]:        130 :     for (i = 0; i < sizeof(order2) / sizeof(Xapian::docid); ++i) {
    1729 [ -  + ][ #  # ]:        117 :         TEST_EQUAL(*mset[i], order2[i]);
    1730                 :            :     }
    1731                 :            : 
    1732                 :         13 :     enquire.set_sort_by_value(1, true);
    1733                 :         13 :     enquire.set_docid_order(Xapian::Enquire::DESCENDING);
    1734                 :            : 
    1735                 :         13 :     mset = enquire.get_mset(0, 10);
    1736   [ -  +  #  # ]:         13 :     TEST_EQUAL(mset.size(), sizeof(order3) / sizeof(Xapian::docid));
    1737         [ +  + ]:        130 :     for (i = 0; i < sizeof(order3) / sizeof(Xapian::docid); ++i) {
    1738 [ -  + ][ #  # ]:        117 :         TEST_EQUAL(*mset[i], order3[i]);
    1739                 :            :     }
    1740                 :            : 
    1741                 :         13 :     enquire.set_sort_by_value(1, false);
    1742                 :         13 :     enquire.set_docid_order(Xapian::Enquire::ASCENDING);
    1743                 :         13 :     mset = enquire.get_mset(0, 10);
    1744   [ -  +  #  # ]:         13 :     TEST_EQUAL(mset.size(), sizeof(order4) / sizeof(Xapian::docid));
    1745         [ +  + ]:        130 :     for (i = 0; i < sizeof(order4) / sizeof(Xapian::docid); ++i) {
    1746 [ -  + ][ #  # ]:        117 :         TEST_EQUAL(*mset[i], order4[i]);
    1747                 :            :     }
    1748                 :            : 
    1749                 :         13 :     enquire.set_sort_by_value(1, false);
    1750                 :         13 :     enquire.set_docid_order(Xapian::Enquire::DESCENDING);
    1751                 :         13 :     mset = enquire.get_mset(0, 10);
    1752   [ -  +  #  # ]:         13 :     TEST_EQUAL(mset.size(), sizeof(order5) / sizeof(Xapian::docid));
    1753         [ +  + ]:        130 :     for (i = 0; i < sizeof(order5) / sizeof(Xapian::docid); ++i) {
    1754 [ -  + ][ #  # ]:        117 :         TEST_EQUAL(*mset[i], order5[i]);
    1755                 :            :     }
    1756                 :            : 
    1757                 :         13 :     enquire.set_sort_by_value_then_relevance(1, false);
    1758                 :         13 :     enquire.set_docid_order(Xapian::Enquire::ASCENDING);
    1759                 :         13 :     mset = enquire.get_mset(0, 10);
    1760   [ -  +  #  # ]:         13 :     TEST_EQUAL(mset.size(), sizeof(order6) / sizeof(Xapian::docid));
    1761         [ +  + ]:        130 :     for (i = 0; i < sizeof(order6) / sizeof(Xapian::docid); ++i) {
    1762 [ -  + ][ #  # ]:        117 :         TEST_EQUAL(*mset[i], order6[i]);
    1763                 :            :     }
    1764                 :            : 
    1765                 :         13 :     enquire.set_sort_by_value_then_relevance(1, false);
    1766                 :         13 :     enquire.set_docid_order(Xapian::Enquire::DESCENDING);
    1767                 :         13 :     mset = enquire.get_mset(0, 10);
    1768   [ -  +  #  # ]:         13 :     TEST_EQUAL(mset.size(), sizeof(order7) / sizeof(Xapian::docid));
    1769         [ +  + ]:        130 :     for (i = 0; i < sizeof(order7) / sizeof(Xapian::docid); ++i) {
    1770 [ -  + ][ #  # ]:        117 :         TEST_EQUAL(*mset[i], order7[i]);
    1771                 :            :     }
    1772                 :            : 
    1773                 :         13 :     enquire.set_sort_by_relevance_then_value(1, true);
    1774                 :         13 :     enquire.set_docid_order(Xapian::Enquire::ASCENDING);
    1775                 :         13 :     mset = enquire.get_mset(0, 10);
    1776   [ -  +  #  # ]:         13 :     TEST_EQUAL(mset.size(), sizeof(order8) / sizeof(Xapian::docid));
    1777         [ +  + ]:        130 :     for (i = 0; i < sizeof(order8) / sizeof(Xapian::docid); ++i) {
    1778 [ -  + ][ #  # ]:        117 :         TEST_EQUAL(*mset[i], order8[i]);
    1779                 :            :     }
    1780                 :            : 
    1781                 :         13 :     enquire.set_sort_by_relevance_then_value(1, true);
    1782                 :         13 :     enquire.set_docid_order(Xapian::Enquire::DESCENDING);
    1783                 :         13 :     mset = enquire.get_mset(0, 10);
    1784   [ -  +  #  # ]:         13 :     TEST_EQUAL(mset.size(), sizeof(order8) / sizeof(Xapian::docid));
    1785         [ +  + ]:        130 :     for (i = 0; i < sizeof(order8) / sizeof(Xapian::docid); ++i) {
    1786 [ -  + ][ #  # ]:        117 :         TEST_EQUAL(*mset[i], order8[i]);
    1787                 :            :     }
    1788                 :            : 
    1789                 :         13 :     enquire.set_sort_by_relevance_then_value(1, false);
    1790                 :         13 :     enquire.set_docid_order(Xapian::Enquire::ASCENDING);
    1791                 :         13 :     mset = enquire.get_mset(0, 10);
    1792   [ -  +  #  # ]:         13 :     TEST_EQUAL(mset.size(), sizeof(order9) / sizeof(Xapian::docid));
    1793         [ +  + ]:        130 :     for (i = 0; i < sizeof(order9) / sizeof(Xapian::docid); ++i) {
    1794 [ -  + ][ #  # ]:        117 :         TEST_EQUAL(*mset[i], order9[i]);
    1795                 :            :     }
    1796                 :            : 
    1797                 :         13 :     enquire.set_sort_by_relevance_then_value(1, false);
    1798                 :         13 :     enquire.set_docid_order(Xapian::Enquire::DESCENDING);
    1799                 :         13 :     mset = enquire.get_mset(0, 10);
    1800   [ -  +  #  # ]:         13 :     TEST_EQUAL(mset.size(), sizeof(order9) / sizeof(Xapian::docid));
    1801         [ +  + ]:        130 :     for (i = 0; i < sizeof(order9) / sizeof(Xapian::docid); ++i) {
    1802 [ -  + ][ #  # ]:        117 :         TEST_EQUAL(*mset[i], order9[i]);
    1803                 :            :     }
    1804                 :            : 
    1805                 :         13 :     return true;
    1806                 :            : }
    1807                 :            : 
    1808                 :            : // Test network stats and local stats give the same results.
    1809                 :          6 : DEFINE_TESTCASE(netstats1, remote) {
    1810                 :          6 :     BackendManagerLocal local_manager;
    1811                 :          6 :     local_manager.set_datadir(test_driver::get_srcdir() + "/testdata/");
    1812                 :            : 
    1813                 :          6 :     const char * words[] = { "paragraph", "word" };
    1814                 :          6 :     Xapian::Query query(Xapian::Query::OP_OR, words, words + 2);
    1815                 :          6 :     const size_t MSET_SIZE = 10;
    1816                 :            : 
    1817                 :          6 :     Xapian::RSet rset;
    1818                 :          6 :     rset.add_document(4);
    1819                 :          6 :     rset.add_document(9);
    1820                 :            : 
    1821                 :          6 :     Xapian::MSet mset_alllocal;
    1822                 :            :     {
    1823                 :          6 :         Xapian::Database db;
    1824                 :          6 :         db.add_database(local_manager.get_database("apitest_simpledata"));
    1825                 :          6 :         db.add_database(local_manager.get_database("apitest_simpledata2"));
    1826                 :            : 
    1827                 :          6 :         Xapian::Enquire enq(db);
    1828                 :          6 :         enq.set_query(query);
    1829                 :          6 :         mset_alllocal = enq.get_mset(0, MSET_SIZE, &rset);
    1830                 :            :     }
    1831                 :            : 
    1832                 :            :     {
    1833                 :          6 :         Xapian::Database db;
    1834                 :          6 :         db.add_database(local_manager.get_database("apitest_simpledata"));
    1835                 :          6 :         db.add_database(get_database("apitest_simpledata2"));
    1836                 :            : 
    1837                 :          6 :         Xapian::Enquire enq(db);
    1838                 :          6 :         enq.set_query(query);
    1839                 :          6 :         Xapian::MSet mset = enq.get_mset(0, MSET_SIZE, &rset);
    1840   [ -  +  #  # ]:          6 :         TEST_EQUAL(mset.get_matches_lower_bound(), mset_alllocal.get_matches_lower_bound());
    1841 [ -  + ][ #  # ]:          6 :         TEST_EQUAL(mset.get_matches_upper_bound(), mset_alllocal.get_matches_upper_bound());
    1842 [ -  + ][ #  # ]:          6 :         TEST_EQUAL(mset.get_matches_estimated(), mset_alllocal.get_matches_estimated());
    1843 [ -  + ][ #  # ]:          6 :         TEST_EQUAL(mset.get_max_attained(), mset_alllocal.get_max_attained());
    1844 [ -  + ][ #  # ]:          6 :         TEST_EQUAL(mset.size(), mset_alllocal.size());
    1845 [ -  + ][ #  # ]:          6 :         TEST(mset_range_is_same(mset, 0, mset_alllocal, 0, mset.size()));
    1846                 :            :     }
    1847                 :            : 
    1848                 :            :     {
    1849                 :          6 :         Xapian::Database db;
    1850                 :          6 :         db.add_database(get_database("apitest_simpledata"));
    1851                 :          6 :         db.add_database(local_manager.get_database("apitest_simpledata2"));
    1852                 :            : 
    1853                 :          6 :         Xapian::Enquire enq(db);
    1854                 :          6 :         enq.set_query(query);
    1855                 :          6 :         Xapian::MSet mset = enq.get_mset(0, MSET_SIZE, &rset);
    1856   [ -  +  #  # ]:          6 :         TEST_EQUAL(mset.get_matches_lower_bound(), mset_alllocal.get_matches_lower_bound());
    1857 [ -  + ][ #  # ]:          6 :         TEST_EQUAL(mset.get_matches_upper_bound(), mset_alllocal.get_matches_upper_bound());
    1858 [ -  + ][ #  # ]:          6 :         TEST_EQUAL(mset.get_matches_estimated(), mset_alllocal.get_matches_estimated());
    1859 [ -  + ][ #  # ]:          6 :         TEST_EQUAL(mset.get_max_attained(), mset_alllocal.get_max_attained());
    1860 [ -  + ][ #  # ]:          6 :         TEST_EQUAL(mset.size(), mset_alllocal.size());
    1861 [ -  + ][ #  # ]:          6 :         TEST(mset_range_is_same(mset, 0, mset_alllocal, 0, mset.size()));
    1862                 :            :     }
    1863                 :            : 
    1864                 :            :     {
    1865                 :          6 :         Xapian::Database db;
    1866                 :          6 :         db.add_database(get_database("apitest_simpledata"));
    1867                 :          6 :         db.add_database(get_database("apitest_simpledata2"));
    1868                 :            : 
    1869                 :          6 :         Xapian::Enquire enq(db);
    1870                 :          6 :         enq.set_query(query);
    1871                 :          6 :         Xapian::MSet mset = enq.get_mset(0, MSET_SIZE, &rset);
    1872   [ -  +  #  # ]:          6 :         TEST_EQUAL(mset.get_matches_lower_bound(), mset_alllocal.get_matches_lower_bound());
    1873 [ -  + ][ #  # ]:          6 :         TEST_EQUAL(mset.get_matches_upper_bound(), mset_alllocal.get_matches_upper_bound());
    1874 [ -  + ][ #  # ]:          6 :         TEST_EQUAL(mset.get_matches_estimated(), mset_alllocal.get_matches_estimated());
    1875 [ -  + ][ #  # ]:          6 :         TEST_EQUAL(mset.get_max_attained(), mset_alllocal.get_max_attained());
    1876 [ -  + ][ #  # ]:          6 :         TEST_EQUAL(mset.size(), mset_alllocal.size());
    1877 [ -  + ][ #  # ]:          6 :         TEST(mset_range_is_same(mset, 0, mset_alllocal, 0, mset.size()));
    1878                 :            :     }
    1879                 :            : 
    1880                 :          6 :     return true;
    1881                 :            : }
    1882                 :            : 
    1883                 :            : // Coordinate matching - scores 1 for each matching term
    1884                 :            : class MyWeight : public Xapian::Weight {
    1885                 :            :     double scale_factor;
    1886                 :            : 
    1887                 :            :   public:
    1888                 :         57 :     MyWeight * clone() const {
    1889                 :         57 :         return new MyWeight;
    1890                 :            :     }
    1891                 :         40 :     void init(double factor) {
    1892                 :         40 :         scale_factor = factor;
    1893                 :         40 :     }
    1894                 :         64 :     MyWeight() { }
    1895 [ +  - ][ -  + ]:         64 :     ~MyWeight() { }
    1896                 :          0 :     std::string name() const { return "MyWeight"; }
    1897                 :          0 :     string serialise() const { return string(); }
    1898                 :          0 :     MyWeight * unserialise(const string &) const { return new MyWeight; }
    1899                 :         98 :     Xapian::weight get_sumpart(Xapian::termcount, Xapian::termcount) const {
    1900                 :         98 :         return scale_factor;
    1901                 :            :     }
    1902                 :         68 :     Xapian::weight get_maxpart() const { return scale_factor; }
    1903                 :            : 
    1904                 :          0 :     Xapian::weight get_sumextra(Xapian::termcount) const { return 0; }
    1905                 :         10 :     Xapian::weight get_maxextra() const { return 0; }
    1906                 :            : };
    1907                 :            : 
    1908                 :            : // tests user weighting scheme.
    1909                 :            : // Would work with remote if we registered the weighting scheme.
    1910                 :            : // FIXME: do this so we also test that functionality...
    1911                 :          7 : DEFINE_TESTCASE(userweight1, backend && !remote) {
    1912                 :          7 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
    1913                 :          7 :     enquire.set_weighting_scheme(MyWeight());
    1914                 :          7 :     const char * query[] = { "this", "line", "paragraph", "rubbish" };
    1915                 :            :     enquire.set_query(Xapian::Query(Xapian::Query::OP_OR, query,
    1916                 :          7 :                                     query + sizeof(query) / sizeof(query[0])));
    1917                 :          7 :     Xapian::MSet mymset1 = enquire.get_mset(0, 100);
    1918                 :            :     // MyWeight scores 1 for each matching term, so the weight should equal
    1919                 :            :     // the number of matching terms.
    1920         [ +  + ]:         49 :     for (Xapian::MSetIterator i = mymset1.begin(); i != mymset1.end(); ++i) {
    1921                 :         42 :         Xapian::termcount matching_terms = 0;
    1922                 :         42 :         Xapian::TermIterator t = enquire.get_matching_terms_begin(i);
    1923         [ +  + ]:        140 :         while (t != enquire.get_matching_terms_end(i)) {
    1924                 :         98 :             ++matching_terms;
    1925                 :         98 :             ++t;
    1926                 :            :         }
    1927 [ -  + ][ #  # ]:         42 :         TEST_EQUAL(i.get_weight(), matching_terms);
    1928                 :          7 :     }
    1929                 :            : 
    1930                 :          7 :     return true;
    1931                 :            : }
    1932                 :            : 
    1933                 :            : // tests MatchAll queries
    1934                 :            : // This is a regression test, which failed with assertion failures in
    1935                 :            : // revision 9094.  Also check that the results aren't ranked by relevance
    1936                 :            : // (regression test for bug fixed in 1.0.9).
    1937                 :         13 : DEFINE_TESTCASE(matchall1, backend) {
    1938                 :         13 :     Xapian::Database db(get_database("apitest_simpledata"));
    1939                 :         13 :     Xapian::Enquire enquire(db);
    1940                 :         13 :     enquire.set_query(Xapian::Query::MatchAll);
    1941                 :         13 :     Xapian::MSet mset = enquire.get_mset(0, 10);
    1942   [ -  +  #  # ]:         13 :     TEST_EQUAL(mset.get_matches_lower_bound(), db.get_doccount());
    1943 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mset.get_uncollapsed_matches_lower_bound(), db.get_doccount());
    1944                 :            : 
    1945                 :            :     enquire.set_query(Xapian::Query(Xapian::Query::OP_OR,
    1946                 :            :                                     Xapian::Query("nosuchterm"),
    1947                 :         13 :                                     Xapian::Query::MatchAll));
    1948                 :         13 :     mset = enquire.get_mset(0, 10);
    1949   [ -  +  #  # ]:         13 :     TEST_EQUAL(mset.get_matches_lower_bound(), db.get_doccount());
    1950 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mset.get_uncollapsed_matches_lower_bound(), db.get_doccount());
    1951                 :            : 
    1952                 :            :     // Check that the results aren't ranked by relevance (fixed in 1.0.9).
    1953 [ -  + ][ #  # ]:         13 :     TEST(mset.size() > 1);
    1954 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(mset[mset.size() - 1].get_weight(), 0);
    1955 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(*mset[0], 1);
    1956 [ -  + ][ #  # ]:         13 :     TEST_EQUAL(*mset[mset.size() - 1], mset.size());
    1957                 :            :  
    1958                 :         13 :     return true;
    1959                 :            : }
    1960                 :            : 
    1961                 :            : // Test using a ValueSetMatchDecider
    1962                 :          7 : DEFINE_TESTCASE(valuesetmatchdecider2, backend && !remote) {
    1963                 :          7 :     Xapian::Database db(get_database("apitest_phrase"));
    1964                 :          7 :     Xapian::Enquire enq(db);
    1965                 :          7 :     enq.set_query(Xapian::Query("leav"));
    1966                 :            : 
    1967                 :          7 :     Xapian::ValueSetMatchDecider vsmd1(1, true);
    1968                 :          7 :     vsmd1.add_value("n");
    1969                 :          7 :     Xapian::ValueSetMatchDecider vsmd2(1, false);
    1970                 :          7 :     vsmd2.add_value("n");
    1971                 :            : 
    1972                 :          7 :     Xapian::MSet mymset = enq.get_mset(0, 20);
    1973                 :          7 :     mset_expect_order(mymset, 8, 6, 4, 5, 7, 10, 12, 11, 13, 9, 14);
    1974                 :          7 :     mymset = enq.get_mset(0, 20, 0, NULL, &vsmd1);
    1975                 :          7 :     mset_expect_order(mymset, 6, 12);
    1976                 :          7 :     mymset = enq.get_mset(0, 20, 0, NULL, &vsmd2);
    1977                 :          7 :     mset_expect_order(mymset, 8, 4, 5, 7, 10, 11, 13, 9, 14);
    1978                 :            : 
    1979                 :          7 :     return true;
    1980                 :            : }

Generated by: LCOV version 1.8