Remove unused header include
[xapian.git] / xapian-core / tests / internaltest.cc
blob7747921d0e90e1c7a9c9e5865c80cc6feaee850a
1 /* internaltest.cc: test of the Xapian internals
3 * Copyright 1999,2000,2001 BrightStation PLC
4 * Copyright 2002 Ananova Ltd
5 * Copyright 2002,2003,2006,2007,2008,2009,2010,2011,2012,2015 Olly Betts
6 * Copyright 2006 Lemur Consulting Ltd
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.
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.
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
24 #include <config.h>
26 #include <xapian.h>
28 #include "safeerrno.h"
30 #include <iostream>
31 #include <string>
33 using namespace std;
35 #include "autoptr.h"
36 #include "testsuite.h"
37 #include "testutils.h"
39 #include "omassert.h"
40 #include "pack.h"
41 #include "str.h"
43 class Test_Exception {
44 public:
45 int value;
46 Test_Exception(int value_) : value(value_) {}
49 // test that nested exceptions work correctly.
50 static bool test_exception1()
52 try {
53 try {
54 throw Test_Exception(1);
55 } catch (...) {
56 try {
57 throw Test_Exception(2);
58 } catch (...) {
60 throw;
62 } catch (const Test_Exception & e) {
63 TEST_EQUAL(e.value, 1);
64 return true;
66 return false;
69 // ###########################################
70 // # Tests of the reference counted pointers #
71 // ###########################################
73 class test_refcnt : public Xapian::Internal::intrusive_base {
74 private:
75 bool &deleted;
76 public:
77 test_refcnt(bool &deleted_) : deleted(deleted_) {
78 tout << "constructor\n";
80 Xapian::Internal::intrusive_ptr<const test_refcnt> test() {
81 return Xapian::Internal::intrusive_ptr<const test_refcnt>(this);
83 ~test_refcnt() {
84 deleted = true;
85 tout << "destructor\n";
89 static bool test_refcnt1()
91 bool deleted = false;
93 test_refcnt *p = new test_refcnt(deleted);
95 TEST_EQUAL(p->_refs, 0);
98 Xapian::Internal::intrusive_ptr<test_refcnt> rcp(p);
100 TEST_EQUAL(rcp->_refs, 1);
103 Xapian::Internal::intrusive_ptr<test_refcnt> rcp2;
104 rcp2 = rcp;
105 TEST_EQUAL(rcp->_refs, 2);
106 // rcp2 goes out of scope here
109 TEST_AND_EXPLAIN(!deleted, "Object prematurely deleted!");
110 TEST_EQUAL(rcp->_refs, 1);
111 // rcp goes out of scope here
114 TEST_AND_EXPLAIN(deleted, "Object not properly deleted");
116 return true;
119 // This is a regression test - our home-made equivalent of intrusive_ptr
120 // (which was called RefCntPtr) used to delete the object pointed to if you
121 // assigned it to itself and the reference count was 1.
122 static bool test_refcnt2()
124 bool deleted = false;
126 test_refcnt *p = new test_refcnt(deleted);
128 Xapian::Internal::intrusive_ptr<test_refcnt> rcp(p);
130 rcp = rcp;
132 TEST_AND_EXPLAIN(!deleted, "Object deleted by self-assignment");
134 return true;
137 // Class for testing AutoPtr<>.
138 class test_autoptr {
139 bool &deleted;
140 public:
141 test_autoptr(bool &deleted_) : deleted(deleted_) {
142 tout << "test_autoptr constructor\n";
144 ~test_autoptr() {
145 deleted = true;
146 tout << "test_autoptr destructor\n";
150 // Test autoptr self-assignment.
151 static bool test_autoptr1()
153 bool deleted = false;
155 test_autoptr * raw_ptr = new test_autoptr(deleted);
157 AutoPtr<test_autoptr> ptr(raw_ptr);
159 TEST_EQUAL(ptr.get(), raw_ptr);
160 TEST(!deleted);
162 ptr.reset(ptr.release());
164 TEST_EQUAL(ptr.get(), raw_ptr);
165 TEST(!deleted);
167 ptr.swap(ptr);
169 TEST_EQUAL(ptr.get(), raw_ptr);
170 TEST(!deleted);
172 swap(ptr, ptr);
174 TEST_EQUAL(ptr.get(), raw_ptr);
175 TEST(!deleted);
178 TEST(deleted);
180 deleted = false;
181 raw_ptr = new test_autoptr(deleted);
183 bool deleted2 = false;
184 test_autoptr * raw_ptr2 = new test_autoptr(deleted2);
185 AutoPtr<test_autoptr> ptr(raw_ptr2);
187 TEST_EQUAL(ptr.get(), raw_ptr2);
188 TEST(!deleted);
189 TEST(!deleted2);
191 ptr.reset(raw_ptr);
192 TEST_EQUAL(ptr.get(), raw_ptr);
193 TEST(!deleted);
194 TEST(deleted2);
196 ptr.reset();
197 TEST_EQUAL(ptr.get(), static_cast<test_autoptr*>(0));
198 TEST(deleted);
200 return true;
203 // test string comparisons
204 static bool test_stringcomp1()
206 bool success = true;
208 string s1;
209 string s2;
211 s1 = "foo";
212 s2 = "foo";
214 if ((s1 != s2) || (s1 > s2)) {
215 success = false;
216 tout << "String comparisons BADLY wrong" << endl;
219 s1 += '\0';
221 if ((s1 == s2) || (s1 < s2)) {
222 success = false;
223 tout << "String comparisons don't cope with extra nulls" << endl;
226 s2 += '\0';
228 s1 += 'a';
229 s2 += 'z';
231 if ((s1.length() != 5) || (s2.length() != 5)) {
232 success = false;
233 tout << "Lengths with added nulls wrong" << endl;
236 if ((s1 == s2) || !(s1 < s2)) {
237 success = false;
238 tout << "Characters after a null ignored in comparisons" << endl;
241 return success;
244 // By default Sun's C++ compiler doesn't call the destructor on a
245 // temporary object until the end of the block (contrary to what
246 // ISO C++ requires). This is done in the name of "compatibility".
247 // Passing -features=tmplife to CC fixes this. This check ensures
248 // that this actually works for Sun's C++ and any other compilers
249 // that might have this problem.
250 struct TempDtorTest {
251 static int count;
252 static TempDtorTest factory() { return TempDtorTest(); }
253 TempDtorTest() { ++count; }
254 ~TempDtorTest() { --count; }
257 int TempDtorTest::count = 0;
259 static bool test_temporarydtor1()
261 TEST_EQUAL(TempDtorTest::count, 0);
262 TempDtorTest::factory();
263 TEST_EQUAL(TempDtorTest::count, 0);
265 return true;
268 static bool test_static_assert1()
270 // These tests aren't so useful now we're using C++11 static_assert(),
271 // but it's not a bad idea to sanity check it.
272 static_assert(true, "true");
273 static_assert(1, "1");
274 static_assert(-1, "-1");
275 static_assert(42, "42");
276 static_assert(sizeof(char) == 1, "sizeof(char) == 1");
278 // FIXME: We should test cases which should fail, but these are hard to
279 // check with our current test framework.
281 STATIC_ASSERT_UNSIGNED_TYPE(bool);
282 STATIC_ASSERT_UNSIGNED_TYPE(unsigned char);
283 STATIC_ASSERT_UNSIGNED_TYPE(unsigned short);
284 STATIC_ASSERT_UNSIGNED_TYPE(unsigned int);
285 STATIC_ASSERT_UNSIGNED_TYPE(unsigned long);
287 // FIXME: We should test cases which should fail, but these are hard to
288 // check with our current test framework.
290 STATIC_ASSERT_TYPE_DOMINATES(unsigned long, unsigned long);
291 STATIC_ASSERT_TYPE_DOMINATES(unsigned int, unsigned int);
292 STATIC_ASSERT_TYPE_DOMINATES(unsigned short, unsigned short);
293 STATIC_ASSERT_TYPE_DOMINATES(unsigned char, unsigned char);
295 STATIC_ASSERT_TYPE_DOMINATES(long, long);
296 STATIC_ASSERT_TYPE_DOMINATES(int, int);
297 STATIC_ASSERT_TYPE_DOMINATES(short, short);
298 STATIC_ASSERT_TYPE_DOMINATES(signed char, signed char);
300 STATIC_ASSERT_TYPE_DOMINATES(char, char);
302 STATIC_ASSERT_TYPE_DOMINATES(unsigned long, unsigned int);
303 STATIC_ASSERT_TYPE_DOMINATES(unsigned int, unsigned short);
304 STATIC_ASSERT_TYPE_DOMINATES(unsigned short, unsigned char);
306 STATIC_ASSERT_TYPE_DOMINATES(long, int);
307 STATIC_ASSERT_TYPE_DOMINATES(int, short);
308 STATIC_ASSERT_TYPE_DOMINATES(short, signed char);
310 STATIC_ASSERT_TYPE_DOMINATES(long, unsigned char);
311 STATIC_ASSERT_TYPE_DOMINATES(int, unsigned char);
312 STATIC_ASSERT_TYPE_DOMINATES(short, unsigned char);
314 // FIXME: We should test cases which should fail, but these are hard to
315 // check with our current test framework.
317 return true;
320 /// Test pack_uint_preserving_sort()
321 static bool test_pack_uint_preserving_sort1()
323 string prev_packed;
324 for (unsigned int i = 0; i != 1000; ++i) {
325 string packed;
326 pack_uint_preserving_sort(packed, i);
327 const char * ptr = packed.data();
328 const char * end = ptr + packed.size();
329 unsigned int result;
330 TEST(unpack_uint_preserving_sort(&ptr, end, &result));
331 TEST_EQUAL(result, i);
332 TEST(ptr == end);
333 TEST_REL(prev_packed, <, packed);
334 swap(prev_packed, packed);
336 for (unsigned int i = 2345; i < 65000; i += 113) {
337 string packed;
338 pack_uint_preserving_sort(packed, i);
339 const char * ptr = packed.data();
340 const char * end = ptr + packed.size();
341 unsigned int result;
342 TEST(unpack_uint_preserving_sort(&ptr, end, &result));
343 TEST_EQUAL(result, i);
344 TEST(ptr == end);
345 TEST_REL(prev_packed, <, packed);
346 swap(prev_packed, packed);
348 unsigned int prev = 64999;
349 for (unsigned int i = 65000; i > prev; prev = i, i = (i << 1) ^ 1337) {
350 string packed;
351 pack_uint_preserving_sort(packed, i);
352 const char * ptr = packed.data();
353 const char * end = ptr + packed.size();
354 unsigned int result;
355 TEST(unpack_uint_preserving_sort(&ptr, end, &result));
356 TEST_EQUAL(result, i);
357 TEST(ptr == end);
358 TEST_REL(prev_packed, <, packed);
359 swap(prev_packed, packed);
362 /* Test packing multiple numbers to one string. */
363 string packed;
364 for (unsigned int i = 23456; i < 765432; i += 1131) {
365 pack_uint_preserving_sort(packed, i);
367 const char * ptr = packed.data();
368 const char * end = ptr + packed.size();
369 for (unsigned int i = 23456; i < 765432; i += 1131) {
370 unsigned int result;
371 TEST(unpack_uint_preserving_sort(&ptr, end, &result));
372 TEST_EQUAL(result, i);
374 TEST(ptr == end);
376 return true;
379 /// Test C_pack_uint_preserving_sort()
380 static bool test_pack_uint_preserving_sort2()
382 string prev_packed;
383 for (unsigned int i = 0; i != 1000; ++i) {
384 string packed;
385 C_pack_uint_preserving_sort(packed, i);
386 const char * ptr = packed.data();
387 const char * end = ptr + packed.size();
388 unsigned int result;
389 TEST(C_unpack_uint_preserving_sort(&ptr, end, &result));
390 TEST_EQUAL(result, i);
391 TEST(ptr == end);
392 TEST_REL(prev_packed, <, packed);
393 swap(prev_packed, packed);
395 for (unsigned int i = 2345; i < 65000; i += 113) {
396 string packed;
397 C_pack_uint_preserving_sort(packed, i);
398 const char * ptr = packed.data();
399 const char * end = ptr + packed.size();
400 unsigned int result;
401 TEST(C_unpack_uint_preserving_sort(&ptr, end, &result));
402 TEST_EQUAL(result, i);
403 TEST(ptr == end);
404 TEST_REL(prev_packed, <, packed);
405 swap(prev_packed, packed);
407 unsigned int prev = 64999;
408 for (unsigned int i = 65000; i > prev; prev = i, i = (i << 1) ^ 1337) {
409 string packed;
410 C_pack_uint_preserving_sort(packed, i);
411 const char * ptr = packed.data();
412 const char * end = ptr + packed.size();
413 unsigned int result;
414 TEST(C_unpack_uint_preserving_sort(&ptr, end, &result));
415 TEST_EQUAL(result, i);
416 TEST(ptr == end);
417 TEST_REL(prev_packed, <, packed);
418 swap(prev_packed, packed);
421 /* Test packing multiple numbers to one string. */
422 string packed;
423 for (unsigned int i = 23456; i < 765432; i += 1131) {
424 C_pack_uint_preserving_sort(packed, i);
426 const char * ptr = packed.data();
427 const char * end = ptr + packed.size();
428 for (unsigned int i = 23456; i < 765432; i += 1131) {
429 unsigned int result;
430 TEST(C_unpack_uint_preserving_sort(&ptr, end, &result));
431 TEST_EQUAL(result, i);
433 TEST(ptr == end);
435 return true;
438 /// Test C_isupper() etc.
439 static bool test_chartype1()
441 char tested[128];
442 memset(tested, 0, sizeof(tested));
443 for (int ch = '0'; ch != '9' + 1; ++ch) {
444 tested[ch] = 1;
445 TEST(!C_isupper(ch));
446 TEST(!C_islower(ch));
447 TEST(!C_isalpha(ch));
448 TEST(C_isalnum(ch));
449 TEST(C_isdigit(ch));
450 TEST(C_isxdigit(ch));
451 TEST(!C_isspace(ch));
452 TEST(C_isnotupper(ch));
453 TEST(C_isnotlower(ch));
454 TEST(C_isnotalpha(ch));
455 TEST(!C_isnotalnum(ch));
456 TEST(!C_isnotdigit(ch));
457 TEST(!C_isnotxdigit(ch));
458 TEST(C_isnotspace(ch));
459 TEST_EQUAL(hex_digit(ch), ch - '0');
462 for (int ch = 'A'; ch != 'F' + 1; ++ch) {
463 tested[ch] = 1;
464 TEST(C_isupper(ch));
465 TEST(!C_islower(ch));
466 TEST(C_isalpha(ch));
467 TEST(C_isalnum(ch));
468 TEST(!C_isdigit(ch));
469 TEST(C_isxdigit(ch));
470 TEST(!C_isspace(ch));
471 TEST(!C_isnotupper(ch));
472 TEST(C_isnotlower(ch));
473 TEST(!C_isnotalpha(ch));
474 TEST(!C_isnotalnum(ch));
475 TEST(C_isnotdigit(ch));
476 TEST(!C_isnotxdigit(ch));
477 TEST(C_isnotspace(ch));
478 TEST_EQUAL(hex_digit(ch), ch - 'A' + 10);
481 for (int ch = 'G'; ch != 'Z' + 1; ++ch) {
482 tested[ch] = 1;
483 TEST(C_isupper(ch));
484 TEST(!C_islower(ch));
485 TEST(C_isalpha(ch));
486 TEST(C_isalnum(ch));
487 TEST(!C_isdigit(ch));
488 TEST(!C_isxdigit(ch));
489 TEST(!C_isspace(ch));
490 TEST(!C_isnotupper(ch));
491 TEST(C_isnotlower(ch));
492 TEST(!C_isnotalpha(ch));
493 TEST(!C_isnotalnum(ch));
494 TEST(C_isnotdigit(ch));
495 TEST(C_isnotxdigit(ch));
496 TEST(C_isnotspace(ch));
499 for (int ch = 'a'; ch != 'f' + 1; ++ch) {
500 tested[ch] = 1;
501 TEST(!C_isupper(ch));
502 TEST(C_islower(ch));
503 TEST(C_isalpha(ch));
504 TEST(C_isalnum(ch));
505 TEST(!C_isdigit(ch));
506 TEST(C_isxdigit(ch));
507 TEST(!C_isspace(ch));
508 TEST(C_isnotupper(ch));
509 TEST(!C_isnotlower(ch));
510 TEST(!C_isnotalpha(ch));
511 TEST(!C_isnotalnum(ch));
512 TEST(C_isnotdigit(ch));
513 TEST(!C_isnotxdigit(ch));
514 TEST(C_isnotspace(ch));
515 TEST_EQUAL(hex_digit(ch), ch - 'a' + 10);
518 for (int ch = 'g'; ch != 'z' + 1; ++ch) {
519 tested[ch] = 1;
520 TEST(!C_isupper(ch));
521 TEST(C_islower(ch));
522 TEST(C_isalpha(ch));
523 TEST(C_isalnum(ch));
524 TEST(!C_isdigit(ch));
525 TEST(!C_isxdigit(ch));
526 TEST(!C_isspace(ch));
527 TEST(C_isnotupper(ch));
528 TEST(!C_isnotlower(ch));
529 TEST(!C_isnotalpha(ch));
530 TEST(!C_isnotalnum(ch));
531 TEST(C_isnotdigit(ch));
532 TEST(C_isnotxdigit(ch));
533 TEST(C_isnotspace(ch));
536 for (const char *p = "\t\n\f\r "; *p; ++p) {
537 int ch = *p;
538 tested[ch] = 1;
539 TEST(!C_isupper(ch));
540 TEST(!C_islower(ch));
541 TEST(!C_isalpha(ch));
542 TEST(!C_isalnum(ch));
543 TEST(!C_isdigit(ch));
544 TEST(!C_isxdigit(ch));
545 TEST(C_isspace(ch));
546 TEST(C_isnotupper(ch));
547 TEST(C_isnotlower(ch));
548 TEST(C_isnotalpha(ch));
549 TEST(C_isnotalnum(ch));
550 TEST(C_isnotdigit(ch));
551 TEST(C_isnotxdigit(ch));
552 TEST(!C_isnotspace(ch));
555 // Check remaining non-top-bit-set characters aren't anything.
556 for (int ch = 0; ch != 128; ++ch) {
557 if (tested[ch]) continue;
558 TEST(!C_isupper(ch));
559 TEST(!C_islower(ch));
560 TEST(!C_isalpha(ch));
561 TEST(!C_isalnum(ch));
562 TEST(!C_isdigit(ch));
563 TEST(!C_isxdigit(ch));
564 TEST(!C_isspace(ch));
565 TEST(C_isnotupper(ch));
566 TEST(C_isnotlower(ch));
567 TEST(C_isnotalpha(ch));
568 TEST(C_isnotalnum(ch));
569 TEST(C_isnotdigit(ch));
570 TEST(C_isnotxdigit(ch));
571 TEST(C_isnotspace(ch));
574 // Non-ASCII characters aren't anything for these functions.
575 for (int ch = 128; ch != 256; ++ch) {
576 TEST(!C_isupper(ch));
577 TEST(!C_islower(ch));
578 TEST(!C_isalpha(ch));
579 TEST(!C_isalnum(ch));
580 TEST(!C_isdigit(ch));
581 TEST(!C_isxdigit(ch));
582 TEST(!C_isspace(ch));
583 TEST(C_isnotupper(ch));
584 TEST(C_isnotlower(ch));
585 TEST(C_isnotalpha(ch));
586 TEST(C_isnotalnum(ch));
587 TEST(C_isnotdigit(ch));
588 TEST(C_isnotxdigit(ch));
589 TEST(C_isnotspace(ch));
592 // Check signed char values work the same way.
593 for (int ch = -128; ch != 0; ++ch) {
594 TEST(!C_isupper(ch));
595 TEST(!C_islower(ch));
596 TEST(!C_isalpha(ch));
597 TEST(!C_isalnum(ch));
598 TEST(!C_isdigit(ch));
599 TEST(!C_isxdigit(ch));
600 TEST(!C_isspace(ch));
601 TEST(C_isnotupper(ch));
602 TEST(C_isnotlower(ch));
603 TEST(C_isnotalpha(ch));
604 TEST(C_isnotalnum(ch));
605 TEST(C_isnotdigit(ch));
606 TEST(C_isnotxdigit(ch));
607 TEST(C_isnotspace(ch));
610 return true;
613 // ##################################################################
614 // # End of actual tests #
615 // ##################################################################
617 /// The lists of tests to perform
618 static const test_desc tests[] = {
619 TESTCASE(exception1),
620 TESTCASE(refcnt1),
621 TESTCASE(refcnt2),
622 TESTCASE(autoptr1),
623 TESTCASE(stringcomp1),
624 TESTCASE(temporarydtor1),
625 TESTCASE(static_assert1),
626 TESTCASE(pack_uint_preserving_sort1),
627 TESTCASE(pack_uint_preserving_sort2),
628 TESTCASE(chartype1),
629 {0, 0}
632 int main(int argc, char **argv)
633 try {
634 test_driver::parse_command_line(argc, argv);
635 return test_driver::run(tests);
636 } catch (const char * e) {
637 cout << e << endl;
638 return 1;