1 /** @file
2 * @brief tests which need a backend with positional information
3 */
4 /* Copyright 1999,2000,2001 BrightStation PLC
5 * Copyright 2002 Ananova Ltd
6 * Copyright 2002,2003,2004,2005,2006,2007,2009,2016 Olly Betts
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_posdb.h"
27
28 #include <string>
29 #include <vector>
30
31 using namespace std;
32
33 #include <xapian.h>
34 #include "testsuite.h"
35 #include "testutils.h"
36
37 #include "apitest.h"
38
39 /// Simple test of NEAR
DEFINE_TESTCASE(near1,positional)40 DEFINE_TESTCASE(near1, positional) {
41 Xapian::Database mydb(get_database("apitest_phrase"));
42 Xapian::Enquire enquire(mydb);
43 Xapian::Stem stemmer("english");
44 enquire.set_weighting_scheme(Xapian::BoolWeight());
45
46 // make a query
47 vector<Xapian::Query> subqs;
48 Xapian::Query q;
49 subqs.push_back(Xapian::Query(stemmer("phrase")));
50 subqs.push_back(Xapian::Query(stemmer("fridge")));
51 q = Xapian::Query(Xapian::Query::OP_PHRASE, subqs.begin(), subqs.end(), 2);
52 enquire.set_query(q);
53
54 // retrieve the top ten results
55 Xapian::MSet mymset = enquire.get_mset(0, 10);
56 mset_expect_order(mymset);
57
58 subqs.clear();
59 subqs.push_back(Xapian::Query(stemmer("phrase")));
60 subqs.push_back(Xapian::Query(stemmer("near")));
61 q = Xapian::Query(Xapian::Query::OP_NEAR, subqs.begin(), subqs.end(), 2);
62 enquire.set_query(q);
63
64 // retrieve the top ten results
65 mymset = enquire.get_mset(0, 10);
66 mset_expect_order(mymset, 3);
67
68 subqs.clear();
69 subqs.push_back(Xapian::Query(stemmer("phrase")));
70 subqs.push_back(Xapian::Query(stemmer("near")));
71 q = Xapian::Query(Xapian::Query::OP_NEAR, subqs.begin(), subqs.end(), 3);
72 enquire.set_query(q);
73
74 // retrieve the top ten results
75 mymset = enquire.get_mset(0, 10);
76 mset_expect_order(mymset, 1, 3);
77
78 subqs.clear();
79 subqs.push_back(Xapian::Query(stemmer("phrase")));
80 subqs.push_back(Xapian::Query(stemmer("near")));
81 q = Xapian::Query(Xapian::Query::OP_NEAR, subqs.begin(), subqs.end(), 5);
82 enquire.set_query(q);
83
84 // retrieve the top ten results
85 mymset = enquire.get_mset(0, 10);
86 mset_expect_order(mymset, 1, 3);
87
88 subqs.clear();
89 subqs.push_back(Xapian::Query(stemmer("phrase")));
90 subqs.push_back(Xapian::Query(stemmer("near")));
91 q = Xapian::Query(Xapian::Query::OP_NEAR, subqs.begin(), subqs.end(), 6);
92 enquire.set_query(q);
93
94 // retrieve the top ten results
95 mymset = enquire.get_mset(0, 10);
96 mset_expect_order(mymset, 1, 2, 3);
97
98 subqs.clear();
99 subqs.push_back(Xapian::Query(stemmer("leave")));
100 subqs.push_back(Xapian::Query(stemmer("fridge")));
101 subqs.push_back(Xapian::Query(stemmer("on")));
102 q = Xapian::Query(Xapian::Query::OP_NEAR, subqs.begin(), subqs.end(), 3);
103 enquire.set_query(q);
104
105 // retrieve the top ten results
106 mymset = enquire.get_mset(0, 10);
107 mset_expect_order(mymset, 4, 5, 6, 7, 8, 9);
108
109 subqs.clear();
110 subqs.push_back(Xapian::Query(stemmer("leave")));
111 subqs.push_back(Xapian::Query(stemmer("fridge")));
112 subqs.push_back(Xapian::Query(stemmer("on")));
113 q = Xapian::Query(Xapian::Query::OP_NEAR, subqs.begin(), subqs.end(), 4);
114 enquire.set_query(q);
115
116 // retrieve the top ten results
117 mymset = enquire.get_mset(0, 10);
118 mset_expect_order(mymset, 4, 5, 6, 7, 8, 9, 10);
119
120 subqs.clear();
121 subqs.push_back(Xapian::Query(stemmer("leave")));
122 subqs.push_back(Xapian::Query(stemmer("fridge")));
123 subqs.push_back(Xapian::Query(stemmer("on")));
124 q = Xapian::Query(Xapian::Query::OP_NEAR, subqs.begin(), subqs.end(), 5);
125 enquire.set_query(q);
126
127 // retrieve the top ten results
128 mymset = enquire.get_mset(0, 10);
129 mset_expect_order(mymset, 4, 5, 6, 7, 8, 9, 10, 11);
130
131 subqs.clear();
132 subqs.push_back(Xapian::Query(stemmer("leave")));
133 subqs.push_back(Xapian::Query(stemmer("fridge")));
134 subqs.push_back(Xapian::Query(stemmer("on")));
135 q = Xapian::Query(Xapian::Query::OP_NEAR, subqs.begin(), subqs.end(), 6);
136 enquire.set_query(q);
137
138 // retrieve the top ten results
139 mymset = enquire.get_mset(0, 10);
140 mset_expect_order(mymset, 4, 5, 6, 7, 8, 9, 10, 11, 12);
141
142 subqs.clear();
143 subqs.push_back(Xapian::Query(stemmer("leave")));
144 subqs.push_back(Xapian::Query(stemmer("fridge")));
145 subqs.push_back(Xapian::Query(stemmer("on")));
146 q = Xapian::Query(Xapian::Query::OP_NEAR, subqs.begin(), subqs.end(), 7);
147 enquire.set_query(q);
148
149 // retrieve the top twenty results
150 mymset = enquire.get_mset(0, 20);
151 mset_expect_order(mymset, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13);
152
153 subqs.clear();
154 subqs.push_back(Xapian::Query(stemmer("leave")));
155 subqs.push_back(Xapian::Query(stemmer("fridge")));
156 subqs.push_back(Xapian::Query(stemmer("on")));
157 q = Xapian::Query(Xapian::Query::OP_NEAR, subqs.begin(), subqs.end(), 8);
158 enquire.set_query(q);
159
160 // retrieve the top twenty results
161 mymset = enquire.get_mset(0, 20);
162 mset_expect_order(mymset, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14);
163
164 subqs.clear();
165 subqs.push_back(Xapian::Query(stemmer("leave")));
166 subqs.push_back(Xapian::Query(stemmer("fridge")));
167 subqs.push_back(Xapian::Query(stemmer("on")));
168 // test really large window size
169 q = Xapian::Query(Xapian::Query::OP_NEAR, subqs.begin(), subqs.end(), 999999999);
170 enquire.set_query(q);
171
172 // retrieve the top twenty results
173 mymset = enquire.get_mset(0, 20);
174 mset_expect_order(mymset, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14);
175 }
176
177 /// Test NEAR over operators
DEFINE_TESTCASE(near2,positional)178 DEFINE_TESTCASE(near2, positional) {
179 Xapian::Database mydb(get_database("apitest_phrase"));
180 Xapian::Enquire enquire(mydb);
181 Xapian::Stem stemmer("english");
182 enquire.set_weighting_scheme(Xapian::BoolWeight());
183 Xapian::MSet mymset;
184
185 // make a query
186 vector<Xapian::Query> subqs;
187 Xapian::Query q;
188 subqs.push_back(Xapian::Query(Xapian::Query::OP_AND,
189 Xapian::Query(stemmer("phrase")),
190 Xapian::Query(stemmer("near"))));
191 subqs.push_back(Xapian::Query(stemmer("and")));
192 TEST_EXCEPTION(Xapian::UnimplementedError,
193 q = Xapian::Query(q.OP_NEAR, subqs.begin(), subqs.end(), 2);
194 enquire.set_query(q);
195
196 // retrieve the top ten results
197 mymset = enquire.get_mset(0, 10)
198 );
199 #if 0 // Disable until we reimplement this.
200 mset_expect_order(mymset, 1);
201
202 subqs.clear();
203 subqs.push_back(Xapian::Query(Xapian::Query::OP_AND,
204 Xapian::Query(stemmer("phrase")),
205 Xapian::Query(stemmer("near"))));
206 subqs.push_back(Xapian::Query(stemmer("operator")));
207 q = Xapian::Query(Xapian::Query::OP_NEAR, subqs.begin(), subqs.end(), 2);
208 enquire.set_query(q);
209
210 // retrieve the top ten results
211 mymset = enquire.get_mset(0, 10);
212 mset_expect_order(mymset, 2);
213
214 subqs.clear();
215 subqs.push_back(Xapian::Query(stemmer("operator")));
216 subqs.push_back(Xapian::Query(Xapian::Query::OP_AND,
217 Xapian::Query(stemmer("phrase")),
218 Xapian::Query(stemmer("near"))));
219 q = Xapian::Query(Xapian::Query::OP_NEAR, subqs.begin(), subqs.end(), 2);
220 enquire.set_query(q);
221
222 // retrieve the top ten results
223 mymset = enquire.get_mset(0, 10);
224 mset_expect_order(mymset, 2);
225 #endif
226 }
227
228 /// Simple test of PHRASE
DEFINE_TESTCASE(phrase1,positional)229 DEFINE_TESTCASE(phrase1, positional) {
230 Xapian::Database mydb(get_database("apitest_phrase"));
231 Xapian::Enquire enquire(mydb);
232 Xapian::Stem stemmer("english");
233 enquire.set_weighting_scheme(Xapian::BoolWeight());
234
235 // make a query
236 vector<Xapian::Query> subqs;
237 Xapian::Query q;
238 subqs.push_back(Xapian::Query(stemmer("phrase")));
239 subqs.push_back(Xapian::Query(stemmer("fridge")));
240 q = Xapian::Query(Xapian::Query::OP_PHRASE, subqs.begin(), subqs.end(), 2);
241 enquire.set_query(q);
242
243 // retrieve the top ten results
244 Xapian::MSet mymset = enquire.get_mset(0, 10);
245 mset_expect_order(mymset);
246
247 subqs.clear();
248 subqs.push_back(Xapian::Query(stemmer("phrase")));
249 subqs.push_back(Xapian::Query(stemmer("near")));
250 q = Xapian::Query(Xapian::Query::OP_PHRASE, subqs.begin(), subqs.end(), 2);
251 enquire.set_query(q);
252
253 // retrieve the top ten results
254 mymset = enquire.get_mset(0, 10);
255 mset_expect_order(mymset);
256
257 subqs.clear();
258 subqs.push_back(Xapian::Query(stemmer("phrase")));
259 subqs.push_back(Xapian::Query(stemmer("near")));
260 q = Xapian::Query(Xapian::Query::OP_PHRASE, subqs.begin(), subqs.end(), 3);
261 enquire.set_query(q);
262
263 // retrieve the top ten results
264 mymset = enquire.get_mset(0, 10);
265 mset_expect_order(mymset, 1);
266
267 subqs.clear();
268 subqs.push_back(Xapian::Query(stemmer("phrase")));
269 subqs.push_back(Xapian::Query(stemmer("near")));
270 q = Xapian::Query(Xapian::Query::OP_PHRASE, subqs.begin(), subqs.end(), 5);
271 enquire.set_query(q);
272
273 // retrieve the top ten results
274 mymset = enquire.get_mset(0, 10);
275 mset_expect_order(mymset, 1);
276
277 subqs.clear();
278 subqs.push_back(Xapian::Query(stemmer("phrase")));
279 subqs.push_back(Xapian::Query(stemmer("near")));
280 q = Xapian::Query(Xapian::Query::OP_PHRASE, subqs.begin(), subqs.end(), 6);
281 enquire.set_query(q);
282
283 // retrieve the top ten results
284 mymset = enquire.get_mset(0, 10);
285 mset_expect_order(mymset, 1, 2);
286
287 subqs.clear();
288 subqs.push_back(Xapian::Query(stemmer("leave")));
289 subqs.push_back(Xapian::Query(stemmer("fridge")));
290 subqs.push_back(Xapian::Query(stemmer("on")));
291 q = Xapian::Query(Xapian::Query::OP_PHRASE, subqs.begin(), subqs.end(), 3);
292 enquire.set_query(q);
293
294 // retrieve the top ten results
295 mymset = enquire.get_mset(0, 10);
296 mset_expect_order(mymset, 4);
297
298 subqs.clear();
299 subqs.push_back(Xapian::Query(stemmer("leave")));
300 subqs.push_back(Xapian::Query(stemmer("fridge")));
301 subqs.push_back(Xapian::Query(stemmer("on")));
302 q = Xapian::Query(Xapian::Query::OP_PHRASE, subqs.begin(), subqs.end(), 4);
303 enquire.set_query(q);
304
305 // retrieve the top ten results
306 mymset = enquire.get_mset(0, 10);
307 mset_expect_order(mymset, 4);
308
309 subqs.clear();
310 subqs.push_back(Xapian::Query(stemmer("leave")));
311 subqs.push_back(Xapian::Query(stemmer("fridge")));
312 subqs.push_back(Xapian::Query(stemmer("on")));
313 q = Xapian::Query(Xapian::Query::OP_PHRASE, subqs.begin(), subqs.end(), 5);
314 enquire.set_query(q);
315
316 // retrieve the top ten results
317 mymset = enquire.get_mset(0, 10);
318 mset_expect_order(mymset, 4);
319
320 subqs.clear();
321 subqs.push_back(Xapian::Query(stemmer("leave")));
322 subqs.push_back(Xapian::Query(stemmer("fridge")));
323 subqs.push_back(Xapian::Query(stemmer("on")));
324 q = Xapian::Query(Xapian::Query::OP_PHRASE, subqs.begin(), subqs.end(), 6);
325 enquire.set_query(q);
326
327 // retrieve the top ten results
328 mymset = enquire.get_mset(0, 10);
329 mset_expect_order(mymset, 4);
330
331 subqs.clear();
332 subqs.push_back(Xapian::Query(stemmer("leave")));
333 subqs.push_back(Xapian::Query(stemmer("fridge")));
334 subqs.push_back(Xapian::Query(stemmer("on")));
335 q = Xapian::Query(Xapian::Query::OP_PHRASE, subqs.begin(), subqs.end(), 7);
336 enquire.set_query(q);
337
338 // retrieve the top twenty results
339 mymset = enquire.get_mset(0, 20);
340 mset_expect_order(mymset, 4);
341
342 subqs.clear();
343 subqs.push_back(Xapian::Query(stemmer("leave")));
344 subqs.push_back(Xapian::Query(stemmer("fridge")));
345 subqs.push_back(Xapian::Query(stemmer("on")));
346 q = Xapian::Query(Xapian::Query::OP_PHRASE, subqs.begin(), subqs.end(), 8);
347 enquire.set_query(q);
348
349 // retrieve the top 20 results
350 mymset = enquire.get_mset(0, 20);
351 mset_expect_order(mymset, 4);
352
353 // test really large window size
354 subqs.clear();
355 subqs.push_back(Xapian::Query(stemmer("leave")));
356 subqs.push_back(Xapian::Query(stemmer("fridge")));
357 subqs.push_back(Xapian::Query(stemmer("on")));
358 q = Xapian::Query(Xapian::Query::OP_PHRASE, subqs.begin(), subqs.end(), 999999999);
359 enquire.set_query(q);
360
361 // retrieve the top 20 results
362 mymset = enquire.get_mset(0, 20);
363 mset_expect_order(mymset, 4);
364
365 // regression test (was matching doc 15, should fail)
366 subqs.clear();
367 subqs.push_back(Xapian::Query(stemmer("first")));
368 subqs.push_back(Xapian::Query(stemmer("second")));
369 subqs.push_back(Xapian::Query(stemmer("third")));
370 q = Xapian::Query(Xapian::Query::OP_PHRASE, subqs.begin(), subqs.end(), 9);
371 enquire.set_query(q);
372
373 // retrieve the top ten results
374 mymset = enquire.get_mset(0, 10);
375 mset_expect_order(mymset);
376
377 // regression test (should match doc 15, make sure still does with fix)
378 subqs.clear();
379 subqs.push_back(Xapian::Query(stemmer("first")));
380 subqs.push_back(Xapian::Query(stemmer("second")));
381 subqs.push_back(Xapian::Query(stemmer("third")));
382 q = Xapian::Query(Xapian::Query::OP_PHRASE, subqs.begin(), subqs.end(), 10);
383 enquire.set_query(q);
384
385 // retrieve the top ten results
386 mymset = enquire.get_mset(0, 10);
387 mset_expect_order(mymset, 15);
388
389 // regression test (phrase matching was getting order wrong when
390 // build_and_tree reordered vector of PostLists)
391 subqs.clear();
392 subqs.push_back(Xapian::Query(stemmer("milk")));
393 subqs.push_back(Xapian::Query(stemmer("rare")));
394 q = Xapian::Query(Xapian::Query::OP_PHRASE, subqs.begin(), subqs.end(), 2);
395 enquire.set_query(q);
396
397 // retrieve the top ten results
398 mymset = enquire.get_mset(0, 10);
399 mset_expect_order(mymset, 16);
400
401 // regression test (phrase matching was getting order wrong when
402 // build_and_tree reordered vector of PostLists)
403 subqs.clear();
404 subqs.push_back(Xapian::Query(stemmer("rare")));
405 subqs.push_back(Xapian::Query(stemmer("milk")));
406 q = Xapian::Query(Xapian::Query::OP_PHRASE, subqs.begin(), subqs.end(), 2);
407 enquire.set_query(q);
408
409 // retrieve the top ten results
410 mymset = enquire.get_mset(0, 10);
411 mset_expect_order(mymset, 17);
412 }
413
414 /// Test PHRASE over operators
DEFINE_TESTCASE(phrase2,positional)415 DEFINE_TESTCASE(phrase2, positional) {
416 Xapian::Database mydb(get_database("apitest_phrase"));
417 Xapian::Enquire enquire(mydb);
418 Xapian::Stem stemmer("english");
419 enquire.set_weighting_scheme(Xapian::BoolWeight());
420 Xapian::MSet mymset;
421
422 // make a query
423 vector<Xapian::Query> subqs;
424 Xapian::Query q;
425 subqs.push_back(Xapian::Query(Xapian::Query::OP_AND,
426 Xapian::Query(stemmer("phrase")),
427 Xapian::Query(stemmer("near"))));
428 subqs.push_back(Xapian::Query(stemmer("and")));
429 TEST_EXCEPTION(Xapian::UnimplementedError,
430 q = Xapian::Query(q.OP_PHRASE, subqs.begin(), subqs.end(), 2);
431 enquire.set_query(q);
432
433 // retrieve the top ten results
434 mymset = enquire.get_mset(0, 10)
435 );
436 #if 0 // Disable until we reimplement this.
437 mset_expect_order(mymset);
438
439 subqs.clear();
440 subqs.push_back(Xapian::Query(Xapian::Query::OP_AND,
441 Xapian::Query(stemmer("phrase")),
442 Xapian::Query(stemmer("near"))));
443 subqs.push_back(Xapian::Query(stemmer("operator")));
444 q = Xapian::Query(Xapian::Query::OP_PHRASE, subqs.begin(), subqs.end(), 2);
445 enquire.set_query(q);
446
447 // retrieve the top ten results
448 mymset = enquire.get_mset(0, 10);
449 mset_expect_order(mymset, 2);
450
451 subqs.clear();
452 subqs.push_back(Xapian::Query(stemmer("operator")));
453 subqs.push_back(Xapian::Query(Xapian::Query::OP_AND,
454 Xapian::Query(stemmer("phrase")),
455 Xapian::Query(stemmer("near"))));
456 q = Xapian::Query(Xapian::Query::OP_PHRASE, subqs.begin(), subqs.end(), 2);
457 enquire.set_query(q);
458
459 // retrieve the top ten results
460 mymset = enquire.get_mset(0, 10);
461 mset_expect_order(mymset);
462 #endif
463 }
464
465 /// Test getting position lists from databases
DEFINE_TESTCASE(poslist1,positional)466 DEFINE_TESTCASE(poslist1, positional) {
467 Xapian::Database mydb(get_database("apitest_poslist"));
468
469 Xapian::Stem stemmer("english");
470 string term = stemmer("sponge");
471
472 Xapian::PositionIterator pli = mydb.positionlist_begin(2, term);
473
474 TEST(pli != mydb.positionlist_end(2, term));
475 TEST_EQUAL(*pli, 1);
476 pli++;
477 TEST(pli != mydb.positionlist_end(2, term));
478 TEST_EQUAL(*pli, 2);
479 pli++;
480 TEST(pli != mydb.positionlist_end(2, term));
481 TEST_EQUAL(*pli, 3);
482 pli++;
483 TEST(pli != mydb.positionlist_end(2, term));
484 TEST_EQUAL(*pli, 5);
485 pli++;
486 TEST(pli != mydb.positionlist_end(2, term));
487 TEST_EQUAL(*pli, 8);
488 pli++;
489 TEST(pli != mydb.positionlist_end(2, term));
490 TEST_EQUAL(*pli, 13);
491 pli++;
492 TEST(pli != mydb.positionlist_end(2, term));
493 TEST_EQUAL(*pli, 21);
494 pli++;
495 TEST(pli != mydb.positionlist_end(2, term));
496 TEST_EQUAL(*pli, 34);
497 pli++;
498 TEST(pli == mydb.positionlist_end(2, term));
499 }
500
DEFINE_TESTCASE(poslist2,positional && writable)501 DEFINE_TESTCASE(poslist2, positional && writable) {
502 Xapian::WritableDatabase db = get_writable_database();
503
504 Xapian::Document doc;
505 doc.add_term("nopos");
506 Xapian::docid did = db.add_document(doc);
507
508 // Check what happens when term doesn't exist - should give an empty list.
509 // Threw RangeError in Xapian < 1.1.0.
510 TEST_EQUAL(db.positionlist_begin(did, "nosuchterm"),
511 db.positionlist_end(did, "nosuchterm"));
512
513 // Check what happens when the document doesn't even exist - should give
514 // an empty list. Threw DocNotFoundError in Xapian < 1.1.0.
515 TEST_EQUAL(db.positionlist_begin(123, "nosuchterm"),
516 db.positionlist_end(123, "nosuchterm"));
517
518 TEST_EQUAL(db.positionlist_begin(did, "nopos"),
519 db.positionlist_end(did, "nopos"));
520
521 Xapian::Document doc2 = db.get_document(did);
522
523 Xapian::TermIterator term = doc2.termlist_begin();
524
525 {
526 Xapian::PositionIterator i = term.positionlist_begin();
527 TEST_EQUAL(i, term.positionlist_end());
528 }
529
530 Xapian::Document doc3;
531 doc3.add_posting("hadpos", 1);
532 Xapian::docid did2 = db.add_document(doc3);
533
534 Xapian::Document doc4 = db.get_document(did2);
535 doc4.remove_posting("hadpos", 1);
536 db.replace_document(did2, doc4);
537
538 {
539 Xapian::PositionIterator i = db.positionlist_begin(did2, "hadpos");
540 TEST_EQUAL(i, db.positionlist_end(did2, "hadpos"));
541 }
542
543 db.delete_document(did);
544 // Check what happens when the document doesn't exist (but once did).
545 TEST_EQUAL(db.positionlist_begin(did, "nosuchterm"),
546 db.positionlist_end(did, "nosuchterm"));
547 }
548
549 /// Test playing with a positionlist, testing skip_to in particular.
550 /// (used to be quartztest's test_positionlist1).
DEFINE_TESTCASE(poslist3,positional && writable)551 DEFINE_TESTCASE(poslist3, positional && writable) {
552 Xapian::WritableDatabase db = get_writable_database();
553
554 Xapian::Document document;
555 document.add_posting("foo", 5);
556 document.add_posting("foo", 8);
557 document.add_posting("foo", 10);
558 document.add_posting("foo", 12);
559 db.add_document(document);
560
561 Xapian::PositionIterator pl = db.positionlist_begin(1, "foo");
562 Xapian::PositionIterator pl_end = db.positionlist_end(1, "foo");
563
564 TEST(pl != pl_end);
565 TEST_EQUAL(*pl, 5);
566 ++pl;
567 TEST(pl != pl_end);
568 TEST_EQUAL(*pl, 8);
569 ++pl;
570 TEST(pl != pl_end);
571 TEST_EQUAL(*pl, 10);
572 ++pl;
573 TEST(pl != pl_end);
574 TEST_EQUAL(*pl, 12);
575 ++pl;
576 TEST(pl == pl_end);
577
578 pl = db.positionlist_begin(1, "foo");
579 pl.skip_to(5);
580 TEST(pl != pl_end);
581 TEST_EQUAL(*pl, 5);
582
583 pl.skip_to(9);
584 TEST(pl != pl_end);
585 TEST_EQUAL(*pl, 10);
586
587 ++pl;
588 TEST(pl != pl_end);
589 TEST_EQUAL(*pl, 12);
590
591 pl.skip_to(12);
592 TEST(pl != pl_end);
593 TEST_EQUAL(*pl, 12);
594
595 pl.skip_to(13);
596 TEST(pl == pl_end);
597 }
598
599 // Regression test - in 0.9.4 (and many previous versions) you couldn't get a
600 // PositionIterator from a TermIterator from Database::termlist_begin().
601 //
602 // Also test that positionlist_count() is implemented for this case, which it
603 // wasn't in 1.0.2 and earlier.
DEFINE_TESTCASE(positfromtermit1,positional)604 DEFINE_TESTCASE(positfromtermit1, positional) {
605 Xapian::Database db(get_database("apitest_phrase"));
606 Xapian::TermIterator t(db.termlist_begin(7));
607 TEST_NOT_EQUAL(t, db.termlist_end(7));
608 Xapian::PositionIterator p = t.positionlist_begin();
609 TEST_NOT_EQUAL(p, t.positionlist_end());
610
611 try {
612 TEST_EQUAL(t.positionlist_count(), 1);
613 t.skip_to("on");
614 TEST_NOT_EQUAL(t, db.termlist_end(7));
615 TEST_EQUAL(t.positionlist_count(), 2);
616 } catch (const Xapian::UnimplementedError &) {
617 SKIP_TEST("TermList::positionlist_count() not yet implemented for this backend");
618 }
619 }
620