LCOV - code coverage report
Current view: top level - home/olly/git/atia-xapian/xapian-core/tests - api_wrdb.cc (source / functions) Hit Total Coverage
Test: Test Coverage for xapian-core r Lines: 1267 1270 99.8 %
Date: 2011-08-21 Functions: 36 36 100.0 %
Branches: 590 1944 30.3 %

           Branch data     Line data    Source code
       1                 :            : /* api_wrdb.cc: tests which need a writable backend
       2                 :            :  *
       3                 :            :  * Copyright 1999,2000,2001 BrightStation PLC
       4                 :            :  * Copyright 2001 Hein Ragas
       5                 :            :  * Copyright 2002 Ananova Ltd
       6                 :            :  * Copyright 2002,2003,2004,2005,2006,2007,2008,2009,2010 Olly Betts
       7                 :            :  * Copyright 2006 Richard Boulton
       8                 :            :  * Copyright 2007 Lemur Consulting Ltd
       9                 :            :  *
      10                 :            :  * This program is free software; you can redistribute it and/or
      11                 :            :  * modify it under the terms of the GNU General Public License as
      12                 :            :  * published by the Free Software Foundation; either version 2 of the
      13                 :            :  * License, or (at your option) any later version.
      14                 :            :  *
      15                 :            :  * This program is distributed in the hope that it will be useful,
      16                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      17                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18                 :            :  * GNU General Public License for more details.
      19                 :            :  *
      20                 :            :  * You should have received a copy of the GNU General Public License
      21                 :            :  * along with this program; if not, write to the Free Software
      22                 :            :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
      23                 :            :  * USA
      24                 :            :  */
      25                 :            : 
      26                 :            : #include <config.h>
      27                 :            : 
      28                 :            : #include "api_wrdb.h"
      29                 :            : 
      30                 :            : #include <xapian.h>
      31                 :            : 
      32                 :            : #include "backendmanager.h" // For XAPIAN_BIN_PATH.
      33                 :            : #include "omassert.h"
      34                 :            : #include "str.h"
      35                 :            : #include "testsuite.h"
      36                 :            : #include "testutils.h"
      37                 :            : #include "unixcmds.h"
      38                 :            : #include "utils.h"
      39                 :            : 
      40                 :            : #include "apitest.h"
      41                 :            : 
      42                 :            : #include <cmath>
      43                 :            : #include <cstdlib>
      44                 :            : #include <map>
      45                 :            : #include <string>
      46                 :            : 
      47                 :            : using namespace std;
      48                 :            : 
      49                 :            : // #######################################################################
      50                 :            : // # Tests start here
      51                 :            : 
      52                 :            : // test that indexing a term more than once at the same position increases
      53                 :            : // the wdf
      54                 :         10 : DEFINE_TESTCASE(adddoc1, writable) {
      55                 :         10 :     Xapian::WritableDatabase db = get_writable_database();
      56                 :            : 
      57                 :         10 :     Xapian::Document doc1, doc2, doc3;
      58                 :            : 
      59                 :            :     // doc1 should come top, but if term "foo" gets wdf of 1, doc2 will beat it
      60                 :            :     // doc3 should beat both
      61                 :            :     // Note: all docs have same length
      62                 :         10 :     doc1.set_data(string("tom"));
      63                 :         10 :     doc1.add_posting("foo", 1);
      64                 :         10 :     doc1.add_posting("foo", 1);
      65                 :         10 :     doc1.add_posting("foo", 1);
      66                 :         10 :     doc1.add_posting("bar", 3);
      67                 :         10 :     doc1.add_posting("bar", 4);
      68                 :         10 :     db.add_document(doc1);
      69                 :            : 
      70                 :         10 :     doc2.set_data(string("dick"));
      71                 :         10 :     doc2.add_posting("foo", 1);
      72                 :         10 :     doc2.add_posting("foo", 2);
      73                 :         10 :     doc2.add_posting("bar", 3);
      74                 :         10 :     doc2.add_posting("bar", 3);
      75                 :         10 :     doc2.add_posting("bar", 3);
      76                 :         10 :     db.add_document(doc2);
      77                 :            : 
      78                 :         10 :     doc3.set_data(string("harry"));
      79                 :         10 :     doc3.add_posting("foo", 1);
      80                 :         10 :     doc3.add_posting("foo", 1);
      81                 :         10 :     doc3.add_posting("foo", 2);
      82                 :         10 :     doc3.add_posting("foo", 2);
      83                 :         10 :     doc3.add_posting("bar", 3);
      84                 :         10 :     db.add_document(doc3);
      85                 :            : 
      86                 :         10 :     Xapian::Query query("foo");
      87                 :            : 
      88                 :         10 :     Xapian::Enquire enq(db);
      89                 :         10 :     enq.set_query(query);
      90                 :            : 
      91                 :         10 :     Xapian::MSet mset = enq.get_mset(0, 10);
      92                 :            : 
      93                 :         10 :     mset_expect_order(mset, 3, 1, 2);
      94                 :            : 
      95                 :         10 :     return true;
      96                 :            : }
      97                 :            : 
      98                 :            : // test that removing a posting and removing a term works
      99                 :         10 : DEFINE_TESTCASE(adddoc2, writable) {
     100                 :         10 :     Xapian::WritableDatabase db = get_writable_database();
     101                 :            : 
     102                 :         10 :     Xapian::Document doc1;
     103                 :            : 
     104                 :         10 :     doc1.add_posting("foo", 1);
     105                 :         10 :     doc1.add_posting("foo", 1);
     106                 :         10 :     doc1.add_posting("foo", 2);
     107                 :         10 :     doc1.add_posting("foo", 2);
     108                 :         10 :     doc1.add_posting("bar", 3);
     109                 :         10 :     doc1.add_posting("gone", 1);
     110                 :            :     // Quartz had a bug handling a term >= 128 characters longer than the
     111                 :            :     // preceding term in the sort order - this is "foo" + 130 "X"s
     112                 :         10 :     doc1.add_posting("fooXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", 1);
     113                 :            :     Xapian::docid did;
     114                 :            : 
     115                 :         10 :     Xapian::Document doc2 = db.get_document(did = db.add_document(doc1));
     116   [ -  +  #  # ]:         10 :     TEST_EQUAL(did, 1);
     117                 :            : 
     118                 :         10 :     Xapian::TermIterator iter1 = doc1.termlist_begin();
     119                 :         10 :     Xapian::TermIterator iter2 = doc2.termlist_begin();
     120 [ -  + ][ #  # ]:         10 :     TEST(iter1 != doc1.termlist_end());
     121 [ -  + ][ #  # ]:         10 :     TEST(iter2 != doc2.termlist_end());
     122 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*iter1, "bar");
     123 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*iter2, *iter1);
     124 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(iter1.get_wdf(), 1);
     125 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(iter2.get_wdf(), 1);
     126                 :            :     //TEST_EQUAL(iter1.get_termfreq(), 0);
     127 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(iter2.get_termfreq(), 1);
     128                 :            : 
     129                 :         10 :     iter1++;
     130                 :         10 :     iter2++;
     131 [ -  + ][ #  # ]:         10 :     TEST(iter1 != doc1.termlist_end());
     132 [ -  + ][ #  # ]:         10 :     TEST(iter2 != doc2.termlist_end());
     133 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*iter1, "foo");
     134 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*iter2, *iter1);
     135 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(iter1.get_wdf(), 4);
     136 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(iter2.get_wdf(), 4);
     137                 :            :     //TEST_EQUAL(iter1.get_termfreq(), 0);
     138 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(iter2.get_termfreq(), 1);
     139                 :            : 
     140                 :         10 :     iter1++;
     141                 :         10 :     iter2++;
     142 [ -  + ][ #  # ]:         10 :     TEST(iter1 != doc1.termlist_end());
     143 [ -  + ][ #  # ]:         10 :     TEST(iter2 != doc2.termlist_end());
     144 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*iter1, "fooXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
     145 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*iter2, *iter1);
     146 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(iter1.get_wdf(), 1);
     147 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(iter2.get_wdf(), 1);
     148                 :            :     // assertion fails in debug build! TEST_EQUAL(iter1.get_termfreq(), 0);
     149 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(iter2.get_termfreq(), 1);
     150                 :            : 
     151                 :         10 :     iter1++;
     152                 :         10 :     iter2++;
     153 [ -  + ][ #  # ]:         10 :     TEST(iter1 != doc1.termlist_end());
     154 [ -  + ][ #  # ]:         10 :     TEST(iter2 != doc2.termlist_end());
     155 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*iter1, "gone");
     156 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*iter2, *iter1);
     157 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(iter1.get_wdf(), 1);
     158 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(iter2.get_wdf(), 1);
     159                 :            :     // assertion fails in debug build! TEST_EQUAL(iter1.get_termfreq(), 0);
     160 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(iter2.get_termfreq(), 1);
     161                 :            : 
     162                 :         10 :     iter1++;
     163                 :         10 :     iter2++;
     164 [ -  + ][ #  # ]:         10 :     TEST(iter1 == doc1.termlist_end());
     165 [ -  + ][ #  # ]:         10 :     TEST(iter2 == doc2.termlist_end());
     166                 :            : 
     167                 :         10 :     doc2.remove_posting("foo", 1, 5);
     168                 :         10 :     doc2.add_term("bat", 0);
     169                 :         10 :     doc2.add_term("bar", 8);
     170                 :         10 :     doc2.add_term("bag", 0);
     171                 :         10 :     doc2.remove_term("gone");
     172                 :         10 :     doc2.remove_term("fooXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
     173                 :            : 
     174                 :            :     // Should have (doc,wdf) pairs: (bag,0)(bar,9)(bat,0)(foo,0)
     175                 :            :     // positionlists (bag,none)(bar,3)(bat,none)(foo,2)
     176                 :            : 
     177                 :         10 :     iter2 = doc2.termlist_begin();
     178 [ -  + ][ #  # ]:         10 :     TEST(iter2 != doc2.termlist_end());
     179 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*iter2, "bag");
     180                 :            :     //TEST_EQUAL(iter2.get_termfreq(), 0);
     181                 :         10 :     iter2++;
     182 [ -  + ][ #  # ]:         10 :     TEST(iter2 != doc2.termlist_end());
     183 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*iter2, "bar");
     184                 :            :     //TEST_EQUAL(iter2.get_termfreq(), 0);
     185                 :         10 :     iter2++;
     186 [ -  + ][ #  # ]:         10 :     TEST(iter2 != doc2.termlist_end());
     187 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*iter2, "bat");
     188                 :            :     //TEST_EQUAL(iter2.get_termfreq(), 0);
     189                 :         10 :     iter2++;
     190 [ -  + ][ #  # ]:         10 :     TEST(iter2 != doc2.termlist_end());
     191 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*iter2, "foo");
     192                 :            :     //TEST_EQUAL(iter2.get_termfreq(), 0);
     193                 :         10 :     iter2++;
     194 [ -  + ][ #  # ]:         10 :     TEST(iter2 == doc2.termlist_end());
     195                 :            : 
     196                 :         10 :     doc1 = db.get_document(did = db.add_document(doc2));
     197   [ -  +  #  # ]:         10 :     TEST_EQUAL(did, 2);
     198                 :            : 
     199                 :         10 :     iter1 = doc1.termlist_begin();
     200                 :         10 :     iter2 = doc2.termlist_begin();
     201 [ -  + ][ #  # ]:         10 :     TEST(iter1 != doc1.termlist_end());
     202 [ -  + ][ #  # ]:         10 :     TEST(iter2 != doc2.termlist_end());
     203 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*iter1, "bag");
     204 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*iter2, *iter1);
     205 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(iter1.get_wdf(), 0);
     206 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(iter2.get_wdf(), 0);
     207 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(iter1.get_termfreq(), 1);
     208                 :            :     //TEST_EQUAL(iter2.get_termfreq(), 0);
     209 [ -  + ][ #  # ]:         10 :     TEST(iter1.positionlist_begin() == iter1.positionlist_end());
     210 [ -  + ][ #  # ]:         10 :     TEST(iter2.positionlist_begin() == iter2.positionlist_end());
     211                 :            : 
     212                 :         10 :     iter1++;
     213                 :         10 :     iter2++;
     214 [ -  + ][ #  # ]:         10 :     TEST(iter1 != doc1.termlist_end());
     215 [ -  + ][ #  # ]:         10 :     TEST(iter2 != doc2.termlist_end());
     216 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*iter1, "bar");
     217 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*iter2, *iter1);
     218 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(iter1.get_wdf(), 9);
     219 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(iter2.get_wdf(), 9);
     220 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(iter1.get_termfreq(), 2);
     221                 :            :     //TEST_EQUAL(iter2.get_termfreq(), 0);
     222                 :            : 
     223                 :         10 :     Xapian::PositionIterator pi1;
     224                 :         10 :     pi1 = iter1.positionlist_begin();
     225                 :         10 :     Xapian::PositionIterator pi2 = iter2.positionlist_begin();
     226   [ -  +  #  # ]:         10 :     TEST_EQUAL(*pi1, 3); pi1++;
     227   [ -  +  #  # ]:         10 :     TEST_EQUAL(*pi2, 3); pi2++;
     228 [ -  + ][ #  # ]:         10 :     TEST(pi1 == iter1.positionlist_end());
     229 [ -  + ][ #  # ]:         10 :     TEST(pi2 == iter2.positionlist_end());
     230                 :            : 
     231                 :         10 :     iter1++;
     232                 :         10 :     iter2++;
     233 [ -  + ][ #  # ]:         10 :     TEST(iter1 != doc1.termlist_end());
     234 [ -  + ][ #  # ]:         10 :     TEST(iter2 != doc2.termlist_end());
     235 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*iter1, "bat");
     236 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*iter2, *iter1);
     237 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(iter1.get_wdf(), 0);
     238 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(iter2.get_wdf(), 0);
     239 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(iter1.get_termfreq(), 1);
     240                 :            :     //TEST_EQUAL(iter2.get_termfreq(), 0);
     241 [ -  + ][ #  # ]:         10 :     TEST(iter1.positionlist_begin() == iter1.positionlist_end());
     242 [ -  + ][ #  # ]:         10 :     TEST(iter2.positionlist_begin() == iter2.positionlist_end());
     243                 :            : 
     244                 :         10 :     iter1++;
     245                 :         10 :     iter2++;
     246 [ -  + ][ #  # ]:         10 :     TEST(iter1 != doc1.termlist_end());
     247 [ -  + ][ #  # ]:         10 :     TEST(iter2 != doc2.termlist_end());
     248 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*iter1, "foo");
     249 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*iter2, *iter1);
     250 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(iter1.get_wdf(), 0);
     251 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(iter2.get_wdf(), 0);
     252 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(iter1.get_termfreq(), 2);
     253                 :            :     //TEST_EQUAL(iter2.get_termfreq(), 0);
     254                 :            : 
     255                 :         10 :     Xapian::PositionIterator temp1 = iter1.positionlist_begin();
     256                 :         10 :     pi1 = temp1;
     257                 :         10 :     Xapian::PositionIterator temp2 = iter2.positionlist_begin();
     258                 :         10 :     pi2 = temp2;
     259   [ -  +  #  # ]:         10 :     TEST_EQUAL(*pi1, 2); pi1++;
     260   [ -  +  #  # ]:         10 :     TEST_EQUAL(*pi2, 2); pi2++;
     261 [ -  + ][ #  # ]:         10 :     TEST(pi1 == iter1.positionlist_end());
     262 [ -  + ][ #  # ]:         10 :     TEST(pi2 == iter2.positionlist_end());
     263                 :            : 
     264                 :         10 :     iter1++;
     265                 :         10 :     iter2++;
     266 [ -  + ][ #  # ]:         10 :     TEST(iter1 == doc1.termlist_end());
     267 [ -  + ][ #  # ]:         10 :     TEST(iter2 == doc2.termlist_end());
     268                 :            : 
     269                 :         10 :     return true;
     270                 :            : }
     271                 :            : 
     272                 :            : // test that adding lots of documents works, and doesn't leak memory
     273                 :            : // REGRESSION FIXED:2003-09-07
     274                 :         10 : DEFINE_TESTCASE(adddoc3, writable) {
     275                 :         10 :     Xapian::WritableDatabase db = get_writable_database();
     276                 :            : 
     277         [ +  + ]:      21010 :     for (Xapian::doccount i = 0; i < 2100; ++i) {
     278                 :      21000 :         Xapian::Document doc;
     279         [ +  + ]:    2121000 :         for (Xapian::termcount t = 0; t < 100; ++t) {
     280                 :    2100000 :             string term("foo");
     281                 :    2100000 :             term += char(t ^ 70 ^ i);
     282                 :    2100000 :             doc.add_posting(term, t);
     283                 :            :         }
     284                 :      21000 :         db.add_document(doc);
     285                 :            :     }
     286                 :         10 :     return true;
     287                 :            : }
     288                 :            : 
     289                 :            : // We want to test that a termlist starting with a 48 character long term works
     290                 :            : // OK since this value currently requires special handling in flint for
     291                 :            : // historical reasons!)  Also test all other term lengths while we're at it.
     292                 :         10 : DEFINE_TESTCASE(adddoc4, writable) {
     293                 :         10 :     Xapian::WritableDatabase db = get_writable_database();
     294                 :            : 
     295         [ +  + ]:       2410 :     for (Xapian::doccount i = 1; i <= 240; ++i) {
     296                 :       2400 :         Xapian::Document doc;
     297                 :       2400 :         string term(i, 'X');
     298                 :       2400 :         doc.add_term(term);
     299                 :       2400 :         db.add_document(doc);
     300                 :            :     }
     301                 :         10 :     db.add_document(Xapian::Document());
     302                 :         10 :     db.commit();
     303                 :            : 
     304         [ +  + ]:       2410 :     for (Xapian::doccount i = 1; i <= 240; ++i) {
     305                 :       2400 :         Xapian::Document doc = db.get_document(i);
     306                 :       2400 :         Xapian::TermIterator t = doc.termlist_begin();
     307 [ -  + ][ #  # ]:       2400 :         TEST(t != doc.termlist_end());
     308 [ -  + ][ #  # ]:       2400 :         TEST_EQUAL((*t).size(), i);
     309                 :       2400 :         ++t;
     310 [ -  + ][ #  # ]:       2400 :         TEST(t == doc.termlist_end());
     311                 :            :     }
     312                 :            : 
     313                 :            :     // And test a document with no terms.
     314                 :         10 :     Xapian::Document doc = db.get_document(241);
     315 [ -  + ][ #  # ]:         10 :     TEST(doc.termlist_begin() == doc.termlist_end());
     316                 :            : 
     317                 :         10 :     return true;
     318                 :            : }
     319                 :            : 
     320                 :            : // Test adding a document, and checking that it got added correctly.
     321                 :            : // This testcase used to be adddoc2 in quartztest.
     322                 :         10 : DEFINE_TESTCASE(adddoc5, writable) {
     323                 :            :     // Inmemory doesn't support get_writable_database_as_database().
     324                 :         12 :     SKIP_TEST_FOR_BACKEND("inmemory");
     325                 :            : 
     326                 :            :     Xapian::docid did;
     327                 :          9 :     Xapian::Document document_in;
     328                 :          9 :     document_in.set_data("Foobar rising");
     329                 :          9 :     document_in.add_value(7, "Value7");
     330                 :          9 :     document_in.add_value(13, "Value13");
     331                 :          9 :     document_in.add_posting("foobar", 1);
     332                 :          9 :     document_in.add_posting("rising", 2);
     333                 :          9 :     document_in.add_posting("foobar", 3);
     334                 :            : 
     335                 :          9 :     Xapian::Document document_in2;
     336                 :          9 :     document_in2.set_data("Foobar falling");
     337                 :          9 :     document_in2.add_posting("foobar", 1);
     338                 :          9 :     document_in2.add_posting("falling", 2);
     339                 :            :     {
     340                 :          9 :         Xapian::WritableDatabase database(get_writable_database());
     341                 :            : 
     342   [ -  +  #  # ]:          9 :         TEST_EQUAL(database.get_doccount(), 0);
     343 [ -  + ][ #  # ]:          9 :         TEST_EQUAL(database.get_avlength(), 0);
     344                 :            : 
     345                 :          9 :         did = database.add_document(document_in);
     346   [ -  +  #  # ]:          9 :         TEST_EQUAL(database.get_doccount(), 1);
     347 [ -  + ][ #  # ]:          9 :         TEST_EQUAL(database.get_avlength(), 3);
     348                 :            : 
     349 [ -  + ][ #  # ]:          9 :         TEST_EQUAL(database.get_termfreq("foobar"), 1);
     350 [ -  + ][ #  # ]:          9 :         TEST_EQUAL(database.get_collection_freq("foobar"), 2);
     351 [ -  + ][ #  # ]:          9 :         TEST_EQUAL(database.get_termfreq("rising"), 1);
     352 [ -  + ][ #  # ]:          9 :         TEST_EQUAL(database.get_collection_freq("rising"), 1);
     353 [ -  + ][ #  # ]:          9 :         TEST_EQUAL(database.get_termfreq("falling"), 0);
     354 [ -  + ][ #  # ]:          9 :         TEST_EQUAL(database.get_collection_freq("falling"), 0);
     355                 :            : 
     356                 :          9 :         Xapian::docid did2 = database.add_document(document_in2);
     357   [ -  +  #  # ]:          9 :         TEST_EQUAL(database.get_doccount(), 2);
     358 [ -  + ][ #  # ]:          9 :         TEST_NOT_EQUAL(did, did2);
     359 [ -  + ][ #  # ]:          9 :         TEST_EQUAL(database.get_avlength(), 5.0/2.0);
     360                 :            : 
     361 [ -  + ][ #  # ]:          9 :         TEST_EQUAL(database.get_termfreq("foobar"), 2);
     362 [ -  + ][ #  # ]:          9 :         TEST_EQUAL(database.get_collection_freq("foobar"), 3);
     363 [ -  + ][ #  # ]:          9 :         TEST_EQUAL(database.get_termfreq("rising"), 1);
     364 [ -  + ][ #  # ]:          9 :         TEST_EQUAL(database.get_collection_freq("rising"), 1);
     365 [ -  + ][ #  # ]:          9 :         TEST_EQUAL(database.get_termfreq("falling"), 1);
     366 [ -  + ][ #  # ]:          9 :         TEST_EQUAL(database.get_collection_freq("falling"), 1);
     367                 :            : 
     368                 :          9 :         database.delete_document(did);
     369   [ -  +  #  # ]:          9 :         TEST_EQUAL(database.get_doccount(), 1);
     370 [ -  + ][ #  # ]:          9 :         TEST_EQUAL(database.get_avlength(), 2);
     371                 :            : 
     372 [ -  + ][ #  # ]:          9 :         TEST_EQUAL(database.get_termfreq("foobar"), 1);
     373 [ -  + ][ #  # ]:          9 :         TEST_EQUAL(database.get_collection_freq("foobar"), 1);
     374 [ -  + ][ #  # ]:          9 :         TEST_EQUAL(database.get_termfreq("rising"), 0);
     375 [ -  + ][ #  # ]:          9 :         TEST_EQUAL(database.get_collection_freq("rising"), 0);
     376 [ -  + ][ #  # ]:          9 :         TEST_EQUAL(database.get_termfreq("falling"), 1);
     377 [ -  + ][ #  # ]:          9 :         TEST_EQUAL(database.get_collection_freq("falling"), 1);
     378                 :            : 
     379                 :          9 :         did = database.add_document(document_in);
     380   [ -  +  #  # ]:          9 :         TEST_EQUAL(database.get_doccount(), 2);
     381 [ -  + ][ #  # ]:          9 :         TEST_EQUAL(database.get_avlength(), 5.0/2.0);
     382                 :            : 
     383 [ -  + ][ #  # ]:          9 :         TEST_EQUAL(database.get_termfreq("foobar"), 2);
     384 [ -  + ][ #  # ]:          9 :         TEST_EQUAL(database.get_collection_freq("foobar"), 3);
     385 [ -  + ][ #  # ]:          9 :         TEST_EQUAL(database.get_termfreq("rising"), 1);
     386 [ -  + ][ #  # ]:          9 :         TEST_EQUAL(database.get_collection_freq("rising"), 1);
     387 [ -  + ][ #  # ]:          9 :         TEST_EQUAL(database.get_termfreq("falling"), 1);
     388 [ -  + ][ #  # ]:          9 :         TEST_EQUAL(database.get_collection_freq("falling"), 1);
     389                 :            :     }
     390                 :            : 
     391                 :            :     {
     392                 :          9 :         Xapian::Database database(get_writable_database_as_database());
     393                 :          9 :         Xapian::Document document_out = database.get_document(did);
     394                 :            : 
     395 [ -  + ][ #  # ]:          9 :         TEST_EQUAL(document_in.get_data(), document_out.get_data());
     396                 :            : 
     397                 :            :         {
     398                 :          9 :             Xapian::ValueIterator i(document_in.values_begin());
     399                 :          9 :             Xapian::ValueIterator j(document_out.values_begin());
     400         [ +  + ]:         27 :             for (; i != document_in.values_end(); i++, j++) {
     401 [ -  + ][ #  # ]:         18 :                 TEST_NOT_EQUAL(j, document_out.values_end());
     402 [ -  + ][ #  # ]:         18 :                 TEST_EQUAL(*i, *j);
     403 [ -  + ][ #  # ]:         18 :                 TEST_EQUAL(i.get_valueno(), j.get_valueno());
     404                 :            :             }
     405 [ -  + ][ #  # ]:          9 :             TEST_EQUAL(j, document_out.values_end());
     406                 :            :         }
     407                 :            : 
     408                 :            :         {
     409                 :            :             // Regression test for bug fixed in 1.0.5 - values_begin() didn't
     410                 :            :             // ensure that values had been read.  However, values_end() did
     411                 :            :             // (and so did values_count()) so this wasn't generally an issue
     412                 :            :             // but it shouldn't happen anyway.
     413                 :          9 :             Xapian::Document doc_tmp = database.get_document(did);
     414                 :          9 :             Xapian::ValueIterator i = document_in.values_begin();
     415                 :          9 :             Xapian::ValueIterator j = doc_tmp.values_begin();
     416 [ -  + ][ #  # ]:          9 :             TEST_EQUAL(*i, *j);
     417                 :            :         }
     418                 :            : 
     419                 :            :         {
     420                 :          9 :             Xapian::TermIterator i(document_in.termlist_begin());
     421                 :          9 :             Xapian::TermIterator j(document_out.termlist_begin());
     422         [ +  + ]:         27 :             for (; i != document_in.termlist_end(); i++, j++) {
     423 [ -  + ][ #  # ]:         18 :                 TEST_NOT_EQUAL(j, document_out.termlist_end());
     424 [ -  + ][ #  # ]:         18 :                 TEST_EQUAL(*i, *j);
     425 [ -  + ][ #  # ]:         18 :                 TEST_EQUAL(i.get_wdf(), j.get_wdf());
     426 [ +  - ][ -  + ]:         36 :                 TEST_EXCEPTION(Xapian::InvalidOperationError,
         [ #  # ][ -  + ]
     427                 :            :                                (void)i.get_termfreq());
     428   [ -  +  #  # ]:         18 :                 TEST_NOT_EQUAL(0, j.get_termfreq());
     429         [ +  + ]:         18 :                 if (*i == "foobar") {
     430                 :            :                     // termfreq of foobar is 2
     431 [ -  + ][ #  # ]:          9 :                     TEST_EQUAL(2, j.get_termfreq());
     432                 :            :                 } else {
     433                 :            :                     // termfreq of rising is 1
     434 [ -  + ][ #  # ]:          9 :                     TEST_EQUAL(*i, "rising");
     435 [ -  + ][ #  # ]:          9 :                     TEST_EQUAL(1, j.get_termfreq());
     436                 :            :                 }
     437                 :         18 :                 Xapian::PositionIterator k(i.positionlist_begin());
     438                 :         18 :                 Xapian::PositionIterator l(j.positionlist_begin());
     439         [ +  + ]:         45 :                 for (; k != i.positionlist_end(); k++, l++) {
     440 [ -  + ][ #  # ]:         27 :                     TEST_NOT_EQUAL(l, j.positionlist_end());
     441 [ -  + ][ #  # ]:         27 :                     TEST_EQUAL(*k, *l);
     442                 :            :                 }
     443 [ -  + ][ #  # ]:         18 :                 TEST_EQUAL(l, j.positionlist_end());
     444                 :            :             }
     445 [ -  + ][ #  # ]:          9 :             TEST_EQUAL(j, document_out.termlist_end());
     446                 :          9 :         }
     447                 :            :     }
     448                 :            : 
     449                 :          9 :     return true;
     450                 :            : }
     451                 :            : 
     452                 :            : // Test adding a document, and checking that it got added correctly.
     453                 :            : // This testcase used to be adddoc3 in quartztest.
     454                 :         10 : DEFINE_TESTCASE(adddoc6, writable) {
     455                 :            :     // Inmemory doesn't support get_writable_database_again().
     456                 :         12 :     SKIP_TEST_FOR_BACKEND("inmemory");
     457                 :            : 
     458                 :            :     Xapian::docid did;
     459                 :          9 :     Xapian::Document document_in;
     460                 :          9 :     document_in.set_data("Foobar rising");
     461                 :          9 :     document_in.add_value(7, "Value7");
     462                 :          9 :     document_in.add_value(13, "Value13");
     463                 :          9 :     document_in.add_posting("foo", 1);
     464                 :          9 :     document_in.add_posting("bar", 2);
     465                 :            : 
     466                 :            :     {
     467                 :          9 :         Xapian::WritableDatabase database(get_writable_database());
     468                 :            : 
     469                 :          9 :         did = database.add_document(document_in);
     470   [ -  +  #  # ]:          9 :         TEST_EQUAL(did, 1);
     471 [ -  + ][ #  # ]:          9 :         TEST_EQUAL(database.get_doccount(), 1);
     472 [ -  + ][ #  # ]:          9 :         TEST_EQUAL(database.get_avlength(), 2);
     473                 :            :     }
     474                 :            : 
     475                 :            :     {
     476                 :          9 :         Xapian::WritableDatabase database(get_writable_database_again());
     477                 :            : 
     478                 :          9 :         document_in.remove_term("foo");
     479                 :          9 :         document_in.add_posting("baz", 1);
     480                 :            : 
     481                 :          9 :         database.replace_document(1, document_in);
     482                 :            : 
     483                 :          9 :         database.delete_document(1);
     484                 :            : 
     485   [ -  +  #  # ]:          9 :         TEST_EQUAL(database.get_doccount(), 0);
     486 [ -  + ][ #  # ]:          9 :         TEST_EQUAL(database.get_avlength(), 0);
     487 [ -  + ][ #  # ]:          9 :         TEST_EQUAL(database.get_termfreq("foo"), 0);
     488 [ -  + ][ #  # ]:          9 :         TEST_EQUAL(database.get_collection_freq("foo"), 0);
     489 [ -  + ][ #  # ]:          9 :         TEST_EQUAL(database.get_termfreq("bar"), 0);
     490 [ -  + ][ #  # ]:          9 :         TEST_EQUAL(database.get_collection_freq("bar"), 0);
     491 [ -  + ][ #  # ]:          9 :         TEST_EQUAL(database.get_termfreq("baz"), 0);
     492 [ -  + ][ #  # ]:          9 :         TEST_EQUAL(database.get_collection_freq("baz"), 0);
     493                 :            :     }
     494                 :            : 
     495                 :          9 :     return true;
     496                 :            : }
     497                 :            : 
     498                 :            : // tests that database destructors commit if it isn't done explicitly
     499                 :         10 : DEFINE_TESTCASE(implicitendsession1, writable) {
     500                 :         10 :     Xapian::WritableDatabase db = get_writable_database();
     501                 :            : 
     502                 :         10 :     Xapian::Document doc;
     503                 :            : 
     504                 :         10 :     doc.set_data(string("top secret"));
     505                 :         10 :     doc.add_posting("cia", 1);
     506                 :         10 :     doc.add_posting("nsa", 2);
     507                 :         10 :     doc.add_posting("fbi", 3);
     508                 :         10 :     db.add_document(doc);
     509                 :            : 
     510                 :         10 :     return true;
     511                 :            : }
     512                 :            : 
     513                 :            : // tests that assignment of Xapian::Database and Xapian::WritableDatabase works
     514                 :            : // as expected
     515                 :         10 : DEFINE_TESTCASE(databaseassign1, writable) {
     516                 :         10 :     Xapian::WritableDatabase wdb = get_writable_database();
     517                 :         10 :     Xapian::Database db = get_database("");
     518                 :         10 :     Xapian::Database actually_wdb = wdb;
     519                 :         10 :     Xapian::WritableDatabase w1(wdb);
     520                 :         10 :     w1 = wdb;
     521                 :         10 :     Xapian::Database d1(wdb);
     522                 :         10 :     Xapian::Database d2(actually_wdb);
     523                 :         10 :     d2 = wdb;
     524                 :         10 :     d2 = actually_wdb;
     525                 :         10 :     wdb = wdb; // check assign to itself works
     526                 :         10 :     db = db; // check assign to itself works
     527                 :         10 :     return true;
     528                 :            : }
     529                 :            : 
     530                 :            : // tests that deletion and updating of documents works as expected
     531                 :         10 : DEFINE_TESTCASE(deldoc1, writable) {
     532                 :         10 :     Xapian::WritableDatabase db = get_writable_database();
     533                 :            : 
     534                 :         10 :     Xapian::Document doc1;
     535                 :            : 
     536                 :         10 :     doc1.add_posting("foo", 1);
     537                 :         10 :     doc1.add_posting("foo", 1);
     538                 :         10 :     doc1.add_posting("foo", 2);
     539                 :         10 :     doc1.add_posting("foo", 2);
     540                 :         10 :     doc1.add_posting("bar", 3);
     541                 :         10 :     doc1.add_posting("gone", 1);
     542                 :            : 
     543                 :         10 :     Xapian::docid did = db.add_document(doc1);
     544   [ -  +  #  # ]:         10 :     TEST_EQUAL(did, 1);
     545                 :            : 
     546                 :         10 :     doc1.remove_term("gone");
     547                 :            : 
     548                 :         10 :     did = db.add_document(doc1);
     549   [ -  +  #  # ]:         10 :     TEST_EQUAL(did, 2);
     550                 :            : 
     551                 :         10 :     doc1.add_term("new", 1);
     552                 :         10 :     did = db.add_document(doc1);
     553   [ -  +  #  # ]:         10 :     TEST_EQUAL(did, 3);
     554                 :            : 
     555                 :         10 :     db.delete_document(1);
     556                 :            : 
     557 [ +  - ][ -  + ]:         20 :     TEST_EXCEPTION(Xapian::DocNotFoundError, db.get_document(1));
         [ #  # ][ -  + ]
     558                 :            : 
     559                 :         10 :     doc1 = db.get_document(2);
     560                 :         10 :     doc1.remove_term("foo");
     561                 :         10 :     doc1.add_term("fwing");
     562                 :         10 :     db.replace_document(2, doc1);
     563                 :            : 
     564                 :         10 :     Xapian::Document doc2 = db.get_document(2);
     565                 :         10 :     Xapian::TermIterator tit = doc2.termlist_begin();
     566 [ -  + ][ #  # ]:         10 :     TEST_NOT_EQUAL(tit, doc2.termlist_end());
     567 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*tit, "bar");
     568                 :         10 :     tit++;
     569 [ -  + ][ #  # ]:         10 :     TEST_NOT_EQUAL(tit, doc2.termlist_end());
     570 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*tit, "fwing");
     571                 :         10 :     tit++;
     572 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(tit, doc2.termlist_end());
     573                 :            : 
     574                 :         10 :     return true;
     575                 :            : }
     576                 :            : 
     577                 :            : // tests that deletion and updating of documents works as expected
     578                 :         10 : DEFINE_TESTCASE(deldoc2, writable) {
     579                 :         10 :     Xapian::WritableDatabase db = get_writable_database();
     580                 :            : 
     581                 :         10 :     Xapian::Document doc1;
     582                 :            : 
     583                 :         10 :     doc1.add_posting("one", 1);
     584                 :         10 :     doc1.add_posting("two", 2);
     585                 :         10 :     doc1.add_posting("two", 3);
     586                 :            :     Xapian::docid did;
     587                 :            : 
     588                 :         10 :     did = db.add_document(doc1);
     589   [ -  +  #  # ]:         10 :     TEST_EQUAL(did, 1);
     590                 :            : 
     591                 :         10 :     doc1.remove_term("one");
     592                 :         10 :     doc1.add_posting("three", 4);
     593                 :            : 
     594                 :         10 :     did = db.add_document(doc1);
     595   [ -  +  #  # ]:         10 :     TEST_EQUAL(did, 2);
     596                 :            : 
     597                 :         10 :     doc1.add_posting("one", 7);
     598                 :         10 :     doc1.remove_term("two");
     599                 :            : 
     600                 :         10 :     did = db.add_document(doc1);
     601   [ -  +  #  # ]:         10 :     TEST_EQUAL(did, 3);
     602                 :            : 
     603                 :         10 :     db.commit();
     604                 :            : 
     605                 :         10 :     db.reopen();
     606                 :            : 
     607                 :         10 :     db.delete_document(1);
     608                 :         10 :     db.delete_document(2);
     609                 :         10 :     db.delete_document(3);
     610                 :            : 
     611                 :         10 :     db.commit();
     612                 :            : 
     613                 :         10 :     db.reopen();
     614                 :            : 
     615 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(db.postlist_begin("one"), db.postlist_end("one"));
     616 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(db.postlist_begin("two"), db.postlist_end("two"));
     617 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(db.postlist_begin("three"), db.postlist_end("three"));
     618                 :            : 
     619 [ +  - ][ -  + ]:         20 :     TEST_EXCEPTION(Xapian::DocNotFoundError, db.termlist_begin(1));
         [ #  # ][ -  + ]
     620 [ +  - ][ -  + ]:         20 :     TEST_EXCEPTION(Xapian::DocNotFoundError, db.termlist_begin(2));
         [ #  # ][ -  + ]
     621 [ +  - ][ -  + ]:         20 :     TEST_EXCEPTION(Xapian::DocNotFoundError, db.termlist_begin(3));
         [ #  # ][ -  + ]
     622 [ +  - ][ -  + ]:         20 :     TEST_EXCEPTION(Xapian::DocNotFoundError, db.termlist_begin(4));
         [ #  # ][ -  + ]
     623                 :            : 
     624                 :            :     // test positionlist_{begin,end}?
     625                 :            : 
     626   [ -  +  #  # ]:         10 :     TEST_EQUAL(db.get_doccount(), 0);
     627 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(db.get_avlength(), 0);
     628 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(db.get_termfreq("one"), 0);
     629 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(db.get_termfreq("two"), 0);
     630 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(db.get_termfreq("three"), 0);
     631                 :            : 
     632 [ -  + ][ #  # ]:         10 :     TEST(!db.term_exists("one"));
     633 [ -  + ][ #  # ]:         10 :     TEST(!db.term_exists("two"));
     634 [ -  + ][ #  # ]:         10 :     TEST(!db.term_exists("three"));
     635                 :            : 
     636 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(db.get_collection_freq("one"), 0);
     637 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(db.get_collection_freq("two"), 0);
     638 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(db.get_collection_freq("three"), 0);
     639                 :            : 
     640 [ +  - ][ -  + ]:         20 :     TEST_EXCEPTION(Xapian::DocNotFoundError, db.get_doclength(1));
         [ #  # ][ -  + ]
     641 [ +  - ][ -  + ]:         20 :     TEST_EXCEPTION(Xapian::DocNotFoundError, db.get_doclength(2));
         [ #  # ][ -  + ]
     642 [ +  - ][ -  + ]:         20 :     TEST_EXCEPTION(Xapian::DocNotFoundError, db.get_doclength(3));
         [ #  # ][ -  + ]
     643                 :            : 
     644 [ +  - ][ -  + ]:         20 :     TEST_EXCEPTION(Xapian::DocNotFoundError, db.get_document(1));
         [ #  # ][ -  + ]
     645 [ +  - ][ -  + ]:         20 :     TEST_EXCEPTION(Xapian::DocNotFoundError, db.get_document(2));
         [ #  # ][ -  + ]
     646 [ +  - ][ -  + ]:         20 :     TEST_EXCEPTION(Xapian::DocNotFoundError, db.get_document(3));
         [ #  # ][ -  + ]
     647                 :            : 
     648 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(db.allterms_begin(), db.allterms_end());
     649                 :            : 
     650                 :         10 :     return true;
     651                 :            : }
     652                 :            : 
     653                 :            : // another test of deletion of documents, a cut-down version of deldoc2
     654                 :         10 : DEFINE_TESTCASE(deldoc3, writable) {
     655                 :         10 :     Xapian::WritableDatabase db = get_writable_database();
     656                 :            : 
     657                 :         10 :     Xapian::Document doc1;
     658                 :            : 
     659                 :         10 :     doc1.add_posting("one", 1);
     660                 :            : 
     661                 :         10 :     Xapian::docid did = db.add_document(doc1);
     662   [ -  +  #  # ]:         10 :     TEST_EQUAL(did, 1);
     663                 :            : 
     664                 :         10 :     db.commit();
     665                 :            : 
     666                 :         10 :     db.reopen();
     667                 :            : 
     668                 :         10 :     db.delete_document(1);
     669                 :            : 
     670                 :         10 :     db.commit();
     671                 :            : 
     672                 :         10 :     db.reopen();
     673                 :            : 
     674 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(db.postlist_begin("one"), db.postlist_end("one"));
     675                 :            : 
     676 [ +  - ][ -  + ]:         20 :     TEST_EXCEPTION(Xapian::DocNotFoundError, db.termlist_begin(1));
         [ #  # ][ -  + ]
     677                 :            :     (void)&db; // gcc 2.95 seems to miscompile without this!!! - Olly
     678 [ +  - ][ -  + ]:         20 :     TEST_EXCEPTION(Xapian::DocNotFoundError, db.termlist_begin(2));
         [ #  # ][ -  + ]
     679                 :            : 
     680                 :            :     // test positionlist_{begin,end}?
     681                 :            : 
     682   [ -  +  #  # ]:         10 :     TEST_EQUAL(db.get_doccount(), 0);
     683 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(db.get_avlength(), 0);
     684 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(db.get_termfreq("one"), 0);
     685                 :            : 
     686 [ -  + ][ #  # ]:         10 :     TEST(!db.term_exists("one"));
     687                 :            : 
     688 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(db.get_collection_freq("one"), 0);
     689                 :            : 
     690 [ +  - ][ -  + ]:         20 :     TEST_EXCEPTION(Xapian::DocNotFoundError, db.get_doclength(1));
         [ #  # ][ -  + ]
     691 [ +  - ][ -  + ]:         20 :     TEST_EXCEPTION(Xapian::DocNotFoundError, db.get_doclength(2));
         [ #  # ][ -  + ]
     692                 :            : 
     693 [ +  - ][ -  + ]:         20 :     TEST_EXCEPTION(Xapian::DocNotFoundError, db.get_document(1));
         [ #  # ][ -  + ]
     694 [ +  - ][ -  + ]:         20 :     TEST_EXCEPTION(Xapian::DocNotFoundError, db.get_document(2));
         [ #  # ][ -  + ]
     695                 :            : 
     696 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(db.allterms_begin(), db.allterms_end());
     697                 :            : 
     698                 :         10 :     return true;
     699                 :            : }
     700                 :            : 
     701                 :            : // tests that deletion and updating of (lots of) documents works as expected
     702                 :         10 : DEFINE_TESTCASE(deldoc4, writable) {
     703                 :         10 :     Xapian::WritableDatabase db = get_writable_database();
     704                 :            : 
     705                 :         10 :     Xapian::Document doc1;
     706                 :            : 
     707                 :         10 :     doc1.add_posting("one", 1);
     708                 :         10 :     doc1.add_posting("two", 2);
     709                 :         10 :     doc1.add_posting("two", 3);
     710                 :            : 
     711                 :         10 :     Xapian::Document doc2 = doc1;
     712                 :         10 :     doc2.remove_term("one");
     713                 :         10 :     doc2.add_posting("three", 4);
     714                 :            : 
     715                 :         10 :     Xapian::Document doc3 = doc2;
     716                 :         10 :     doc3.add_posting("one", 7);
     717                 :         10 :     doc3.remove_term("two");
     718                 :            : 
     719                 :         10 :     const Xapian::docid maxdoc = 1000 * 3;
     720                 :            :     Xapian::docid did;
     721         [ +  + ]:      10010 :     for (Xapian::docid i = 0; i < maxdoc / 3; ++i) {
     722                 :      10000 :         did = db.add_document(doc1);
     723   [ -  +  #  # ]:      10000 :         TEST_EQUAL(did, i * 3 + 1);
     724                 :      10000 :         did = db.add_document(doc2);
     725   [ -  +  #  # ]:      10000 :         TEST_EQUAL(did, i * 3 + 2);
     726                 :      10000 :         did = db.add_document(doc3);
     727   [ -  +  #  # ]:      10000 :         TEST_EQUAL(did, i * 3 + 3);
     728                 :            : 
     729                 :      10000 :         bool is_power_of_two = ((i & (i - 1)) == 0);
     730         [ +  + ]:      10000 :         if (is_power_of_two) {
     731                 :        110 :             db.commit();
     732                 :        110 :             db.reopen();
     733                 :            :         }
     734                 :            :     }
     735                 :         10 :     db.commit();
     736                 :         10 :     db.reopen();
     737                 :            : 
     738                 :            :     /* delete the documents in a peculiar order */
     739         [ +  + ]:      10010 :     for (Xapian::docid i = 0; i < maxdoc / 3; ++i) {
     740                 :      10000 :         db.delete_document(maxdoc - i);
     741                 :      10000 :         db.delete_document(maxdoc / 3 + i + 1);
     742                 :      10000 :         db.delete_document(i + 1);
     743                 :            :     }
     744                 :            : 
     745                 :         10 :     db.commit();
     746                 :            : 
     747                 :         10 :     db.reopen();
     748                 :            : 
     749 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(db.postlist_begin("one"), db.postlist_end("one"));
     750 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(db.postlist_begin("two"), db.postlist_end("two"));
     751 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(db.postlist_begin("three"), db.postlist_end("three"));
     752                 :            : 
     753         [ +  + ]:      30010 :     for (Xapian::docid i = 1; i <= maxdoc; ++i) {
     754                 :            :         // TEST_EXCEPTION writes to tout each time if the test is run
     755                 :            :         // in verbose mode and some string stream implementations get
     756                 :            :         // very inefficient with large strings, so clear tout on each pass of
     757                 :            :         // the loop to speed up the test since the older information isn't
     758                 :            :         // interesting anyway.
     759                 :      30000 :         tout.str(string());
     760 [ +  - ][ -  + ]:      60000 :         TEST_EXCEPTION(Xapian::DocNotFoundError, db.termlist_begin(i));
         [ #  # ][ -  + ]
     761 [ +  - ][ -  + ]:      60000 :         TEST_EXCEPTION(Xapian::DocNotFoundError, db.get_doclength(i));
         [ #  # ][ -  + ]
     762 [ +  - ][ -  + ]:      60000 :         TEST_EXCEPTION(Xapian::DocNotFoundError, db.get_document(i));
         [ #  # ][ -  + ]
     763                 :            :     }
     764                 :            : 
     765                 :            :     // test positionlist_{begin,end}?
     766                 :            : 
     767 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(db.get_doccount(), 0);
     768 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(db.get_avlength(), 0);
     769 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(db.get_termfreq("one"), 0);
     770 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(db.get_termfreq("two"), 0);
     771 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(db.get_termfreq("three"), 0);
     772                 :            : 
     773 [ -  + ][ #  # ]:         10 :     TEST(!db.term_exists("one"));
     774 [ -  + ][ #  # ]:         10 :     TEST(!db.term_exists("two"));
     775 [ -  + ][ #  # ]:         10 :     TEST(!db.term_exists("three"));
     776                 :            : 
     777 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(db.get_collection_freq("one"), 0);
     778 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(db.get_collection_freq("two"), 0);
     779 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(db.get_collection_freq("three"), 0);
     780                 :            : 
     781 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(db.allterms_begin(), db.allterms_end());
     782                 :            : 
     783                 :         10 :     return true;
     784                 :            : }
     785                 :            : 
     786                 :            : // Test deleting a document which was added in the same batch.
     787                 :         10 : DEFINE_TESTCASE(deldoc5, writable) {
     788                 :         10 :     Xapian::WritableDatabase db = get_writable_database();
     789                 :            : 
     790                 :         10 :     Xapian::Document doc1;
     791                 :            : 
     792                 :         10 :     doc1.add_posting("foo", 1);
     793                 :         10 :     doc1.add_posting("bar", 2);
     794                 :         10 :     doc1.add_posting("aardvark", 3);
     795                 :            : 
     796                 :         10 :     Xapian::docid did = db.add_document(doc1);
     797   [ -  +  #  # ]:         10 :     TEST_EQUAL(did, 1);
     798                 :            : 
     799                 :         10 :     doc1.remove_term("bar");
     800                 :         10 :     doc1.add_term("hello");
     801                 :            : 
     802                 :         10 :     did = db.add_document(doc1);
     803   [ -  +  #  # ]:         10 :     TEST_EQUAL(did, 2);
     804                 :            : 
     805                 :         10 :     doc1.add_term("world", 1);
     806                 :         10 :     did = db.add_document(doc1);
     807   [ -  +  #  # ]:         10 :     TEST_EQUAL(did, 3);
     808                 :            : 
     809                 :         10 :     db.delete_document(2);
     810                 :            : 
     811 [ +  - ][ -  + ]:         20 :     TEST_EXCEPTION(Xapian::DocNotFoundError, db.get_document(2));
         [ #  # ][ -  + ]
     812                 :            : 
     813                 :         10 :     db.commit();
     814                 :            : 
     815 [ +  - ][ -  + ]:         20 :     TEST_EXCEPTION(Xapian::DocNotFoundError, db.get_document(2));
         [ #  # ][ -  + ]
     816                 :            : 
     817 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(db.get_termfreq("foo"), 2);
     818 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(db.get_termfreq("aardvark"), 2);
     819 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(db.get_termfreq("hello"), 1);
     820                 :            : 
     821                 :         10 :     Xapian::PostingIterator p = db.postlist_begin("foo");
     822 [ -  + ][ #  # ]:         10 :     TEST_NOT_EQUAL(p, db.postlist_end("foo"));
     823 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*p, 1);
     824                 :         10 :     ++p;
     825 [ -  + ][ #  # ]:         10 :     TEST_NOT_EQUAL(p, db.postlist_end("foo"));
     826 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*p, 3);
     827                 :         10 :     ++p;
     828 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(p, db.postlist_end("foo"));
     829                 :            : 
     830                 :         10 :     return true;
     831                 :            : }
     832                 :            : 
     833                 :            : // Regression test for bug in quartz and flint, fixed in 1.0.2.
     834                 :         10 : DEFINE_TESTCASE(deldoc6, writable) {
     835                 :         10 :     Xapian::WritableDatabase db = get_writable_database();
     836                 :            : 
     837                 :         10 :     Xapian::Document doc1;
     838                 :            : 
     839                 :         10 :     doc1.add_posting("foo", 1);
     840                 :         10 :     doc1.add_posting("bar", 2);
     841                 :         10 :     doc1.add_posting("aardvark", 3);
     842                 :            : 
     843                 :         10 :     Xapian::docid did = db.add_document(doc1);
     844   [ -  +  #  # ]:         10 :     TEST_EQUAL(did, 1);
     845                 :            : 
     846                 :         10 :     doc1.remove_term("bar");
     847                 :         10 :     doc1.add_term("hello");
     848                 :            : 
     849                 :         10 :     did = db.add_document(doc1);
     850   [ -  +  #  # ]:         10 :     TEST_EQUAL(did, 2);
     851                 :            : 
     852                 :         10 :     db.commit();
     853                 :            : 
     854                 :         10 :     db.delete_document(2);
     855 [ +  - ][ -  + ]:         20 :     TEST_EXCEPTION(Xapian::DocNotFoundError, db.delete_document(3));
         [ #  # ][ -  + ]
     856                 :            : 
     857                 :         10 :     db.commit();
     858                 :            : 
     859 [ +  - ][ -  + ]:         20 :     TEST_EXCEPTION(Xapian::DocNotFoundError, db.get_document(2));
         [ #  # ][ -  + ]
     860                 :            : 
     861                 :         10 :     return true;
     862                 :            : }
     863                 :            : 
     864                 :         10 : DEFINE_TESTCASE(replacedoc1, writable) {
     865                 :         10 :     Xapian::WritableDatabase db = get_writable_database();
     866                 :            : 
     867                 :         10 :     Xapian::Document doc1;
     868                 :            : 
     869                 :         10 :     doc1.add_posting("foo", 1);
     870                 :         10 :     doc1.add_posting("foo", 2);
     871                 :         10 :     doc1.add_posting("gone",3);
     872                 :         10 :     doc1.add_posting("bar", 4);
     873                 :         10 :     doc1.add_posting("foo", 5);
     874                 :            :     Xapian::docid did;
     875                 :            : 
     876                 :         10 :     did = db.add_document(doc1);
     877   [ -  +  #  # ]:         10 :     TEST_EQUAL(did, 1);
     878                 :            : 
     879                 :         10 :     Xapian::Document doc2;
     880                 :            : 
     881                 :         10 :     doc2.add_posting("foo", 1);
     882                 :         10 :     doc2.add_posting("pipco", 2);
     883                 :         10 :     doc2.add_posting("bar", 4);
     884                 :         10 :     doc2.add_posting("foo", 5);
     885                 :            : 
     886                 :         10 :     db.replace_document(did, doc2);
     887                 :            : 
     888                 :         10 :     Xapian::Document doc3 = db.get_document(did);
     889                 :         10 :     Xapian::TermIterator tIter = doc3.termlist_begin();
     890 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*tIter, "bar");
     891                 :         10 :     Xapian::PositionIterator pIter = tIter.positionlist_begin();
     892   [ -  +  #  # ]:         10 :     TEST_EQUAL(*pIter, 4);
     893                 :         10 :     ++tIter;
     894 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*tIter, "foo");
     895                 :         10 :     Xapian::PositionIterator qIter = tIter.positionlist_begin();
     896   [ -  +  #  # ]:         10 :     TEST_EQUAL(*qIter, 1);
     897                 :         10 :     ++qIter;
     898   [ -  +  #  # ]:         10 :     TEST_EQUAL(*qIter, 5);
     899                 :         10 :     ++tIter;
     900 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*tIter, "pipco");
     901                 :         10 :     Xapian::PositionIterator rIter = tIter.positionlist_begin();
     902   [ -  +  #  # ]:         10 :     TEST_EQUAL(*rIter, 2);
     903                 :         10 :     ++tIter;
     904 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(tIter, doc3.termlist_end());
     905                 :         10 :     return true;
     906                 :            : }
     907                 :            : 
     908                 :            : // Test of new feature: WritableDatabase::replace_document accepts a docid
     909                 :            : // which doesn't yet exist as of Xapian 0.8.2.
     910                 :         10 : DEFINE_TESTCASE(replacedoc2, writable) {
     911                 :         10 :     Xapian::WritableDatabase db = get_writable_database();
     912                 :            : 
     913                 :         10 :     Xapian::Document doc1;
     914                 :            : 
     915                 :         10 :     doc1.add_posting("foo", 1);
     916                 :         10 :     doc1.add_posting("foo", 2);
     917                 :         10 :     doc1.add_posting("gone",3);
     918                 :         10 :     doc1.add_posting("bar", 4);
     919                 :         10 :     doc1.add_posting("foo", 5);
     920                 :         10 :     Xapian::docid did = 31770;
     921                 :            : 
     922                 :         10 :     db.replace_document(did, doc1);
     923                 :            : 
     924                 :            :     // Regression tests for bug in the InMemory backend - fixed in 1.0.2.
     925 [ +  - ][ -  + ]:         20 :     TEST_EXCEPTION(Xapian::DocNotFoundError, db.get_document(1));
         [ #  # ][ -  + ]
     926                 :         10 :     Xapian::PostingIterator postit = db.postlist_begin("");
     927 [ -  + ][ #  # ]:         10 :     TEST(postit != db.postlist_end(""));
     928 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*postit, 31770);
     929                 :            : 
     930                 :         10 :     Xapian::Document doc2;
     931                 :            : 
     932                 :         10 :     doc2.add_posting("foo", 1);
     933                 :         10 :     doc2.add_posting("pipco", 2);
     934                 :         10 :     doc2.add_posting("bar", 4);
     935                 :         10 :     doc2.add_posting("foo", 5);
     936                 :            : 
     937                 :         10 :     db.replace_document(did, doc2);
     938   [ -  +  #  # ]:         10 :     TEST_EQUAL(db.get_doccount(), 1);
     939                 :            : 
     940                 :         10 :     Xapian::Document doc3 = db.get_document(did);
     941                 :         10 :     Xapian::TermIterator tIter = doc3.termlist_begin();
     942 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*tIter, "bar");
     943                 :         10 :     Xapian::PositionIterator pIter = tIter.positionlist_begin();
     944   [ -  +  #  # ]:         10 :     TEST_EQUAL(*pIter, 4);
     945                 :         10 :     ++tIter;
     946 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*tIter, "foo");
     947                 :         10 :     Xapian::PositionIterator qIter = tIter.positionlist_begin();
     948   [ -  +  #  # ]:         10 :     TEST_EQUAL(*qIter, 1);
     949                 :         10 :     ++qIter;
     950   [ -  +  #  # ]:         10 :     TEST_EQUAL(*qIter, 5);
     951                 :         10 :     ++tIter;
     952 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*tIter, "pipco");
     953                 :         10 :     Xapian::PositionIterator rIter = tIter.positionlist_begin();
     954   [ -  +  #  # ]:         10 :     TEST_EQUAL(*rIter, 2);
     955                 :         10 :     ++tIter;
     956 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(tIter, doc3.termlist_end());
     957                 :            : 
     958                 :         10 :     did = db.add_document(doc1);
     959   [ -  +  #  # ]:         10 :     TEST_EQUAL(did, 31771);
     960 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(db.get_doccount(), 2);
     961                 :            : 
     962 [ +  - ][ -  + ]:         20 :     TEST_EXCEPTION(Xapian::InvalidArgumentError, db.replace_document(0, doc2));
         [ #  # ][ -  + ]
     963                 :            : 
     964                 :         10 :     return true;
     965                 :            : }
     966                 :            : 
     967                 :            : // Test replacing a document which was added in the same batch.
     968                 :         10 : DEFINE_TESTCASE(replacedoc3, writable) {
     969                 :         10 :     Xapian::WritableDatabase db = get_writable_database();
     970                 :            : 
     971                 :         10 :     Xapian::Document doc1;
     972                 :            : 
     973                 :         10 :     doc1.add_posting("foo", 1);
     974                 :         10 :     doc1.add_posting("bar", 2);
     975                 :         10 :     doc1.add_posting("aardvark", 3);
     976                 :            : 
     977                 :         10 :     Xapian::docid did = db.add_document(doc1);
     978   [ -  +  #  # ]:         10 :     TEST_EQUAL(did, 1);
     979                 :            : 
     980                 :         10 :     doc1.remove_term("bar");
     981                 :         10 :     doc1.add_term("hello");
     982                 :            : 
     983                 :         10 :     did = db.add_document(doc1);
     984   [ -  +  #  # ]:         10 :     TEST_EQUAL(did, 2);
     985                 :            : 
     986                 :         10 :     doc1.add_term("world", 1);
     987                 :         10 :     did = db.add_document(doc1);
     988   [ -  +  #  # ]:         10 :     TEST_EQUAL(did, 3);
     989                 :            : 
     990                 :         10 :     Xapian::Document doc2;
     991                 :         10 :     doc2.add_term("world");
     992                 :         10 :     db.replace_document(2, doc2);
     993                 :            : 
     994                 :         10 :     db.commit();
     995                 :            : 
     996                 :            :     // Check that the document exists (no DocNotFoundError).
     997                 :         10 :     doc2 = db.get_document(2);
     998                 :            : 
     999 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(db.get_termfreq("foo"), 2);
    1000 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(db.get_termfreq("aardvark"), 2);
    1001 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(db.get_termfreq("hello"), 1);
    1002 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(db.get_termfreq("world"), 2);
    1003                 :            : 
    1004 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(db.get_doclength(1), 3);
    1005 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(db.get_doclength(2), 1);
    1006 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(db.get_doclength(3), 4);
    1007                 :            : 
    1008                 :         10 :     Xapian::PostingIterator p = db.postlist_begin("foo");
    1009 [ -  + ][ #  # ]:         10 :     TEST_NOT_EQUAL(p, db.postlist_end("foo"));
    1010 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*p, 1);
    1011 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(p.get_doclength(), 3);
    1012                 :         10 :     ++p;
    1013 [ -  + ][ #  # ]:         10 :     TEST_NOT_EQUAL(p, db.postlist_end("foo"));
    1014 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*p, 3);
    1015 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(p.get_doclength(), 4);
    1016                 :         10 :     ++p;
    1017 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(p, db.postlist_end("foo"));
    1018                 :            : 
    1019                 :         10 :     p = db.postlist_begin("world");
    1020 [ -  + ][ #  # ]:         10 :     TEST_NOT_EQUAL(p, db.postlist_end("world"));
    1021 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*p, 2);
    1022 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(p.get_doclength(), 1);
    1023                 :         10 :     ++p;
    1024 [ -  + ][ #  # ]:         10 :     TEST_NOT_EQUAL(p, db.postlist_end("world"));
    1025 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*p, 3);
    1026 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(p.get_doclength(), 4);
    1027                 :         10 :     ++p;
    1028 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(p, db.postlist_end("world"));
    1029                 :            : 
    1030                 :         10 :     return true;
    1031                 :            : }
    1032                 :            : 
    1033                 :            : // Test replacing a document which was deleted in the same batch.
    1034                 :         10 : DEFINE_TESTCASE(replacedoc4, writable) {
    1035                 :         10 :     Xapian::WritableDatabase db = get_writable_database();
    1036                 :            : 
    1037                 :         10 :     Xapian::Document doc1;
    1038                 :            : 
    1039                 :         10 :     doc1.add_posting("foo", 1);
    1040                 :         10 :     doc1.add_posting("bar", 2);
    1041                 :         10 :     doc1.add_posting("aardvark", 3);
    1042                 :            : 
    1043                 :         10 :     Xapian::docid did = db.add_document(doc1);
    1044   [ -  +  #  # ]:         10 :     TEST_EQUAL(did, 1);
    1045                 :            : 
    1046                 :         10 :     doc1.remove_term("bar");
    1047                 :         10 :     doc1.add_term("hello");
    1048                 :            : 
    1049                 :         10 :     did = db.add_document(doc1);
    1050   [ -  +  #  # ]:         10 :     TEST_EQUAL(did, 2);
    1051                 :            : 
    1052                 :         10 :     doc1.add_term("world", 1);
    1053                 :         10 :     did = db.add_document(doc1);
    1054   [ -  +  #  # ]:         10 :     TEST_EQUAL(did, 3);
    1055                 :            : 
    1056                 :         10 :     db.delete_document(2);
    1057                 :            : 
    1058                 :         10 :     Xapian::Document doc2;
    1059                 :         10 :     doc2.add_term("world");
    1060                 :         10 :     db.replace_document(2, doc2);
    1061                 :            : 
    1062                 :         10 :     db.commit();
    1063                 :            : 
    1064                 :            :     // Check that the document exists (no DocNotFoundError).
    1065                 :         10 :     doc2 = db.get_document(2);
    1066                 :            : 
    1067 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(db.get_termfreq("foo"), 2);
    1068 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(db.get_termfreq("aardvark"), 2);
    1069 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(db.get_termfreq("hello"), 1);
    1070 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(db.get_termfreq("world"), 2);
    1071                 :            : 
    1072                 :         10 :     Xapian::PostingIterator p = db.postlist_begin("foo");
    1073 [ -  + ][ #  # ]:         10 :     TEST_NOT_EQUAL(p, db.postlist_end("foo"));
    1074 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*p, 1);
    1075                 :         10 :     ++p;
    1076 [ -  + ][ #  # ]:         10 :     TEST_NOT_EQUAL(p, db.postlist_end("foo"));
    1077 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*p, 3);
    1078                 :         10 :     ++p;
    1079 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(p, db.postlist_end("foo"));
    1080                 :            : 
    1081                 :         10 :     p = db.postlist_begin("world");
    1082 [ -  + ][ #  # ]:         10 :     TEST_NOT_EQUAL(p, db.postlist_end("world"));
    1083 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*p, 2);
    1084                 :         10 :     ++p;
    1085 [ -  + ][ #  # ]:         10 :     TEST_NOT_EQUAL(p, db.postlist_end("world"));
    1086 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*p, 3);
    1087                 :         10 :     ++p;
    1088 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(p, db.postlist_end("world"));
    1089                 :            : 
    1090                 :         10 :     return true;
    1091                 :            : }
    1092                 :            : 
    1093                 :            : // Test replacing a document with itself without modifying postings.
    1094                 :            : // Regression test for bug in 0.9.9 and earlier - there flint and quartz
    1095                 :            : // lose all positional information for the document when you do this.
    1096                 :         10 : DEFINE_TESTCASE(replacedoc5, writable) {
    1097                 :         10 :     Xapian::WritableDatabase db = get_writable_database();
    1098                 :            : 
    1099                 :            :     {
    1100                 :         10 :         Xapian::Document doc;
    1101                 :         10 :         doc.add_posting("hello", 1);
    1102                 :         10 :         doc.add_posting("world", 2);
    1103                 :            : 
    1104                 :         10 :         Xapian::docid did = db.add_document(doc);
    1105   [ -  +  #  # ]:         10 :         TEST_EQUAL(did, 1);
    1106                 :         10 :         db.commit();
    1107                 :            :     }
    1108                 :            : 
    1109                 :            :     {
    1110                 :         10 :         Xapian::Document doc = db.get_document(1);
    1111   [ -  +  #  # ]:         10 :         TEST(db.has_positions());
    1112 [ -  + ][ #  # ]:         10 :         TEST(db.positionlist_begin(1, "hello") != db.positionlist_end(1, "hello"));
    1113 [ -  + ][ #  # ]:         10 :         TEST(db.positionlist_begin(1, "world") != db.positionlist_end(1, "world"));
    1114                 :         10 :         db.replace_document(1, doc);
    1115                 :         10 :         db.commit();
    1116                 :            : 
    1117   [ -  +  #  # ]:         10 :         TEST(db.has_positions());
    1118 [ -  + ][ #  # ]:         10 :         TEST(db.positionlist_begin(1, "hello") != db.positionlist_end(1, "hello"));
    1119 [ -  + ][ #  # ]:         10 :         TEST(db.positionlist_begin(1, "world") != db.positionlist_end(1, "world"));
    1120                 :            :     }
    1121                 :            : 
    1122                 :            :     // Brass, chert and flint now spot simple cases of replacing the same
    1123                 :            :     // document and don't do needless work.  Force them to actually do the
    1124                 :            :     // replacement to make sure that case works.
    1125                 :            : 
    1126                 :            :     {
    1127                 :         10 :         Xapian::Document doc;
    1128                 :         10 :         doc.add_term("Q2");
    1129                 :         10 :         db.add_document(doc);
    1130                 :         10 :         db.commit();
    1131                 :            :     }
    1132                 :            : 
    1133                 :            :     {
    1134                 :         10 :         Xapian::Document doc = db.get_document(1);
    1135   [ -  +  #  # ]:         10 :         TEST(db.has_positions());
    1136 [ -  + ][ #  # ]:         10 :         TEST(db.positionlist_begin(1, "hello") != db.positionlist_end(1, "hello"));
    1137 [ -  + ][ #  # ]:         10 :         TEST(db.positionlist_begin(1, "world") != db.positionlist_end(1, "world"));
    1138                 :         10 :         (void)db.get_document(2);
    1139                 :         10 :         db.replace_document(1, doc);
    1140                 :         10 :         db.commit();
    1141                 :            : 
    1142   [ -  +  #  # ]:         10 :         TEST(db.has_positions());
    1143 [ -  + ][ #  # ]:         10 :         TEST(db.positionlist_begin(1, "hello") != db.positionlist_end(1, "hello"));
    1144 [ -  + ][ #  # ]:         10 :         TEST(db.positionlist_begin(1, "world") != db.positionlist_end(1, "world"));
    1145                 :            :     }
    1146                 :            : 
    1147                 :         10 :     return true;
    1148                 :            : }
    1149                 :            : 
    1150                 :            : // Test replacing a document while adding values, without changing anything
    1151                 :            : // else.  Regression test for a bug introduced while implementing lazy update,
    1152                 :            : // and also covers a few other code paths.
    1153                 :         10 : DEFINE_TESTCASE(replacedoc6, writable) {
    1154                 :         10 :     Xapian::WritableDatabase db = get_writable_database();
    1155                 :            : 
    1156                 :         10 :     Xapian::Document doc;
    1157                 :         10 :     Xapian::docid did = db.add_document(doc);
    1158   [ -  +  #  # ]:         10 :     TEST_EQUAL(did, 1);
    1159                 :         10 :     db.commit();
    1160                 :            : 
    1161                 :            :     // Add document
    1162                 :         10 :     doc = db.get_document(1);
    1163 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(doc.get_value(1), "");
    1164 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(doc.get_value(2), "");
    1165                 :         10 :     doc.add_value(1, "banana1");
    1166                 :         10 :     db.replace_document(1, doc);
    1167                 :            : 
    1168                 :         10 :     doc = db.get_document(1);
    1169 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(doc.get_value(1), "banana1");
    1170 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(doc.get_value(2), "");
    1171                 :         10 :     db.commit();
    1172                 :            : 
    1173                 :         10 :     doc = db.get_document(1);
    1174 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(doc.get_value(1), "banana1");
    1175 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(doc.get_value(2), "");
    1176                 :         10 :     doc.add_value(2, "banana2");
    1177                 :         10 :     db.replace_document(1, doc);
    1178                 :            : 
    1179 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(doc.get_value(1), "banana1");
    1180 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(doc.get_value(2), "banana2");
    1181                 :         10 :     db.commit();
    1182                 :            : 
    1183                 :         10 :     doc = db.get_document(1);
    1184 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(doc.get_value(1), "banana1");
    1185 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(doc.get_value(2), "banana2");
    1186                 :            : 
    1187                 :         10 :     return true;
    1188                 :            : }
    1189                 :            : 
    1190                 :            : // Test of new feature: WritableDatabase::replace_document and delete_document
    1191                 :            : // can take a unique termname instead of a document id as of Xapian 0.8.2.
    1192                 :         10 : DEFINE_TESTCASE(uniqueterm1, writable) {
    1193                 :         10 :     Xapian::WritableDatabase db = get_writable_database();
    1194                 :            : 
    1195         [ +  + ]:        210 :     for (int n = 1; n <= 20; ++n) {
    1196                 :        200 :         Xapian::Document doc;
    1197                 :        200 :         string uterm = "U" + str(n % 16);
    1198                 :        200 :         doc.add_term(uterm);
    1199                 :        200 :         doc.add_term(str(n));
    1200                 :        200 :         doc.add_term(str(n ^ 9));
    1201                 :        200 :         doc.add_term("all");
    1202                 :        200 :         doc.set_data("pass1");
    1203                 :        200 :         db.add_document(doc);
    1204                 :            :     }
    1205                 :            : 
    1206 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(db.get_doccount(), 20);
    1207                 :            : 
    1208                 :            :     static const Xapian::doccount sizes[20] = {
    1209                 :            :         19, 17, 16, 15,
    1210                 :            :         15, 15, 15, 15,
    1211                 :            :         15, 15, 15, 15,
    1212                 :            :         15, 15, 15, 15,
    1213                 :            :         15, 15, 15, 15
    1214                 :            :     };
    1215         [ +  + ]:        210 :     for (int n = 1; n <= 20; ++n) {
    1216                 :        200 :         string uterm = "U" + str(n % 16);
    1217         [ +  + ]:        200 :         if (uterm == "U2") {
    1218                 :         20 :             db.delete_document(uterm);
    1219                 :            :         } else {
    1220                 :        180 :             Xapian::Document doc;
    1221                 :        180 :             doc.add_term(uterm);
    1222                 :        180 :             doc.add_term(str(n));
    1223                 :        180 :             doc.add_term(str(n ^ 9));
    1224                 :        180 :             doc.add_term("all");
    1225                 :        180 :             doc.set_data("pass2");
    1226                 :        180 :             db.replace_document(uterm, doc);
    1227                 :            :         }
    1228 [ -  + ][ #  # ]:        200 :         TEST_EQUAL(db.get_doccount(), sizes[n - 1]);
    1229                 :            :     }
    1230                 :            : 
    1231                 :         10 :     string uterm = "U571";
    1232                 :         10 :     Xapian::Document doc;
    1233                 :         10 :     doc.add_term(uterm);
    1234                 :         10 :     doc.set_data("pass3");
    1235                 :         10 :     db.replace_document(uterm, doc);
    1236                 :            : 
    1237   [ -  +  #  # ]:         10 :     TEST_EQUAL(db.get_doccount(), 16);
    1238                 :            : 
    1239                 :         10 :     db.delete_document("U2");
    1240                 :            : 
    1241   [ -  +  #  # ]:         10 :     TEST_EQUAL(db.get_doccount(), 16);
    1242                 :            : 
    1243                 :         10 :     return true;
    1244                 :            : }
    1245                 :            : 
    1246                 :            : // tests all document postlists
    1247                 :         10 : DEFINE_TESTCASE(allpostlist2, writable) {
    1248                 :         10 :     Xapian::WritableDatabase db(get_writable_database("apitest_manydocs"));
    1249                 :         10 :     Xapian::PostingIterator i = db.postlist_begin("");
    1250                 :         10 :     unsigned int j = 1;
    1251         [ +  + ]:       5130 :     while (i != db.postlist_end("")) {
    1252 [ -  + ][ #  # ]:       5120 :         TEST_EQUAL(*i, j);
    1253                 :       5120 :         i++;
    1254                 :       5120 :         j++;
    1255                 :            :     }
    1256 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(j, 513);
    1257                 :            : 
    1258                 :         10 :     db.delete_document(1);
    1259                 :         10 :     db.delete_document(50);
    1260                 :         10 :     db.delete_document(512);
    1261                 :            : 
    1262                 :         10 :     i = db.postlist_begin("");
    1263                 :         10 :     j = 2;
    1264         [ +  + ]:       5100 :     while (i != db.postlist_end("")) {
    1265 [ -  + ][ #  # ]:       5090 :         TEST_EQUAL(*i, j);
    1266                 :       5090 :         i++;
    1267                 :       5090 :         j++;
    1268         [ +  + ]:       5090 :         if (j == 50) j++;
    1269                 :            :     }
    1270 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(j, 512);
    1271                 :            : 
    1272                 :         10 :     i = db.postlist_begin("");
    1273                 :         10 :     j = 2;
    1274         [ +  + ]:       5000 :     while (i != db.postlist_end("")) {
    1275 [ -  + ][ #  # ]:       4990 :         TEST_EQUAL(*i, j);
    1276                 :       4990 :         i++;
    1277                 :       4990 :         j++;
    1278         [ +  + ]:       4990 :         if (j == 40) {
    1279                 :         10 :             j += 10;
    1280                 :         10 :             i.skip_to(j);
    1281                 :         10 :             j++;
    1282                 :            :         }
    1283                 :            :     }
    1284 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(j, 512);
    1285                 :            : 
    1286                 :         10 :     return true;
    1287                 :            : }
    1288                 :            : 
    1289                 :         70 : static void test_emptyterm2_helper(Xapian::WritableDatabase & db)
    1290                 :            : {
    1291                 :            :     // Don't bother with postlist_begin() because allpostlist tests cover that.
    1292 [ +  - ][ -  + ]:        280 :     TEST_EXCEPTION(Xapian::InvalidArgumentError, db.positionlist_begin(1, ""));
         [ #  # ][ -  + ]
    1293 [ -  + ][ #  # ]:         70 :     TEST_EQUAL(db.get_doccount(), db.get_termfreq(""));
    1294 [ -  + ][ #  # ]:         70 :     TEST_EQUAL(db.get_doccount() != 0, db.term_exists(""));
    1295 [ -  + ][ #  # ]:         70 :     TEST_EQUAL(db.get_doccount(), db.get_collection_freq(""));
    1296                 :         70 : }
    1297                 :            : 
    1298                 :            : // tests results of passing an empty term to various methods
    1299                 :            : // equivalent of emptyterm1 for a writable database
    1300                 :         10 : DEFINE_TESTCASE(emptyterm2, writable) {
    1301                 :            :     {
    1302                 :         10 :         Xapian::WritableDatabase db(get_writable_database("apitest_manydocs"));
    1303   [ -  +  #  # ]:         10 :         TEST_EQUAL(db.get_doccount(), 512);
    1304                 :         10 :         test_emptyterm2_helper(db);
    1305                 :         10 :         db.delete_document(1);
    1306   [ -  +  #  # ]:         10 :         TEST_EQUAL(db.get_doccount(), 511);
    1307                 :         10 :         test_emptyterm2_helper(db);
    1308                 :         10 :         db.delete_document(50);
    1309   [ -  +  #  # ]:         10 :         TEST_EQUAL(db.get_doccount(), 510);
    1310                 :         10 :         test_emptyterm2_helper(db);
    1311                 :         10 :         db.delete_document(512);
    1312   [ -  +  #  # ]:         10 :         TEST_EQUAL(db.get_doccount(), 509);
    1313                 :         10 :         test_emptyterm2_helper(db);
    1314                 :            :     }
    1315                 :            : 
    1316                 :            :     {
    1317                 :         10 :         Xapian::WritableDatabase db(get_writable_database("apitest_onedoc"));
    1318   [ -  +  #  # ]:         10 :         TEST_EQUAL(db.get_doccount(), 1);
    1319                 :         10 :         test_emptyterm2_helper(db);
    1320                 :         10 :         db.delete_document(1);
    1321   [ -  +  #  # ]:         10 :         TEST_EQUAL(db.get_doccount(), 0);
    1322                 :         10 :         test_emptyterm2_helper(db);
    1323                 :            :     }
    1324                 :            : 
    1325                 :            :     {
    1326                 :         10 :         Xapian::WritableDatabase db(get_writable_database());
    1327   [ -  +  #  # ]:         10 :         TEST_EQUAL(db.get_doccount(), 0);
    1328                 :         10 :         test_emptyterm2_helper(db);
    1329                 :            :     }
    1330                 :            : 
    1331                 :         10 :     return true;
    1332                 :            : }
    1333                 :            : 
    1334                 :            : // Check that PHRASE/NEAR becomes AND if there's no positional info in the
    1335                 :            : // database.
    1336                 :         10 : DEFINE_TESTCASE(phraseorneartoand1, writable) {
    1337                 :         10 :     Xapian::WritableDatabase db = get_writable_database();
    1338                 :            : 
    1339         [ +  + ]:        210 :     for (int n = 1; n <= 20; ++n) {
    1340                 :        200 :         Xapian::Document doc;
    1341                 :        200 :         doc.add_term(str(n));
    1342                 :        200 :         doc.add_term(str(n ^ 9));
    1343                 :        200 :         doc.add_term("all");
    1344                 :        200 :         doc.set_data("pass1");
    1345                 :        200 :         db.add_document(doc);
    1346                 :            :     }
    1347                 :         10 :     db.commit();
    1348                 :            : 
    1349                 :         10 :     Xapian::Enquire enquire(db);
    1350                 :         10 :     Xapian::MSet mymset;
    1351                 :            : 
    1352                 :         10 :     const char * q1[] = { "all", "1" };
    1353                 :         10 :     enquire.set_query(Xapian::Query(Xapian::Query::OP_PHRASE, q1, q1 + 2));
    1354                 :         10 :     mymset = enquire.get_mset(0, 10);
    1355   [ -  +  #  # ]:         10 :     TEST_EQUAL(2, mymset.size());
    1356                 :            : 
    1357                 :         10 :     enquire.set_query(Xapian::Query(Xapian::Query::OP_NEAR, q1, q1 + 2));
    1358                 :         10 :     mymset = enquire.get_mset(0, 10);
    1359   [ -  +  #  # ]:         10 :     TEST_EQUAL(2, mymset.size());
    1360                 :            : 
    1361                 :         10 :     const char * q2[] = { "1", "2" };
    1362                 :         10 :     enquire.set_query(Xapian::Query(Xapian::Query::OP_PHRASE, q2, q2 + 2));
    1363                 :         10 :     mymset = enquire.get_mset(0, 10);
    1364   [ -  +  #  # ]:         10 :     TEST_EQUAL(0, mymset.size());
    1365                 :            : 
    1366                 :         10 :     enquire.set_query(Xapian::Query(Xapian::Query::OP_NEAR, q2, q2 + 2));
    1367                 :         10 :     mymset = enquire.get_mset(0, 10);
    1368   [ -  +  #  # ]:         10 :     TEST_EQUAL(0, mymset.size());
    1369                 :            : 
    1370                 :         10 :     return true;
    1371                 :            : }
    1372                 :            : 
    1373                 :            : // Check that a large number of position list entries for a particular term
    1374                 :            : // works - regression test for flint.
    1375                 :         10 : DEFINE_TESTCASE(longpositionlist1, writable) {
    1376                 :         10 :     Xapian::WritableDatabase db = get_writable_database();
    1377                 :            : 
    1378                 :         10 :     Xapian::Document doc;
    1379                 :            :     Xapian::termpos n;
    1380         [ +  + ]:      20010 :     for (n = 1; n <= 2000; ++n) {
    1381                 :      20000 :         doc.add_posting("fork", n * 3);
    1382                 :      20000 :         doc.add_posting("knife", n * unsigned(log(double(n + 2))));
    1383                 :      20000 :         doc.add_posting("spoon", n * n);
    1384                 :            :     }
    1385                 :         10 :     doc.set_data("cutlery");
    1386                 :         10 :     Xapian::docid did = db.add_document(doc);
    1387                 :         10 :     db.commit();
    1388                 :            : 
    1389                 :         10 :     doc = db.get_document(did);
    1390                 :            : 
    1391                 :         10 :     Xapian::TermIterator t, tend;
    1392                 :         10 :     Xapian::PositionIterator p, pend;
    1393                 :            : 
    1394                 :         10 :     t = doc.termlist_begin();
    1395                 :         10 :     tend = doc.termlist_end();
    1396                 :            : 
    1397   [ -  +  #  # ]:         10 :     TEST(t != tend);
    1398 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*t, "fork");
    1399                 :         10 :     p = t.positionlist_begin();
    1400                 :         10 :     pend = t.positionlist_end();
    1401         [ +  + ]:      20010 :     for (n = 1; n <= 2000; ++n) {
    1402 [ -  + ][ #  # ]:      20000 :         TEST(p != pend);
    1403 [ -  + ][ #  # ]:      20000 :         TEST_EQUAL(*p, n * 3);
    1404                 :      20000 :         ++p;
    1405                 :            :     }
    1406 [ -  + ][ #  # ]:         10 :     TEST(p == pend);
    1407                 :            : 
    1408                 :         10 :     ++t;
    1409   [ -  +  #  # ]:         10 :     TEST(t != tend);
    1410 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*t, "knife");
    1411                 :         10 :     p = t.positionlist_begin();
    1412                 :         10 :     pend = t.positionlist_end();
    1413         [ +  + ]:      20010 :     for (n = 1; n <= 2000; ++n) {
    1414 [ -  + ][ #  # ]:      20000 :         TEST(p != pend);
    1415 [ -  + ][ #  # ]:      20000 :         TEST_EQUAL(*p, n * unsigned(log(double(n + 2))));
    1416                 :      20000 :         ++p;
    1417                 :            :     }
    1418 [ -  + ][ #  # ]:         10 :     TEST(p == pend);
    1419                 :            : 
    1420                 :         10 :     ++t;
    1421   [ -  +  #  # ]:         10 :     TEST(t != tend);
    1422 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*t, "spoon");
    1423                 :         10 :     p = t.positionlist_begin();
    1424                 :         10 :     pend = t.positionlist_end();
    1425         [ +  + ]:      20010 :     for (n = 1; n <= 2000; ++n) {
    1426 [ -  + ][ #  # ]:      20000 :         TEST(p != pend);
    1427 [ -  + ][ #  # ]:      20000 :         TEST_EQUAL(*p, n * n);
    1428                 :      20000 :         ++p;
    1429                 :            :     }
    1430 [ -  + ][ #  # ]:         10 :     TEST(p == pend);
    1431                 :            : 
    1432                 :         10 :     ++t;
    1433   [ -  +  #  # ]:         10 :     TEST(t == tend);
    1434                 :            : 
    1435                 :         10 :     return true;
    1436                 :            : }
    1437                 :            : 
    1438                 :            : // Regression test for bug#110: Inconsistent sort order between pages with
    1439                 :            : // set_sort_by_value_then_relevance.
    1440                 :         10 : DEFINE_TESTCASE(consistency2, writable) {
    1441                 :         10 :     Xapian::WritableDatabase db = get_writable_database();
    1442                 :         10 :     char buf[2] = "X";
    1443                 :         10 :     int i = 0;
    1444                 :            : 
    1445                 :            :     // Add 5 documents indexed by "test" with wdf 1.
    1446         [ +  + ]:         60 :     for (i = 0; i < 5; ++i) {
    1447                 :         50 :         Xapian::Document doc;
    1448                 :         50 :         *buf = '0' + i;
    1449                 :         50 :         doc.add_value(0, buf);
    1450                 :         50 :         doc.add_term("test");
    1451                 :         50 :         db.add_document(doc);
    1452                 :            :     }
    1453                 :            : 
    1454                 :            :     // Add 5 documents indexed by "test" with wdf 2.
    1455         [ +  + ]:         60 :     for (i = 0; i < 5; ++i) {
    1456                 :         50 :         Xapian::Document doc;
    1457                 :         50 :         *buf = '0' + i;
    1458                 :         50 :         doc.add_value(0, buf);
    1459                 :         50 :         doc.add_term("test", 2);
    1460                 :         50 :         db.add_document(doc);
    1461                 :            :     }
    1462                 :            : 
    1463                 :         10 :     db.commit();
    1464                 :            : 
    1465                 :         10 :     Xapian::Enquire enq(db);
    1466                 :         10 :     enq.set_query(Xapian::Query("test"));
    1467                 :            : 
    1468                 :         10 :     enq.set_sort_by_value_then_relevance(0, true);
    1469                 :            : 
    1470                 :            :     // 10 results, unpaged.
    1471                 :         10 :     Xapian::MSet mset1 = enq.get_mset(0, 10);
    1472   [ -  +  #  # ]:         10 :     TEST_EQUAL(mset1.size(), 10);
    1473                 :            : 
    1474                 :            :     // 10 results, split.
    1475                 :         10 :     Xapian::MSet mset2a = enq.get_mset(0, 1);
    1476   [ -  +  #  # ]:         10 :     TEST_EQUAL(mset2a.size(), 1);
    1477                 :         10 :     Xapian::MSet mset2b = enq.get_mset(1, 1);
    1478   [ -  +  #  # ]:         10 :     TEST_EQUAL(mset2b.size(), 1);
    1479                 :         10 :     Xapian::MSet mset2c = enq.get_mset(2, 8);
    1480   [ -  +  #  # ]:         10 :     TEST_EQUAL(mset2c.size(), 8);
    1481                 :            : 
    1482 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*mset1[0], *mset2a[0]);
    1483 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*mset1[1], *mset2b[0]);
    1484         [ +  + ]:         90 :     for (i = 0; i < 8; ++i) {
    1485 [ -  + ][ #  # ]:         80 :         TEST_EQUAL(*mset1[i + 2], *mset2c[i]);
    1486                 :            :     }
    1487                 :            : 
    1488                 :         10 :     return true;
    1489                 :            : }
    1490                 :            : 
    1491                 :          3 : DEFINE_TESTCASE(crashrecovery1, brass || chert || flint) {
    1492                 :          3 :     const string & dbtype = get_dbtype();
    1493                 :          3 :     string path = ".";
    1494                 :          3 :     path += dbtype;
    1495                 :          3 :     path += "/dbw";
    1496                 :          3 :     const char * base_ext = ".baseB";
    1497                 :            : 
    1498                 :          3 :     Xapian::Document doc;
    1499                 :            :     {
    1500                 :          3 :         Xapian::WritableDatabase db = get_writable_database();
    1501                 :          3 :         Xapian::Database dbr(get_writable_database_as_database());
    1502   [ -  +  #  # ]:          3 :         TEST_EQUAL(dbr.get_doccount(), 0);
    1503                 :            : 
    1504                 :            :         // Xapian::Database has full set of baseA, no baseB
    1505                 :            : 
    1506                 :          3 :         db.add_document(doc);
    1507                 :          3 :         db.commit();
    1508                 :          3 :         dbr.reopen();
    1509   [ -  +  #  # ]:          3 :         TEST_EQUAL(dbr.get_doccount(), 1);
    1510                 :            : 
    1511                 :            :         // Xapian::Database has full set of baseB, old baseA
    1512                 :            : 
    1513                 :          3 :         db.add_document(doc);
    1514                 :          3 :         db.commit();
    1515                 :          3 :         dbr.reopen();
    1516   [ -  +  #  # ]:          3 :         TEST_EQUAL(dbr.get_doccount(), 2);
    1517                 :            : 
    1518                 :            :         // Xapian::Database has full set of baseA, old baseB
    1519                 :            : 
    1520                 :            :         // Simulate a transaction starting, some of the baseB getting removed,
    1521                 :            :         // but then the transaction fails.
    1522                 :          3 :         unlink(path + "/record" + base_ext);
    1523                 :          3 :         unlink(path + "/termlist" + base_ext);
    1524                 :            : 
    1525                 :          3 :         dbr.reopen();
    1526   [ -  +  #  # ]:          3 :         TEST_EQUAL(dbr.get_doccount(), 2);
    1527                 :            :     }
    1528                 :            : 
    1529                 :          3 :     Xapian::WritableDatabase db(path, Xapian::DB_OPEN);
    1530                 :            :     // Xapian::Database has full set of baseA, some old baseB
    1531                 :          3 :     Xapian::Database dbr = Xapian::Database(path);
    1532                 :            : 
    1533                 :          3 :     db.add_document(doc);
    1534                 :          3 :     db.commit();
    1535                 :          3 :     dbr.reopen();
    1536   [ -  +  #  # ]:          3 :     TEST_EQUAL(dbr.get_doccount(), 3);
    1537                 :            : 
    1538                 :            :     // Xapian::Database has full set of baseB, old baseA
    1539                 :            : 
    1540                 :          3 :     db.add_document(doc);
    1541                 :          3 :     db.commit();
    1542                 :          3 :     dbr.reopen();
    1543   [ -  +  #  # ]:          3 :     TEST_EQUAL(dbr.get_doccount(), 4);
    1544                 :            : 
    1545                 :          3 :     return true;
    1546                 :            : }
    1547                 :            : 
    1548                 :            : // Check that DatabaseError is thrown if the docid counter would wrap.
    1549                 :            : // Regression test for bug#152.
    1550                 :         10 : DEFINE_TESTCASE(nomoredocids1, writable) {
    1551                 :            :     // The InMemory backend uses a vector for the documents, so trying to add
    1552                 :            :     // document "-1" will fail because we can't allocate enough memory!
    1553                 :         12 :     SKIP_TEST_FOR_BACKEND("inmemory");
    1554                 :            : 
    1555                 :          9 :     Xapian::WritableDatabase db = get_writable_database();
    1556                 :          9 :     Xapian::Document doc;
    1557                 :          9 :     doc.set_data("prose");
    1558                 :          9 :     doc.add_term("word");
    1559                 :            : 
    1560                 :          9 :     db.replace_document(Xapian::docid(-1), doc);
    1561                 :            : 
    1562 [ +  - ][ -  + ]:         18 :     TEST_EXCEPTION(Xapian::DatabaseError, db.add_document(doc));
         [ #  # ][ -  + ]
    1563                 :            : 
    1564                 :          9 :     return true;
    1565                 :            : }
    1566                 :            : 
    1567                 :            : // Test synonym iterators.
    1568                 :          3 : DEFINE_TESTCASE(synonymitor1, writable && synonyms) {
    1569                 :          3 :     Xapian::WritableDatabase db = get_writable_database();
    1570                 :            : 
    1571                 :            :     // Test iterators for terms which aren't there.
    1572 [ -  + ][ #  # ]:          3 :     TEST(db.synonyms_begin("abc") == db.synonyms_end("abc"));
    1573                 :            : 
    1574                 :            :     // Test iterating the synonym keys when there aren't any.
    1575 [ -  + ][ #  # ]:          3 :     TEST(db.synonym_keys_begin() == db.synonym_keys_end());
    1576                 :            : 
    1577                 :          3 :     db.add_synonym("hello", "howdy");
    1578                 :          3 :     db.add_synonym("hello", "hi");
    1579                 :          3 :     db.add_synonym("goodbye", "bye");
    1580                 :          3 :     db.add_synonym("goodbye", "farewell");
    1581                 :            : 
    1582                 :          3 :     Xapian::TermIterator t;
    1583                 :          3 :     string s;
    1584                 :            : 
    1585                 :            :     // Try these tests twice - once before committing and once after.
    1586         [ +  + ]:          9 :     for (int times = 1; times <= 2; ++times) {
    1587                 :            :         // Test iterators for terms which aren't there.
    1588 [ -  + ][ #  # ]:          6 :         TEST(db.synonyms_begin("abc") == db.synonyms_end("abc"));
    1589 [ -  + ][ #  # ]:          6 :         TEST(db.synonyms_begin("ghi") == db.synonyms_end("ghi"));
    1590 [ -  + ][ #  # ]:          6 :         TEST(db.synonyms_begin("zzzzz") == db.synonyms_end("zzzzz"));
    1591                 :            : 
    1592                 :          6 :         s = "|";
    1593                 :          6 :         t = db.synonyms_begin("hello");
    1594         [ +  + ]:         18 :         while (t != db.synonyms_end("hello")) {
    1595                 :         12 :             s += *t++;
    1596                 :         12 :             s += '|';
    1597                 :            :         }
    1598 [ -  + ][ #  # ]:          6 :         TEST_STRINGS_EQUAL(s, "|hi|howdy|");
    1599                 :            : 
    1600                 :          6 :         s = "|";
    1601                 :          6 :         t = db.synonyms_begin("goodbye");
    1602         [ +  + ]:         18 :         while (t != db.synonyms_end("goodbye")) {
    1603                 :         12 :             s += *t++;
    1604                 :         12 :             s += '|';
    1605                 :            :         }
    1606 [ -  + ][ #  # ]:          6 :         TEST_STRINGS_EQUAL(s, "|bye|farewell|");
    1607                 :            : 
    1608                 :          6 :         s = "|";
    1609                 :          6 :         t = db.synonym_keys_begin();
    1610         [ +  + ]:         18 :         while (t != db.synonym_keys_end()) {
    1611                 :         12 :             s += *t++;
    1612                 :         12 :             s += '|';
    1613                 :            :         }
    1614 [ -  + ][ #  # ]:          6 :         TEST_STRINGS_EQUAL(s, "|goodbye|hello|");
    1615                 :            : 
    1616                 :          6 :         db.commit();
    1617                 :            :     }
    1618                 :            : 
    1619                 :            :     // Delete a synonym for "hello" and all synonyms for "goodbye".
    1620                 :          3 :     db.remove_synonym("hello", "hi");
    1621                 :          3 :     db.clear_synonyms("goodbye");
    1622                 :            : 
    1623                 :            :     // Try these tests twice - once before committing and once after.
    1624         [ +  + ]:          9 :     for (int times = 1; times <= 2; ++times) {
    1625                 :            :         // Test iterators for terms which aren't there.
    1626 [ -  + ][ #  # ]:          6 :         TEST(db.synonyms_begin("abc") == db.synonyms_end("abc"));
    1627 [ -  + ][ #  # ]:          6 :         TEST(db.synonyms_begin("ghi") == db.synonyms_end("ghi"));
    1628 [ -  + ][ #  # ]:          6 :         TEST(db.synonyms_begin("zzzzz") == db.synonyms_end("zzzzz"));
    1629                 :            : 
    1630                 :          6 :         s = "|";
    1631                 :          6 :         t = db.synonyms_begin("hello");
    1632         [ +  + ]:         12 :         while (t != db.synonyms_end("hello")) {
    1633                 :          6 :             s += *t++;
    1634                 :          6 :             s += '|';
    1635                 :            :         }
    1636 [ -  + ][ #  # ]:          6 :         TEST_STRINGS_EQUAL(s, "|howdy|");
    1637                 :            : 
    1638 [ -  + ][ #  # ]:          6 :         TEST(db.synonyms_begin("goodbye") == db.synonyms_end("goodbye"));
    1639                 :            : 
    1640                 :          6 :         s = "|";
    1641                 :          6 :         t = db.synonym_keys_begin();
    1642         [ +  + ]:         12 :         while (t != db.synonym_keys_end()) {
    1643                 :          6 :             s += *t++;
    1644                 :          6 :             s += '|';
    1645                 :            :         }
    1646 [ -  + ][ #  # ]:          6 :         TEST_STRINGS_EQUAL(s, "|hello|");
    1647                 :            : 
    1648                 :          6 :         db.commit();
    1649                 :            :     }
    1650                 :            : 
    1651                 :          3 :     Xapian::Database db_multi;
    1652                 :          3 :     db_multi.add_database(db);
    1653                 :          3 :     db_multi.add_database(get_database("apitest_simpledata"));
    1654                 :            : 
    1655                 :            :     // Test iterators for terms which aren't there.
    1656 [ -  + ][ #  # ]:          3 :     TEST(db_multi.synonyms_begin("abc") == db_multi.synonyms_end("abc"));
    1657 [ -  + ][ #  # ]:          3 :     TEST(db_multi.synonyms_begin("ghi") == db_multi.synonyms_end("ghi"));
    1658 [ -  + ][ #  # ]:          3 :     TEST(db_multi.synonyms_begin("zzzzz") == db_multi.synonyms_end("zzzzz"));
    1659                 :            : 
    1660                 :          3 :     s = "|";
    1661                 :          3 :     t = db_multi.synonyms_begin("hello");
    1662         [ +  + ]:          6 :     while (t != db_multi.synonyms_end("hello")) {
    1663                 :          3 :         s += *t++;
    1664                 :          3 :         s += '|';
    1665                 :            :     }
    1666 [ -  + ][ #  # ]:          3 :     TEST_STRINGS_EQUAL(s, "|howdy|");
    1667                 :            : 
    1668 [ -  + ][ #  # ]:          3 :     TEST(db_multi.synonyms_begin("goodbye") == db_multi.synonyms_end("goodbye"));
    1669                 :            : 
    1670                 :          3 :     s = "|";
    1671                 :          3 :     t = db_multi.synonym_keys_begin();
    1672         [ +  + ]:          6 :     while (t != db_multi.synonym_keys_end()) {
    1673                 :          3 :         s += *t++;
    1674                 :          3 :         s += '|';
    1675                 :            :     }
    1676 [ -  + ][ #  # ]:          3 :     TEST_STRINGS_EQUAL(s, "|hello|");
    1677                 :            : 
    1678                 :          3 :     return true;
    1679                 :            : }
    1680                 :            : 
    1681                 :            : // Test that adding a document with a really long term gives an error on
    1682                 :            : // add_document() rather than on commit().
    1683                 :         10 : DEFINE_TESTCASE(termtoolong1, writable) {
    1684                 :            :     // Inmemory doesn't impose a limit.
    1685                 :         12 :     SKIP_TEST_FOR_BACKEND("inmemory");
    1686                 :            : 
    1687                 :          9 :     Xapian::WritableDatabase db = get_writable_database();
    1688                 :            : 
    1689         [ +  + ]:        414 :     for (Xapian::doccount i = 246; i <= 290; ++i) {
    1690                 :        405 :         tout.str(string());
    1691                 :        405 :         tout << "Term length " << i << endl;
    1692                 :        405 :         Xapian::Document doc;
    1693                 :        405 :         string term(i, 'X');
    1694                 :        405 :         doc.add_term(term);
    1695                 :            :         try {
    1696                 :        405 :             db.add_document(doc);
    1697         [ #  # ]:          0 :             TEST_AND_EXPLAIN(false, "Expecting exception InvalidArgumentError");
    1698                 :        810 :         } catch (const Xapian::InvalidArgumentError &e) {
    1699                 :            :             // Check that the max length is correctly expressed in the
    1700                 :            :             // exception message - we've got this wrong in two different ways
    1701                 :            :             // in the past!
    1702                 :        405 :             tout << e.get_msg() << endl;
    1703   [ -  +  #  # ]:        405 :             TEST(e.get_msg().find("Term too long (> 245)") != string::npos);
    1704                 :            :         }
    1705                 :            :     }
    1706                 :            : 
    1707         [ +  + ]:         63 :     for (Xapian::doccount j = 240; j <= 245; ++j) {
    1708                 :         54 :         tout.str(string());
    1709                 :         54 :         tout << "Term length " << j << endl;
    1710                 :         54 :         Xapian::Document doc;
    1711                 :         54 :         string term(j, 'X');
    1712                 :         54 :         doc.add_term(term);
    1713                 :         54 :         db.add_document(doc);
    1714                 :            :     }
    1715                 :            : 
    1716                 :          9 :     db.commit();
    1717                 :            : 
    1718                 :            :     {
    1719                 :            :         // Currently brass, flint and chert escape zero bytes from terms in
    1720                 :            :         // keys for some tables, so a term with 127 zero bytes won't work
    1721                 :            :         // either.
    1722                 :          9 :         Xapian::Document doc;
    1723                 :          9 :         doc.add_term(string(127, '\0'));
    1724                 :          9 :         db.add_document(doc);
    1725                 :            :         try {
    1726                 :          9 :             db.commit();
    1727         [ #  # ]:          0 :             TEST_AND_EXPLAIN(false, "Expecting exception InvalidArgumentError");
    1728                 :         18 :         } catch (const Xapian::InvalidArgumentError &e) {
    1729                 :            :             // Check that the max length is correctly expressed in the
    1730                 :            :             // exception message - we've got this wrong in two different ways
    1731                 :            :             // in the past!
    1732                 :          9 :             tout << e.get_msg() << endl;
    1733   [ -  +  #  # ]:          9 :             TEST(e.get_msg().find(" is 252 bytes") != string::npos);
    1734                 :          9 :         }
    1735                 :            :     }
    1736                 :            : 
    1737                 :          9 :     return true;
    1738                 :            : }
    1739                 :            : 
    1740                 :            : /// Test playing with a postlist
    1741                 :         10 : DEFINE_TESTCASE(postlist7, writable) {
    1742                 :         10 :     Xapian::WritableDatabase db_w = get_writable_database();
    1743                 :            : 
    1744                 :            :     {
    1745                 :         10 :         Xapian::Document doc;
    1746                 :         10 :         doc.add_term("foo", 3);
    1747                 :         10 :         doc.add_term("zz", 4);
    1748                 :         10 :         db_w.replace_document(5, doc);
    1749                 :            :     }
    1750                 :            : 
    1751                 :         10 :     Xapian::PostingIterator p;
    1752                 :         10 :     p = db_w.postlist_begin("foo");
    1753 [ -  + ][ #  # ]:         10 :     TEST(p != db_w.postlist_end("foo"));
    1754 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*p, 5);
    1755 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(p.get_wdf(), 3);
    1756 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(p.get_doclength(), 7);
    1757                 :         10 :     ++p;
    1758 [ -  + ][ #  # ]:         10 :     TEST(p == db_w.postlist_end("foo"));
    1759                 :            : 
    1760                 :            :     {
    1761                 :         10 :         Xapian::Document doc;
    1762                 :         10 :         doc.add_term("foo", 1);
    1763                 :         10 :         doc.add_term("zz", 1);
    1764                 :         10 :         db_w.replace_document(6, doc);
    1765                 :            :     }
    1766                 :            : 
    1767                 :         10 :     p = db_w.postlist_begin("foo");
    1768 [ -  + ][ #  # ]:         10 :     TEST(p != db_w.postlist_end("foo"));
    1769 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*p, 5);
    1770 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(p.get_wdf(), 3);
    1771 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(p.get_doclength(), 7);
    1772                 :         10 :     ++p;
    1773 [ -  + ][ #  # ]:         10 :     TEST(p != db_w.postlist_end("foo"));
    1774 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*p, 6);
    1775 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(p.get_wdf(), 1);
    1776 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(p.get_doclength(), 2);
    1777                 :         10 :     ++p;
    1778 [ -  + ][ #  # ]:         10 :     TEST(p == db_w.postlist_end("foo"));
    1779                 :            : 
    1780                 :         10 :     return true;
    1781                 :            : }
    1782                 :            : 
    1783                 :          3 : DEFINE_TESTCASE(lazytablebug1, brass || chert || flint) {
    1784                 :            :     {
    1785                 :          3 :         Xapian::WritableDatabase db = get_named_writable_database("lazytablebug1", string());
    1786                 :            : 
    1787                 :          3 :         Xapian::Document doc;
    1788                 :          3 :         doc.add_term("foo");
    1789                 :          3 :         db.add_document(doc);
    1790                 :          3 :         db.commit();
    1791                 :            : 
    1792                 :          3 :         string synonym(255, 'x');
    1793                 :          3 :         char buf[] = " iamafish!!!!!!!!!!";
    1794         [ +  + ]:        264 :         for (int i = 33; i < 120; ++i) {
    1795                 :        261 :             db.add_synonym(buf, synonym);
    1796                 :        261 :             ++buf[0];
    1797                 :            :         }
    1798                 :            : 
    1799                 :          3 :         db.commit();
    1800                 :            :     }
    1801                 :            : 
    1802                 :          3 :     Xapian::Database db = get_writable_database_as_database();
    1803         [ +  + ]:        264 :     for (Xapian::TermIterator t = db.synonym_keys_begin(); t != db.synonym_keys_end(); ++t) {
    1804                 :        261 :         tout << *t << endl;
    1805                 :          3 :     }
    1806                 :            : 
    1807                 :          3 :     return true;
    1808                 :            : }
    1809                 :            : 
    1810                 :            : /** Regression test for bug #287 for flint.
    1811                 :            :  *
    1812                 :            :  *  Chert also has the same duff code but this testcase doesn't actually 
    1813                 :            :  *  tickle the bug there.
    1814                 :            :  */
    1815                 :          3 : DEFINE_TESTCASE(cursordelbug1, brass || chert || flint) {
    1816                 :            :     static const int terms[] = { 219, 221, 222, 223, 224, 225, 226 };
    1817                 :            :     static const int copies[] = { 74, 116, 199, 21, 45, 155, 189 };
    1818                 :            : 
    1819                 :          3 :     Xapian::WritableDatabase db;
    1820                 :          3 :     db = get_named_writable_database("cursordelbug1", string());
    1821                 :            : 
    1822         [ +  + ]:         24 :     for (size_t i = 0; i < sizeof(terms) / sizeof(terms[0]); ++i) {
    1823                 :         21 :         Xapian::Document doc;
    1824                 :         21 :         doc.add_term("XC" + str(terms[i]));
    1825                 :         21 :         doc.add_term("XTabc");
    1826                 :         21 :         doc.add_term("XAdef");
    1827                 :         21 :         doc.add_term("XRghi");
    1828                 :         21 :         doc.add_term("XYabc");
    1829                 :         21 :         size_t c = copies[i];
    1830         [ +  + ]:       2418 :         while (c--) db.add_document(doc);
    1831                 :            :     }
    1832                 :            : 
    1833                 :          3 :     db.commit();
    1834                 :            : 
    1835         [ +  + ]:         24 :     for (size_t i = 0; i < sizeof(terms) / sizeof(terms[0]); ++i) {
    1836                 :         21 :         db.delete_document("XC" + str(terms[i]));
    1837                 :            :     }
    1838                 :            : 
    1839                 :          3 :     db.commit();
    1840                 :            : 
    1841                 :          3 :     string cmd = XAPIAN_BIN_PATH"xapian-check ";
    1842                 :          3 :     cmd += get_named_writable_database_path("cursordelbug1");
    1843                 :            : #ifdef __WIN32__
    1844                 :            :     cmd += " >nul";
    1845                 :            : #else
    1846                 :          3 :     cmd += " >/dev/null";
    1847                 :            : #endif
    1848         [ -  + ]:          3 :     if (system(cmd.c_str()) != 0)
    1849                 :          0 :         return false;
    1850                 :            : 
    1851                 :          3 :     return true;
    1852                 :            : }
    1853                 :            : 
    1854                 :            : /** Helper function for modifyvalues1.
    1855                 :            :  *
    1856                 :            :  * Check that the values stored in the database match */
    1857                 :            : static void
    1858                 :        120 : check_vals(const Xapian::Database & db, const map<Xapian::docid, string> & vals)
    1859                 :            : {
    1860 [ -  + ][ #  # ]:        120 :     TEST_EQUAL(db.get_doccount(), vals.size());
    1861         [ -  + ]:        120 :     if (vals.size() == 0) return;
    1862 [ -  + ][ #  # ]:        120 :     TEST_REL(vals.rbegin()->first,<=,db.get_lastdocid());
    1863                 :        120 :     map<Xapian::docid, string>::const_iterator i;
    1864         [ +  + ]:     120120 :     for (i = vals.begin(); i != vals.end(); ++i) {
    1865                 :     120000 :         tout.str(string());
    1866                 :     120000 :         tout << "Checking value in doc " << i->first << " - should be '" << i->second << "'\n";
    1867                 :     120000 :         Xapian::Document doc = db.get_document(i->first);
    1868                 :     120000 :         string dbval = doc.get_value(1);
    1869   [ -  +  #  # ]:     120000 :         TEST_EQUAL(dbval, i->second);
    1870         [ +  + ]:     120000 :         if (dbval.empty()) {
    1871 [ -  + ][ #  # ]:      23420 :             TEST_EQUAL(0, doc.values_count());
    1872 [ -  + ][ #  # ]:      23420 :             TEST_EQUAL(doc.values_begin(), doc.values_end());
    1873                 :            :         } else {
    1874 [ -  + ][ #  # ]:      96580 :             TEST_EQUAL(1, doc.values_count());
    1875                 :      96580 :             Xapian::ValueIterator valit = doc.values_begin();
    1876   [ -  +  #  # ]:      96580 :             TEST_NOT_EQUAL(valit, doc.values_end());
    1877 [ -  + ][ #  # ]:      96580 :             TEST_EQUAL(dbval, *valit);
    1878 [ -  + ][ #  # ]:      96580 :             TEST_EQUAL(1, valit.get_valueno());
    1879                 :      96580 :             ++valit;
    1880   [ -  +  #  # ]:      96580 :             TEST_EQUAL(valit, doc.values_end());
    1881                 :            :         }
    1882                 :            :     }
    1883                 :            : }
    1884                 :            : 
    1885                 :            : /** Regression test for bug in initial streaming values implementation in
    1886                 :            :  *  chert.
    1887                 :            :  */
    1888                 :         10 : DEFINE_TESTCASE(modifyvalues1, writable) {
    1889                 :         10 :     unsigned int seed = 7;
    1890                 :         10 :     Xapian::WritableDatabase db = get_writable_database();
    1891                 :            :     // Note: doccount must be coprime with 13
    1892                 :         10 :     const Xapian::doccount doccount = 1000;
    1893                 :            :     STATIC_ASSERT(doccount % 13 != 0);
    1894                 :            : 
    1895                 :         10 :     map<Xapian::docid, string> vals;
    1896                 :            : 
    1897         [ +  + ]:      10010 :     for (Xapian::doccount num = 1; num <= doccount; ++num) {
    1898                 :      10000 :         tout.str(string());
    1899                 :      10000 :         Xapian::Document doc;
    1900                 :      10000 :         string val = "val" + str(num);
    1901                 :      10000 :         tout << "Setting val '" << val << "' in doc " << num << "\n";
    1902                 :      10000 :         doc.add_value(1, val);
    1903                 :      10000 :         db.add_document(doc);
    1904                 :      10000 :         vals[num] = val;
    1905                 :            :     }
    1906                 :         10 :     check_vals(db, vals);
    1907                 :         10 :     db.commit();
    1908                 :         10 :     check_vals(db, vals);
    1909                 :            : 
    1910                 :            :     // Modify one of the values (this is a regression test which failed with
    1911                 :            :     // the initial implementation of streaming values).
    1912                 :            :     {
    1913                 :         10 :         Xapian::Document doc;
    1914                 :         10 :         string val = "newval0";
    1915                 :         10 :         tout << "Setting val '" << val << "' in doc 2\n";
    1916                 :         10 :         doc.add_value(1, val);
    1917                 :         10 :         db.replace_document(2, doc);
    1918                 :         10 :         vals[2] = val;
    1919                 :         10 :         check_vals(db, vals);
    1920                 :         10 :         db.commit();
    1921                 :         10 :         check_vals(db, vals);
    1922                 :            :     }
    1923                 :            : 
    1924                 :            :     // Check that value doesn't get lost when replacing a document with itself.
    1925                 :            :     {
    1926                 :         10 :         tout << "Replacing document 1 with itself\n";
    1927                 :         10 :         Xapian::Document doc = db.get_document(1);
    1928                 :         10 :         db.replace_document(1, doc);
    1929                 :         10 :         check_vals(db, vals);
    1930                 :         10 :         db.commit();
    1931                 :         10 :         check_vals(db, vals);
    1932                 :            :     }
    1933                 :            : 
    1934                 :            :     // Check that value doesn't get lost when replacing a document with itself,
    1935                 :            :     // accessing another document in the meantime.  This is a regression test
    1936                 :            :     // for a bug in the code which implements lazy updates - this used to
    1937                 :            :     // forget the values in the document in this situation.
    1938                 :            :     {
    1939                 :         10 :         tout << "Replacing document 1 with itself, after reading doc 2.\n";
    1940                 :         10 :         Xapian::Document doc = db.get_document(1);
    1941                 :         10 :         db.get_document(2);
    1942                 :         10 :         db.replace_document(1, doc);
    1943                 :         10 :         check_vals(db, vals);
    1944                 :         10 :         db.commit();
    1945                 :         10 :         check_vals(db, vals);
    1946                 :            :     }
    1947                 :            : 
    1948                 :            :     // Do some random modifications: seed random generator, for repeatable
    1949                 :            :     // results.
    1950                 :         10 :     tout << "Setting seed to " << seed << "\n";
    1951                 :         10 :     srand(seed);
    1952         [ +  + ]:      20010 :     for (Xapian::doccount num = 1; num <= doccount * 2; ++num) {
    1953                 :      20000 :         tout.str(string());
    1954                 :      20000 :         Xapian::docid did = ((rand() >> 8) % doccount) + 1;
    1955                 :      20000 :         Xapian::Document doc;
    1956                 :      20000 :         string val;
    1957                 :            : 
    1958         [ +  + ]:      20000 :         if (num % 5 != 0) {
    1959                 :      16000 :             val = "newval" + str(num);
    1960                 :      16000 :             tout << "Setting val '" << val << "' in doc " << did << "\n";
    1961                 :      16000 :             doc.add_value(1, val);
    1962                 :            :         } else {
    1963                 :       4000 :             tout << "Adding/replacing empty document " << did << "\n";
    1964                 :            :         }
    1965                 :      20000 :         db.replace_document(did, doc);
    1966                 :      20000 :         vals[did] = val;
    1967                 :            :     }
    1968                 :         10 :     check_vals(db, vals);
    1969                 :         10 :     db.commit();
    1970                 :         10 :     check_vals(db, vals);
    1971                 :            : 
    1972                 :            :     // Delete all the remaining values, in a slightly shuffled order.
    1973                 :            :     // This is where it's important that doccount is coprime with 13.
    1974         [ +  + ]:      10010 :     for (Xapian::doccount num = 0; num < doccount * 13; num += 13) {
    1975                 :      10000 :         tout.str(string());
    1976                 :      10000 :         Xapian::docid did = (num % doccount) + 1;
    1977                 :      10000 :         tout << "Clearing val in doc " << did << "\n";
    1978                 :      10000 :         Xapian::Document doc;
    1979                 :      10000 :         db.replace_document(did, doc);
    1980                 :      10000 :         vals[did] = string();
    1981                 :            :     }
    1982                 :         10 :     check_vals(db, vals);
    1983                 :         10 :     db.commit();
    1984                 :         10 :     check_vals(db, vals);
    1985                 :            : 
    1986                 :         10 :     return true;
    1987                 :            : }

Generated by: LCOV version 1.8