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
28 #include "safeerrno.h"
36 #include "testsuite.h"
37 #include "testutils.h"
43 class Test_Exception
{
46 Test_Exception(int value_
) : value(value_
) {}
49 // test that nested exceptions work correctly.
50 static bool test_exception1()
54 throw Test_Exception(1);
57 throw Test_Exception(2);
62 } catch (const Test_Exception
& e
) {
63 TEST_EQUAL(e
.value
, 1);
69 // ###########################################
70 // # Tests of the reference counted pointers #
71 // ###########################################
73 class test_refcnt
: public Xapian::Internal::intrusive_base
{
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);
85 tout
<< "destructor\n";
89 static bool test_refcnt1()
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
;
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");
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
);
132 TEST_AND_EXPLAIN(!deleted
, "Object deleted by self-assignment");
137 // Class for testing AutoPtr<>.
141 test_autoptr(bool &deleted_
) : deleted(deleted_
) {
142 tout
<< "test_autoptr constructor\n";
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
);
162 ptr
.reset(ptr
.release());
164 TEST_EQUAL(ptr
.get(), raw_ptr
);
169 TEST_EQUAL(ptr
.get(), raw_ptr
);
174 TEST_EQUAL(ptr
.get(), raw_ptr
);
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
);
192 TEST_EQUAL(ptr
.get(), raw_ptr
);
197 TEST_EQUAL(ptr
.get(), static_cast<test_autoptr
*>(0));
203 // test string comparisons
204 static bool test_stringcomp1()
214 if ((s1
!= s2
) || (s1
> s2
)) {
216 tout
<< "String comparisons BADLY wrong" << endl
;
221 if ((s1
== s2
) || (s1
< s2
)) {
223 tout
<< "String comparisons don't cope with extra nulls" << endl
;
231 if ((s1
.length() != 5) || (s2
.length() != 5)) {
233 tout
<< "Lengths with added nulls wrong" << endl
;
236 if ((s1
== s2
) || !(s1
< s2
)) {
238 tout
<< "Characters after a null ignored in comparisons" << endl
;
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
{
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);
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.
320 /// Test pack_uint_preserving_sort()
321 static bool test_pack_uint_preserving_sort1()
324 for (unsigned int i
= 0; i
!= 1000; ++i
) {
326 pack_uint_preserving_sort(packed
, i
);
327 const char * ptr
= packed
.data();
328 const char * end
= ptr
+ packed
.size();
330 TEST(unpack_uint_preserving_sort(&ptr
, end
, &result
));
331 TEST_EQUAL(result
, i
);
333 TEST_REL(prev_packed
, <, packed
);
334 swap(prev_packed
, packed
);
336 for (unsigned int i
= 2345; i
< 65000; i
+= 113) {
338 pack_uint_preserving_sort(packed
, i
);
339 const char * ptr
= packed
.data();
340 const char * end
= ptr
+ packed
.size();
342 TEST(unpack_uint_preserving_sort(&ptr
, end
, &result
));
343 TEST_EQUAL(result
, i
);
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) {
351 pack_uint_preserving_sort(packed
, i
);
352 const char * ptr
= packed
.data();
353 const char * end
= ptr
+ packed
.size();
355 TEST(unpack_uint_preserving_sort(&ptr
, end
, &result
));
356 TEST_EQUAL(result
, i
);
358 TEST_REL(prev_packed
, <, packed
);
359 swap(prev_packed
, packed
);
362 /* Test packing multiple numbers to one string. */
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) {
371 TEST(unpack_uint_preserving_sort(&ptr
, end
, &result
));
372 TEST_EQUAL(result
, i
);
379 /// Test C_pack_uint_preserving_sort()
380 static bool test_pack_uint_preserving_sort2()
383 for (unsigned int i
= 0; i
!= 1000; ++i
) {
385 C_pack_uint_preserving_sort(packed
, i
);
386 const char * ptr
= packed
.data();
387 const char * end
= ptr
+ packed
.size();
389 TEST(C_unpack_uint_preserving_sort(&ptr
, end
, &result
));
390 TEST_EQUAL(result
, i
);
392 TEST_REL(prev_packed
, <, packed
);
393 swap(prev_packed
, packed
);
395 for (unsigned int i
= 2345; i
< 65000; i
+= 113) {
397 C_pack_uint_preserving_sort(packed
, i
);
398 const char * ptr
= packed
.data();
399 const char * end
= ptr
+ packed
.size();
401 TEST(C_unpack_uint_preserving_sort(&ptr
, end
, &result
));
402 TEST_EQUAL(result
, i
);
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) {
410 C_pack_uint_preserving_sort(packed
, i
);
411 const char * ptr
= packed
.data();
412 const char * end
= ptr
+ packed
.size();
414 TEST(C_unpack_uint_preserving_sort(&ptr
, end
, &result
));
415 TEST_EQUAL(result
, i
);
417 TEST_REL(prev_packed
, <, packed
);
418 swap(prev_packed
, packed
);
421 /* Test packing multiple numbers to one string. */
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) {
430 TEST(C_unpack_uint_preserving_sort(&ptr
, end
, &result
));
431 TEST_EQUAL(result
, i
);
438 /// Test C_isupper() etc.
439 static bool test_chartype1()
442 memset(tested
, 0, sizeof(tested
));
443 for (int ch
= '0'; ch
!= '9' + 1; ++ch
) {
445 TEST(!C_isupper(ch
));
446 TEST(!C_islower(ch
));
447 TEST(!C_isalpha(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
) {
465 TEST(!C_islower(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
) {
484 TEST(!C_islower(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
) {
501 TEST(!C_isupper(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
) {
520 TEST(!C_isupper(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
) {
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
));
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
));
613 // ##################################################################
614 // # End of actual tests #
615 // ##################################################################
617 /// The lists of tests to perform
618 static const test_desc tests
[] = {
619 TESTCASE(exception1
),
623 TESTCASE(stringcomp1
),
624 TESTCASE(temporarydtor1
),
625 TESTCASE(static_assert1
),
626 TESTCASE(pack_uint_preserving_sort1
),
627 TESTCASE(pack_uint_preserving_sort2
),
632 int main(int argc
, char **argv
)
634 test_driver::parse_command_line(argc
, argv
);
635 return test_driver::run(tests
);
636 } catch (const char * e
) {