xapian-core  1.4.22
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 basic metadata access methods.
37 DEFINE_TESTCASE(metadata1, writable) {
39 
40  TEST_EQUAL(db.get_metadata("foo"), "");
41  try {
42  db.set_metadata("foo", "bar");
43  } catch (const Xapian::UnimplementedError &) {
44  SKIP_TEST("Metadata not supported by this backend");
45  }
46  TEST_EQUAL(db.get_metadata("foo"), "bar");
47  db.set_metadata("foo", "baz");
48  TEST_EQUAL(db.get_doccount(), 0);
49  TEST_EQUAL(db.get_metadata("foo"), "baz");
50  db.set_metadata("foo", "");
51  TEST_EQUAL(db.get_metadata("foo"), "");
52 
53  TEST_EQUAL(db.get_doccount(), 0);
54 
55  // Check for transparent handling of zero bytes.
56  db.set_metadata("foo", "value of foo");
57  db.set_metadata(string("foo\0bar", 7), string(1, '\0'));
58  db.set_metadata(string("foo\0", 4), string("foo\0bar", 7));
59 
60  TEST_EQUAL(db.get_metadata("foo"), "value of foo");
61  TEST_EQUAL(db.get_metadata(string("foo\0bar", 7)), string(1, '\0'));
62  TEST_EQUAL(db.get_metadata(string("foo\0", 4)), string("foo\0bar", 7));
63 
64  db.commit();
65 
66  TEST_EQUAL(db.get_metadata("foo"), "value of foo");
67  TEST_EQUAL(db.get_metadata(string("foo\0bar", 7)), string(1, '\0'));
68  TEST_EQUAL(db.get_metadata(string("foo\0", 4)), string("foo\0bar", 7));
69 }
70 
71 // Test that metadata gets applied at same time as other changes.
72 DEFINE_TESTCASE(metadata2, metadata && !inmemory) {
75 
76  TEST_EQUAL(db.get_metadata("foo"), "");
77  db.set_metadata("foo", "bar");
78  TEST_EQUAL(db.get_metadata("foo"), "bar");
79  TEST_EQUAL(dbr.get_metadata("foo"), "");
80  db.commit();
81  TEST_EQUAL(dbr.get_metadata("foo"), "");
82  TEST(dbr.reopen());
83  TEST_EQUAL(db.get_metadata("foo"), "bar");
84  TEST_EQUAL(dbr.get_metadata("foo"), "bar");
85  TEST_EQUAL(dbr.get_doccount(), 0);
86 
88  db.set_metadata("foo", "baz");
89  TEST_EQUAL(db.get_doccount(), 1);
90  TEST_EQUAL(db.get_metadata("foo"), "baz");
91  db.commit();
92 
93  TEST_EQUAL(dbr.get_metadata("foo"), "bar");
94  TEST(dbr.reopen());
95  TEST_EQUAL(dbr.get_metadata("foo"), "baz");
96 
97  db.set_metadata("foo", "");
98  TEST_EQUAL(db.get_metadata("foo"), "");
99  db.commit();
100  TEST_EQUAL(dbr.get_metadata("foo"), "baz");
101  TEST(dbr.reopen());
102  TEST_EQUAL(dbr.get_metadata("foo"), "");
103 
104  TEST_EQUAL(db.get_doccount(), 1);
105 }
106 
107 // Test the empty metadata keys give an error correctly.
108 DEFINE_TESTCASE(metadata3, metadata) {
110 
114 }
115 
116 // Regression test for adding a piece of metadata on its own before adding
117 // other things.
118 DEFINE_TESTCASE(metadata4, metadata && !inmemory) {
120 
121  db.set_metadata("foo", "foo");
122  db.commit();
123 
124  Xapian::Document doc;
125  doc.add_posting("foo", 1);
126  db.add_document(doc);
127 
129 }
130 
131 // Test metadata iterators.
132 DEFINE_TESTCASE(metadata5, writable) {
134 
135  // Check that iterator on empty database returns nothing.
137  iter = db.metadata_keys_begin();
138  TEST_EQUAL(iter, db.metadata_keys_end());
139 
140  // FIXME: inmemory doesn't implement metadata iterators yet, except in the
141  // trivial case of there being no keys to iterate.
142  SKIP_TEST_FOR_BACKEND("inmemory");
143 
144  try {
145  db.set_metadata("foo", "val");
146  } catch (const Xapian::UnimplementedError &) {
147  SKIP_TEST("Metadata not supported by this backend");
148  }
149  db.commit();
150 
151  // Check iterator on a database with only metadata items.
152  iter = db.metadata_keys_begin();
153  TEST(iter != db.metadata_keys_end());
154  TEST_EQUAL(*iter, "foo");
155  ++iter;
156  TEST(iter == db.metadata_keys_end());
157 
158  // Check iterator on a database with metadata items and documents.
159  Xapian::Document doc;
160  doc.add_posting("foo", 1);
161  db.add_document(doc);
162  db.commit();
163 
164  iter = db.metadata_keys_begin();
165  TEST(iter != db.metadata_keys_end());
166  TEST_EQUAL(*iter, "foo");
167  ++iter;
168  TEST(iter == db.metadata_keys_end());
169 
170  // Check iterator on a database with documents but no metadata. Also
171  // checks that setting metadata to empty stops the iterator returning it.
172  db.set_metadata("foo", "");
173  db.commit();
174  iter = db.metadata_keys_begin();
175  TEST(iter == db.metadata_keys_end());
176 
177  // Check use of a prefix, and skip_to.
178  db.set_metadata("a", "val");
179  db.set_metadata("foo", "val");
180  db.set_metadata("foo1", "val");
181  db.set_metadata("foo2", "val");
182  db.set_metadata("z", "val");
183  db.commit();
184 
185  iter = db.metadata_keys_begin();
186  TEST(iter != db.metadata_keys_end());
187  TEST_EQUAL(*iter, "a");
188  ++iter;
189  TEST(iter != db.metadata_keys_end());
190  TEST_EQUAL(*iter, "foo");
191  ++iter;
192  TEST(iter != db.metadata_keys_end());
193  TEST_EQUAL(*iter, "foo1");
194  ++iter;
195  TEST(iter != db.metadata_keys_end());
196  TEST_EQUAL(*iter, "foo2");
197  ++iter;
198  TEST(iter != db.metadata_keys_end());
199  TEST_EQUAL(*iter, "z");
200  ++iter;
201  TEST(iter == db.metadata_keys_end());
202 
203  iter = db.metadata_keys_begin("foo");
204  TEST(iter != db.metadata_keys_end("foo"));
205  TEST_EQUAL(*iter, "foo");
206  ++iter;
207  TEST(iter != db.metadata_keys_end("foo"));
208  TEST_EQUAL(*iter, "foo1");
209  ++iter;
210  TEST(iter != db.metadata_keys_end("foo"));
211  TEST_EQUAL(*iter, "foo2");
212  ++iter;
213  TEST(iter == db.metadata_keys_end("foo"));
214 
215  iter = db.metadata_keys_begin("foo1");
216  TEST(iter != db.metadata_keys_end("foo1"));
217  TEST_EQUAL(*iter, "foo1");
218  ++iter;
219  TEST(iter == db.metadata_keys_end("foo1"));
220 
221  iter = db.metadata_keys_begin();
222  TEST(iter != db.metadata_keys_end());
223  TEST_EQUAL(*iter, "a");
224 
225  // Skip to "" should move to the first key.
226  iter.skip_to("");
227  TEST(iter != db.metadata_keys_end());
228  TEST_EQUAL(*iter, "a");
229 
230  // This skip_to should skip the "foo" key.
231  iter.skip_to("foo1");
232  TEST(iter != db.metadata_keys_end());
233  TEST_EQUAL(*iter, "foo1");
234 
235  // Check that skipping to the current key works.
236  iter.skip_to("foo1");
237  TEST(iter != db.metadata_keys_end());
238  TEST_EQUAL(*iter, "foo1");
239 
240  // Check that skip_to a key before the current one doesn't move forwards.
241  iter.skip_to("a");
242  TEST(iter != db.metadata_keys_end());
243  TEST_REL(*iter, <=, "foo1");
244 
245  // Make sure we're back on foo1.
246  iter.skip_to("foo1");
247  TEST(iter != db.metadata_keys_end());
248  TEST_EQUAL(*iter, "foo1");
249 
250  // Check that advancing after a skip_to() works correctly.
251  ++iter;
252  TEST(iter != db.metadata_keys_end());
253  TEST_EQUAL(*iter, "foo2");
254 
255  // Check that skipping to a key after the last key works.
256  iter.skip_to("zoo");
257  TEST(iter == db.metadata_keys_end());
258 }
259 
261 DEFINE_TESTCASE(writeread1, writable && metadata) {
263  db_w.set_metadata("1", "2");
264  string longitem(20000, 'j');
265  db_w.set_metadata("2", longitem);
266 
267  string readitem = db_w.get_metadata("2");
268  TEST_EQUAL(readitem, longitem);
269 }
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
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:785
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
#define SKIP_TEST(MSG)
Skip the current testcase with message MSG.
Definition: testsuite.h:74
Xapian-specific test helper functions and macros.
DEFINE_TESTCASE(metadata1, writable)
Definition: api_metadata.cc:37
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:506