Branch data Line data Source code
1 : : /* internaltest.cc: test of the Xapian internals
2 : : *
3 : : * Copyright 1999,2000,2001 BrightStation PLC
4 : : * Copyright 2002 Ananova Ltd
5 : : * Copyright 2002,2003,2006,2007,2008,2009,2010 Olly Betts
6 : : * Copyright 2006 Lemur Consulting Ltd
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 <xapian.h>
27 : :
28 : : #include <cfloat>
29 : : #include "safeerrno.h"
30 : :
31 : : #include <iostream>
32 : : #include <string>
33 : :
34 : : using namespace std;
35 : :
36 : : #include "autoptr.h"
37 : : #include "testsuite.h"
38 : : #include "testutils.h"
39 : :
40 : : #include "omassert.h"
41 : : #include "omqueryinternal.h"
42 : : #include "pack.h"
43 : : #include "serialise.h"
44 : : #include "serialise-double.h"
45 : : #include "str.h"
46 : :
47 : 1 : static bool test_except1()
48 : : {
49 : : try {
50 : 1 : throw 1;
51 : 1 : } catch (int) {
52 : : }
53 : 1 : return true;
54 : : }
55 : :
56 : : class Test_Exception {
57 : : public:
58 : : int value;
59 : 2 : Test_Exception(int value_) : value(value_) {}
60 : : };
61 : :
62 : : // test that nested exceptions work correctly.
63 : 1 : static bool test_exception1()
64 : : {
65 : : try {
66 : : try {
67 : 1 : throw Test_Exception(1);
68 : 2 : } catch (...) {
69 : : try {
70 : 1 : throw Test_Exception(2);
71 : 1 : } catch (...) {
72 : : }
73 : 1 : throw;
74 : : }
75 : 2 : } catch (const Test_Exception & e) {
76 [ - + ][ # # ]: 1 : TEST_EQUAL(e.value, 1);
77 : 1 : return true;
78 : : }
79 : : return false;
80 : : }
81 : :
82 : : // ###########################################
83 : : // # Tests of the reference counted pointers #
84 : : // ###########################################
85 : :
86 : : class test_refcnt : public Xapian::Internal::RefCntBase {
87 : : private:
88 : : bool &deleted;
89 : : public:
90 : 2 : test_refcnt(bool &deleted_) : deleted(deleted_) {
91 : 2 : tout << "constructor\n";
92 : 2 : }
93 : : Xapian::Internal::RefCntPtr<const test_refcnt> test() {
94 : : return Xapian::Internal::RefCntPtr<const test_refcnt>(this);
95 : : }
96 : 2 : ~test_refcnt() {
97 : 2 : deleted = true;
98 : 2 : tout << "destructor\n";
99 : 2 : }
100 : : };
101 : :
102 : 1 : static bool test_refcnt1()
103 : : {
104 : 1 : bool deleted = false;
105 : :
106 : 1 : test_refcnt *p = new test_refcnt(deleted);
107 : :
108 [ - + # # ]: 1 : TEST_EQUAL(p->ref_count, 0);
109 : :
110 : : {
111 : 1 : Xapian::Internal::RefCntPtr<test_refcnt> rcp(p);
112 : :
113 [ - + # # ]: 1 : TEST_EQUAL(rcp->ref_count, 1);
114 : :
115 : : {
116 : 1 : Xapian::Internal::RefCntPtr<test_refcnt> rcp2;
117 : 1 : rcp2 = rcp;
118 [ - + # # ]: 1 : TEST_EQUAL(rcp->ref_count, 2);
119 : : // rcp2 goes out of scope here
120 : : }
121 : :
122 [ - + # # ]: 1 : TEST_AND_EXPLAIN(!deleted, "Object prematurely deleted!");
123 [ - + ][ # # ]: 1 : TEST_EQUAL(rcp->ref_count, 1);
124 : : // rcp goes out of scope here
125 : : }
126 : :
127 [ - + # # ]: 1 : TEST_AND_EXPLAIN(deleted, "Object not properly deleted");
128 : :
129 : 1 : return true;
130 : : }
131 : :
132 : : // This is a regression test - a RefCntPtr used to delete the object pointed
133 : : // to if you assigned it to itself and the reference count was 1.
134 : 1 : static bool test_refcnt2()
135 : : {
136 : 1 : bool deleted = false;
137 : :
138 : 1 : test_refcnt *p = new test_refcnt(deleted);
139 : :
140 : 1 : Xapian::Internal::RefCntPtr<test_refcnt> rcp(p);
141 : :
142 : 1 : rcp = rcp;
143 : :
144 [ - + # # ]: 1 : TEST_AND_EXPLAIN(!deleted, "Object deleted by self-assignment");
145 : :
146 : 1 : return true;
147 : : }
148 : :
149 : : // Class for testing AutoPtr<>.
150 : : class test_autoptr {
151 : : bool &deleted;
152 : : public:
153 : 1 : test_autoptr(bool &deleted_) : deleted(deleted_) {
154 : 1 : tout << "test_autoptr constructor\n";
155 : 1 : }
156 : 1 : ~test_autoptr() {
157 : 1 : deleted = true;
158 : 1 : tout << "test_autoptr destructor\n";
159 : 1 : }
160 : : };
161 : :
162 : : // Test autoptr self-assignment.
163 : 1 : static bool test_autoptr1()
164 : : {
165 : 1 : bool deleted = false;
166 : :
167 : 1 : test_autoptr * raw_ptr = new test_autoptr(deleted);
168 : : {
169 : 1 : AutoPtr<test_autoptr> ptr(raw_ptr);
170 : :
171 [ - + # # ]: 1 : TEST_EQUAL(ptr.get(), raw_ptr);
172 : :
173 [ - + ][ # # ]: 1 : TEST(!deleted);
174 : :
175 : 1 : ptr = ptr;
176 : :
177 [ - + # # ]: 1 : TEST_EQUAL(ptr.get(), raw_ptr);
178 : :
179 [ - + ][ # # ]: 1 : TEST(!deleted);
180 : : }
181 : :
182 [ - + # # ]: 1 : TEST(deleted);
183 : :
184 : 1 : return true;
185 : : }
186 : :
187 : : // test string comparisions
188 : 1 : static bool test_stringcomp1()
189 : : {
190 : 1 : bool success = true;
191 : :
192 : 1 : string s1;
193 : 1 : string s2;
194 : :
195 : 1 : s1 = "foo";
196 : 1 : s2 = "foo";
197 : :
198 [ + - - + ]: 1 : if ((s1 != s2) || (s1 > s2)) {
[ - + ]
199 : 0 : success = false;
200 : 0 : tout << "String comparisons BADLY wrong" << endl;
201 : : }
202 : :
203 : 1 : s1 += '\0';
204 : :
205 [ + - - + ]: 1 : if ((s1 == s2) || (s1 < s2)) {
[ - + ]
206 : 0 : success = false;
207 : 0 : tout << "String comparisions don't cope with extra nulls" << endl;
208 : : }
209 : :
210 : 1 : s2 += '\0';
211 : :
212 : 1 : s1 += 'a';
213 : 1 : s2 += 'z';
214 : :
215 [ + - - + ]: 1 : if ((s1.length() != 5) || (s2.length() != 5)) {
[ - + ]
216 : 0 : success = false;
217 : 0 : tout << "Lengths with added nulls wrong" << endl;
218 : : }
219 : :
220 [ + - ][ - + ]: 1 : if ((s1 == s2) || !(s1 < s2)) {
[ - + ]
221 : 0 : success = false;
222 : 0 : tout << "Characters after a null ignored in comparisons" << endl;
223 : : }
224 : :
225 : 1 : return success;
226 : : }
227 : :
228 : 1 : static bool test_tostring1()
229 : : {
230 [ - + ][ # # ]: 1 : TEST_EQUAL(str(0), "0");
231 [ - + ][ # # ]: 1 : TEST_EQUAL(str(10), "10");
232 [ - + ][ # # ]: 1 : TEST_EQUAL(str(10u), "10");
233 [ - + ][ # # ]: 1 : TEST_EQUAL(str(-10), "-10");
234 [ - + ][ # # ]: 1 : TEST_EQUAL(str(0xffffffff), "4294967295");
235 [ - + ][ # # ]: 1 : TEST_EQUAL(str(0x7fffffff), "2147483647");
236 [ - + ][ # # ]: 1 : TEST_EQUAL(str(0x7fffffffu), "2147483647");
237 [ - + ][ # # ]: 1 : TEST_EQUAL(str(-0x7fffffff), "-2147483647");
238 : :
239 : : #ifdef __WIN32__
240 : : /* Test the 64 bit integer conversion to string.
241 : : * (Currently only exists for windows.)
242 : : */
243 : : TEST_EQUAL(str(10ll), "10");
244 : : TEST_EQUAL(str(-10ll), "-10");
245 : : TEST_EQUAL(str(0x200000000ll), "8589934592");
246 : : // We don't currently have an "unsigned long long" version since it's not required
247 : : // anywhere in the library.
248 : : // TEST_EQUAL(str(0x200000000ull), "8589934592");
249 : : #endif
250 : :
251 : 1 : return true;
252 : : }
253 : :
254 : : #ifdef XAPIAN_HAS_REMOTE_BACKEND
255 : : // Check serialisation of lengths.
256 : 1 : static bool test_serialiselength1()
257 : : {
258 : 1 : size_t n = 0;
259 [ + + ]: 84754 : while (n < 0xff000000) {
260 : 84753 : string s = encode_length(n);
261 : 84753 : const char *p = s.data();
262 : 84753 : const char *p_end = p + s.size();
263 : 84753 : size_t decoded_n = decode_length(&p, p_end, false);
264 [ + - - + ]: 84753 : if (n != decoded_n || p != p_end) tout << "[" << s << "]" << endl;
265 [ - + ][ # # ]: 84753 : TEST_EQUAL(n, decoded_n);
266 [ - + ][ # # ]: 84753 : TEST_EQUAL(p_end - p, 0);
267 [ + + ]: 84753 : if (n < 5000) {
268 : 5000 : ++n;
269 : : } else {
270 : 79753 : n += 53643;
271 : : }
272 : : }
273 : :
274 : 1 : return true;
275 : : }
276 : :
277 : : // Regression test: vetting the remaining buffer length
278 : 1 : static bool test_serialiselength2()
279 : : {
280 : : // Special case tests for 0
281 : : {
282 : 1 : string s = encode_length(0);
283 : : {
284 : 1 : const char *p = s.data();
285 : 1 : const char *p_end = p + s.size();
286 [ - + # # ]: 1 : TEST(decode_length(&p, p_end, true) == 0);
287 [ - + ][ # # ]: 1 : TEST(p == p_end);
288 : : }
289 : 1 : s += 'x';
290 : : {
291 : 1 : const char *p = s.data();
292 : 1 : const char *p_end = p + s.size();
293 [ - + # # ]: 1 : TEST(decode_length(&p, p_end, true) == 0);
294 [ - + ][ # # ]: 1 : TEST_EQUAL(p_end - p, 1);
295 : 1 : }
296 : : }
297 : : // Special case tests for 1
298 : : {
299 : 1 : string s = encode_length(1);
300 [ + - ][ - + ]: 2 : TEST_EXCEPTION(Xapian::NetworkError,
[ # # ][ # # ]
[ # # ][ - + ]
301 : : const char *p = s.data();
302 : : const char *p_end = p + s.size();
303 : : TEST(decode_length(&p, p_end, true) == 1);
304 : : );
305 : 1 : s += 'x';
306 : : {
307 : 1 : const char *p = s.data();
308 : 1 : const char *p_end = p + s.size();
309 [ - + # # ]: 1 : TEST(decode_length(&p, p_end, true) == 1);
310 [ - + ][ # # ]: 1 : TEST_EQUAL(p_end - p, 1);
311 : : }
312 : 1 : s += 'x';
313 : : {
314 : 1 : const char *p = s.data();
315 : 1 : const char *p_end = p + s.size();
316 [ - + # # ]: 1 : TEST(decode_length(&p, p_end, true) == 1);
317 [ - + ][ # # ]: 1 : TEST_EQUAL(p_end - p, 2);
318 : 1 : }
319 : : }
320 : : // Nothing magic here, just test a range of odd and even values.
321 [ + + ]: 8 : for (size_t n = 2; n < 1000; n = (n + 1) * 2 + (n >> 1)) {
322 : 7 : string s = encode_length(n);
323 [ + - ][ - + ]: 14 : TEST_EXCEPTION(Xapian::NetworkError,
[ # # ][ # # ]
[ # # ][ - + ]
324 : : const char *p = s.data();
325 : : const char *p_end = p + s.size();
326 : : TEST(decode_length(&p, p_end, true) == n);
327 : : );
328 : 7 : s.append(n-1, 'x');
329 [ + - ][ - + ]: 14 : TEST_EXCEPTION(Xapian::NetworkError,
[ # # ][ # # ]
[ # # ][ - + ]
330 : : const char *p = s.data();
331 : : const char *p_end = p + s.size();
332 : : TEST(decode_length(&p, p_end, true) == n);
333 : : );
334 : 7 : s += 'x';
335 : : {
336 : 7 : const char *p = s.data();
337 : 7 : const char *p_end = p + s.size();
338 [ - + # # ]: 7 : TEST(decode_length(&p, p_end, true) == n);
339 [ - + ][ # # ]: 7 : TEST_EQUAL(size_t(p_end - p), n);
340 : : }
341 : 7 : s += 'x';
342 : : {
343 : 7 : const char *p = s.data();
344 : 7 : const char *p_end = p + s.size();
345 [ - + # # ]: 7 : TEST(decode_length(&p, p_end, true) == n);
346 [ - + ][ # # ]: 7 : TEST_EQUAL(size_t(p_end - p), n + 1);
347 : : }
348 : : }
349 : :
350 : 1 : return true;
351 : : }
352 : : #endif
353 : :
354 : 39 : static void check_double_serialisation(double u)
355 : : {
356 : 39 : string encoded = serialise_double(u);
357 : 39 : const char * ptr = encoded.data();
358 : 39 : const char * end = ptr + encoded.size();
359 : 39 : double v = unserialise_double(&ptr, end);
360 [ + - - + ]: 39 : if (ptr != end || u != v) {
361 : 0 : tout << u << " -> " << v << ", difference = " << v - u << endl;
362 : 0 : tout << "FLT_RADIX = " << FLT_RADIX << endl;
363 : 0 : tout << "DBL_MAX_EXP = " << DBL_MAX_EXP << endl;
364 : : }
365 [ - + ][ # # ]: 39 : TEST(ptr == end);
366 [ - + ][ # # ]: 39 : TEST_EQUAL(u, v);
367 : 39 : }
368 : :
369 : : // Check serialisation of doubles.
370 : 1 : static bool test_serialisedouble1()
371 : : {
372 : : static const double test_values[] = {
373 : : 3.14159265,
374 : : 1e57,
375 : : 123.1,
376 : : 257.12,
377 : : 1234.567e123,
378 : : 255.5,
379 : : 256.125,
380 : : 257.03125,
381 : : };
382 : :
383 : 1 : check_double_serialisation(0.0);
384 : 1 : check_double_serialisation(1.0);
385 : 1 : check_double_serialisation(-1.0);
386 : 1 : check_double_serialisation(DBL_MAX);
387 : 1 : check_double_serialisation(-DBL_MAX);
388 : 1 : check_double_serialisation(DBL_MIN);
389 : 1 : check_double_serialisation(-DBL_MIN);
390 : :
391 : : const double *p;
392 [ + + ]: 9 : for (p = test_values; p < test_values + sizeof(test_values) / sizeof(double); ++p) {
393 : 8 : double val = *p;
394 : 8 : check_double_serialisation(val);
395 : 8 : check_double_serialisation(-val);
396 : 8 : check_double_serialisation(1.0 / val);
397 : 8 : check_double_serialisation(-1.0 / val);
398 : : }
399 : :
400 : 1 : return true;
401 : : }
402 : :
403 : : #ifdef XAPIAN_HAS_REMOTE_BACKEND
404 : : // Check serialisation of documents.
405 : 1 : static bool test_serialisedoc1()
406 : : {
407 : 1 : Xapian::Document doc;
408 : :
409 : 1 : string s;
410 : :
411 : 1 : s = serialise_document(doc);
412 [ - + ][ # # ]: 1 : TEST(serialise_document(unserialise_document(s)) == s);
413 : :
414 : 1 : doc.set_data("helllooooo");
415 : 1 : doc.add_term("term");
416 : 1 : doc.add_value(1, "foo");
417 : :
418 : 1 : s = serialise_document(doc);
419 [ - + ][ # # ]: 1 : TEST(serialise_document(unserialise_document(s)) == s);
420 : :
421 : 1 : return true;
422 : : }
423 : :
424 : : static void
425 : 5 : serialisequery1_helper(const Xapian::Query & query)
426 : : {
427 : 5 : string before = query.internal->serialise();
428 : 5 : Xapian::Registry reg;
429 : : Xapian::Query::Internal * qint;
430 : 5 : qint = Xapian::Query::Internal::unserialise(before, reg);
431 : 5 : string after = qint->serialise();
432 [ + - ]: 5 : delete qint;
433 [ - + ][ # # ]: 5 : TEST(before == after);
434 : 5 : }
435 : :
436 : : // Check serialisation of queries.
437 : 1 : static bool test_serialisequery1()
438 : : {
439 : 1 : string s;
440 : :
441 : 1 : serialisequery1_helper(Xapian::Query("foo"));
442 : :
443 : : // Regression test for bug in 0.9.10 and earlier.
444 : 1 : serialisequery1_helper(Xapian::Query("foo", 1, 1));
445 : :
446 : : serialisequery1_helper(Xapian::Query(Xapian::Query::OP_OR,
447 : : Xapian::Query("foo", 1, 1),
448 : 1 : Xapian::Query("bar", 1, 1)));
449 : :
450 : : static const char * words[] = { "paragraph", "word" };
451 : 1 : serialisequery1_helper(Xapian::Query(Xapian::Query::OP_OR, words, words + 2));
452 : :
453 : : static const char * words2[] = { "milk", "on", "fridge" };
454 : : serialisequery1_helper(
455 : : Xapian::Query(Xapian::Query::OP_SCALE_WEIGHT,
456 : : Xapian::Query(Xapian::Query::OP_OR,
457 : : Xapian::Query("leave"),
458 : : Xapian::Query(Xapian::Query::OP_PHRASE, words2, words2 + 3)
459 : : ),
460 : : 2.5)
461 : 1 : );
462 : :
463 : 1 : return true;
464 : : }
465 : :
466 : : // Check serialisation of Xapian::Error.
467 : 1 : static bool test_serialiseerror1()
468 : : {
469 : 1 : string enoent_msg(strerror(ENOENT));
470 : 1 : Xapian::DatabaseOpeningError e("Failed to open database", ENOENT);
471 : : // Regression test for bug in 1.0.0 - it didn't convert errno values for
472 : : // get_description() if they hadn't already been converted.
473 [ - + ][ # # ]: 1 : TEST_STRINGS_EQUAL(e.get_description(), "DatabaseOpeningError: Failed to open database (" + enoent_msg + ")");
474 : :
475 [ - + ][ # # ]: 1 : TEST_STRINGS_EQUAL(e.get_error_string(), enoent_msg);
476 : :
477 : 1 : string serialisation = serialise_error(e);
478 : :
479 : : // Test if unserialise_error() throws with a flag to avoid the possibility
480 : : // of an "unreachable code" warning when we get around to marking
481 : : // unserialise_error() as "noreturn".
482 : 1 : bool threw = false;
483 : : try {
484 : : // unserialise_error throws an exception.
485 : 5 : unserialise_error(serialisation, "", "");
486 : 2 : } catch (const Xapian::Error & ecaught) {
487 [ - + ][ # # ]: 1 : TEST_STRINGS_EQUAL(ecaught.get_error_string(), enoent_msg);
488 : 1 : threw = true;
489 : : }
490 [ - + # # ]: 1 : TEST(threw);
491 : :
492 : : // Check that the original is still OK.
493 [ - + ][ # # ]: 1 : TEST_STRINGS_EQUAL(e.get_error_string(), enoent_msg);
494 : :
495 : : // Regression test - in 1.0.0, copying used to duplicate the error_string
496 : : // pointer, resulting in double calls to free().
497 : 1 : Xapian::DatabaseOpeningError ecopy(e);
498 [ - + # # ]: 1 : TEST_STRINGS_EQUAL(ecopy.get_error_string(), enoent_msg);
499 : :
500 : 1 : return true;
501 : : }
502 : : #endif
503 : :
504 : : // By default Sun's C++ compiler doesn't call the destructor on a
505 : : // temporary object until the end of the block (contrary to what
506 : : // ISO C++ requires). This is done in the name of "compatibility".
507 : : // Passing -features=tmplife to CC fixes this. This check ensures
508 : : // that this actually works for Sun's C++ and any other compilers
509 : : // that might have this problem.
510 : : struct TempDtorTest {
511 : : static int count;
512 : 1 : static TempDtorTest factory() { return TempDtorTest(); }
513 : 1 : TempDtorTest() { ++count; }
514 : 1 : ~TempDtorTest() { --count; }
515 : : };
516 : :
517 : : int TempDtorTest::count = 0;
518 : :
519 : 1 : static bool test_temporarydtor1()
520 : : {
521 [ - + ][ # # ]: 1 : TEST_EQUAL(TempDtorTest::count, 0);
522 : 1 : TempDtorTest::factory();
523 [ - + # # ]: 1 : TEST_EQUAL(TempDtorTest::count, 0);
524 : :
525 : 1 : return true;
526 : : }
527 : :
528 : 1 : static bool test_static_assert1()
529 : : {
530 : : STATIC_ASSERT(true);
531 : : STATIC_ASSERT(1);
532 : : STATIC_ASSERT(-1);
533 : : STATIC_ASSERT(42);
534 : : STATIC_ASSERT(sizeof(char) == 1);
535 : :
536 : : // FIXME: We should test cases which should fail, but these are hard to
537 : : // check with our current test framework.
538 : :
539 : : STATIC_ASSERT_UNSIGNED_TYPE(bool);
540 : : STATIC_ASSERT_UNSIGNED_TYPE(unsigned char);
541 : : STATIC_ASSERT_UNSIGNED_TYPE(unsigned short);
542 : : STATIC_ASSERT_UNSIGNED_TYPE(unsigned int);
543 : : STATIC_ASSERT_UNSIGNED_TYPE(unsigned long);
544 : :
545 : : // FIXME: We should test cases which should fail, but these are hard to
546 : : // check with our current test framework.
547 : :
548 : : STATIC_ASSERT_TYPE_DOMINATES(unsigned long, unsigned long);
549 : : STATIC_ASSERT_TYPE_DOMINATES(unsigned int, unsigned int);
550 : : STATIC_ASSERT_TYPE_DOMINATES(unsigned short, unsigned short);
551 : : STATIC_ASSERT_TYPE_DOMINATES(unsigned char, unsigned char);
552 : :
553 : : STATIC_ASSERT_TYPE_DOMINATES(long, long);
554 : : STATIC_ASSERT_TYPE_DOMINATES(int, int);
555 : : STATIC_ASSERT_TYPE_DOMINATES(short, short);
556 : : STATIC_ASSERT_TYPE_DOMINATES(signed char, signed char);
557 : :
558 : : STATIC_ASSERT_TYPE_DOMINATES(char, char);
559 : :
560 : : STATIC_ASSERT_TYPE_DOMINATES(unsigned long, unsigned int);
561 : : STATIC_ASSERT_TYPE_DOMINATES(unsigned int, unsigned short);
562 : : STATIC_ASSERT_TYPE_DOMINATES(unsigned short, unsigned char);
563 : :
564 : : STATIC_ASSERT_TYPE_DOMINATES(long, int);
565 : : STATIC_ASSERT_TYPE_DOMINATES(int, short);
566 : : STATIC_ASSERT_TYPE_DOMINATES(short, signed char);
567 : :
568 : : STATIC_ASSERT_TYPE_DOMINATES(long, unsigned char);
569 : : STATIC_ASSERT_TYPE_DOMINATES(int, unsigned char);
570 : : STATIC_ASSERT_TYPE_DOMINATES(short, unsigned char);
571 : :
572 : : // FIXME: We should test cases which should fail, but these are hard to
573 : : // check with our current test framework.
574 : :
575 : 1 : return true;
576 : : }
577 : :
578 : : /// Regression test for bug fixed in 1.1.1.
579 : 1 : static bool test_strbool1()
580 : : {
581 [ - + ][ # # ]: 1 : TEST_EQUAL(str(true), "1");
582 [ - + ][ # # ]: 1 : TEST_EQUAL(str(false), "0");
583 : 1 : return true;
584 : : }
585 : :
586 : : /// Test pack_uint_preserving_sort()
587 : 1 : static bool test_pack_uint_preserving_sort1()
588 : : {
589 : 1 : string prev_packed;
590 [ + + ]: 1001 : for (unsigned int i = 0; i != 1000; ++i) {
591 : 1000 : string packed;
592 : 1000 : pack_uint_preserving_sort(packed, i);
593 : 1000 : const char * ptr = packed.data();
594 : 1000 : const char * end = ptr + packed.size();
595 : : unsigned int result;
596 [ - + # # ]: 1000 : TEST(unpack_uint_preserving_sort(&ptr, end, &result));
597 [ - + ][ # # ]: 1000 : TEST_EQUAL(result, i);
598 [ - + ][ # # ]: 1000 : TEST(ptr == end);
599 [ - + ][ # # ]: 1000 : TEST_REL(prev_packed, <, packed);
600 : 1000 : swap(prev_packed, packed);
601 : : }
602 : 1 : return true;
603 : : }
604 : :
605 : : // ##################################################################
606 : : // # End of actual tests #
607 : : // ##################################################################
608 : :
609 : : /// The lists of tests to perform
610 : : static const test_desc tests[] = {
611 : : {"except1", test_except1},
612 : : {"exception1", test_exception1},
613 : : {"refcnt1", test_refcnt1},
614 : : {"refcnt2", test_refcnt2},
615 : : {"autoptr1", test_autoptr1},
616 : : {"stringcomp1", test_stringcomp1},
617 : : {"temporarydtor1", test_temporarydtor1},
618 : : {"tostring1", test_tostring1},
619 : : {"serialisedouble1", test_serialisedouble1},
620 : : #ifdef XAPIAN_HAS_REMOTE_BACKEND
621 : : {"serialiselength1", test_serialiselength1},
622 : : {"serialiselength2", test_serialiselength2},
623 : : {"serialisedoc1", test_serialisedoc1},
624 : : {"serialisequery1", test_serialisequery1},
625 : : {"serialiseerror1", test_serialiseerror1},
626 : : #endif
627 : : {"static_assert1", test_static_assert1},
628 : : {"strbool1", test_strbool1},
629 : : {"pack1", test_pack_uint_preserving_sort1},
630 : : {0, 0}
631 : : };
632 : :
633 : 1 : int main(int argc, char **argv)
634 : : try {
635 : 1 : test_driver::parse_command_line(argc, argv);
636 : 1 : return test_driver::run(tests);
637 : 1 : } catch (const char * e) {
638 : 0 : cout << e << endl;
639 : 0 : return 1;
640 [ + - ][ + - ]: 3 : }
|