Document xapian-compact --blocksize takes an argument
[xapian.git] / xapian-core / tests / api_metadata.cc
blobeb6b20d65bb63b9b1d6076d6b3c2555a4df84427
1 /** @file api_metadata.cc
2 * @brief Test the user metadata functionality.
3 */
4 /* Copyright (C) 2007,2009,2011 Olly Betts
5 * Copyright (C) 2007,2008,2009 Lemur Consulting Ltd
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.
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.
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
22 #include <config.h>
24 #include "api_metadata.h"
26 #include <xapian.h>
28 #include "apitest.h"
29 #include "testsuite.h"
30 #include "testutils.h"
32 #include <string>
34 using namespace std;
36 // Test basic metadata access methods.
37 DEFINE_TESTCASE(metadata1, writable) {
38 Xapian::WritableDatabase db = get_writable_database();
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");
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"), "");
53 TEST_EQUAL(db.get_doccount(), 0);
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));
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));
64 db.commit();
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));
70 return true;
73 // Test that metadata gets applied at same time as other changes.
74 DEFINE_TESTCASE(metadata2, metadata && !inmemory) {
75 Xapian::WritableDatabase db = get_writable_database();
76 Xapian::Database dbr = get_writable_database_as_database();
78 TEST_EQUAL(db.get_metadata("foo"), "");
79 db.set_metadata("foo", "bar");
80 TEST_EQUAL(db.get_metadata("foo"), "bar");
81 TEST_EQUAL(dbr.get_metadata("foo"), "");
82 db.commit();
83 TEST_EQUAL(dbr.get_metadata("foo"), "");
84 TEST(dbr.reopen());
85 TEST_EQUAL(db.get_metadata("foo"), "bar");
86 TEST_EQUAL(dbr.get_metadata("foo"), "bar");
87 TEST_EQUAL(dbr.get_doccount(), 0);
89 db.add_document(Xapian::Document());
90 db.set_metadata("foo", "baz");
91 TEST_EQUAL(db.get_doccount(), 1);
92 TEST_EQUAL(db.get_metadata("foo"), "baz");
93 db.commit();
95 TEST_EQUAL(dbr.get_metadata("foo"), "bar");
96 TEST(dbr.reopen());
97 TEST_EQUAL(dbr.get_metadata("foo"), "baz");
99 db.set_metadata("foo", "");
100 TEST_EQUAL(db.get_metadata("foo"), "");
101 db.commit();
102 TEST_EQUAL(dbr.get_metadata("foo"), "baz");
103 TEST(dbr.reopen());
104 TEST_EQUAL(dbr.get_metadata("foo"), "");
106 TEST_EQUAL(db.get_doccount(), 1);
108 return true;
111 // Test the empty metadata keys give an error correctly.
112 DEFINE_TESTCASE(metadata3, metadata) {
113 Xapian::WritableDatabase db = get_writable_database();
115 TEST_EXCEPTION(Xapian::InvalidArgumentError, db.get_metadata(""));
116 TEST_EXCEPTION(Xapian::InvalidArgumentError, db.set_metadata("", "foo"));
117 TEST_EXCEPTION(Xapian::InvalidArgumentError, db.get_metadata(""));
119 return true;
122 // Regression test for adding a piece of metadata on its own before adding
123 // other things.
124 DEFINE_TESTCASE(metadata4, metadata && !inmemory) {
125 Xapian::WritableDatabase db = get_writable_database();
127 db.set_metadata("foo", "foo");
128 db.commit();
130 Xapian::Document doc;
131 doc.add_posting("foo", 1);
132 db.add_document(doc);
134 Xapian::Database dbr(get_writable_database_as_database());
136 return true;
139 // Test metadata iterators.
140 DEFINE_TESTCASE(metadata5, writable) {
141 Xapian::WritableDatabase db = get_writable_database();
143 // Check that iterator on empty database returns nothing.
144 Xapian::TermIterator iter;
145 iter = db.metadata_keys_begin();
146 TEST_EQUAL(iter, db.metadata_keys_end());
148 // FIXME: inmemory doesn't implement metadata iterators yet, except in the
149 // trivial case of there being no keys to iterate.
150 SKIP_TEST_FOR_BACKEND("inmemory");
152 try {
153 db.set_metadata("foo", "val");
154 } catch (const Xapian::UnimplementedError &) {
155 SKIP_TEST("Metadata not supported by this backend");
157 db.commit();
159 // Check iterator on a database with only metadata items.
160 iter = db.metadata_keys_begin();
161 TEST(iter != db.metadata_keys_end());
162 TEST_EQUAL(*iter, "foo");
163 ++iter;
164 TEST(iter == db.metadata_keys_end());
166 // Check iterator on a database with metadata items and documents.
167 Xapian::Document doc;
168 doc.add_posting("foo", 1);
169 db.add_document(doc);
170 db.commit();
172 iter = db.metadata_keys_begin();
173 TEST(iter != db.metadata_keys_end());
174 TEST_EQUAL(*iter, "foo");
175 ++iter;
176 TEST(iter == db.metadata_keys_end());
178 // Check iterator on a database with documents but no metadata. Also
179 // checks that setting metadata to empty stops the iterator returning it.
180 db.set_metadata("foo", "");
181 db.commit();
182 iter = db.metadata_keys_begin();
183 TEST(iter == db.metadata_keys_end());
185 // Check use of a prefix, and skip_to.
186 db.set_metadata("a", "val");
187 db.set_metadata("foo", "val");
188 db.set_metadata("foo1", "val");
189 db.set_metadata("foo2", "val");
190 db.set_metadata("z", "val");
191 db.commit();
193 iter = db.metadata_keys_begin();
194 TEST(iter != db.metadata_keys_end());
195 TEST_EQUAL(*iter, "a");
196 ++iter;
197 TEST(iter != db.metadata_keys_end());
198 TEST_EQUAL(*iter, "foo");
199 ++iter;
200 TEST(iter != db.metadata_keys_end());
201 TEST_EQUAL(*iter, "foo1");
202 ++iter;
203 TEST(iter != db.metadata_keys_end());
204 TEST_EQUAL(*iter, "foo2");
205 ++iter;
206 TEST(iter != db.metadata_keys_end());
207 TEST_EQUAL(*iter, "z");
208 ++iter;
209 TEST(iter == db.metadata_keys_end());
211 iter = db.metadata_keys_begin("foo");
212 TEST(iter != db.metadata_keys_end("foo"));
213 TEST_EQUAL(*iter, "foo");
214 ++iter;
215 TEST(iter != db.metadata_keys_end("foo"));
216 TEST_EQUAL(*iter, "foo1");
217 ++iter;
218 TEST(iter != db.metadata_keys_end("foo"));
219 TEST_EQUAL(*iter, "foo2");
220 ++iter;
221 TEST(iter == db.metadata_keys_end("foo"));
223 iter = db.metadata_keys_begin("foo1");
224 TEST(iter != db.metadata_keys_end("foo1"));
225 TEST_EQUAL(*iter, "foo1");
226 ++iter;
227 TEST(iter == db.metadata_keys_end("foo1"));
229 iter = db.metadata_keys_begin();
230 TEST(iter != db.metadata_keys_end());
231 TEST_EQUAL(*iter, "a");
233 // Skip to "" should move to the first key.
234 iter.skip_to("");
235 TEST(iter != db.metadata_keys_end());
236 TEST_EQUAL(*iter, "a");
238 // This skip_to should skip the "foo" key.
239 iter.skip_to("foo1");
240 TEST(iter != db.metadata_keys_end());
241 TEST_EQUAL(*iter, "foo1");
243 // Check that skipping to the current key works.
244 iter.skip_to("foo1");
245 TEST(iter != db.metadata_keys_end());
246 TEST_EQUAL(*iter, "foo1");
248 // Check that skip_to a key before the current one doesn't move forwards.
249 iter.skip_to("a");
250 TEST(iter != db.metadata_keys_end());
251 TEST_REL(*iter, <=, "foo1");
253 // Make sure we're back on foo1.
254 iter.skip_to("foo1");
255 TEST(iter != db.metadata_keys_end());
256 TEST_EQUAL(*iter, "foo1");
258 // Check that advancing after a skip_to() works correctly.
259 ++iter;
260 TEST(iter != db.metadata_keys_end());
261 TEST_EQUAL(*iter, "foo2");
263 // Check that skipping to a key after the last key works.
264 iter.skip_to("zoo");
265 TEST(iter == db.metadata_keys_end());
267 return true;
270 /// Regression test of reading after writing but not committing.
271 DEFINE_TESTCASE(writeread1, writable && metadata) {
272 Xapian::WritableDatabase db_w = get_writable_database();
273 db_w.set_metadata("1", "2");
274 string longitem(20000, 'j');
275 db_w.set_metadata("2", longitem);
277 string readitem = db_w.get_metadata("2");
278 TEST_EQUAL(readitem, longitem);
280 return true;