Branch data Line data Source code
1 : : /** @file api_closedb.cc
2 : : * @brief Tests of closing databases.
3 : : */
4 : : /* Copyright 2008,2009 Lemur Consulting Ltd
5 : : * Copyright 2009 Olly Betts
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_closedb.h"
25 : :
26 : : #include <xapian.h>
27 : :
28 : : #include "apitest.h"
29 : : #include "testutils.h"
30 : :
31 : : using namespace std;
32 : :
33 : : #define COUNT_CLOSEDEXC(CODE) \
34 : : try { CODE; } catch (const Xapian::DatabaseError &) { ++closedexc_count; }
35 : :
36 : : #define IF_NOT_CLOSEDEXC(CODE) \
37 : : do { \
38 : : hadexc = false; \
39 : : try { \
40 : : CODE; \
41 : : } catch (const Xapian::DatabaseError &) { \
42 : : ++closedexc_count; \
43 : : hadexc = true; \
44 : : } \
45 : : } while (false); if (hadexc)
46 : :
47 : : // Iterators used by closedb1.
48 : 26 : struct closedb1_iterators {
49 : : Xapian::Database db;
50 : : Xapian::Document doc1;
51 : : Xapian::PostingIterator pl1;
52 : : Xapian::PostingIterator pl2;
53 : : Xapian::PostingIterator plend;
54 : :
55 : 26 : void setup(Xapian::Database db_) {
56 : 26 : db = db_;
57 : :
58 : : // Set up the iterators for the test.
59 : 26 : pl1 = db.postlist_begin("paragraph");
60 : 26 : pl2 = db.postlist_begin("paragraph");
61 : 26 : ++pl2;
62 : 26 : plend = db.postlist_end("paragraph");
63 : 26 : }
64 : :
65 : 26 : int perform() {
66 : 26 : int closedexc_count = 0;
67 : : bool hadexc;
68 : :
69 : : // Getting a document may throw closed.
70 [ + + ]: 35 : IF_NOT_CLOSEDEXC(doc1 = db.get_document(1)) {
71 [ - + ][ # # ]: 12 : COUNT_CLOSEDEXC(TEST_EQUAL(doc1.get_data().substr(0, 33),
72 : : "This is a test document used with"));
73 : 18 : COUNT_CLOSEDEXC(doc1.termlist_begin());
74 : : }
75 : :
76 : : // Causing the database to access its files raises the "database
77 : : // closed" error.
78 : 65 : COUNT_CLOSEDEXC(db.postlist_begin("paragraph"));
79 : 43 : COUNT_CLOSEDEXC(db.get_document(1).get_value(1));
80 : :
81 : : // Reopen raises the "database closed" error.
82 : 39 : COUNT_CLOSEDEXC(db.reopen());
83 : :
84 [ - + ][ # # ]: 26 : TEST_NOT_EQUAL(pl1, plend);
85 : :
86 : 65 : COUNT_CLOSEDEXC(db.postlist_begin("paragraph"));
87 : :
88 [ - + ][ # # ]: 27 : COUNT_CLOSEDEXC(TEST_EQUAL(*pl1, 1));
89 [ - + ][ # # ]: 33 : COUNT_CLOSEDEXC(TEST_EQUAL(pl1.get_doclength(), 28));
90 : :
91 : : // Advancing the iterator may or may not raise an error, but if it
92 : : // doesn't it must return the correct answers.
93 : 26 : bool advanced = false;
94 : : try {
95 : 26 : ++pl1;
96 : 25 : advanced = true;
97 : 1 : } catch (const Xapian::DatabaseError &) {}
98 : :
99 [ + + ]: 26 : if (advanced) {
100 [ - + ][ # # ]: 25 : COUNT_CLOSEDEXC(TEST_EQUAL(*pl1, 2));
101 [ - + ][ # # ]: 31 : COUNT_CLOSEDEXC(TEST_EQUAL(pl1.get_doclength(), 81));
102 : : }
103 : :
104 : 26 : return closedexc_count;
105 : : }
106 : : };
107 : :
108 : : // Test for closing a database
109 : 13 : DEFINE_TESTCASE(closedb1, backend) {
110 : 13 : Xapian::Database db(get_database("apitest_simpledata"));
111 : 13 : closedb1_iterators iters;
112 : :
113 : : // Run the test, checking that we get no "closed" exceptions.
114 : 13 : iters.setup(db);
115 : 13 : int closedexc_count = iters.perform();
116 [ - + # # ]: 13 : TEST_EQUAL(closedexc_count, 0);
117 : :
118 : : // Setup for the next test.
119 : 13 : iters.setup(db);
120 : :
121 : : // Close the database.
122 : 13 : db.close();
123 : :
124 : : // Reopening a closed database should always raise DatabaseError.
125 [ + - ][ - + ]: 26 : TEST_EXCEPTION(Xapian::DatabaseError, db.reopen());
[ # # ][ - + ]
126 : :
127 : : // Run the test again, checking that we get some "closed" exceptions.
128 : 13 : closedexc_count = iters.perform();
129 [ - + # # ]: 13 : TEST_NOT_EQUAL(closedexc_count, 0);
130 : :
131 : : // Calling close repeatedly is okay.
132 : 13 : db.close();
133 : :
134 : 13 : return true;
135 : : }
136 : :
137 : : // Test closing a writable database, and that it drops the lock.
138 : 3 : DEFINE_TESTCASE(closedb2, writable && !inmemory && !remote) {
139 : 3 : Xapian::WritableDatabase dbw1(get_named_writable_database("apitest_closedb2"));
140 [ + - ][ - + ]: 15 : TEST_EXCEPTION(Xapian::DatabaseLockError,
[ # # ][ - + ]
141 : : Xapian::WritableDatabase db(get_named_writable_database_path("apitest_closedb2"),
142 : : Xapian::DB_OPEN));
143 : 3 : dbw1.close();
144 : 3 : Xapian::WritableDatabase dbw2 = get_named_writable_database("apitest_closedb2");
145 [ + - ][ - + ]: 12 : TEST_EXCEPTION(Xapian::DatabaseError, dbw1.postlist_begin("paragraph"));
[ # # ][ - + ]
146 [ - + ][ # # ]: 3 : TEST_EQUAL(dbw2.postlist_begin("paragraph"), dbw2.postlist_end("paragraph"));
147 : :
148 : 3 : return true;
149 : : }
150 : :
151 : : /// Check API methods which might either work or throw an exception.
152 : 13 : DEFINE_TESTCASE(closedb3, backend) {
153 : 13 : Xapian::Database db(get_database("etext"));
154 : 13 : db.close();
155 : : try {
156 [ - + # # ]: 13 : TEST(db.has_positions());
157 : 7 : } catch (const Xapian::DatabaseError &) {
158 : : }
159 : : try {
160 [ - + ][ # # ]: 13 : TEST_EQUAL(db.get_doccount(), 566);
161 : 7 : } catch (const Xapian::DatabaseError &) {
162 : : }
163 : 13 : return true;
164 : : }
165 : :
166 : : /// Regression test for bug fixed in 1.1.4 - close() should implicitly commit().
167 : 9 : DEFINE_TESTCASE(closedb4, writable && !inmemory) {
168 : 9 : Xapian::WritableDatabase wdb(get_writable_database());
169 : 9 : wdb.add_document(Xapian::Document());
170 [ - + # # ]: 9 : TEST_EQUAL(wdb.get_doccount(), 1);
171 : 9 : wdb.close();
172 : 9 : Xapian::Database db(get_writable_database_as_database());
173 [ - + # # ]: 9 : TEST_EQUAL(db.get_doccount(), 1);
174 : 9 : return true;
175 : : }
176 : :
177 : : /// If a transaction is active, close() shouldn't implicitly commit().
178 : 3 : DEFINE_TESTCASE(closedb5, transactions && !remote) {
179 : : // FIXME: Fails with the remote backend, but I suspect it may be a test
180 : : // harness issue.
181 : : {
182 : 3 : Xapian::WritableDatabase wdb = get_writable_database();
183 : 3 : wdb.begin_transaction();
184 : 3 : wdb.add_document(Xapian::Document());
185 [ - + # # ]: 3 : TEST_EQUAL(wdb.get_doccount(), 1);
186 : 3 : wdb.close();
187 : 3 : Xapian::Database db = get_writable_database_as_database();
188 [ - + # # ]: 3 : TEST_EQUAL(db.get_doccount(), 0);
189 : : }
190 : :
191 : : {
192 : : // Same test but for an unflushed transaction.
193 : 3 : Xapian::WritableDatabase wdb = get_writable_database();
194 : 3 : wdb.begin_transaction(false);
195 : 3 : wdb.add_document(Xapian::Document());
196 [ - + # # ]: 3 : TEST_EQUAL(wdb.get_doccount(), 1);
197 : 3 : wdb.close();
198 : 3 : Xapian::Database db = get_writable_database_as_database();
199 [ - + # # ]: 3 : TEST_EQUAL(db.get_doccount(), 0);
200 : : }
201 : 3 : return true;
202 : : }
|