2 * @brief Tests of closing databases.
4 /* Copyright 2008,2009 Lemur Consulting Ltd
5 * Copyright 2009,2012,2015,2023 Olly Betts
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
24 #include "api_closedb.h"
28 #include "safeunistd.h"
31 #include "testutils.h"
35 #define COUNT_EXCEPTION(CODE, EXCEPTION) \
38 } catch (const Xapian::EXCEPTION&) { \
42 #define COUNT_CLOSED(CODE) COUNT_EXCEPTION(CODE, DatabaseClosedError)
44 // Iterators used by closedb1.
45 struct closedb1_iterators
{
47 Xapian::Document doc1
;
48 Xapian::PostingIterator pl1
;
49 Xapian::PostingIterator pl2
;
50 Xapian::PostingIterator pl1end
;
51 Xapian::PostingIterator pl2end
;
52 Xapian::TermIterator tl1
;
53 Xapian::TermIterator tlend
;
54 Xapian::TermIterator atl1
;
55 Xapian::TermIterator atlend
;
56 Xapian::PositionIterator pil1
;
57 Xapian::PositionIterator pilend
;
59 void setup(Xapian::Database db_
) {
62 // Set up the iterators for the test.
63 pl1
= db
.postlist_begin("paragraph");
64 pl2
= db
.postlist_begin("this");
66 pl1end
= db
.postlist_end("paragraph");
67 pl2end
= db
.postlist_end("this");
68 tl1
= db
.termlist_begin(1);
69 tlend
= db
.termlist_end(1);
70 atl1
= db
.allterms_begin("t");
71 atlend
= db
.allterms_end("t");
72 pil1
= db
.positionlist_begin(1, "paragraph");
73 pilend
= db
.positionlist_end(1, "paragraph");
77 int exception_count
= 0;
79 // Getting a document may throw.
81 doc1
= db
.get_document(1);
82 // Only do these if get_document() succeeded.
83 COUNT_CLOSED(TEST_EQUAL(doc1
.get_data().substr(0, 33),
84 "This is a test document used with"));
85 COUNT_CLOSED(doc1
.termlist_begin());
88 // Causing the database to access its files raises the "database
90 COUNT_CLOSED(db
.postlist_begin("paragraph"));
91 COUNT_CLOSED(db
.get_document(1).get_value(1));
92 COUNT_CLOSED(db
.termlist_begin(1));
93 COUNT_CLOSED(db
.positionlist_begin(1, "paragraph"));
94 COUNT_CLOSED(db
.allterms_begin());
95 COUNT_CLOSED(db
.allterms_begin("p"));
96 COUNT_CLOSED(db
.get_termfreq("paragraph"));
97 COUNT_CLOSED(db
.get_collection_freq("paragraph"));
98 COUNT_CLOSED(db
.term_exists("paragraph"));
99 COUNT_CLOSED(db
.get_value_freq(1));
100 COUNT_CLOSED(db
.get_value_lower_bound(1));
101 COUNT_CLOSED(db
.get_value_upper_bound(1));
102 COUNT_CLOSED(db
.valuestream_begin(1));
103 COUNT_CLOSED(db
.get_doclength(1));
104 COUNT_CLOSED(db
.get_unique_terms(1));
106 // Reopen raises the "database closed" error.
107 COUNT_CLOSED(db
.reopen());
109 TEST_NOT_EQUAL(pl1
, pl1end
);
110 TEST_NOT_EQUAL(pl2
, pl2end
);
111 TEST_NOT_EQUAL(tl1
, tlend
);
112 TEST_NOT_EQUAL(atl1
, atlend
);
113 TEST_NOT_EQUAL(pil1
, pilend
);
115 COUNT_CLOSED(db
.postlist_begin("paragraph"));
117 COUNT_CLOSED(TEST_EQUAL(*pl1
, 1));
118 COUNT_CLOSED(TEST_EQUAL(pl1
.get_doclength(), 28));
119 COUNT_CLOSED(TEST_EQUAL(pl1
.get_unique_terms(), 21));
121 COUNT_CLOSED(TEST_EQUAL(*pl2
, 2));
122 COUNT_CLOSED(TEST_EQUAL(pl2
.get_doclength(), 81));
123 COUNT_CLOSED(TEST_EQUAL(pl2
.get_unique_terms(), 56));
125 COUNT_CLOSED(TEST_EQUAL(*tl1
, "a"));
126 COUNT_CLOSED(TEST_EQUAL(tl1
.get_wdf(), 2));
127 COUNT_CLOSED(TEST_EQUAL(tl1
.get_termfreq(), 3));
129 COUNT_CLOSED(TEST_EQUAL(*atl1
, "test"));
130 COUNT_CLOSED(TEST_EQUAL(atl1
.get_termfreq(), 1));
132 COUNT_CLOSED(TEST_EQUAL(*pil1
, 12));
134 // Advancing the iterator may or may not raise an error, but if it
135 // doesn't it must return the correct answers.
138 COUNT_CLOSED(TEST_EQUAL(*pl1
, 2));
139 COUNT_CLOSED(TEST_EQUAL(pl1
.get_doclength(), 81));
140 COUNT_CLOSED(TEST_EQUAL(pl1
.get_unique_terms(), 56));
145 COUNT_CLOSED(TEST_EQUAL(*pl2
, 3));
146 COUNT_CLOSED(TEST_EQUAL(pl2
.get_doclength(), 15));
147 COUNT_CLOSED(TEST_EQUAL(pl2
.get_unique_terms(), 14));
152 COUNT_CLOSED(TEST_EQUAL(*tl1
, "api"));
153 COUNT_CLOSED(TEST_EQUAL(tl1
.get_wdf(), 1));
154 COUNT_CLOSED(TEST_EQUAL(tl1
.get_termfreq(), 1));
159 COUNT_CLOSED(TEST_EQUAL(*atl1
, "that"));
160 COUNT_CLOSED(TEST_EQUAL(atl1
.get_termfreq(), 2));
165 COUNT_CLOSED(TEST_EQUAL(*pil1
, 28));
168 return exception_count
;
172 // Test for closing a database
173 DEFINE_TESTCASE(closedb1
, backend
) {
174 Xapian::Database
db(get_database("apitest_simpledata"));
175 closedb1_iterators iters
;
177 // Run the test, checking that we get no "closed" exceptions.
179 int exception_count
= iters
.perform();
180 TEST_EQUAL(exception_count
, 0);
182 // Setup for the next test.
185 // Close the database.
188 // Dup stdout to the fds which the database was using, to try to catch
189 // issues with lingering references to closed fds (regression test for
190 // early development versions of honey).
192 for (int i
= 0; i
!= 6; ++i
) {
193 fds
.push_back(dup(1));
196 // Reopening a closed database should always raise DatabaseClosedError.
197 TEST_EXCEPTION(Xapian::DatabaseClosedError
, db
.reopen());
199 // Run the test again, checking that we get some "closed" exceptions.
200 exception_count
= iters
.perform();
201 TEST_NOT_EQUAL(exception_count
, 0);
203 // get_description() shouldn't throw an exception. Actually do something
204 // with the description, in case this method is marked as "pure" in the
206 TEST(!db
.get_description().empty());
208 // Calling close repeatedly is okay.
216 // Test closing a writable database, and that it drops the lock.
217 DEFINE_TESTCASE(closedb2
, writable
&& path
) {
218 Xapian::WritableDatabase
dbw1(get_named_writable_database("apitest_closedb2"));
219 TEST_EXCEPTION(Xapian::DatabaseLockError
,
220 Xapian::WritableDatabase
db(get_named_writable_database_path("apitest_closedb2"),
223 Xapian::WritableDatabase dbw2
= get_named_writable_database("apitest_closedb2");
224 TEST_EXCEPTION(Xapian::DatabaseClosedError
,
225 dbw1
.postlist_begin("paragraph"));
226 TEST_EQUAL(dbw2
.postlist_begin("paragraph"), dbw2
.postlist_end("paragraph"));
229 /// Check API methods which might either work or throw an exception.
230 DEFINE_TESTCASE(closedb3
, backend
) {
231 Xapian::Database
db(get_database("etext"));
232 const string
& uuid
= db
.get_uuid();
235 TEST_EQUAL(db
.get_uuid(), uuid
);
236 } catch (const Xapian::DatabaseClosedError
&) {
239 TEST(db
.has_positions());
240 } catch (const Xapian::DatabaseClosedError
&) {
243 TEST_EQUAL(db
.get_doccount(), 566);
244 } catch (const Xapian::DatabaseClosedError
&) {
247 TEST_EQUAL(db
.get_lastdocid(), 566);
248 } catch (const Xapian::DatabaseClosedError
&) {
251 TEST_REL(db
.get_doclength_lower_bound(), <, db
.get_avlength());
252 } catch (const Xapian::DatabaseClosedError
&) {
255 TEST_REL(db
.get_doclength_upper_bound(), >, db
.get_avlength());
256 } catch (const Xapian::DatabaseClosedError
&) {
259 TEST(db
.get_wdf_upper_bound("king"));
260 } catch (const Xapian::DatabaseClosedError
&) {
263 // For non-remote databases, keep_alive() is a no-op anyway.
265 } catch (const Xapian::DatabaseClosedError
&) {
269 /// Regression test for bug fixed in 1.1.4 - close() should implicitly commit().
270 DEFINE_TESTCASE(closedb4
, writable
&& !inmemory
) {
271 Xapian::WritableDatabase
wdb(get_writable_database());
272 wdb
.add_document(Xapian::Document());
273 TEST_EQUAL(wdb
.get_doccount(), 1);
275 Xapian::Database
db(get_writable_database_as_database());
276 TEST_EQUAL(db
.get_doccount(), 1);
279 /// Test the effects of close() on transactions
280 DEFINE_TESTCASE(closedb5
, transactions
) {
282 // If a transaction is active, close() shouldn't implicitly commit().
283 Xapian::WritableDatabase wdb
= get_writable_database();
284 wdb
.begin_transaction();
285 wdb
.add_document(Xapian::Document());
286 TEST_EQUAL(wdb
.get_doccount(), 1);
288 Xapian::Database db
= get_writable_database_as_database();
289 TEST_EQUAL(db
.get_doccount(), 0);
293 // Same test but for an unflushed transaction.
294 Xapian::WritableDatabase wdb
= get_writable_database();
295 wdb
.begin_transaction(false);
296 wdb
.add_document(Xapian::Document());
297 TEST_EQUAL(wdb
.get_doccount(), 1);
299 Xapian::Database db
= get_writable_database_as_database();
300 TEST_EQUAL(db
.get_doccount(), 0);
304 // commit_transaction() throws InvalidOperationError when
305 // not in a transaction.
306 Xapian::WritableDatabase wdb
= get_writable_database();
308 TEST_EXCEPTION(Xapian::InvalidOperationError
,
309 wdb
.commit_transaction());
311 // begin_transaction() is no-op or throws DatabaseClosedError. We may be
312 // able to call db.begin_transaction(), but we can't make any changes
313 // inside that transaction. If begin_transaction() succeeds, then
314 // commit_transaction() either end the transaction or throw
315 // DatabaseClosedError.
317 wdb
.begin_transaction();
319 wdb
.commit_transaction();
320 } catch (const Xapian::DatabaseClosedError
&) {
322 } catch (const Xapian::DatabaseClosedError
&) {
327 // Same test but for cancel_transaction().
328 Xapian::WritableDatabase wdb
= get_writable_database();
330 TEST_EXCEPTION(Xapian::InvalidOperationError
,
331 wdb
.cancel_transaction());
334 wdb
.begin_transaction();
336 wdb
.cancel_transaction();
337 } catch (const Xapian::DatabaseClosedError
&) {
339 } catch (const Xapian::DatabaseClosedError
&) {
344 /// Database::keep_alive() should fail after close() for a remote database.
345 DEFINE_TESTCASE(closedb6
, remote
) {
346 Xapian::Database
db(get_database("etext"));
351 FAIL_TEST("Expected DatabaseClosedError wasn't thrown");
352 } catch (const Xapian::DatabaseClosedError
&) {
356 // Test WritableDatabase methods.
357 DEFINE_TESTCASE(closedb7
, writable
) {
358 Xapian::WritableDatabase
db(get_writable_database());
359 db
.add_document(Xapian::Document());
362 // Since we can't make any changes which need to be committed,
363 // db.commit() is a no-op, and so doesn't have to fail.
366 } catch (const Xapian::DatabaseClosedError
&) {
369 TEST_EXCEPTION(Xapian::DatabaseClosedError
,
370 db
.add_document(Xapian::Document()));
371 TEST_EXCEPTION(Xapian::DatabaseClosedError
,
372 db
.delete_document(1));
373 TEST_EXCEPTION(Xapian::DatabaseClosedError
,
374 db
.replace_document(1, Xapian::Document()));
375 TEST_EXCEPTION(Xapian::DatabaseClosedError
,
376 db
.replace_document(2, Xapian::Document()));
377 TEST_EXCEPTION(Xapian::DatabaseClosedError
,
378 db
.replace_document("Qi", Xapian::Document()));
381 // Test spelling related methods.
382 DEFINE_TESTCASE(closedb8
, writable
&& spelling
) {
383 Xapian::WritableDatabase
db(get_writable_database());
384 db
.add_spelling("pneumatic");
385 db
.add_spelling("pneumonia");
388 TEST_EXCEPTION(Xapian::DatabaseClosedError
,
389 db
.add_spelling("penmanship"));
390 TEST_EXCEPTION(Xapian::DatabaseClosedError
,
391 db
.remove_spelling("pneumatic"));
392 TEST_EXCEPTION(Xapian::DatabaseClosedError
,
393 db
.get_spelling_suggestion("newmonia"));
394 TEST_EXCEPTION(Xapian::DatabaseClosedError
,
395 db
.spellings_begin());
398 // Test synonym related methods.
399 DEFINE_TESTCASE(closedb9
, writable
&& synonyms
) {
400 Xapian::WritableDatabase
db(get_writable_database());
401 db
.add_synonym("color", "colour");
402 db
.add_synonym("honor", "honour");
405 TEST_EXCEPTION(Xapian::DatabaseClosedError
,
406 db
.add_synonym("behavior", "behaviour"));
407 TEST_EXCEPTION(Xapian::DatabaseClosedError
,
408 db
.remove_synonym("honor", "honour"));
409 TEST_EXCEPTION(Xapian::DatabaseClosedError
,
410 db
.clear_synonyms("honor"));
411 TEST_EXCEPTION(Xapian::DatabaseClosedError
,
412 db
.synonyms_begin("color"));
413 TEST_EXCEPTION(Xapian::DatabaseClosedError
,
414 db
.synonym_keys_begin());
417 // Test metadata related methods.
418 DEFINE_TESTCASE(closedb10
, writable
&& metadata
) {
419 Xapian::WritableDatabase
db(get_writable_database());
420 db
.set_metadata("foo", "FOO");
421 db
.set_metadata("bar", "BAR");
424 TEST_EXCEPTION(Xapian::DatabaseClosedError
,
425 db
.set_metadata("test", "TEST"));
426 TEST_EXCEPTION(Xapian::DatabaseClosedError
,
427 db
.get_metadata("foo"));
428 TEST_EXCEPTION(Xapian::DatabaseClosedError
,
429 db
.get_metadata("bar"));
430 TEST_EXCEPTION(Xapian::DatabaseClosedError
,
431 db
.metadata_keys_begin());
434 #define COUNT_NETWORK(CODE) COUNT_EXCEPTION(CODE, NetworkError)
436 // Iterators used by remotefailure1.
437 struct remotefailure1_iterators
{
439 Xapian::Document doc1
;
440 Xapian::PostingIterator pl1
;
441 Xapian::PostingIterator pl2
;
442 Xapian::PostingIterator pl1end
;
443 Xapian::PostingIterator pl2end
;
444 Xapian::TermIterator tl1
;
445 Xapian::TermIterator tlend
;
446 Xapian::TermIterator atl1
;
447 Xapian::TermIterator atlend
;
448 Xapian::PositionIterator pil1
;
449 Xapian::PositionIterator pilend
;
451 void setup(Xapian::Database db_
) {
454 // Set up the iterators for the test.
455 pl1
= db
.postlist_begin("paragraph");
456 pl2
= db
.postlist_begin("this");
458 pl1end
= db
.postlist_end("paragraph");
459 pl2end
= db
.postlist_end("this");
460 tl1
= db
.termlist_begin(1);
461 tlend
= db
.termlist_end(1);
462 atl1
= db
.allterms_begin("t");
463 atlend
= db
.allterms_end("t");
464 pil1
= db
.positionlist_begin(1, "paragraph");
465 pilend
= db
.positionlist_end(1, "paragraph");
469 int exception_count
= 0;
471 // Getting a document may throw.
473 doc1
= db
.get_document(1);
474 // Only do these if get_document() succeeded.
475 COUNT_NETWORK(TEST_EQUAL(doc1
.get_data().substr(0, 33),
476 "This is a test document used with"));
477 COUNT_NETWORK(doc1
.termlist_begin());
480 // These should always fail.
481 COUNT_NETWORK(db
.postlist_begin("paragraph"));
482 COUNT_NETWORK(db
.get_document(1).get_value(1));
483 COUNT_NETWORK(db
.termlist_begin(1));
484 COUNT_NETWORK(db
.positionlist_begin(1, "paragraph"));
485 COUNT_NETWORK(db
.allterms_begin());
486 COUNT_NETWORK(db
.allterms_begin("p"));
487 COUNT_NETWORK(db
.get_termfreq("paragraph"));
488 COUNT_NETWORK(db
.get_collection_freq("paragraph"));
489 COUNT_NETWORK(db
.term_exists("paragraph"));
490 COUNT_NETWORK(db
.get_value_freq(1));
491 COUNT_NETWORK(db
.get_value_lower_bound(1));
492 COUNT_NETWORK(db
.get_value_upper_bound(1));
493 COUNT_NETWORK(db
.valuestream_begin(1));
494 COUNT_NETWORK(db
.get_doclength(1));
495 COUNT_NETWORK(db
.get_unique_terms(1));
497 // Should always fail.
498 COUNT_NETWORK(db
.reopen());
500 TEST_NOT_EQUAL(pl1
, pl1end
);
501 TEST_NOT_EQUAL(pl2
, pl2end
);
502 TEST_NOT_EQUAL(tl1
, tlend
);
503 TEST_NOT_EQUAL(atl1
, atlend
);
504 TEST_NOT_EQUAL(pil1
, pilend
);
506 COUNT_NETWORK(db
.postlist_begin("paragraph"));
508 COUNT_NETWORK(TEST_EQUAL(*pl1
, 1));
509 COUNT_NETWORK(TEST_EQUAL(pl1
.get_doclength(), 28));
510 COUNT_NETWORK(TEST_EQUAL(pl1
.get_unique_terms(), 21));
512 COUNT_NETWORK(TEST_EQUAL(*pl2
, 2));
513 COUNT_NETWORK(TEST_EQUAL(pl2
.get_doclength(), 81));
514 COUNT_NETWORK(TEST_EQUAL(pl2
.get_unique_terms(), 56));
516 COUNT_NETWORK(TEST_EQUAL(*tl1
, "a"));
517 COUNT_NETWORK(TEST_EQUAL(tl1
.get_wdf(), 2));
518 COUNT_NETWORK(TEST_EQUAL(tl1
.get_termfreq(), 3));
520 COUNT_NETWORK(TEST_EQUAL(*atl1
, "test"));
521 COUNT_NETWORK(TEST_EQUAL(atl1
.get_termfreq(), 1));
523 COUNT_NETWORK(TEST_EQUAL(*pil1
, 12));
525 // Advancing the iterator may or may not raise an error, but if it
526 // doesn't it must return the correct answers.
529 COUNT_NETWORK(TEST_EQUAL(*pl1
, 2));
530 COUNT_NETWORK(TEST_EQUAL(pl1
.get_doclength(), 81));
531 COUNT_NETWORK(TEST_EQUAL(pl1
.get_unique_terms(), 56));
536 COUNT_NETWORK(TEST_EQUAL(*pl2
, 3));
537 COUNT_NETWORK(TEST_EQUAL(pl2
.get_doclength(), 15));
538 COUNT_NETWORK(TEST_EQUAL(pl2
.get_unique_terms(), 14));
543 COUNT_NETWORK(TEST_EQUAL(*tl1
, "api"));
544 COUNT_NETWORK(TEST_EQUAL(tl1
.get_wdf(), 1));
545 COUNT_NETWORK(TEST_EQUAL(tl1
.get_termfreq(), 1));
550 COUNT_NETWORK(TEST_EQUAL(*atl1
, "that"));
551 COUNT_NETWORK(TEST_EQUAL(atl1
.get_termfreq(), 2));
556 COUNT_NETWORK(TEST_EQUAL(*pil1
, 28));
559 return exception_count
;
563 // Test for a remote server failing.
564 DEFINE_TESTCASE(remotefailure1
, remotetcp
) {
566 XFAIL("Remote failure handling or testing is buggy on __MINGW32__");
568 Xapian::Database
db(get_database("apitest_simpledata"));
569 remotefailure1_iterators iters
;
571 // Run the test, checking that we get no exceptions.
573 int exception_count
= iters
.perform();
574 TEST_EQUAL(exception_count
, 0);
576 // Setup for the next test.
579 // Simulate remote server failure.
582 // Dup stdout to the fds which the database was using, to try to catch
583 // issues with lingering references to closed fds.
585 for (int i
= 0; i
!= 6; ++i
) {
586 fds
.push_back(dup(1));
589 // Run the test again, checking that we get some "NetworkError" exceptions.
590 exception_count
= iters
.perform();
591 TEST_NOT_EQUAL(exception_count
, 0);
593 // get_description() shouldn't throw an exception. Actually do something
594 // with the description, in case this method is marked as "pure" in the
596 TEST(!db
.get_description().empty());
603 // There's no remotefailure2 plus other gaps in the numbering - these testcases
604 // are adapted versions of the closedb testcases, but some closedb testcases
605 // don't make sense to convert.
607 /// Check API methods which might either work or throw an exception.
608 DEFINE_TESTCASE(remotefailure3
, remotetcp
) {
610 XFAIL("Remote failure handling or testing is buggy on __MINGW32__");
612 Xapian::Database
db(get_database("etext"));
613 const string
& uuid
= db
.get_uuid();
616 TEST_EQUAL(db
.get_uuid(), uuid
);
617 } catch (const Xapian::NetworkError
&) {
620 TEST(db
.has_positions());
621 } catch (const Xapian::NetworkError
&) {
624 TEST_EQUAL(db
.get_doccount(), 566);
625 } catch (const Xapian::NetworkError
&) {
628 TEST_EQUAL(db
.get_lastdocid(), 566);
629 } catch (const Xapian::NetworkError
&) {
632 TEST_REL(db
.get_doclength_lower_bound(), <, db
.get_avlength());
633 } catch (const Xapian::NetworkError
&) {
636 TEST_REL(db
.get_doclength_upper_bound(), >, db
.get_avlength());
637 } catch (const Xapian::NetworkError
&) {
640 TEST(db
.get_wdf_upper_bound("king"));
641 } catch (const Xapian::NetworkError
&) {
643 TEST_EXCEPTION(Xapian::NetworkError
, db
.keep_alive());
646 /// Test the effects of remote server failure on transactions
647 DEFINE_TESTCASE(remotefailure5
, remotetcp
) {
649 XFAIL("Remote failure handling or testing is buggy on __MINGW32__");
652 Xapian::WritableDatabase wdb
= get_writable_database();
655 // commit_transaction() and cancel_transaction() should throw
656 // InvalidOperationError because we aren't in a transaction.
657 TEST_EXCEPTION(Xapian::InvalidOperationError
,
658 wdb
.commit_transaction());
660 TEST_EXCEPTION(Xapian::InvalidOperationError
,
661 wdb
.cancel_transaction());
663 // begin_transaction() only sets state locally so works.
664 wdb
.begin_transaction();
665 // commit_transaction() should only communicate with the server if
666 // there are changes in the transaction.
667 wdb
.commit_transaction();
669 wdb
.begin_transaction();
670 // cancel_transaction() should only communicate with the server if
671 // there are changes in the transaction.
672 wdb
.cancel_transaction();
676 Xapian::WritableDatabase wdb
= get_writable_database();
677 wdb
.begin_transaction();
678 wdb
.add_document(Xapian::Document());
680 // With a transaction active, commit_transaction() should fail with
682 TEST_EXCEPTION(Xapian::NetworkError
,
683 wdb
.commit_transaction());
687 Xapian::WritableDatabase wdb
= get_writable_database();
688 wdb
.begin_transaction();
689 wdb
.add_document(Xapian::Document());
691 // With a transaction active, cancel_transaction() should fail with
693 TEST_EXCEPTION(Xapian::NetworkError
,
694 wdb
.cancel_transaction());
698 // Test WritableDatabase methods.
699 DEFINE_TESTCASE(remotefailure7
, remotetcp
) {
701 XFAIL("Remote failure handling or testing is buggy on __MINGW32__");
703 Xapian::WritableDatabase
db(get_writable_database());
704 db
.add_document(Xapian::Document());
707 // We have a pending change from before the kill so this should fail.
708 TEST_EXCEPTION(Xapian::NetworkError
,
710 TEST_EXCEPTION(Xapian::NetworkError
,
711 db
.add_document(Xapian::Document()));
712 TEST_EXCEPTION(Xapian::NetworkError
,
713 db
.delete_document(1));
714 TEST_EXCEPTION(Xapian::NetworkError
,
715 db
.replace_document(1, Xapian::Document()));
716 TEST_EXCEPTION(Xapian::NetworkError
,
717 db
.replace_document(2, Xapian::Document()));
718 TEST_EXCEPTION(Xapian::NetworkError
,
719 db
.replace_document("Qi", Xapian::Document()));
722 // Test spelling related methods.
723 DEFINE_TESTCASE(remotefailure8
, remotetcp
) {
725 XFAIL("Remote failure handling or testing is buggy on __MINGW32__");
727 Xapian::WritableDatabase
db(get_writable_database());
728 db
.add_spelling("pneumatic");
729 db
.add_spelling("pneumonia");
732 TEST_EXCEPTION(Xapian::NetworkError
,
733 db
.add_spelling("penmanship"));
734 TEST_EXCEPTION(Xapian::NetworkError
,
735 db
.remove_spelling("pneumatic"));
736 // These methods aren't implemented for remote databases - they're no-ops
737 // which don't fail even when we kill the remote server. Once remote
738 // spelling suggestions are working we can uncomment them.
739 // TEST_EXCEPTION(Xapian::NetworkError,
740 // db.get_spelling_suggestion("newmonia"));
741 // TEST_EXCEPTION(Xapian::NetworkError,
742 // db.spellings_begin());
745 // Test synonym related methods.
746 DEFINE_TESTCASE(remotefailure9
, remotetcp
) {
748 XFAIL("Remote failure handling or testing is buggy on __MINGW32__");
750 Xapian::WritableDatabase
db(get_writable_database());
751 db
.add_synonym("color", "colour");
752 db
.add_synonym("honor", "honour");
755 TEST_EXCEPTION(Xapian::NetworkError
,
756 db
.add_synonym("behavior", "behaviour"));
757 TEST_EXCEPTION(Xapian::NetworkError
,
758 db
.remove_synonym("honor", "honour"));
759 TEST_EXCEPTION(Xapian::NetworkError
,
760 db
.clear_synonyms("honor"));
761 TEST_EXCEPTION(Xapian::NetworkError
,
762 db
.synonyms_begin("color"));
763 TEST_EXCEPTION(Xapian::NetworkError
,
764 db
.synonym_keys_begin());
767 // Test metadata related methods.
768 DEFINE_TESTCASE(remotefailure10
, remotetcp
) {
770 XFAIL("Remote failure handling or testing is buggy on __MINGW32__");
772 Xapian::WritableDatabase
db(get_writable_database());
773 db
.set_metadata("foo", "FOO");
774 db
.set_metadata("bar", "BAR");
777 TEST_EXCEPTION(Xapian::NetworkError
,
778 db
.set_metadata("test", "TEST"));
779 TEST_EXCEPTION(Xapian::NetworkError
,
780 db
.get_metadata("foo"));
781 TEST_EXCEPTION(Xapian::NetworkError
,
782 db
.get_metadata("bar"));
783 TEST_EXCEPTION(Xapian::NetworkError
,
784 db
.metadata_keys_begin());