LCOV - code coverage report
Current view: top level - home/olly/git/atia-xapian/xapian-core/tests - dbcheck.cc (source / functions) Hit Total Coverage
Test: Test Coverage for xapian-core r Lines: 173 177 97.7 %
Date: 2011-08-21 Functions: 7 7 100.0 %
Branches: 88 184 47.8 %

           Branch data     Line data    Source code
       1                 :            : /* dbcheck.cc: test database contents and consistency.
       2                 :            :  *
       3                 :            :  * Copyright 2009 Richard Boulton
       4                 :            :  * Copyright 2010 Olly Betts
       5                 :            :  *
       6                 :            :  * This program is free software; you can redistribute it and/or
       7                 :            :  * modify it under the terms of the GNU General Public License as
       8                 :            :  * published by the Free Software Foundation; either version 2 of the
       9                 :            :  * License, or (at your option) any later version.
      10                 :            :  *
      11                 :            :  * This program is distributed in the hope that it will be useful,
      12                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14                 :            :  * GNU General Public License for more details.
      15                 :            :  *
      16                 :            :  * You should have received a copy of the GNU General Public License
      17                 :            :  * along with this program; if not, write to the Free Software
      18                 :            :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
      19                 :            :  * USA
      20                 :            :  */
      21                 :            : 
      22                 :            : #include <config.h>
      23                 :            : 
      24                 :            : #include "dbcheck.h"
      25                 :            : 
      26                 :            : #include "str.h"
      27                 :            : #include "testsuite.h"
      28                 :            : 
      29                 :            : using namespace std;
      30                 :            : 
      31                 :            : string
      32                 :     103253 : positions_to_string(Xapian::PositionIterator & it,
      33                 :            :                     const Xapian::PositionIterator & end,
      34                 :            :                     Xapian::termcount * count)
      35                 :            : {
      36                 :     103253 :     string result;
      37                 :     103253 :     bool need_comma = false;
      38                 :     103253 :     Xapian::termcount c = 0;
      39         [ +  + ]:     116165 :     while (it != end) {
      40         [ +  + ]:      12912 :         if (need_comma)
      41                 :       2466 :             result += ", ";
      42                 :      12912 :         result += str(*it);
      43                 :      12912 :         need_comma = true;
      44                 :      12912 :         ++it;
      45                 :      12912 :         ++c;
      46                 :            :     }
      47         [ +  + ]:     103253 :     if (count) {
      48                 :     103253 :         *count = c;
      49                 :            :     }
      50                 :          0 :     return result;
      51                 :            : }
      52                 :            : 
      53                 :            : string
      54                 :        192 : postlist_to_string(const Xapian::Database & db, const string & tname)
      55                 :            : {
      56                 :        192 :     string result;
      57                 :        192 :     bool need_comma = false;
      58                 :            : 
      59         [ +  + ]:        602 :     for (Xapian::PostingIterator p = db.postlist_begin(tname);
      60                 :            :          p != db.postlist_end(tname);
      61                 :            :          ++p) {
      62         [ +  + ]:        410 :         if (need_comma)
      63                 :        228 :             result += ", ";
      64                 :            : 
      65                 :        410 :         Xapian::PositionIterator it(p.positionlist_begin());
      66                 :        410 :         string posrepr = positions_to_string(it, p.positionlist_end());
      67         [ +  + ]:        410 :         if (!posrepr.empty()) {
      68                 :        316 :             posrepr = ", pos=[" + posrepr + "]";
      69                 :            :         }
      70                 :            : 
      71                 :            :         result += "(" + str(*p) +
      72                 :            :                 ", doclen=" + str(p.get_doclength()) +
      73                 :            :                 ", wdf=" + str(p.get_wdf()) +
      74                 :        410 :                 posrepr + ")";
      75                 :        410 :         need_comma = true;
      76                 :        192 :     }
      77                 :          0 :     return result;
      78                 :            : }
      79                 :            : 
      80                 :            : string
      81                 :        260 : docterms_to_string(const Xapian::Database & db, Xapian::docid did)
      82                 :            : {
      83                 :        260 :     string result;
      84                 :        260 :     bool need_comma = false;
      85                 :            : 
      86         [ +  + ]:        920 :     for (Xapian::TermIterator t = db.termlist_begin(did);
      87                 :            :          t != db.termlist_end(did);
      88                 :            :          ++t) {
      89                 :        660 :         Xapian::PositionIterator it(t.positionlist_begin());
      90                 :        660 :         string posrepr = positions_to_string(it, t.positionlist_end());
      91         [ +  + ]:        660 :         if (!posrepr.empty()) {
      92                 :         80 :             posrepr = ", pos=[" + posrepr + "]";
      93                 :            :         }
      94         [ +  + ]:        660 :         if (need_comma)
      95                 :        410 :             result += ", ";
      96                 :        660 :         result += "Term(" + *t + ", wdf=" + str(t.get_wdf()) + posrepr + ")";
      97                 :        660 :         need_comma = true;
      98                 :        250 :     }
      99                 :         10 :     return result;
     100                 :            : }
     101                 :            : 
     102                 :            : string
     103                 :         10 : docstats_to_string(const Xapian::Database & db, Xapian::docid did)
     104                 :            : {
     105                 :         10 :     string result;
     106                 :            : 
     107                 :         10 :     result += "len=" + str(db.get_doclength(did));
     108                 :            : 
     109                 :         10 :     return result;
     110                 :            : }
     111                 :            : 
     112                 :            : string
     113                 :         10 : termstats_to_string(const Xapian::Database & db, const string & term)
     114                 :            : {
     115                 :         10 :     string result;
     116                 :            : 
     117                 :         10 :     result += "tf=" + str(db.get_termfreq(term));
     118                 :         10 :     result += ",cf=" + str(db.get_collection_freq(term));
     119                 :            : 
     120                 :          0 :     return result;
     121                 :            : }
     122                 :            : 
     123                 :            : string
     124                 :         10 : dbstats_to_string(const Xapian::Database & db)
     125                 :            : {
     126                 :         10 :     string result;
     127                 :            : 
     128                 :         10 :     result += "dc=" + str(db.get_doccount());
     129                 :         10 :     result += ",al=" + str(db.get_avlength());
     130                 :         10 :     result += ",ld=" + str(db.get_lastdocid());
     131                 :            : 
     132                 :          0 :     return result;
     133                 :            : }
     134                 :            : 
     135                 :            : void
     136                 :        262 : dbcheck(const Xapian::Database & db,
     137                 :            :         Xapian::doccount expected_doccount,
     138                 :            :         Xapian::docid expected_lastdocid)
     139                 :            : {
     140 [ -  + ][ #  # ]:        262 :     TEST_EQUAL(db.get_doccount(), expected_doccount);
     141 [ -  + ][ #  # ]:        262 :     TEST_EQUAL(db.get_lastdocid(), expected_lastdocid);
     142                 :            : 
     143                 :            :     // Note - may not be a very big type, but we're only expecting to use this
     144                 :            :     // for small databases, so should be fine.
     145                 :        262 :     unsigned long totlen = 0;
     146                 :            : 
     147                 :            :     // A map from term to a representation of the posting list for that term.
     148                 :            :     // We build this up from the documents, and then check it against the
     149                 :            :     // equivalent built up from the posting lists.
     150                 :        262 :     map<string, string> posting_reprs;
     151                 :        262 :     map<Xapian::valueno, string> value_reprs;
     152                 :            : 
     153                 :        262 :     Xapian::termcount doclen_lower_bound = Xapian::termcount(-1);
     154                 :        262 :     Xapian::termcount doclen_upper_bound = 0;
     155                 :            : 
     156         [ +  + ]:      30775 :     for (Xapian::PostingIterator dociter = db.postlist_begin(string());
     157                 :            :          dociter != db.postlist_end(string());
     158                 :            :          ++dociter) {
     159                 :      30513 :         Xapian::docid did = *dociter;
     160   [ -  +  #  # ]:      30513 :         TEST_EQUAL(dociter.get_wdf(), 1);
     161                 :      30513 :         Xapian::Document doc(db.get_document(did));
     162                 :      30513 :         Xapian::termcount doclen(db.get_doclength(did));
     163         [ +  + ]:      30513 :         if (doclen < doclen_lower_bound)
     164                 :        267 :             doclen_lower_bound = doclen;
     165         [ +  + ]:      30513 :         if (doclen > doclen_upper_bound)
     166                 :        281 :             doclen_upper_bound = doclen;
     167                 :      30513 :         totlen += doclen;
     168                 :            : 
     169                 :      30513 :         Xapian::termcount found_termcount = 0;
     170                 :      30513 :         Xapian::termcount wdf_sum = 0;
     171                 :      30513 :         Xapian::TermIterator t, t2;
     172         [ +  + ]:      64574 :         for (t = doc.termlist_begin(), t2 = db.termlist_begin(did);
     173                 :            :              t != doc.termlist_end();
     174                 :            :              ++t, ++t2) {
     175 [ -  + ][ #  # ]:      34061 :             TEST(t2 != db.termlist_end(did));
     176                 :            : 
     177                 :      34061 :             ++found_termcount;
     178                 :      34061 :             wdf_sum += t.get_wdf();
     179                 :            : 
     180 [ -  + ][ #  # ]:      34061 :             TEST_EQUAL(*t, *t2);
     181 [ -  + ][ #  # ]:      34061 :             TEST_EQUAL(t.get_wdf(), t2.get_wdf());
     182 [ -  + ][ #  # ]:      34061 :             TEST_EQUAL(db.get_termfreq(*t), t.get_termfreq());
     183 [ -  + ][ #  # ]:      34061 :             TEST_EQUAL(db.get_termfreq(*t), t2.get_termfreq());
     184                 :            : 
     185                 :            :             // Check the position lists are equal.
     186                 :            :             Xapian::termcount tc1, tc2;
     187                 :      34061 :             Xapian::PositionIterator it1(t.positionlist_begin());
     188                 :      34061 :             string posrepr = positions_to_string(it1, t.positionlist_end(), &tc1);
     189                 :      34061 :             Xapian::PositionIterator it2(t2.positionlist_begin());
     190                 :      34061 :             string posrepr2 = positions_to_string(it2, t2.positionlist_end(), &tc2);
     191   [ -  +  #  # ]:      34061 :             TEST_EQUAL(posrepr, posrepr2);
     192 [ -  + ][ #  # ]:      34061 :             TEST_EQUAL(tc1, tc2);
     193                 :            :             try {
     194 [ -  + ][ #  # ]:      34061 :                 TEST_EQUAL(tc1, t.positionlist_count());
     195                 :        330 :             } catch (const Xapian::UnimplementedError &) {
     196                 :            :                 // positionlist_count() isn't implemented for remote databases.
     197                 :            :             }
     198                 :            : 
     199                 :            :             // Make a representation of the posting.
     200         [ +  + ]:      34061 :             if (!posrepr.empty()) {
     201                 :       3350 :                 posrepr = ",[" + posrepr + "]";
     202                 :            :             }
     203                 :            :             string posting_repr = "(" + str(did) + "," +
     204                 :            :                     str(t.get_wdf()) + "/" + str(doclen) +
     205                 :      34061 :                     posrepr + ")";
     206                 :            : 
     207                 :            :             // Append the representation to the list for the term.
     208                 :      34061 :             map<string, string>::iterator i = posting_reprs.find(*t);
     209         [ +  + ]:      34061 :             if (i == posting_reprs.end()) {
     210                 :       2477 :                 posting_reprs[*t] = posting_repr;
     211                 :            :             } else {
     212                 :      31584 :                 i->second += "," + posting_repr;
     213                 :            :             }
     214                 :            :         }
     215                 :            : 
     216                 :      30513 :         Xapian::termcount vcount = 0;
     217         [ +  + ]:      32361 :         for (Xapian::ValueIterator v = doc.values_begin();
     218                 :            :              v != doc.values_end();
     219                 :            :              ++v, ++vcount) {
     220 [ -  + ][ #  # ]:       1848 :             TEST((*v).size() != 0);
     221                 :       1848 :             string value_repr = "(" + str(did) + "," + *v + ")";
     222                 :            : 
     223                 :            :             // Append the values to the value lists.
     224                 :       1848 :             map<Xapian::valueno, string>::iterator i;
     225                 :       1848 :             i = value_reprs.find(v.get_valueno());
     226         [ +  + ]:       1848 :             if (i == value_reprs.end()) {
     227                 :        210 :                 value_reprs[v.get_valueno()] = value_repr;
     228                 :            :             } else {
     229                 :       1638 :                 i->second += "," + value_repr;
     230                 :            :             }
     231                 :      30513 :         }
     232   [ -  +  #  # ]:      30513 :         TEST_EQUAL(vcount, doc.values_count());
     233 [ -  + ][ #  # ]:      30513 :         TEST(t2 == db.termlist_end(did));
     234                 :      30513 :         Xapian::termcount expected_termcount = doc.termlist_count();
     235   [ -  +  #  # ]:      30513 :         TEST_EQUAL(expected_termcount, found_termcount);
     236 [ -  + ][ #  # ]:      30513 :         TEST_EQUAL(doclen, wdf_sum);
     237                 :        262 :     }
     238                 :            : 
     239   [ -  +  #  # ]:        262 :     TEST_REL(doclen_lower_bound, >=, db.get_doclength_lower_bound());
     240 [ -  + ][ #  # ]:        262 :     TEST_REL(doclen_upper_bound, <=, db.get_doclength_upper_bound());
     241                 :            : 
     242                 :        262 :     Xapian::TermIterator t;
     243                 :        262 :     map<string, string>::const_iterator i;
     244         [ +  + ]:       2739 :     for (t = db.allterms_begin(), i = posting_reprs.begin();
     245                 :            :          t != db.allterms_end();
     246                 :            :          ++t, ++i) {
     247 [ -  + ][ #  # ]:       2477 :         TEST(db.term_exists(*t));
     248 [ -  + ][ #  # ]:       2477 :         TEST(i != posting_reprs.end());
     249 [ -  + ][ #  # ]:       2477 :         TEST_EQUAL(i->first, *t);
     250                 :            : 
     251                 :       2477 :         Xapian::doccount tf_count = 0;
     252                 :       2477 :         Xapian::termcount cf_count = 0;
     253                 :       2477 :         Xapian::termcount wdf_upper_bound = 0;
     254                 :       2477 :         string posting_repr;
     255                 :       2477 :         bool need_comma = false;
     256         [ +  + ]:      36538 :         for (Xapian::PostingIterator p = db.postlist_begin(*t);
     257                 :            :              p != db.postlist_end(*t);
     258                 :            :              ++p) {
     259         [ +  + ]:      34061 :             if (need_comma) {
     260                 :      31584 :                 posting_repr += ",";
     261                 :            :             }
     262                 :            : 
     263                 :      34061 :             ++tf_count;
     264                 :      34061 :             cf_count += p.get_wdf();
     265                 :            : 
     266                 :      34061 :             Xapian::PositionIterator it(p.positionlist_begin());
     267                 :      34061 :             string posrepr = positions_to_string(it, p.positionlist_end());
     268         [ +  + ]:      34061 :             if (!posrepr.empty()) {
     269                 :       3350 :                 posrepr = ",[" + posrepr + "]";
     270                 :            :             }
     271                 :            :             posting_repr += "(" + str(*p) + "," +
     272                 :            :                     str(p.get_wdf()) + "/" + str(p.get_doclength()) +
     273                 :      34061 :                     posrepr + ")";
     274         [ +  + ]:      34061 :             if (wdf_upper_bound < p.get_wdf())
     275                 :       2394 :                 wdf_upper_bound = p.get_wdf();
     276                 :      34061 :             need_comma = true;
     277                 :       2477 :         }
     278                 :            : 
     279   [ -  +  #  # ]:       2477 :         TEST_EQUAL(posting_repr, i->second);
     280 [ -  + ][ #  # ]:       2477 :         TEST_EQUAL(tf_count, t.get_termfreq());
     281 [ -  + ][ #  # ]:       2477 :         TEST_EQUAL(tf_count, db.get_termfreq(*t));
     282 [ -  + ][ #  # ]:       2477 :         TEST_EQUAL(cf_count, db.get_collection_freq(*t));
     283 [ -  + ][ #  # ]:       2477 :         TEST_REL(wdf_upper_bound, <=, db.get_wdf_upper_bound(*t));
     284                 :            :     }
     285 [ -  + ][ #  # ]:        262 :     TEST(i == posting_reprs.end());
     286                 :            : 
     287                 :        262 :     map<Xapian::valueno, string>::const_iterator j;
     288         [ +  + ]:        472 :     for (j = value_reprs.begin(); j != value_reprs.end(); ++j) {
     289                 :        210 :         string value_repr;
     290                 :        210 :         string value_lower_bound;
     291                 :        210 :         string value_upper_bound;
     292                 :        210 :         bool first = true;
     293         [ +  + ]:       2058 :         for (Xapian::ValueIterator v = db.valuestream_begin(j->first);
     294                 :            :              v != db.valuestream_end(j->first); ++v) {
     295         [ +  + ]:       1848 :             if (first) {
     296                 :        210 :                 value_lower_bound = *v;
     297                 :        210 :                 value_upper_bound = *v;
     298                 :        210 :                 first = false;
     299                 :            :             } else {
     300                 :       1638 :                 value_repr += ",";
     301         [ +  + ]:       1638 :                 if (*v > value_upper_bound) {
     302                 :        261 :                     value_upper_bound = *v;
     303                 :            :                 }
     304         [ +  + ]:       1638 :                 if (*v < value_lower_bound) {
     305                 :        234 :                     value_lower_bound = *v;
     306                 :            :                 }
     307                 :            :             }
     308                 :       1848 :             value_repr += "(" + str(v.get_docid()) + "," + *v + ")";
     309                 :        210 :         }
     310   [ -  +  #  # ]:        210 :         TEST_EQUAL(value_repr, j->second);
     311                 :            :         try {
     312 [ -  + ][ #  # ]:        210 :             TEST_REL(value_upper_bound, <=, db.get_value_upper_bound(j->first));
     313 [ -  + ][ #  # ]:        140 :             TEST_REL(value_lower_bound, >=, db.get_value_lower_bound(j->first));
     314                 :         70 :         } catch (const Xapian::UnimplementedError &) {
     315                 :            :             // Skip the checks if the methods to get the bounds aren't
     316                 :            :             // implemented for this backend.
     317                 :            :         }
     318                 :            :     }
     319                 :            : 
     320         [ +  + ]:        262 :     if (expected_doccount == 0) {
     321 [ -  + ][ #  # ]:         10 :         TEST_EQUAL(0, db.get_avlength());
     322                 :            :     } else {
     323 [ -  + ][ #  # ]:        252 :         TEST_EQUAL_DOUBLE(double(totlen) / expected_doccount,
     324                 :            :                           db.get_avlength());
     325                 :        262 :     }
     326                 :        262 : }

Generated by: LCOV version 1.8