xapian-core  1.4.25
api_metadata.cc
Go to the documentation of this file.
1 
4 /* Copyright (C) 2007,2009,2011 Olly Betts
5  * Copyright (C) 2007,2008,2009 Lemur Consulting Ltd
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_metadata.h"
25 
26 #include <xapian.h>
27 
28 #include "apitest.h"
29 #include "testsuite.h"
30 #include "testutils.h"
31 
32 #include <string>
33 
34 using namespace std;
35 
36 // Test metadata methods for non-writable databases.
37 DEFINE_TESTCASE(metadata1, metadata) {
38  Xapian::Database db = get_database("metadata1",
40  const string&)
41  {
42  wdb.set_metadata("empty", "");
43  wdb.set_metadata("foo", "bar");
44  wdb.set_metadata(string("", 1),
45  string("", 1));
46  wdb.set_metadata(string("\0fo", 3),
47  string("\0xx", 3));
48  wdb.set_metadata(string("f\0o", 3),
49  string("x\0x", 3));
50  wdb.set_metadata(string("fo\0", 3),
51  string("xx\0", 3));
52  });
53  TEST_EQUAL(db.get_doccount(), 0);
54  TEST_EQUAL(db.get_metadata("empty"), "");
55  TEST_EQUAL(db.get_metadata("unset"), "");
56  TEST_EQUAL(db.get_metadata("foo"), "bar");
57 
58  // Check for transparent handling of zero bytes.
59  TEST_EQUAL(db.get_metadata(string("", 1)), string("", 1));
60  TEST_EQUAL(db.get_metadata(string("\0fo", 3)), string("\0xx", 3));
61  TEST_EQUAL(db.get_metadata(string("f\0o", 3)), string("x\0x", 3));
62  TEST_EQUAL(db.get_metadata(string("fo\0", 3)), string("xx\0", 3));
63 
65 }
66 
67 // Basic test of metadata methods.
68 DEFINE_TESTCASE(metadata2, metadata && writable) {
70 
71  TEST_EQUAL(db.get_metadata("foo"), "");
72  db.set_metadata("foo", "bar");
73  TEST_EQUAL(db.get_metadata("foo"), "bar");
74  db.set_metadata("foo", "baz");
75  TEST_EQUAL(db.get_doccount(), 0);
76  TEST_EQUAL(db.get_metadata("foo"), "baz");
77  db.set_metadata("foo", "");
78  TEST_EQUAL(db.get_metadata("foo"), "");
79 
80  TEST_EQUAL(db.get_doccount(), 0);
81 
82  // Check for transparent handling of zero bytes.
83  db.set_metadata("foo", "value of foo");
84  db.set_metadata(string("foo\0bar", 7), string(1, '\0'));
85  db.set_metadata(string("foo\0", 4), string("foo\0bar", 7));
86 
87  TEST_EQUAL(db.get_metadata("foo"), "value of foo");
88  TEST_EQUAL(db.get_metadata(string("foo\0bar", 7)), string(1, '\0'));
89  TEST_EQUAL(db.get_metadata(string("foo\0", 4)), string("foo\0bar", 7));
90 
91  db.commit();
92 
93  TEST_EQUAL(db.get_metadata("foo"), "value of foo");
94  TEST_EQUAL(db.get_metadata(string("foo\0bar", 7)), string(1, '\0'));
95  TEST_EQUAL(db.get_metadata(string("foo\0", 4)), string("foo\0bar", 7));
96 }
97 
98 // Test that metadata gets applied at same time as other changes.
99 DEFINE_TESTCASE(metadata3, metadata && writable && !inmemory) {
100  // get_writable_database_as_database() not implemented for inmemory.
103 
104  TEST_EQUAL(db.get_metadata("foo"), "");
105  db.set_metadata("foo", "bar");
106  TEST_EQUAL(db.get_metadata("foo"), "bar");
107  TEST_EQUAL(dbr.get_metadata("foo"), "");
108  db.commit();
109  TEST_EQUAL(dbr.get_metadata("foo"), "");
110  TEST(dbr.reopen());
111  TEST_EQUAL(db.get_metadata("foo"), "bar");
112  TEST_EQUAL(dbr.get_metadata("foo"), "bar");
113  TEST_EQUAL(dbr.get_doccount(), 0);
114 
116  db.set_metadata("foo", "baz");
117  TEST_EQUAL(db.get_doccount(), 1);
118  TEST_EQUAL(db.get_metadata("foo"), "baz");
119  db.commit();
120 
121  TEST_EQUAL(dbr.get_metadata("foo"), "bar");
122  TEST(dbr.reopen());
123  TEST_EQUAL(dbr.get_metadata("foo"), "baz");
124 
125  db.set_metadata("foo", "");
126  TEST_EQUAL(db.get_metadata("foo"), "");
127  db.commit();
128  TEST_EQUAL(dbr.get_metadata("foo"), "baz");
129  TEST(dbr.reopen());
130  TEST_EQUAL(dbr.get_metadata("foo"), "");
131 
132  TEST_EQUAL(db.get_doccount(), 1);
133 }
134 
135 // Test the empty metadata keys give an error correctly.
136 DEFINE_TESTCASE(metadata4, metadata && writable) {
138 
142 }
143 
144 // Regression test for adding a piece of metadata on its own before adding
145 // other things.
146 DEFINE_TESTCASE(metadata5, metadata && writable && !inmemory) {
147  // get_writable_database_as_database() not implemented for inmemory.
149 
150  db.set_metadata("foo", "foo");
151  db.commit();
152 
153  Xapian::Document doc;
154  doc.add_posting("foo", 1);
155  db.add_document(doc);
156 
158 }
159 
160 // Test metadata iterators.
161 DEFINE_TESTCASE(metadata6, writable) {
163 
164  // Check that iterator on empty database returns nothing.
166  iter = db.metadata_keys_begin();
167  TEST_EQUAL(iter, db.metadata_keys_end());
168 
169  // FIXME: inmemory doesn't implement metadata iterators yet, except in the
170  // trivial case of there being no keys to iterate.
171  SKIP_TEST_FOR_BACKEND("inmemory");
172 
173  try {
174  db.set_metadata("foo", "val");
175  } catch (const Xapian::UnimplementedError &) {
176  SKIP_TEST("Metadata not supported by this backend");
177  }
178  db.commit();
179 
180  // Check iterator on a database with only metadata items.
181  iter = db.metadata_keys_begin();
182  TEST(iter != db.metadata_keys_end());
183  TEST_EQUAL(*iter, "foo");
184  ++iter;
185  TEST(iter == db.metadata_keys_end());
186 
187  // Check iterator on a database with metadata items and documents.
188  Xapian::Document doc;
189  doc.add_posting("foo", 1);
190  db.add_document(doc);
191  db.commit();
192 
193  iter = db.metadata_keys_begin();
194  TEST(iter != db.metadata_keys_end());
195  TEST_EQUAL(*iter, "foo");
196  ++iter;
197  TEST(iter == db.metadata_keys_end());
198 
199  // Check iterator on a database with documents but no metadata. Also
200  // checks that setting metadata to empty stops the iterator returning it.
201  db.set_metadata("foo", "");
202  db.commit();
203  iter = db.metadata_keys_begin();
204  TEST(iter == db.metadata_keys_end());
205 
206  // Check use of a prefix, and skip_to.
207  db.set_metadata("a", "val");
208  db.set_metadata("foo", "val");
209  db.set_metadata("foo1", "val");
210  db.set_metadata("foo2", "val");
211  db.set_metadata("z", "val");
212  db.commit();
213 
214  iter = db.metadata_keys_begin();
215  TEST(iter != db.metadata_keys_end());
216  TEST_EQUAL(*iter, "a");
217  ++iter;
218  TEST(iter != db.metadata_keys_end());
219  TEST_EQUAL(*iter, "foo");
220  ++iter;
221  TEST(iter != db.metadata_keys_end());
222  TEST_EQUAL(*iter, "foo1");
223  ++iter;
224  TEST(iter != db.metadata_keys_end());
225  TEST_EQUAL(*iter, "foo2");
226  ++iter;
227  TEST(iter != db.metadata_keys_end());
228  TEST_EQUAL(*iter, "z");
229  ++iter;
230  TEST(iter == db.metadata_keys_end());
231 
232  iter = db.metadata_keys_begin("foo");
233  TEST(iter != db.metadata_keys_end("foo"));
234  TEST_EQUAL(*iter, "foo");
235  ++iter;
236  TEST(iter != db.metadata_keys_end("foo"));
237  TEST_EQUAL(*iter, "foo1");
238  ++iter;
239  TEST(iter != db.metadata_keys_end("foo"));
240  TEST_EQUAL(*iter, "foo2");
241  ++iter;
242  TEST(iter == db.metadata_keys_end("foo"));
243 
244  iter = db.metadata_keys_begin("foo1");
245  TEST(iter != db.metadata_keys_end("foo1"));
246  TEST_EQUAL(*iter, "foo1");
247  ++iter;
248  TEST(iter == db.metadata_keys_end("foo1"));
249 
250  iter = db.metadata_keys_begin();
251  TEST(iter != db.metadata_keys_end());
252  TEST_EQUAL(*iter, "a");
253 
254  // Skip to "" should move to the first key.
255  iter.skip_to("");
256  TEST(iter != db.metadata_keys_end());
257  TEST_EQUAL(*iter, "a");
258 
259  // This skip_to should skip the "foo" key.
260  iter.skip_to("foo1");
261  TEST(iter != db.metadata_keys_end());
262  TEST_EQUAL(*iter, "foo1");
263 
264  // Check that skipping to the current key works.
265  iter.skip_to("foo1");
266  TEST(iter != db.metadata_keys_end());
267  TEST_EQUAL(*iter, "foo1");
268 
269  // Check that skip_to a key before the current one doesn't move forwards.
270  iter.skip_to("a");
271  TEST(iter != db.metadata_keys_end());
272  TEST_REL(*iter, <=, "foo1");
273 
274  // Make sure we're back on foo1.
275  iter.skip_to("foo1");
276  TEST(iter != db.metadata_keys_end());
277  TEST_EQUAL(*iter, "foo1");
278 
279  // Check that advancing after a skip_to() works correctly.
280  ++iter;
281  TEST(iter != db.metadata_keys_end());
282  TEST_EQUAL(*iter, "foo2");
283 
284  // Check that skipping to a key after the last key works.
285  iter.skip_to("zoo");
286  TEST(iter == db.metadata_keys_end());
287 }
288 
290 DEFINE_TESTCASE(writeread1, metadata && writable) {
292  db_w.set_metadata("1", "2");
293  string longitem(20000, 'j');
294  db_w.set_metadata("2", longitem);
295 
296  string readitem = db_w.get_metadata("2");
297  TEST_EQUAL(readitem, longitem);
298 }
Xapian::docid add_document(const Xapian::Document &document)
Add a new document to the database.
Definition: omdatabase.cc:902
#define TEST(a)
Test a condition, without an additional explanation for failure.
Definition: testsuite.h:275
This class is used to access a database, or a group of databases.
Definition: database.h:68
Xapian::WritableDatabase get_writable_database(const string &dbname)
Definition: apitest.cc:87
a generic test suite engine
bool reopen()
Re-open the database.
Definition: omdatabase.cc:125
STL namespace.
void set_metadata(const std::string &key, const std::string &metadata)
Set the user-specified metadata associated with a given key.
Definition: omdatabase.cc:1064
Xapian::doccount get_doccount() const
Get the number of documents in the database.
Definition: omdatabase.cc:267
DEFINE_TESTCASE(metadata1, metadata)
Definition: api_metadata.cc:37
std::string get_metadata(const std::string &key) const
Get the user-specified metadata associated with a given key.
Definition: omdatabase.cc:758
test functionality of the Xapian API
Class for iterating over a list of terms.
Definition: termiterator.h:41
#define TEST_REL(A, REL, B)
Test a relation holds,e.g. TEST_REL(a,>,b);.
Definition: testmacros.h:32
InvalidArgumentError indicates an invalid parameter value was passed to the API.
Definition: error.h:241
This class provides read/write access to a database.
Definition: database.h:789
Public interfaces for the Xapian library.
#define TEST_EXCEPTION(TYPE, CODE)
Check that CODE throws exactly Xapian exception TYPE.
Definition: testutils.h:109
void commit()
Commit any pending modifications made to the database.
Definition: omdatabase.cc:857
Xapian::Database get_writable_database_as_database()
Definition: apitest.cc:119
#define SKIP_TEST_FOR_BACKEND(B)
Definition: apitest.h:75
void add_posting(const std::string &tname, Xapian::termpos tpos, Xapian::termcount wdfinc=1)
Add an occurrence of a term at a particular position.
Definition: omdocument.cc:128
Xapian::Database get_database(const string &dbname)
Definition: apitest.cc:48
#define SKIP_TEST(MSG)
Skip the current testcase with message MSG.
Definition: testsuite.h:74
Xapian-specific test helper functions and macros.
Xapian::TermIterator metadata_keys_begin(const std::string &prefix=std::string()) const
An iterator which returns all user-specified metadata keys.
Definition: omdatabase.cc:768
#define TEST_EQUAL(a, b)
Test for equality of two things.
Definition: testsuite.h:278
A handle representing a document in a Xapian database.
Definition: document.h:61
UnimplementedError indicates an attempt to use an unimplemented feature.
Definition: error.h:325
Xapian::TermIterator metadata_keys_end(const std::string &=std::string()) const
Corresponding end iterator to metadata_keys_begin().
Definition: database.h:510