Remove unused header include
[xapian.git] / xapian-core / tests / api_none.cc
bloba3dbb608ef1ec732bad52092c73086106ac1b74a
1 /** @file api_none.cc
2 * @brief tests which don't need a backend
3 */
4 /* Copyright (C) 2009 Richard Boulton
5 * Copyright (C) 2009,2010,2011,2013,2014,2015,2016 Olly Betts
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of the
10 * License, or (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
20 * USA
23 #include <config.h>
25 #include "api_none.h"
27 #define XAPIAN_DEPRECATED(D) D
28 #include <xapian.h>
30 #include "apitest.h"
31 #include "str.h"
32 #include "testsuite.h"
33 #include "testutils.h"
35 using namespace std;
37 // Check the version functions give consistent results.
38 DEFINE_TESTCASE(version1, !backend) {
39 string version = str(Xapian::major_version());
40 version += '.';
41 version += str(Xapian::minor_version());
42 version += '.';
43 version += str(Xapian::revision());
44 TEST_EQUAL(Xapian::version_string(), version);
45 return true;
48 // Regression test: various methods on Database() used to segfault or cause
49 // division by 0. Fixed in 1.1.4 and 1.0.18. Ticket#415.
50 DEFINE_TESTCASE(nosubdatabases1, !backend) {
51 Xapian::Database db;
52 // Fails to compile with g++ 3.3.5 on OpenBSD (ticket#458):
53 // TEST_EQUAL(db.get_metadata("foo"), std::string());
54 TEST(db.get_metadata("foo").empty());
55 TEST_EQUAL(db.metadata_keys_begin(), db.metadata_keys_end());
56 TEST_EXCEPTION(Xapian::InvalidOperationError, db.termlist_begin(1));
57 TEST_EQUAL(db.allterms_begin(), db.allterms_end());
58 TEST_EQUAL(db.allterms_begin("foo"), db.allterms_end("foo"));
59 TEST_EXCEPTION(Xapian::InvalidOperationError, db.positionlist_begin(1, "foo"));
60 TEST_EQUAL(db.get_lastdocid(), 0);
61 TEST_EQUAL(db.valuestream_begin(7), db.valuestream_end(7));
62 TEST_EXCEPTION(Xapian::InvalidOperationError, db.get_doclength(1));
63 TEST_EXCEPTION(Xapian::InvalidOperationError, db.get_unique_terms(1));
64 TEST_EXCEPTION(Xapian::InvalidOperationError, db.get_document(1));
65 return true;
68 /// Feature test for Document::add_boolean_term(), new in 1.0.18/1.1.4.
69 DEFINE_TESTCASE(document1, !backend) {
70 Xapian::Document doc;
71 doc.add_boolean_term("Hxapian.org");
72 TEST_EQUAL(doc.termlist_count(), 1);
73 Xapian::TermIterator t = doc.termlist_begin();
74 TEST(t != doc.termlist_end());
75 TEST_EQUAL(*t, "Hxapian.org");
76 TEST_EQUAL(t.get_wdf(), 0);
77 TEST(++t == doc.termlist_end());
78 doc.remove_term("Hxapian.org");
79 TEST_EQUAL(doc.termlist_count(), 0);
80 TEST(doc.termlist_begin() == doc.termlist_end());
81 return true;
84 /// Regression test - the docid wasn't initialised prior to 1.0.22/1.2.4.
85 DEFINE_TESTCASE(document2, !backend) {
86 Xapian::Document doc;
87 // The return value is uninitialised, so running under valgrind this
88 // will fail reliably prior to the fix.
89 TEST_EQUAL(doc.get_docid(), 0);
90 return true;
93 DEFINE_TESTCASE(emptyquery4, !backend) {
94 // Test we get an empty query from applying any of the following ops to
95 // an empty list of subqueries.
96 Xapian::Query q;
97 TEST(Xapian::Query(q.OP_AND, &q, &q).empty());
98 TEST(Xapian::Query(q.OP_OR, &q, &q).empty());
99 TEST(Xapian::Query(q.OP_AND_NOT, &q, &q).empty());
100 TEST(Xapian::Query(q.OP_XOR, &q, &q).empty());
101 TEST(Xapian::Query(q.OP_AND_MAYBE, &q, &q).empty());
102 TEST(Xapian::Query(q.OP_FILTER, &q, &q).empty());
103 TEST(Xapian::Query(q.OP_NEAR, &q, &q).empty());
104 TEST(Xapian::Query(q.OP_PHRASE, &q, &q).empty());
105 TEST(Xapian::Query(q.OP_ELITE_SET, &q, &q).empty());
106 TEST(Xapian::Query(q.OP_SYNONYM, &q, &q).empty());
107 TEST(Xapian::Query(q.OP_MAX, &q, &q).empty());
108 return true;
111 DEFINE_TESTCASE(singlesubquery1, !backend) {
112 // Test that we get just the subquery if we apply any of the following
113 // ops to just that subquery.
114 #define singlesubquery1_(OP) \
115 TEST_STRINGS_EQUAL(Xapian::Query(q->OP, q, q + 1).get_description(),\
116 "Query(test)")
117 Xapian::Query q[1] = { Xapian::Query("test") };
118 singlesubquery1_(OP_AND);
119 singlesubquery1_(OP_OR);
120 singlesubquery1_(OP_AND_NOT);
121 singlesubquery1_(OP_XOR);
122 singlesubquery1_(OP_AND_MAYBE);
123 singlesubquery1_(OP_FILTER);
124 singlesubquery1_(OP_NEAR);
125 singlesubquery1_(OP_PHRASE);
126 singlesubquery1_(OP_ELITE_SET);
127 singlesubquery1_(OP_SYNONYM);
128 singlesubquery1_(OP_MAX);
129 return true;
132 DEFINE_TESTCASE(singlesubquery2, !backend) {
133 // Like the previous test, but using MatchNothing as the subquery.
134 #define singlesubquery2_(OP) \
135 TEST_STRINGS_EQUAL(Xapian::Query(q->OP, q, q + 1).get_description(),\
136 "Query()")
137 Xapian::Query q[1] = { Xapian::Query::MatchNothing };
138 singlesubquery2_(OP_AND);
139 singlesubquery2_(OP_OR);
140 singlesubquery2_(OP_AND_NOT);
141 singlesubquery2_(OP_XOR);
142 singlesubquery2_(OP_AND_MAYBE);
143 singlesubquery2_(OP_FILTER);
144 singlesubquery2_(OP_NEAR);
145 singlesubquery2_(OP_PHRASE);
146 singlesubquery2_(OP_ELITE_SET);
147 singlesubquery2_(OP_SYNONYM);
148 singlesubquery2_(OP_MAX);
149 return true;
152 DEFINE_TESTCASE(singlesubquery3, !backend) {
153 // Like the previous test, but using MatchAll as the subquery.
154 #define singlesubquery3_(OP) \
155 TEST_STRINGS_EQUAL(Xapian::Query(q->OP, q, q + 1).get_description(),\
156 "Query(<alldocuments>)")
157 Xapian::Query q[1] = { Xapian::Query::MatchAll };
158 singlesubquery3_(OP_AND);
159 singlesubquery3_(OP_OR);
160 singlesubquery3_(OP_AND_NOT);
161 singlesubquery3_(OP_XOR);
162 singlesubquery3_(OP_AND_MAYBE);
163 singlesubquery3_(OP_FILTER);
164 // OP_NEAR and OP_PHRASE over MatchAll doesn't really make sense.
165 singlesubquery3_(OP_ELITE_SET);
166 singlesubquery3_(OP_SYNONYM);
167 singlesubquery3_(OP_MAX);
168 return true;
171 /// Check we no longer combine wqf for same term at the same position.
172 DEFINE_TESTCASE(combinewqfnomore1, !backend) {
173 Xapian::Query q(Xapian::Query::OP_OR,
174 Xapian::Query("beer", 1, 1),
175 Xapian::Query("beer", 1, 1));
176 // Prior to 1.3.0, we would have given beer@2, but we decided that wasn't
177 // really useful or helpful.
178 TEST_EQUAL(q.get_description(), "Query((beer@1 OR beer@1))");
179 return true;
182 class DestroyedFlag {
183 bool & destroyed;
185 public:
186 DestroyedFlag(bool & destroyed_) : destroyed(destroyed_) {
187 destroyed = false;
190 ~DestroyedFlag() {
191 destroyed = true;
195 class TestRangeProcessor : public Xapian::RangeProcessor {
196 DestroyedFlag destroyed;
198 public:
199 TestRangeProcessor(bool & destroyed_)
200 : Xapian::RangeProcessor(0), destroyed(destroyed_) { }
202 Xapian::Query operator()(const std::string&, const std::string&)
204 return Xapian::Query::MatchAll;
208 /// Check reference counting of user-subclassable classes.
209 DEFINE_TESTCASE(subclassablerefcount1, !backend) {
210 bool gone_auto, gone;
212 // Simple test of release().
214 Xapian::RangeProcessor * rp = new TestRangeProcessor(gone);
215 TEST(!gone);
216 Xapian::QueryParser qp;
217 qp.add_rangeprocessor(rp->release());
218 TEST(!gone);
220 TEST(gone);
222 // Check a second call to release() has no effect.
224 Xapian::RangeProcessor * rp = new TestRangeProcessor(gone);
225 TEST(!gone);
226 Xapian::QueryParser qp;
227 qp.add_rangeprocessor(rp->release());
228 rp->release();
229 TEST(!gone);
231 TEST(gone);
233 // Test reference counting works, and that a VRP with automatic storage
234 // works OK.
236 TestRangeProcessor rp_auto(gone_auto);
237 TEST(!gone_auto);
239 Xapian::QueryParser qp1;
241 Xapian::QueryParser qp2;
242 Xapian::RangeProcessor * rp;
243 rp = new TestRangeProcessor(gone);
244 TEST(!gone);
245 qp1.add_rangeprocessor(rp->release());
246 TEST(!gone);
247 qp2.add_rangeprocessor(rp);
248 TEST(!gone);
249 qp2.add_rangeprocessor(&rp_auto);
250 TEST(!gone);
251 TEST(!gone_auto);
253 TEST(!gone);
255 TEST(gone);
256 TEST(!gone_auto);
258 TEST(gone_auto);
260 // Regression test for initial implementation, where ~opt_instrusive_ptr()
261 // checked the reference of the object, which may have already been deleted
262 // if it wasn't been reference counted.
264 Xapian::QueryParser qp;
266 Xapian::RangeProcessor * rp = new TestRangeProcessor(gone);
267 TEST(!gone);
268 qp.add_rangeprocessor(rp);
269 delete rp;
270 TEST(gone);
272 // At the end of this block, qp is destroyed, but mustn't dereference
273 // the pointer it has to rp. If it does, that should get caught
274 // when tests are run under valgrind.
277 return true;
280 class TestFieldProcessor : public Xapian::FieldProcessor {
281 DestroyedFlag destroyed;
283 public:
284 TestFieldProcessor(bool & destroyed_) : destroyed(destroyed_) { }
286 Xapian::Query operator()(const string &str) {
287 return Xapian::Query(str);
291 /// Check reference counting of user-subclassable classes.
292 DEFINE_TESTCASE(subclassablerefcount2, !backend) {
293 bool gone_auto, gone;
295 // Simple test of release().
297 Xapian::FieldProcessor * proc = new TestFieldProcessor(gone);
298 TEST(!gone);
299 Xapian::QueryParser qp;
300 qp.add_prefix("foo", proc->release());
301 TEST(!gone);
303 TEST(gone);
305 // Check a second call to release() has no effect.
307 Xapian::FieldProcessor * proc = new TestFieldProcessor(gone);
308 TEST(!gone);
309 Xapian::QueryParser qp;
310 qp.add_prefix("foo", proc->release());
311 proc->release();
312 TEST(!gone);
314 TEST(gone);
316 // Test reference counting works, and that a FieldProcessor with automatic
317 // storage works OK.
319 TestFieldProcessor proc_auto(gone_auto);
320 TEST(!gone_auto);
322 Xapian::QueryParser qp1;
324 Xapian::QueryParser qp2;
325 Xapian::FieldProcessor * proc;
326 proc = new TestFieldProcessor(gone);
327 TEST(!gone);
328 qp1.add_prefix("foo", proc->release());
329 TEST(!gone);
330 qp2.add_prefix("foo", proc);
331 TEST(!gone);
332 qp2.add_prefix("bar", &proc_auto);
333 TEST(!gone);
334 TEST(!gone_auto);
336 TEST(!gone);
338 TEST(gone);
339 TEST(!gone_auto);
341 TEST(gone_auto);
343 return true;
346 class TestMatchSpy : public Xapian::MatchSpy {
347 DestroyedFlag destroyed;
349 public:
350 TestMatchSpy(bool & destroyed_) : destroyed(destroyed_) { }
352 void operator()(const Xapian::Document &, double) { }
355 /// Check reference counting of MatchSpy.
356 DEFINE_TESTCASE(subclassablerefcount3, backend) {
357 Xapian::Database db = get_database("apitest_simpledata");
359 bool gone_auto, gone;
361 // Simple test of release().
363 Xapian::MatchSpy * spy = new TestMatchSpy(gone);
364 TEST(!gone);
365 Xapian::Enquire enquire(db);
366 enquire.add_matchspy(spy->release());
367 TEST(!gone);
369 TEST(gone);
371 // Check a second call to release() has no effect.
373 Xapian::MatchSpy * spy = new TestMatchSpy(gone);
374 TEST(!gone);
375 Xapian::Enquire enquire(db);
376 enquire.add_matchspy(spy->release());
377 spy->release();
378 TEST(!gone);
380 TEST(gone);
382 // Test reference counting works, and that a MatchSpy with automatic
383 // storage works OK.
385 TestMatchSpy spy_auto(gone_auto);
386 TEST(!gone_auto);
388 Xapian::Enquire enq1(db);
390 Xapian::Enquire enq2(db);
391 Xapian::MatchSpy * spy;
392 spy = new TestMatchSpy(gone);
393 TEST(!gone);
394 enq1.add_matchspy(spy->release());
395 TEST(!gone);
396 enq2.add_matchspy(spy);
397 TEST(!gone);
398 enq2.add_matchspy(&spy_auto);
399 TEST(!gone);
400 TEST(!gone_auto);
402 TEST(!gone);
404 TEST(gone);
405 TEST(!gone_auto);
407 TEST(gone_auto);
409 return true;
412 class TestStopper : public Xapian::Stopper {
413 DestroyedFlag destroyed;
415 public:
416 TestStopper(bool & destroyed_) : destroyed(destroyed_) { }
418 bool operator()(const std::string&) const { return true; }
421 /// Check reference counting of Stopper with QueryParser.
422 DEFINE_TESTCASE(subclassablerefcount4, !backend) {
423 bool gone_auto, gone;
425 // Simple test of release().
427 Xapian::Stopper * stopper = new TestStopper(gone);
428 TEST(!gone);
429 Xapian::QueryParser qp;
430 qp.set_stopper(stopper->release());
431 TEST(!gone);
433 TEST(gone);
435 // Test that setting a new stopper causes the previous one to be released.
437 bool gone0;
438 Xapian::Stopper * stopper0 = new TestStopper(gone0);
439 TEST(!gone0);
440 Xapian::QueryParser qp;
441 qp.set_stopper(stopper0->release());
442 TEST(!gone0);
444 Xapian::Stopper * stopper = new TestStopper(gone);
445 TEST(!gone);
446 qp.set_stopper(stopper->release());
447 TEST(gone0);
448 TEST(!gone);
450 TEST(gone);
452 // Check a second call to release() has no effect.
454 Xapian::Stopper * stopper = new TestStopper(gone);
455 TEST(!gone);
456 Xapian::QueryParser qp;
457 qp.set_stopper(stopper->release());
458 stopper->release();
459 TEST(!gone);
461 TEST(gone);
463 // Test reference counting works, and that a Stopper with automatic
464 // storage works OK.
466 TestStopper stopper_auto(gone_auto);
467 TEST(!gone_auto);
469 Xapian::QueryParser qp1;
471 Xapian::QueryParser qp2;
472 Xapian::Stopper * stopper;
473 stopper = new TestStopper(gone);
474 TEST(!gone);
475 qp1.set_stopper(stopper->release());
476 TEST(!gone);
477 qp2.set_stopper(stopper);
478 TEST(!gone);
479 qp2.set_stopper(&stopper_auto);
480 TEST(!gone);
481 TEST(!gone_auto);
483 TEST(!gone);
485 TEST(gone);
486 TEST(!gone_auto);
488 TEST(gone_auto);
490 return true;
493 /// Check reference counting of Stopper with TermGenerator.
494 DEFINE_TESTCASE(subclassablerefcount5, !backend) {
495 bool gone_auto, gone;
497 // Simple test of release().
499 Xapian::Stopper * stopper = new TestStopper(gone);
500 TEST(!gone);
501 Xapian::TermGenerator indexer;
502 indexer.set_stopper(stopper->release());
503 TEST(!gone);
505 TEST(gone);
507 // Test that setting a new stopper causes the previous one to be released.
509 bool gone0;
510 Xapian::Stopper * stopper0 = new TestStopper(gone0);
511 TEST(!gone0);
512 Xapian::TermGenerator indexer;
513 indexer.set_stopper(stopper0->release());
514 TEST(!gone0);
516 Xapian::Stopper * stopper = new TestStopper(gone);
517 TEST(!gone);
518 indexer.set_stopper(stopper->release());
519 TEST(gone0);
520 TEST(!gone);
522 TEST(gone);
524 // Check a second call to release() has no effect.
526 Xapian::Stopper * stopper = new TestStopper(gone);
527 TEST(!gone);
528 Xapian::TermGenerator indexer;
529 indexer.set_stopper(stopper->release());
530 stopper->release();
531 TEST(!gone);
533 TEST(gone);
535 // Test reference counting works, and that a Stopper with automatic
536 // storage works OK.
538 TestStopper stopper_auto(gone_auto);
539 TEST(!gone_auto);
541 Xapian::TermGenerator indexer1;
543 Xapian::TermGenerator indexer2;
544 Xapian::Stopper * stopper;
545 stopper = new TestStopper(gone);
546 TEST(!gone);
547 indexer1.set_stopper(stopper->release());
548 TEST(!gone);
549 indexer2.set_stopper(stopper);
550 TEST(!gone);
551 indexer2.set_stopper(&stopper_auto);
552 TEST(!gone);
553 TEST(!gone_auto);
555 TEST(!gone);
557 TEST(gone);
558 TEST(!gone_auto);
560 TEST(gone_auto);
562 return true;
565 class TestKeyMaker : public Xapian::KeyMaker {
566 DestroyedFlag destroyed;
568 public:
569 TestKeyMaker(bool & destroyed_) : destroyed(destroyed_) { }
571 string operator()(const Xapian::Document&) const { return string(); }
574 /// Check reference counting of KeyMaker.
575 DEFINE_TESTCASE(subclassablerefcount6, backend) {
576 Xapian::Database db = get_database("apitest_simpledata");
578 bool gone_auto, gone;
580 // Simple test of release().
582 Xapian::KeyMaker * keymaker = new TestKeyMaker(gone);
583 TEST(!gone);
584 Xapian::Enquire enq(db);
585 enq.set_sort_by_key(keymaker->release(), false);
586 TEST(!gone);
588 TEST(gone);
590 // Test that setting a new keymaker causes the previous one to be released.
592 bool gone0;
593 Xapian::KeyMaker * keymaker0 = new TestKeyMaker(gone0);
594 TEST(!gone0);
595 Xapian::Enquire enq(db);
596 enq.set_sort_by_key(keymaker0->release(), false);
597 TEST(!gone0);
599 Xapian::KeyMaker * keymaker = new TestKeyMaker(gone);
600 TEST(!gone);
601 enq.set_sort_by_key_then_relevance(keymaker->release(), false);
602 TEST(gone0);
603 TEST(!gone);
605 TEST(gone);
607 // Check a second call to release() has no effect.
609 Xapian::KeyMaker * keymaker = new TestKeyMaker(gone);
610 TEST(!gone);
611 Xapian::Enquire enq(db);
612 enq.set_sort_by_key(keymaker->release(), false);
613 keymaker->release();
614 TEST(!gone);
616 TEST(gone);
618 // Test reference counting works, and that a KeyMaker with automatic
619 // storage works OK.
621 TestKeyMaker keymaker_auto(gone_auto);
622 TEST(!gone_auto);
624 Xapian::Enquire enq1(db);
626 Xapian::Enquire enq2(db);
627 Xapian::KeyMaker * keymaker;
628 keymaker = new TestKeyMaker(gone);
629 TEST(!gone);
630 enq1.set_sort_by_key(keymaker->release(), false);
631 TEST(!gone);
632 enq2.set_sort_by_relevance_then_key(keymaker, false);
633 TEST(!gone);
634 enq2.set_sort_by_key_then_relevance(&keymaker_auto, false);
635 TEST(!gone);
636 TEST(!gone_auto);
638 TEST(!gone);
640 TEST(gone);
641 TEST(!gone_auto);
643 TEST(gone_auto);
645 return true;
648 class TestExpandDecider : public Xapian::ExpandDecider {
649 DestroyedFlag destroyed;
651 public:
652 TestExpandDecider(bool & destroyed_) : destroyed(destroyed_) { }
654 bool operator()(const string&) const { return true; }
657 /// Check reference counting of ExpandDecider.
658 DEFINE_TESTCASE(subclassablerefcount7, backend) {
659 Xapian::Database db = get_database("apitest_simpledata");
660 Xapian::Enquire enq(db);
661 Xapian::RSet rset;
662 rset.add_document(1);
664 bool gone_auto, gone;
666 for (int flags = 0;
667 flags <= Xapian::Enquire::INCLUDE_QUERY_TERMS;
668 flags += Xapian::Enquire::INCLUDE_QUERY_TERMS) {
669 // Test of auto lifetime ExpandDecider.
671 TestExpandDecider edecider_auto(gone_auto);
672 TEST(!gone_auto);
673 (void)enq.get_eset(5, rset, 0, &edecider_auto);
674 TEST(!gone_auto);
676 TEST(gone_auto);
678 // Simple test of release().
680 Xapian::ExpandDecider * edecider = new TestExpandDecider(gone);
681 TEST(!gone);
682 (void)enq.get_eset(5, rset, 0, edecider);
683 TEST(!gone);
684 delete edecider;
685 TEST(gone);
688 // Test that a released ExpandDecider gets cleaned up by get_eset().
690 Xapian::ExpandDecider * edecider = new TestExpandDecider(gone);
691 TEST(!gone);
692 (void)enq.get_eset(5, rset, 0, edecider->release());
693 TEST(gone);
696 // Check a second call to release() has no effect.
698 Xapian::ExpandDecider * edecider = new TestExpandDecider(gone);
699 TEST(!gone);
700 edecider->release();
701 TEST(!gone);
702 (void)enq.get_eset(5, rset, 0, edecider->release());
703 TEST(gone);
707 // Test combinations of released/non-released with ExpandDeciderAnd.
709 TestExpandDecider edecider_auto(gone_auto);
710 TEST(!gone_auto);
711 Xapian::ExpandDecider * edecider = new TestExpandDecider(gone);
712 TEST(!gone);
713 (void)enq.get_eset(5, rset, 0,
714 (new Xapian::ExpandDeciderAnd(
715 &edecider_auto,
716 edecider->release()))->release());
717 TEST(!gone_auto);
718 TEST(gone);
720 TEST(gone_auto);
722 TestExpandDecider edecider_auto(gone_auto);
723 TEST(!gone_auto);
724 Xapian::ExpandDecider * edecider = new TestExpandDecider(gone);
725 TEST(!gone);
726 (void)enq.get_eset(5, rset, 0,
727 (new Xapian::ExpandDeciderAnd(
728 edecider->release(),
729 &edecider_auto))->release());
730 TEST(!gone_auto);
731 TEST(gone);
733 TEST(gone_auto);
735 return true;
738 class TestValueRangeProcessor : public Xapian::ValueRangeProcessor {
739 DestroyedFlag destroyed;
741 public:
742 TestValueRangeProcessor(bool & destroyed_) : destroyed(destroyed_) { }
744 Xapian::valueno operator()(std::string &, std::string &) {
745 return 42;
749 /// Check reference counting of user-subclassable classes.
750 DEFINE_TESTCASE(subclassablerefcount8, !backend) {
751 bool gone_auto, gone;
753 // Simple test of release().
755 Xapian::ValueRangeProcessor * vrp = new TestValueRangeProcessor(gone);
756 TEST(!gone);
757 Xapian::QueryParser qp;
758 qp.add_valuerangeprocessor(vrp->release());
759 TEST(!gone);
761 TEST(gone);
763 // Check a second call to release() has no effect.
765 Xapian::ValueRangeProcessor * vrp = new TestValueRangeProcessor(gone);
766 TEST(!gone);
767 Xapian::QueryParser qp;
768 qp.add_valuerangeprocessor(vrp->release());
769 vrp->release();
770 TEST(!gone);
772 TEST(gone);
774 // Test reference counting works, and that a VRP with automatic storage
775 // works OK.
777 TestValueRangeProcessor vrp_auto(gone_auto);
778 TEST(!gone_auto);
780 Xapian::QueryParser qp1;
782 Xapian::QueryParser qp2;
783 Xapian::ValueRangeProcessor * vrp;
784 vrp = new TestValueRangeProcessor(gone);
785 TEST(!gone);
786 qp1.add_valuerangeprocessor(vrp->release());
787 TEST(!gone);
788 qp2.add_valuerangeprocessor(vrp);
789 TEST(!gone);
790 qp2.add_valuerangeprocessor(&vrp_auto);
791 TEST(!gone);
792 TEST(!gone_auto);
794 TEST(!gone);
796 TEST(gone);
797 TEST(!gone_auto);
799 TEST(gone_auto);
801 // Regression test for initial implementation, where ~opt_instrusive_ptr()
802 // checked the reference of the object, which may have already been deleted
803 // if it wasn't been reference counted.
805 Xapian::QueryParser qp;
807 Xapian::ValueRangeProcessor * vrp =
808 new TestValueRangeProcessor(gone);
809 TEST(!gone);
810 qp.add_valuerangeprocessor(vrp);
811 delete vrp;
812 TEST(gone);
814 // At the end of this block, qp is destroyed, but mustn't dereference
815 // the pointer it has to vrp. If it does, that should get caught
816 // when tests are run under valgrind.
819 return true;
822 /// Check encoding of non-UTF8 document data.
823 DEFINE_TESTCASE(nonutf8docdesc1, !backend) {
824 Xapian::Document doc;
825 doc.set_data("\xc0\x80\xf5\x80\x80\x80\xfe\xff");
826 TEST_EQUAL(doc.get_description(),
827 "Document(data='\\xc0\\x80\\xf5\\x80\\x80\\x80\\xfe\\xff')");
828 doc.set_data(string("\x00\x1f", 2));
829 TEST_EQUAL(doc.get_description(),
830 "Document(data='\\x00\\x1f')");
831 // Check that backslashes are encoded so output isn't ambiguous.
832 doc.set_data("back\\slash");
833 TEST_EQUAL(doc.get_description(),
834 "Document(data='back\\x5cslash')");
835 return true;