LCOV - code coverage report
Current view: top level - tests - api_percentages.cc (source / functions) Hit Total Coverage
Test: Test Coverage for xapian-core 954b5873a738 Lines: 192 195 98.5 %
Date: 2019-06-30 05:20:33 Functions: 31 32 96.9 %
Branches: 288 1196 24.1 %

           Branch data     Line data    Source code
       1                 :            : /** @file api_percentages.cc
       2                 :            :  * @brief Tests of percentage calculations.
       3                 :            :  */
       4                 :            : /* Copyright (C) 2008,2009 Lemur Consulting Ltd
       5                 :            :  * Copyright (C) 2008,2009,2010,2011,2012,2014 Olly Betts
       6                 :            :  *
       7                 :            :  * This program is free software; you can redistribute it and/or modify
       8                 :            :  * it under the terms of the GNU General Public License as published by
       9                 :            :  * the Free Software Foundation; either version 2 of the License, or
      10                 :            :  * (at your option) any later version.
      11                 :            :  *
      12                 :            :  * This program is distributed in the hope that it will be useful,
      13                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15                 :            :  * GNU General Public License for more details.
      16                 :            :  *
      17                 :            :  * You should have received a copy of the GNU General Public License
      18                 :            :  * along with this program; if not, write to the Free Software
      19                 :            :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
      20                 :            :  */
      21                 :            : 
      22                 :            : #include <config.h>
      23                 :            : 
      24                 :            : #include "api_percentages.h"
      25                 :            : 
      26                 :            : #include <xapian.h>
      27                 :            : 
      28                 :            : #include "apitest.h"
      29                 :            : #include "backendmanager_local.h"
      30                 :            : #include "str.h"
      31                 :            : #include "testutils.h"
      32                 :            : 
      33                 :            : #include <cfloat>
      34                 :            : 
      35                 :            : using namespace std;
      36                 :            : 
      37                 :            : // Test that percentages reported are the same regardless of which part of the
      38                 :            : // mset is returned, for sort-by-value search.  Regression test for bug#216 in
      39                 :            : // 1.0.10 and earlier with returned percentages.
      40                 :          7 : DEFINE_TESTCASE(consistency3, backend) {
      41 [ +  - ][ +  - ]:          7 :     Xapian::Database db(get_database("apitest_sortconsist"));
      42         [ +  - ]:         14 :     Xapian::Enquire enquire(db);
      43 [ +  - ][ +  - ]:          7 :     enquire.set_query(Xapian::Query("foo"));
                 [ +  - ]
      44         [ +  - ]:          7 :     enquire.set_sort_by_value(1, 0);
      45                 :          7 :     Xapian::doccount lots = 3;
      46         [ +  - ]:         14 :     Xapian::MSet bigmset = enquire.get_mset(0, lots);
      47 [ +  - ][ -  + ]:          7 :     TEST_EQUAL(bigmset.size(), lots);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
      48         [ +  + ]:         28 :     for (Xapian::doccount start = 0; start < lots; ++start) {
      49 [ +  - ][ +  - ]:         42 :         tout << *bigmset[start] << ":" << bigmset[start].get_weight() << ":"
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
      50 [ +  - ][ +  - ]:         63 :              << bigmset[start].get_percent() << "%" << endl;
         [ +  - ][ +  - ]
                 [ +  - ]
      51         [ +  + ]:         63 :         for (Xapian::doccount size = 0; size < lots - start; ++size) {
      52         [ +  - ]:         42 :             Xapian::MSet mset = enquire.get_mset(start, size);
      53 [ +  - ][ +  + ]:         42 :             if (mset.size()) {
      54 [ +  - ][ +  - ]:         21 :                 TEST_EQUAL(start + mset.size(),
         [ -  + ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
      55                 :            :                            min(start + size, bigmset.size()));
      56         [ -  + ]:         21 :             } else if (size) {
      57 [ #  # ][ #  # ]:          0 :                 TEST(start >= bigmset.size());
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
      58                 :            :             }
      59 [ +  - ][ +  + ]:         70 :             for (Xapian::doccount i = 0; i < mset.size(); ++i) {
      60 [ +  - ][ +  - ]:         28 :                 TEST_EQUAL(*mset[i], *bigmset[start + i]);
         [ +  - ][ +  - ]
         [ -  + ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
      61 [ +  - ][ +  - ]:         28 :                 TEST_EQUAL_DOUBLE(mset[i].get_weight(),
         [ +  - ][ +  - ]
         [ +  - ][ -  + ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
      62                 :            :                                   bigmset[start + i].get_weight());
      63 [ +  - ][ +  - ]:         28 :                 TEST_EQUAL_DOUBLE(mset[i].get_percent(),
         [ +  - ][ +  - ]
         [ +  - ][ -  + ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
      64                 :            :                                   bigmset[start + i].get_percent());
      65                 :            :             }
      66                 :         42 :         }
      67                 :            :     }
      68                 :          7 :     return true;
      69                 :            : }
      70                 :            : 
      71         [ -  + ]:       4608 : class MyPostingSource : public Xapian::PostingSource {
      72                 :            :     vector<pair<Xapian::docid, double>> weights;
      73                 :            :     vector<pair<Xapian::docid, double>>::const_iterator i;
      74                 :            :     bool started;
      75                 :            : 
      76                 :        924 :     MyPostingSource(const vector<pair<Xapian::docid, double>>& weights_,
      77                 :            :                     double max_wt)
      78         [ +  - ]:        924 :         : weights(weights_), started(false)
      79                 :            :     {
      80         [ +  - ]:        924 :         set_maxweight(max_wt);
      81                 :        924 :     }
      82                 :            : 
      83                 :            :   public:
      84                 :        912 :     MyPostingSource() : started(false) { }
      85                 :            : 
      86                 :        924 :     PostingSource * clone() const
      87                 :            :     {
      88         [ +  - ]:        924 :         return new MyPostingSource(weights, get_maxweight());
      89                 :            :     }
      90                 :            : 
      91                 :        924 :     void append_docweight(Xapian::docid did, double wt) {
      92         [ +  - ]:        924 :         weights.push_back(make_pair(did, wt));
      93         [ +  + ]:        924 :         if (wt > get_maxweight()) set_maxweight(wt);
      94                 :        924 :     }
      95                 :            : 
      96                 :        468 :     void init(const Xapian::Database &) { started = false; }
      97                 :            : 
      98                 :       1968 :     double get_weight() const { return i->second; }
      99                 :            : 
     100                 :        936 :     Xapian::doccount get_termfreq_min() const { return weights.size(); }
     101                 :        936 :     Xapian::doccount get_termfreq_est() const { return weights.size(); }
     102                 :        936 :     Xapian::doccount get_termfreq_max() const { return weights.size(); }
     103                 :            : 
     104                 :       1452 :     void next(double /*wt*/) {
     105         [ +  + ]:       1452 :         if (!started) {
     106                 :        468 :             i = weights.begin();
     107                 :        468 :             started = true;
     108                 :            :         } else {
     109                 :        984 :             ++i;
     110                 :            :         }
     111                 :       1452 :     }
     112                 :            : 
     113                 :       1452 :     bool at_end() const {
     114                 :       1452 :         return (i == weights.end());
     115                 :            :     }
     116                 :            : 
     117                 :       1968 :     Xapian::docid get_docid() const { return i->first; }
     118                 :            : 
     119                 :          0 :     string get_description() const {
     120         [ #  # ]:          0 :         return "MyPostingSource";
     121                 :            :     }
     122                 :            : };
     123                 :            : 
     124                 :            : /// Test for rounding errors in percentage weight calculations and cutoffs.
     125                 :          4 : DEFINE_TESTCASE(pctcutoff4, backend && !remote && !multi) {
     126                 :            :     // Find the number of DBL_EPSILONs to subtract which result in the
     127                 :            :     // percentage of the second hit being 49% instead of 50%.
     128                 :          4 :     int epsilons = 0;
     129 [ +  - ][ +  - ]:          4 :     Xapian::Database db(get_database("apitest_simpledata"));
     130         [ +  - ]:          8 :     Xapian::Enquire enquire(db);
     131                 :            :     while (true) {
     132                 :        452 :         MyPostingSource source;
     133         [ +  - ]:        452 :         source.append_docweight(1, 100);
     134         [ +  - ]:        452 :         source.append_docweight(2, 50 - epsilons * DBL_EPSILON);
     135 [ +  - ][ +  - ]:        452 :         enquire.set_query(Xapian::Query(&source));
     136 [ +  - ][ +  + ]:        904 :         Xapian::MSet mset = enquire.get_mset(0, 10);
     137 [ +  - ][ -  + ]:        452 :         TEST_EQUAL(mset.size(), 2);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     138 [ +  - ][ +  - ]:        452 :         if (mset[1].get_percent() != 50) break;
                 [ +  + ]
     139         [ +  + ]:        452 :         ++epsilons;
     140                 :        448 :     }
     141                 :            : 
     142                 :            :     // Make a set of document weights including ones on either side of the
     143                 :            :     // 49% / 50% boundary.
     144                 :          8 :     MyPostingSource source;
     145         [ +  - ]:          4 :     source.append_docweight(1, 100);
     146         [ +  - ]:          4 :     source.append_docweight(2, 50);
     147         [ +  - ]:          4 :     source.append_docweight(3, 50 - (epsilons - 1) * DBL_EPSILON);
     148         [ +  - ]:          4 :     source.append_docweight(4, 50 - epsilons * DBL_EPSILON);
     149         [ +  - ]:          4 :     source.append_docweight(5, 25);
     150                 :            : 
     151 [ +  - ][ +  - ]:          4 :     enquire.set_query(Xapian::Query(&source));
     152         [ +  - ]:          8 :     Xapian::MSet mset1 = enquire.get_mset(0, 10);
     153 [ +  - ][ -  + ]:          4 :     TEST_EQUAL(mset1.size(), 5);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     154 [ +  - ][ +  - ]:          4 :     TEST_EQUAL(mset1[2].get_percent(), 50);
         [ -  + ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     155 [ +  - ][ +  - ]:          4 :     TEST_EQUAL(mset1[3].get_percent(), 49);
         [ -  + ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     156                 :            : 
     157                 :            :     // Use various different percentage cutoffs, and check that the values
     158                 :            :     // returned are as expected.
     159                 :          4 :     int percent = 100;
     160 [ +  - ][ +  - ]:         24 :     for (Xapian::MSetIterator i = mset1.begin(); i != mset1.end(); ++i) {
                 [ +  + ]
     161         [ +  - ]:         20 :         int new_percent = mset1.convert_to_percent(i);
     162 [ +  - ][ +  - ]:         20 :         tout << "mset1 item = " << i.get_percent() << "%\n";
         [ +  - ][ +  - ]
     163         [ +  + ]:         20 :         if (new_percent != percent) {
     164         [ +  - ]:         12 :             enquire.set_cutoff(percent);
     165         [ +  - ]:         12 :             Xapian::MSet mset2 = enquire.get_mset(0, 10);
     166 [ +  - ][ +  - ]:         12 :             tout << "cutoff = " << percent << "%, "
     167 [ +  - ][ +  - ]:         24 :                     "mset size = " << mset2.size() << "\n";
         [ +  - ][ +  - ]
     168 [ +  - ][ +  - ]:         12 :             TEST_EQUAL(mset2.size(), i.get_rank());
         [ -  + ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     169                 :         12 :             percent = new_percent;
     170                 :            :         }
     171                 :          4 :     }
     172                 :            : 
     173                 :          4 :     return true;
     174                 :            : }
     175                 :            : 
     176                 :            : /// Check we throw for a percentage cutoff while sorting primarily by value.
     177                 :          7 : DEFINE_TESTCASE(pctcutoff5, backend) {
     178 [ +  - ][ +  - ]:          7 :     Xapian::Database db(get_database("apitest_simpledata"));
     179         [ +  - ]:         14 :     Xapian::Enquire enquire(db);
     180 [ +  - ][ +  - ]:          7 :     enquire.set_query(Xapian::Query("test"));
                 [ +  - ]
     181         [ +  - ]:          7 :     enquire.set_cutoff(42);
     182         [ +  - ]:         14 :     Xapian::MSet mset;
     183                 :            : 
     184         [ +  - ]:          7 :     enquire.set_sort_by_value(0, false);
     185 [ +  - ][ -  + ]:          7 :     TEST_EXCEPTION(Xapian::UnimplementedError, mset = enquire.get_mset(0, 10));
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ -  + ]
           [ -  +  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
           #  # ][ +  - ]
     186                 :            : 
     187         [ +  - ]:          7 :     enquire.set_sort_by_value(0, true);
     188 [ +  - ][ -  +  :          7 :     TEST_EXCEPTION(Xapian::UnimplementedError, mset = enquire.get_mset(0, 10));
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
         [ -  + ][ -  +  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
                 [ +  - ]
     189                 :            : 
     190         [ +  - ]:          7 :     enquire.set_sort_by_value_then_relevance(0, false);
     191 [ +  - ][ -  +  :          7 :     TEST_EXCEPTION(Xapian::UnimplementedError, mset = enquire.get_mset(0, 10));
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
         [ -  + ][ -  +  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
                 [ +  - ]
     192                 :            : 
     193         [ +  - ]:          7 :     enquire.set_sort_by_value_then_relevance(0, true);
     194 [ +  - ][ -  +  :          7 :     TEST_EXCEPTION(Xapian::UnimplementedError, mset = enquire.get_mset(0, 10));
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
         [ -  + ][ -  +  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
                 [ +  - ]
     195                 :            : 
     196                 :          7 :     return true;
     197                 :            : }
     198                 :            : 
     199                 :            : // Regression test for bug fixed in 1.0.14.
     200                 :          2 : DEFINE_TESTCASE(topercent3, remote) {
     201 [ +  - ][ +  - ]:          2 :     BackendManagerLocal local_manager(test_driver::get_srcdir() + "/testdata/");
                 [ +  - ]
     202         [ +  - ]:          4 :     Xapian::Database db;
     203 [ +  - ][ +  - ]:          2 :     db.add_database(get_database("apitest_simpledata"));
                 [ +  - ]
     204 [ +  - ][ +  - ]:          2 :     db.add_database(local_manager.get_database("apitest_simpledata"));
                 [ +  - ]
     205                 :            : 
     206         [ +  - ]:          4 :     Xapian::Enquire enquire(db);
     207         [ +  - ]:          2 :     enquire.set_sort_by_value(1, false);
     208                 :            : 
     209                 :            :     static const char * const terms[] = { "paragraph", "banana" };
     210 [ +  - ][ +  - ]:          2 :     enquire.set_query(Xapian::Query(Xapian::Query::OP_OR, terms, terms + 2));
     211                 :            : 
     212         [ +  - ]:          4 :     Xapian::MSet mset = enquire.get_mset(0, 20);
     213                 :            : 
     214         [ +  - ]:          4 :     Xapian::MSetIterator i;
     215 [ +  - ][ +  - ]:         26 :     for (i = mset.begin(); i != mset.end(); ++i) {
         [ +  - ][ +  + ]
     216                 :            :         // We should never achieve 100%.
     217 [ +  - ][ -  + ]:         24 :         TEST_REL(i.get_percent(),<,100);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     218                 :            :     }
     219                 :            : 
     220                 :          2 :     return true;
     221                 :            : }
     222                 :            : 
     223                 :            : // Regression test for bug introduced temporarily by the "percent without
     224                 :            : // termlist" patch.
     225                 :          7 : DEFINE_TESTCASE(topercent4, backend) {
     226 [ +  - ][ +  - ]:          7 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
                 [ +  - ]
     227                 :            : 
     228                 :            :     Xapian::Query query(Xapian::Query::OP_FILTER,
     229                 :            :                         Xapian::Query("paragraph"),
     230 [ +  - ][ +  - ]:         14 :                         Xapian::Query("queri"));
         [ +  - ][ +  - ]
                 [ +  - ]
     231 [ +  - ][ +  - ]:         14 :     query = Xapian::Query(Xapian::Query::OP_XOR,
                 [ +  - ]
     232         [ +  - ]:          7 :                           query, Xapian::Query("rubbish"));
     233                 :            : 
     234         [ +  - ]:          7 :     enquire.set_query(query);
     235         [ +  - ]:         14 :     Xapian::MSet mset = enquire.get_mset(0, 10);
     236                 :            : 
     237                 :            :     // We should get 50% not 33%.
     238 [ +  - ][ -  + ]:          7 :     TEST(!mset.empty());
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     239 [ +  - ][ +  - ]:          7 :     TEST_EQUAL(mset[0].get_percent(), 50);
         [ -  + ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     240                 :            : 
     241                 :          7 :     return true;
     242                 :            : }
     243                 :            : 
     244                 :            : /// Test that a search with a non-existent term doesn't get 100%.
     245                 :          7 : DEFINE_TESTCASE(topercent5, backend) {
     246 [ +  - ][ +  - ]:          7 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
                 [ +  - ]
     247                 :            :     Xapian::Query q(Xapian::Query::OP_OR,
     248 [ +  - ][ +  - ]:         14 :                     Xapian::Query("paragraph"), Xapian::Query("xyzzy"));
         [ +  - ][ +  - ]
                 [ +  - ]
     249         [ +  - ]:          7 :     enquire.set_query(q);
     250         [ +  - ]:         14 :     Xapian::MSet mset = enquire.get_mset(0, 10);
     251 [ +  - ][ -  + ]:          7 :     TEST(!mset.empty());
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     252 [ +  - ][ +  - ]:          7 :     TEST(mset[0].get_percent() < 100);
         [ -  + ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     253                 :            :     // It would be odd if the non-existent term was worth more, but in 1.0.x
     254                 :            :     // the top hit got 4% in this testcase.  In 1.2.x it gets 50%, which is
     255                 :            :     // better, but >50% would be more natural.
     256 [ +  - ][ +  - ]:          7 :     TEST_REL(mset[0].get_percent(), >=, 50);
         [ -  + ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     257                 :          7 :     return true;
     258                 :            : }
     259                 :            : 
     260                 :            : /// Test that OP_FILTER doesn't affect percentages.
     261                 :            : //  Regression test for bug#590 fixed in 1.3.1 and 1.2.10.
     262                 :          7 : DEFINE_TESTCASE(topercent6, backend) {
     263 [ +  - ][ +  - ]:          7 :     Xapian::Enquire enquire(get_database("apitest_simpledata"));
                 [ +  - ]
     264                 :            :     Xapian::Query q(Xapian::Query::OP_OR,
     265 [ +  - ][ +  - ]:         14 :                     Xapian::Query("rubbish"), Xapian::Query("letter"));
         [ +  - ][ +  - ]
                 [ +  - ]
     266         [ +  - ]:          7 :     enquire.set_query(q);
     267         [ +  - ]:         14 :     Xapian::MSet mset = enquire.get_mset(0, 10);
     268 [ +  - ][ -  + ]:          7 :     TEST(!mset.empty());
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     269 [ +  - ][ +  - ]:          7 :     TEST(mset[0].get_percent() < 100);
         [ -  + ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     270                 :            : 
     271 [ +  - ][ +  - ]:          7 :     q = Xapian::Query(q.OP_FILTER, q, Xapian::Query("this"));
         [ +  - ][ +  - ]
     272         [ +  - ]:          7 :     enquire.set_query(q);
     273         [ +  - ]:         14 :     Xapian::MSet mset2 = enquire.get_mset(0, 10);
     274 [ +  - ][ -  + ]:          7 :     TEST(!mset2.empty());
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     275 [ +  - ][ +  - ]:          7 :     TEST_EQUAL(mset[0].get_percent(), mset2[0].get_percent());
         [ +  - ][ +  - ]
         [ -  + ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     276                 :          7 :     return true;
     277                 :            : }
     278                 :            : 
     279                 :            : static void
     280                 :          4 : make_topercent7_db(Xapian::WritableDatabase &db, const string &)
     281                 :            : {
     282         [ +  + ]:         28 :     for (int i = 1; i <= 6; ++i) {
     283         [ +  - ]:         24 :         Xapian::Document d;
     284 [ +  - ][ +  - ]:         24 :         d.set_data(str(i));
     285 [ +  - ][ +  - ]:         24 :         d.add_term("boom", 2 + (i - 4)*(i - 2));
     286         [ +  + ]:         24 :         if (i != 5)
     287 [ +  - ][ +  - ]:         20 :             d.add_boolean_term("XCAT122");
     288         [ +  - ]:         24 :         db.add_document(d);
     289                 :         24 :     }
     290                 :          4 :     db.commit();
     291                 :          4 : }
     292                 :            : 
     293                 :            : /// Test that a term with wdf always = 0 gets counted.
     294                 :            : //  Regression test for bug introduced in 1.2.10 by the original fix for #590,
     295                 :            : //  and fixed in 1.2.13 (and in trunk before 1.3.1 was released).
     296                 :          6 : DEFINE_TESTCASE(topercent7, generated) {
     297 [ +  - ][ +  - ]:          6 :     Xapian::Database db(get_database("topercent7", make_topercent7_db));
                 [ +  - ]
     298                 :            : 
     299                 :         12 :     Xapian::Query q;
     300 [ +  - ][ +  - ]:          6 :     q = Xapian::Query(q.OP_OR, Xapian::Query("tomb"), Xapian::Query("boom"));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     301 [ +  - ][ +  - ]:          6 :     q = Xapian::Query(q.OP_AND, q, Xapian::Query("XCAT122"));
         [ +  - ][ +  - ]
     302                 :            : 
     303         [ +  - ]:         12 :     Xapian::Enquire enq(db);
     304         [ +  - ]:          6 :     enq.set_query(q);
     305         [ +  - ]:         12 :     Xapian::MSet m = enq.get_mset(0, 10);
     306 [ +  - ][ -  + ]:          6 :     TEST(!m.empty());
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     307 [ +  - ][ +  - ]:          6 :     TEST_REL(m[0].get_percent(),>,60);
         [ -  + ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     308                 :          6 :     return true;
     309                 :            : }
     310                 :            : 
     311         [ -  + ]:        126 : class ZWeight : public Xapian::Weight {
     312                 :            :   public:
     313                 :         68 :     ZWeight() {
     314                 :         34 :         need_stat(DOC_LENGTH);
     315                 :         34 :     }
     316                 :            : 
     317                 :         24 :     void init(double) { }
     318                 :            : 
     319                 :         29 :     Weight * clone() const {
     320                 :         29 :         return new ZWeight();
     321                 :            :     }
     322                 :            : 
     323                 :         40 :     double get_sumpart(Xapian::termcount,
     324                 :            :                        Xapian::termcount,
     325                 :            :                        Xapian::termcount) const {
     326                 :         40 :         return 0.0;
     327                 :            :     }
     328                 :            : 
     329                 :         36 :     double get_maxpart() const {
     330                 :         36 :         return 0.0;
     331                 :            :     }
     332                 :            : 
     333                 :         30 :     double get_sumextra(Xapian::termcount doclen,
     334                 :            :                         Xapian::termcount) const {
     335                 :         30 :         return 1.0 / doclen;
     336                 :            :     }
     337                 :            : 
     338                 :         12 :     double get_maxextra() const {
     339                 :         12 :         return 1.0;
     340                 :            :     }
     341                 :            : };
     342                 :            : 
     343                 :            : /// Regression test for bug introduced in 1.3.1 and fixed in 1.3.2.
     344                 :          5 : DEFINE_TESTCASE(checkzeromaxpartopt1, backend && !remote) {
     345 [ +  - ][ +  - ]:          5 :     Xapian::Database db = get_database("apitest_simpledata");
     346         [ +  - ]:         10 :     Xapian::Enquire enquire(db);
     347                 :            :     // "this" indexes all documents, so will get replaced with MatchAll
     348                 :            :     // internally.
     349                 :            :     static const char * const terms[] = { "this", "spoken", "blank" };
     350 [ +  - ][ +  - ]:          5 :     enquire.set_query(Xapian::Query(Xapian::Query::OP_OR, terms, terms + 3));
     351                 :         10 :     ZWeight wt;
     352         [ +  - ]:          5 :     enquire.set_weighting_scheme(wt);
     353 [ +  - ][ +  - ]:         10 :     Xapian::MSet mset = enquire.get_mset(0, db.get_doccount());
     354                 :            :     // No documents match all 3 terms, so the score shouldn't be 100%.
     355 [ +  - ][ +  - ]:          5 :     TEST(mset[0].get_percent() != 100);
         [ -  + ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     356                 :            :     // Make sure the percentage score isn't 0 or 1 though.
     357 [ +  - ][ +  - ]:          5 :     TEST_REL(mset[0].get_percent(), >, 1);
         [ -  + ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     358                 :          5 :     return true;
     359                 :            : }

Generated by: LCOV version 1.11