LCOV - code coverage report
Current view: top level - home/olly/git/atia-xapian/xapian-core/tests - api_opvalue.cc (source / functions) Hit Total Coverage
Test: Test Coverage for xapian-core r Lines: 126 126 100.0 %
Date: 2011-08-21 Functions: 11 11 100.0 %
Branches: 46 88 52.3 %

           Branch data     Line data    Source code
       1                 :            : /** @file api_opvalue.cc
       2                 :            :  * @brief Tests of the OP_VALUE_* query operators.
       3                 :            :  */
       4                 :            : /* Copyright 2007,2008,2009,2010,2010 Olly Betts
       5                 :            :  * Copyright 2008 Lemur Consulting Ltd
       6                 :            :  * Copyright 2010 Richard Boulton
       7                 :            :  *
       8                 :            :  * This program is free software; you can redistribute it and/or
       9                 :            :  * modify it under the terms of the GNU General Public License as
      10                 :            :  * published by the Free Software Foundation; either version 2 of the
      11                 :            :  * License, or (at your option) any later version.
      12                 :            :  *
      13                 :            :  * This program is distributed in the hope that it will be useful,
      14                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      15                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16                 :            :  * GNU General Public License for more details.
      17                 :            :  *
      18                 :            :  * You should have received a copy of the GNU General Public License
      19                 :            :  * along with this program; if not, write to the Free Software
      20                 :            :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
      21                 :            :  * USA
      22                 :            :  */
      23                 :            : 
      24                 :            : #include <config.h>
      25                 :            : 
      26                 :            : #include "api_opvalue.h"
      27                 :            : 
      28                 :            : #include <xapian.h>
      29                 :            : 
      30                 :            : #include "apitest.h"
      31                 :            : #include "testsuite.h"
      32                 :            : #include "testutils.h"
      33                 :            : 
      34                 :            : #include <string>
      35                 :            : 
      36                 :            : using namespace std;
      37                 :            : 
      38                 :            : // Feature test for Query::OP_VALUE_RANGE.
      39                 :         13 : DEFINE_TESTCASE(valuerange1, backend) {
      40                 :         13 :     Xapian::Database db(get_database("apitest_phrase"));
      41                 :         13 :     Xapian::Enquire enq(db);
      42                 :            :     static const char * vals[] = {
      43                 :            :         "", " ", "a", "aa", "abcd", "e", "g", "h", "hzz", "i", "l", "z", NULL
      44                 :            :     };
      45         [ +  + ]:        169 :     for (const char **start = vals; *start; ++start) {
      46         [ +  + ]:       2028 :         for (const char **end = vals; *end; ++end) {
      47                 :       1872 :             Xapian::Query query(Xapian::Query::OP_VALUE_RANGE, 1, *start, *end);
      48                 :       1872 :             enq.set_query(query);
      49                 :       1872 :             Xapian::MSet mset = enq.get_mset(0, 20);
      50                 :            :             // Check that documents in the MSet match the value range filter.
      51                 :       1872 :             set<Xapian::docid> matched;
      52                 :       1872 :             Xapian::MSetIterator i;
      53         [ +  + ]:       7774 :             for (i = mset.begin(); i != mset.end(); ++i) {
      54                 :       5902 :                 matched.insert(*i);
      55                 :       5902 :                 string value = db.get_document(*i).get_value(1);
      56   [ -  +  #  # ]:       5902 :                 TEST_REL(value,>=,*start);
      57 [ -  + ][ #  # ]:       5902 :                 TEST_REL(value,<=,*end);
      58                 :            :             }
      59                 :            :             // Check that documents not in the MSet don't match the value range filter.
      60         [ +  + ]:      33696 :             for (Xapian::docid j = db.get_lastdocid(); j != 0; --j) {
      61         [ +  + ]:      31824 :                 if (matched.find(j) == matched.end()) {
      62                 :      25922 :                     string value = db.get_document(j).get_value(1);
      63                 :      25922 :                     tout << value << " < '" << *start << "' or > '" << *end << "'" << endl;
      64   [ +  +  -  + ]:      25922 :                     TEST(value < *start || value > *end);
         [ -  + ][ #  # ]
      65                 :            :                 }
      66                 :            :             }
      67                 :            :         }
      68                 :            :     }
      69                 :         13 :     return true;
      70                 :            : }
      71                 :            : 
      72                 :            : // Regression test for Query::OP_VALUE_LE - used to return document IDs for
      73                 :            : // non-existent documents.
      74                 :         10 : DEFINE_TESTCASE(valuerange2, writable) {
      75                 :         10 :     Xapian::WritableDatabase db = get_writable_database();
      76                 :         10 :     Xapian::Document doc;
      77                 :         10 :     doc.set_data("5");
      78                 :         10 :     doc.add_value(0, "5");
      79                 :         10 :     db.replace_document(5, doc);
      80                 :         10 :     Xapian::Enquire enq(db);
      81                 :            : 
      82                 :         10 :     Xapian::Query query(Xapian::Query::OP_VALUE_LE, 0, "6");
      83                 :         10 :     enq.set_query(query);
      84                 :         10 :     Xapian::MSet mset = enq.get_mset(0, 20);
      85                 :            : 
      86   [ -  +  #  # ]:         10 :     TEST_EQUAL(mset.size(), 1);
      87 [ -  + ][ #  # ]:         10 :     TEST_EQUAL(*(mset[0]), 5);
      88                 :         10 :     return true;
      89                 :            : }
      90                 :            : 
      91                 :            : static void
      92                 :          3 : make_valuerange5(Xapian::WritableDatabase &db, const string &)
      93                 :            : {
      94                 :          3 :     Xapian::Document doc;
      95                 :          3 :     doc.add_value(0, "BOOK");
      96                 :          3 :     db.add_document(doc);
      97                 :          3 :     doc.add_value(0, "VOLUME");
      98                 :          3 :     db.add_document(doc);
      99                 :          3 : }
     100                 :            : 
     101                 :            : // Check that lower and upper bounds are used.
     102                 :          3 : DEFINE_TESTCASE(valuerange5, generated) {
     103                 :          3 :     Xapian::Database db = get_database("valuerange5", make_valuerange5);
     104         [ +  + ]:          3 :     if (db.get_value_lower_bound(0).empty()) {
     105                 :            :         // This backend (i.e. flint) doesn't support value bounds, or else
     106                 :            :         // there are no instances of this value.  In the former case,
     107                 :            :         // get_value_upper_bound() should throw an exception.
     108 [ +  - ][ -  + ]:          2 :         TEST_EXCEPTION(Xapian::UnimplementedError,
         [ #  # ][ -  + ]
     109                 :            :                 db.get_value_upper_bound(0));
     110                 :          1 :         return true;
     111                 :            :     }
     112                 :            : 
     113                 :          2 :     Xapian::Enquire enq(db);
     114                 :            : 
     115                 :          2 :     Xapian::Query query(Xapian::Query::OP_VALUE_RANGE, 0, "APPLE", "BANANA");
     116                 :          2 :     enq.set_query(query);
     117                 :          2 :     Xapian::MSet mset = enq.get_mset(0, 0);
     118   [ -  +  #  # ]:          2 :     TEST_EQUAL(mset.get_matches_estimated(), 0);
     119                 :            : 
     120                 :          2 :     Xapian::Query query2(Xapian::Query::OP_VALUE_RANGE, 0, "WALRUS", "ZEBRA");
     121                 :          2 :     enq.set_query(query2);
     122                 :          2 :     mset = enq.get_mset(0, 0);
     123   [ -  +  #  # ]:          2 :     TEST_EQUAL(mset.get_matches_estimated(), 0);
     124                 :            : 
     125                 :          3 :     return true;
     126                 :            : }
     127                 :            : 
     128                 :            : // Feature test for Query::OP_VALUE_GE.
     129                 :         13 : DEFINE_TESTCASE(valuege1, backend) {
     130                 :         13 :     Xapian::Database db(get_database("apitest_phrase"));
     131                 :         13 :     Xapian::Enquire enq(db);
     132                 :            :     static const char * vals[] = {
     133                 :            :         "", " ", "a", "aa", "abcd", "e", "g", "h", "hzz", "i", "l", "z", NULL
     134                 :            :     };
     135         [ +  + ]:        169 :     for (const char **start = vals; *start; ++start) {
     136                 :        156 :         Xapian::Query query(Xapian::Query::OP_VALUE_GE, 1, *start);
     137                 :        156 :         enq.set_query(query);
     138                 :        156 :         Xapian::MSet mset = enq.get_mset(0, 20);
     139                 :            :         // Check that documents in the MSet match the value range filter.
     140                 :        156 :         set<Xapian::docid> matched;
     141                 :        156 :         Xapian::MSetIterator i;
     142         [ +  + ]:       1833 :         for (i = mset.begin(); i != mset.end(); ++i) {
     143                 :       1677 :             matched.insert(*i);
     144                 :       1677 :             string value = db.get_document(*i).get_value(1);
     145                 :       1677 :             tout << "'" << *start << "' <= '" << value << "'" << endl;
     146   [ -  +  #  # ]:       1677 :             TEST_REL(value,>=,*start);
     147                 :            :         }
     148                 :            :         // Check that documents not in the MSet don't match the value range
     149                 :            :         // filter.
     150         [ +  + ]:       2808 :         for (Xapian::docid j = db.get_lastdocid(); j != 0; --j) {
     151         [ +  + ]:       2652 :             if (matched.find(j) == matched.end()) {
     152                 :        975 :                 string value = db.get_document(j).get_value(1);
     153                 :        975 :                 tout << value << " < '" << *start << "'" << endl;
     154   [ -  +  #  # ]:        975 :                 TEST_REL(value,<,*start);
     155                 :            :             }
     156                 :            :         }
     157                 :            :     }
     158                 :         13 :     return true;
     159                 :            : }
     160                 :            : 
     161                 :            : // Regression test for Query::OP_VALUE_GE - used to segfault if check() got
     162                 :            : // called.
     163                 :         13 : DEFINE_TESTCASE(valuege2, backend) {
     164                 :         13 :     Xapian::Database db(get_database("apitest_phrase"));
     165                 :         13 :     Xapian::Enquire enq(db);
     166                 :            :     Xapian::Query query(Xapian::Query::OP_AND,
     167                 :            :                         Xapian::Query("what"),
     168                 :         13 :                         Xapian::Query(Xapian::Query::OP_VALUE_GE, 1, "aa"));
     169                 :         13 :     enq.set_query(query);
     170                 :         13 :     Xapian::MSet mset = enq.get_mset(0, 20);
     171                 :         13 :     return true;
     172                 :            : }
     173                 :            : 
     174                 :            : // Feature test for Query::OP_VALUE_LE.
     175                 :         13 : DEFINE_TESTCASE(valuele1, backend) {
     176                 :         13 :     Xapian::Database db(get_database("apitest_phrase"));
     177                 :         13 :     Xapian::Enquire enq(db);
     178                 :            :     static const char * vals[] = {
     179                 :            :         "", " ", "a", "aa", "abcd", "e", "g", "h", "hzz", "i", "l", "z", NULL
     180                 :            :     };
     181         [ +  + ]:        169 :     for (const char **end = vals; *end; ++end) {
     182                 :        156 :         Xapian::Query query(Xapian::Query::OP_VALUE_LE, 1, *end);
     183                 :        156 :         enq.set_query(query);
     184                 :        156 :         Xapian::MSet mset = enq.get_mset(0, 20);
     185                 :            :         // Check that documents in the MSet match the value range filter.
     186                 :        156 :         set<Xapian::docid> matched;
     187                 :        156 :         Xapian::MSetIterator i;
     188         [ +  + ]:       1274 :         for (i = mset.begin(); i != mset.end(); ++i) {
     189                 :       1118 :             matched.insert(*i);
     190                 :       1118 :             string value = db.get_document(*i).get_value(1);
     191   [ -  +  #  # ]:       1118 :             TEST_REL(value,<=,*end);
     192                 :            :         }
     193                 :            :         // Check that documents not in the MSet don't match the value range
     194                 :            :         // filter.
     195         [ +  + ]:       2808 :         for (Xapian::docid j = db.get_lastdocid(); j != 0; --j) {
     196         [ +  + ]:       2652 :             if (matched.find(j) == matched.end()) {
     197                 :       1534 :                 string value = db.get_document(j).get_value(1);
     198   [ -  +  #  # ]:       1534 :                 TEST_REL(value,>,*end);
     199                 :            :             }
     200                 :            :         }
     201                 :            :     }
     202                 :         13 :     return true;
     203                 :            : }
     204                 :            : 
     205                 :            : // Check that Query(OP_VALUE_GE, 0, "") -> Query::MatchAll.
     206                 :          1 : DEFINE_TESTCASE(valuege3, !backend) {
     207                 :          1 :     Xapian::Query query(Xapian::Query::OP_VALUE_GE, 0, "");
     208 [ -  + ][ #  # ]:          1 :     TEST_STRINGS_EQUAL(query.get_description(), Xapian::Query::MatchAll.get_description());
     209                 :          1 :     return true;
     210                 :            : }
     211                 :            : 
     212                 :            : // Test Query::OP_VALUE_GE in a query which causes its skip_to() to be used.
     213                 :         13 : DEFINE_TESTCASE(valuege4, backend) {
     214                 :         13 :     Xapian::Database db(get_database("apitest_phrase"));
     215                 :         13 :     Xapian::Enquire enq(db);
     216                 :            : 
     217                 :            :     // This query should put the ValueGePostList on the LHS of the AND because
     218                 :            :     // it has a lower estimated termfreq than the term "fridg".  As a result,
     219                 :            :     // the skip_to() method is used to advance the ValueGePostList.
     220                 :            :     Xapian::Query query(Xapian::Query::OP_AND,
     221                 :            :                         Xapian::Query("fridg"),
     222                 :         13 :                         Xapian::Query(Xapian::Query::OP_VALUE_GE, 1, "aa"));
     223                 :         13 :     enq.set_query(query);
     224                 :         13 :     Xapian::MSet mset = enq.get_mset(0, 20);
     225                 :         13 :     return true;
     226                 :            : }
     227                 :            : 
     228                 :            : // Test Query::OP_VALUE_RANGE in a query which causes its check() to be used.
     229                 :         13 : DEFINE_TESTCASE(valuerange3, backend) {
     230                 :         13 :     Xapian::Database db(get_database("apitest_phrase"));
     231                 :         13 :     Xapian::Enquire enq(db);
     232                 :            :     Xapian::Query query(Xapian::Query::OP_AND,
     233                 :            :                         Xapian::Query("what"),
     234                 :            :                         Xapian::Query(Xapian::Query::OP_VALUE_RANGE, 1,
     235                 :         13 :                                       "aa", "z"));
     236                 :         13 :     enq.set_query(query);
     237                 :         13 :     Xapian::MSet mset = enq.get_mset(0, 20);
     238                 :         13 :     return true;
     239                 :            : }
     240                 :            : 
     241                 :            : // Test Query::OP_VALUE_RANGE in a query which causes its skip_to() to be used.
     242                 :         13 : DEFINE_TESTCASE(valuerange4, backend) {
     243                 :         13 :     Xapian::Database db(get_database("apitest_phrase"));
     244                 :         13 :     Xapian::Enquire enq(db);
     245                 :            :     Xapian::Query query(Xapian::Query::OP_AND,
     246                 :            :                         Xapian::Query("fridg"),
     247                 :            :                         Xapian::Query(Xapian::Query::OP_VALUE_RANGE, 1,
     248                 :         13 :                                       "aa", "z"));
     249                 :         13 :     enq.set_query(query);
     250                 :         13 :     Xapian::MSet mset = enq.get_mset(0, 20);
     251                 :         13 :     return true;
     252                 :            : }

Generated by: LCOV version 1.8