xapian-core  2.0.0
api_qpbackend.cc
Go to the documentation of this file.
1 
4 /* Copyright (c) 2009,2015 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, see
18  * <https://www.gnu.org/licenses/>.
19  */
20 
21 #include <config.h>
22 
23 #include "api_qpbackend.h"
24 
25 #include <xapian.h>
26 
27 #include "backendmanager.h"
28 #include "testsuite.h"
29 #include "testutils.h"
30 
31 #include "apitest.h"
32 
33 using namespace std;
34 
35 namespace {
36 struct test {
37  const char *query;
38  const char *expect;
39 };
40 }
41 
43 DEFINE_TESTCASE(qpsynonympartial1, synonyms) {
44  static const test test_queries[] = {
45  { "hello", "(WILDCARD SYNONYM hello OR hello@1)" },
46  { "~hello", "(hello@1 SYNONYM hi@1 SYNONYM howdy@1)" },
47  { "hello world", "(hello@1 OR (WILDCARD SYNONYM world OR world@2))" },
48  { "~hello world", "((hello@1 SYNONYM hi@1 SYNONYM howdy@1) OR (WILDCARD SYNONYM world OR world@2))" },
49  { "world ~hello", "(world@1 OR (hello@2 SYNONYM hi@2 SYNONYM howdy@2))" },
50  { NULL, NULL }
51  };
52  static const test test_queries_auto[] = {
53  { "hello", "(hello@1 SYNONYM hi@1 SYNONYM howdy@1)" },
54  { "~hello", "(hello@1 SYNONYM hi@1 SYNONYM howdy@1)" },
55  { "hello world", "((hello@1 SYNONYM hi@1 SYNONYM howdy@1) OR world@2)" },
56  { "~hello world", "((hello@1 SYNONYM hi@1 SYNONYM howdy@1) OR world@2)" },
57  { "world ~hello", "(world@1 OR (hello@2 SYNONYM hi@2 SYNONYM howdy@2))" },
58  { NULL, NULL }
59  };
60  static const test test_queries_partial_auto[] = {
61  { "hello", "(WILDCARD SYNONYM hello OR hello@1)" },
62  { "~hello", "(WILDCARD SYNONYM hello OR hello@1)" },
63  { "hello world", "((hello@1 SYNONYM hi@1 SYNONYM howdy@1) OR (WILDCARD SYNONYM world OR world@2))" },
64  { "~hello world", "((hello@1 SYNONYM hi@1 SYNONYM howdy@1) OR (WILDCARD SYNONYM world OR world@2))" },
65  { "world ~hello", "(world@1 OR (WILDCARD SYNONYM hello OR hello@2))" },
66  { NULL, NULL }
67  };
68 
69  Xapian::Database db = get_database("qpsynonympartial1",
71  const string&) {
72  wdb.add_synonym("hello", "hi");
73  wdb.add_synonym("hello", "howdy");
74  });
75  Xapian::Enquire enquire(db);
77  Xapian::Stem stemmmer("english");
78  qp.set_database(db);
79  qp.add_prefix("foo", "XFOO");
80 
81  const test *p;
82  for (p = test_queries; p->query; ++p) {
83  string expect, parsed;
84  if (p->expect)
85  expect = p->expect;
86  else
87  expect = "parse error";
88  try {
89  unsigned f = qp.FLAG_SYNONYM | qp.FLAG_PARTIAL | qp.FLAG_DEFAULT;
90  Xapian::Query qobj = qp.parse_query(p->query, f);
91  parsed = qobj.get_description();
92  expect = string("Query(") + expect + ')';
93  } catch (const Xapian::QueryParserError &e) {
94  parsed = e.get_msg();
95  } catch (const Xapian::Error &e) {
96  parsed = e.get_description();
97  } catch (...) {
98  parsed = "Unknown exception!";
99  }
100  tout << "Query: " << p->query << '\n';
101  TEST_STRINGS_EQUAL(parsed, expect);
102  }
103 
104  for (p = test_queries_auto; p->query; ++p) {
105  string expect, parsed;
106  if (p->expect)
107  expect = p->expect;
108  else
109  expect = "parse error";
110  try {
111  unsigned f = qp.FLAG_AUTO_SYNONYMS | qp.FLAG_DEFAULT;
112  Xapian::Query qobj = qp.parse_query(p->query, f);
113  parsed = qobj.get_description();
114  expect = string("Query(") + expect + ')';
115  } catch (const Xapian::QueryParserError &e) {
116  parsed = e.get_msg();
117  } catch (const Xapian::Error &e) {
118  parsed = e.get_description();
119  } catch (...) {
120  parsed = "Unknown exception!";
121  }
122  tout << "Query: " << p->query << '\n';
123  TEST_STRINGS_EQUAL(parsed, expect);
124  }
125 
126  for (p = test_queries_partial_auto; p->query; ++p) {
127  string expect, parsed;
128  if (p->expect)
129  expect = p->expect;
130  else
131  expect = "parse error";
132  try {
133  unsigned f = qp.FLAG_AUTO_SYNONYMS | qp.FLAG_PARTIAL;
134  f |= qp.FLAG_DEFAULT;
135  Xapian::Query qobj = qp.parse_query(p->query, f);
136  parsed = qobj.get_description();
137  expect = string("Query(") + expect + ')';
138  } catch (const Xapian::QueryParserError &e) {
139  parsed = e.get_msg();
140  } catch (const Xapian::Error &e) {
141  parsed = e.get_description();
142  } catch (...) {
143  parsed = "Unknown exception!";
144  }
145  tout << "Query: " << p->query << '\n';
146  TEST_STRINGS_EQUAL(parsed, expect);
147  }
148 }
static Xapian::Query query(Xapian::Query::op op, const string &t1=string(), const string &t2=string(), const string &t3=string(), const string &t4=string(), const string &t5=string(), const string &t6=string(), const string &t7=string(), const string &t8=string(), const string &t9=string(), const string &t10=string())
Definition: api_anydb.cc:62
DEFINE_TESTCASE(qpsynonympartial1, synonyms)
Regression test for bug#407 fixed in 1.0.17 and 1.1.3.
Xapian::Database get_database(const string &dbname)
Definition: apitest.cc:47
test functionality of the Xapian API
Base class for backend handling in test harness.
An indexed database of documents.
Definition: database.h:75
Querying session.
Definition: enquire.h:57
All exceptions thrown by Xapian are subclasses of Xapian::Error.
Definition: error.h:41
const std::string & get_msg() const noexcept
Message giving details of the error, intended for human consumption.
Definition: error.h:111
std::string get_description() const
Return a string describing this object.
Definition: error.cc:93
Indicates a query string can't be parsed.
Definition: error.h:875
Build a Xapian::Query object from a user query string.
Definition: queryparser.h:516
void set_database(const Database &db)
Specify the database being searched.
Definition: queryparser.cc:138
void add_prefix(std::string_view field, std::string_view prefix)
Add a free-text field term prefix.
Definition: queryparser.cc:200
Query parse_query(std::string_view query_string, unsigned flags=FLAG_DEFAULT, std::string_view default_prefix={})
Parse a query.
Definition: queryparser.cc:174
@ FLAG_AUTO_SYNONYMS
Enable automatic use of synonyms for single terms.
Definition: queryparser.h:604
@ FLAG_DEFAULT
The default flags.
Definition: queryparser.h:784
@ FLAG_SYNONYM
Enable synonym operator '~'.
Definition: queryparser.h:598
@ FLAG_PARTIAL
Enable partial matching.
Definition: queryparser.h:577
Class representing a query.
Definition: query.h:45
std::string get_description() const
Return a string describing this object.
Definition: query.cc:307
Class representing a stemming algorithm.
Definition: stem.h:74
This class provides read/write access to a database.
Definition: database.h:964
void add_synonym(std::string_view term, std::string_view synonym) const
Add a synonym for a term.
Definition: database.cc:614
PositionList * p
std::ostringstream tout
The debug printing stream.
Definition: testsuite.cc:104
a generic test suite engine
#define TEST_STRINGS_EQUAL(a, b)
Test for equality of two strings.
Definition: testsuite.h:285
Xapian-specific test helper functions and macros.
Public interfaces for the Xapian library.