Fix integer type used by ESet
[xapian.git] / xapian-core / tests / internaltest.cc
blob10bd291fbc987722d4895eee09fbff7e827cc99d
1 /** @file
2 * @brief test of the Xapian internals
3 */
4 /* Copyright 1999,2000,2001 BrightStation PLC
5 * Copyright 2002 Ananova Ltd
6 * Copyright 2002,2003,2006,2007,2008,2009,2010,2011,2012,2015 Olly Betts
7 * Copyright 2006 Lemur Consulting Ltd
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of the
12 * License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
22 * USA
25 #include <config.h>
27 #include <xapian.h>
29 #include <iostream>
30 #include <string>
32 using namespace std;
34 #include "autoptr.h"
35 #include "testsuite.h"
36 #include "testutils.h"
38 #include "pack.h"
39 #include "str.h"
41 class Test_Exception {
42 public:
43 int value;
44 Test_Exception(int value_) : value(value_) {}
47 // test that nested exceptions work correctly.
48 static void test_exception1()
50 try {
51 try {
52 throw Test_Exception(1);
53 } catch (...) {
54 try {
55 throw Test_Exception(2);
56 } catch (...) {
58 throw;
60 } catch (const Test_Exception & e) {
61 TEST_EQUAL(e.value, 1);
65 // ###########################################
66 // # Tests of the reference counted pointers #
67 // ###########################################
69 class test_refcnt : public Xapian::Internal::intrusive_base {
70 bool &deleted;
72 public:
73 test_refcnt(bool &deleted_) : deleted(deleted_) {
74 tout << "constructor\n";
77 Xapian::Internal::intrusive_ptr<const test_refcnt> test() {
78 return Xapian::Internal::intrusive_ptr<const test_refcnt>(this);
81 ~test_refcnt() {
82 deleted = true;
83 tout << "destructor\n";
87 static void test_refcnt1()
89 bool deleted = false;
91 test_refcnt *p = new test_refcnt(deleted);
93 TEST_EQUAL(p->_refs, 0);
96 Xapian::Internal::intrusive_ptr<test_refcnt> rcp(p);
98 TEST_EQUAL(rcp->_refs, 1);
101 Xapian::Internal::intrusive_ptr<test_refcnt> rcp2;
102 rcp2 = rcp;
103 TEST_EQUAL(rcp->_refs, 2);
104 // rcp2 goes out of scope here
107 TEST_AND_EXPLAIN(!deleted, "Object prematurely deleted!");
108 TEST_EQUAL(rcp->_refs, 1);
109 // rcp goes out of scope here
112 TEST_AND_EXPLAIN(deleted, "Object not properly deleted");
115 // This is a regression test - our home-made equivalent of intrusive_ptr
116 // (which was called RefCntPtr) used to delete the object pointed to if you
117 // assigned it to itself and the reference count was 1.
118 static void test_refcnt2()
120 bool deleted = false;
122 test_refcnt *p = new test_refcnt(deleted);
124 Xapian::Internal::intrusive_ptr<test_refcnt> rcp(p);
126 #ifdef __has_warning
127 # if __has_warning("-Wself-assign-overloaded")
128 // Suppress warning from newer clang about self-assignment so we can
129 // test that self-assignment works!
130 # pragma clang diagnostic push
131 # pragma clang diagnostic ignored "-Wself-assign-overloaded"
132 # endif
133 #endif
134 rcp = rcp;
135 #ifdef __has_warning
136 # if __has_warning("-Wself-assign-overloaded")
137 # pragma clang diagnostic pop
138 # endif
139 #endif
141 TEST_AND_EXPLAIN(!deleted, "Object deleted by self-assignment");
144 // Class for testing AutoPtr<>.
145 class test_autoptr {
146 bool &deleted;
147 public:
148 test_autoptr(bool &deleted_) : deleted(deleted_) {
149 tout << "test_autoptr constructor\n";
151 ~test_autoptr() {
152 deleted = true;
153 tout << "test_autoptr destructor\n";
157 // Test autoptr self-assignment.
158 static void test_autoptr1()
160 bool deleted = false;
162 test_autoptr * raw_ptr = new test_autoptr(deleted);
164 AutoPtr<test_autoptr> ptr(raw_ptr);
166 TEST_EQUAL(ptr.get(), raw_ptr);
167 TEST(!deleted);
169 ptr.reset(ptr.release());
171 TEST_EQUAL(ptr.get(), raw_ptr);
172 TEST(!deleted);
174 ptr.swap(ptr);
176 TEST_EQUAL(ptr.get(), raw_ptr);
177 TEST(!deleted);
179 swap(ptr, ptr);
181 TEST_EQUAL(ptr.get(), raw_ptr);
182 TEST(!deleted);
185 TEST(deleted);
187 deleted = false;
188 raw_ptr = new test_autoptr(deleted);
190 bool deleted2 = false;
191 test_autoptr * raw_ptr2 = new test_autoptr(deleted2);
192 AutoPtr<test_autoptr> ptr(raw_ptr2);
194 TEST_EQUAL(ptr.get(), raw_ptr2);
195 TEST(!deleted);
196 TEST(!deleted2);
198 ptr.reset(raw_ptr);
199 TEST_EQUAL(ptr.get(), raw_ptr);
200 TEST(!deleted);
201 TEST(deleted2);
203 ptr.reset();
204 TEST_EQUAL(ptr.get(), static_cast<test_autoptr*>(0));
205 TEST(deleted);
208 // test string comparisons
209 static void test_stringcomp1()
211 string s1;
212 string s2;
214 s1 = "foo";
215 s2 = "foo";
217 if ((s1 != s2) || (s1 > s2)) {
218 FAIL_TEST("String comparisons BADLY wrong");
221 s1 += '\0';
223 if ((s1 == s2) || (s1 < s2)) {
224 FAIL_TEST("String comparisons don't cope with extra nulls");
227 s2 += '\0';
229 s1 += 'a';
230 s2 += 'z';
232 if ((s1.length() != 5) || (s2.length() != 5)) {
233 FAIL_TEST("Lengths with added nulls wrong");
236 if ((s1 == s2) || !(s1 < s2)) {
237 FAIL_TEST("Characters after a null ignored in comparisons");
241 // By default Sun's C++ compiler doesn't call the destructor on a
242 // temporary object until the end of the block (contrary to what
243 // ISO C++ requires). This is done in the name of "compatibility".
244 // Passing -features=tmplife to CC fixes this. This check ensures
245 // that this actually works for Sun's C++ and any other compilers
246 // that might have this problem.
247 struct TempDtorTest {
248 static int count;
249 static TempDtorTest factory() { return TempDtorTest(); }
250 TempDtorTest() { ++count; }
251 ~TempDtorTest() { --count; }
254 int TempDtorTest::count = 0;
256 static void test_temporarydtor1()
258 TEST_EQUAL(TempDtorTest::count, 0);
259 TempDtorTest::factory();
260 TEST_EQUAL(TempDtorTest::count, 0);
263 /// Test pack_uint_preserving_sort()
264 static void test_pack_uint_preserving_sort1()
266 string prev_packed;
267 for (unsigned int i = 0; i != 1000; ++i) {
268 string packed;
269 pack_uint_preserving_sort(packed, i);
270 const char * ptr = packed.data();
271 const char * end = ptr + packed.size();
272 unsigned int result;
273 TEST(unpack_uint_preserving_sort(&ptr, end, &result));
274 TEST_EQUAL(result, i);
275 TEST(ptr == end);
276 TEST_REL(prev_packed, <, packed);
277 swap(prev_packed, packed);
279 for (unsigned int i = 2345; i < 65000; i += 113) {
280 string packed;
281 pack_uint_preserving_sort(packed, i);
282 const char * ptr = packed.data();
283 const char * end = ptr + packed.size();
284 unsigned int result;
285 TEST(unpack_uint_preserving_sort(&ptr, end, &result));
286 TEST_EQUAL(result, i);
287 TEST(ptr == end);
288 TEST_REL(prev_packed, <, packed);
289 swap(prev_packed, packed);
291 unsigned int prev = 64999;
292 for (unsigned int i = 65000; i > prev; prev = i, i = (i << 1) ^ 1337) {
293 string packed;
294 pack_uint_preserving_sort(packed, i);
295 const char * ptr = packed.data();
296 const char * end = ptr + packed.size();
297 unsigned int result;
298 TEST(unpack_uint_preserving_sort(&ptr, end, &result));
299 TEST_EQUAL(result, i);
300 TEST(ptr == end);
301 TEST_REL(prev_packed, <, packed);
302 swap(prev_packed, packed);
305 /* Test packing multiple numbers to one string. */
306 string packed;
307 for (unsigned int i = 23456; i < 765432; i += 1131) {
308 pack_uint_preserving_sort(packed, i);
310 const char * ptr = packed.data();
311 const char * end = ptr + packed.size();
312 for (unsigned int i = 23456; i < 765432; i += 1131) {
313 unsigned int result;
314 TEST(unpack_uint_preserving_sort(&ptr, end, &result));
315 TEST_EQUAL(result, i);
317 TEST(ptr == end);
320 /// Test C_pack_uint_preserving_sort()
321 static void test_pack_uint_preserving_sort2()
323 string prev_packed;
324 for (unsigned int i = 0; i != 1000; ++i) {
325 string packed;
326 C_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(C_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 C_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(C_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 C_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(C_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 C_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(C_unpack_uint_preserving_sort(&ptr, end, &result));
372 TEST_EQUAL(result, i);
374 TEST(ptr == end);
377 /// Test C_isupper() etc.
378 static void test_chartype1()
380 char tested[128];
381 memset(tested, 0, sizeof(tested));
382 for (int ch = '0'; ch != '9' + 1; ++ch) {
383 tested[ch] = 1;
384 TEST(!C_isupper(ch));
385 TEST(!C_islower(ch));
386 TEST(!C_isalpha(ch));
387 TEST(C_isalnum(ch));
388 TEST(C_isdigit(ch));
389 TEST(C_isxdigit(ch));
390 TEST(!C_isspace(ch));
391 TEST(C_isnotupper(ch));
392 TEST(C_isnotlower(ch));
393 TEST(C_isnotalpha(ch));
394 TEST(!C_isnotalnum(ch));
395 TEST(!C_isnotdigit(ch));
396 TEST(!C_isnotxdigit(ch));
397 TEST(C_isnotspace(ch));
398 TEST_EQUAL(hex_digit(ch), ch - '0');
401 for (int ch = 'A'; ch != 'F' + 1; ++ch) {
402 tested[ch] = 1;
403 TEST(C_isupper(ch));
404 TEST(!C_islower(ch));
405 TEST(C_isalpha(ch));
406 TEST(C_isalnum(ch));
407 TEST(!C_isdigit(ch));
408 TEST(C_isxdigit(ch));
409 TEST(!C_isspace(ch));
410 TEST(!C_isnotupper(ch));
411 TEST(C_isnotlower(ch));
412 TEST(!C_isnotalpha(ch));
413 TEST(!C_isnotalnum(ch));
414 TEST(C_isnotdigit(ch));
415 TEST(!C_isnotxdigit(ch));
416 TEST(C_isnotspace(ch));
417 TEST_EQUAL(hex_digit(ch), ch - 'A' + 10);
420 for (int ch = 'G'; ch != 'Z' + 1; ++ch) {
421 tested[ch] = 1;
422 TEST(C_isupper(ch));
423 TEST(!C_islower(ch));
424 TEST(C_isalpha(ch));
425 TEST(C_isalnum(ch));
426 TEST(!C_isdigit(ch));
427 TEST(!C_isxdigit(ch));
428 TEST(!C_isspace(ch));
429 TEST(!C_isnotupper(ch));
430 TEST(C_isnotlower(ch));
431 TEST(!C_isnotalpha(ch));
432 TEST(!C_isnotalnum(ch));
433 TEST(C_isnotdigit(ch));
434 TEST(C_isnotxdigit(ch));
435 TEST(C_isnotspace(ch));
438 for (int ch = 'a'; ch != 'f' + 1; ++ch) {
439 tested[ch] = 1;
440 TEST(!C_isupper(ch));
441 TEST(C_islower(ch));
442 TEST(C_isalpha(ch));
443 TEST(C_isalnum(ch));
444 TEST(!C_isdigit(ch));
445 TEST(C_isxdigit(ch));
446 TEST(!C_isspace(ch));
447 TEST(C_isnotupper(ch));
448 TEST(!C_isnotlower(ch));
449 TEST(!C_isnotalpha(ch));
450 TEST(!C_isnotalnum(ch));
451 TEST(C_isnotdigit(ch));
452 TEST(!C_isnotxdigit(ch));
453 TEST(C_isnotspace(ch));
454 TEST_EQUAL(hex_digit(ch), ch - 'a' + 10);
457 for (int ch = 'g'; ch != 'z' + 1; ++ch) {
458 tested[ch] = 1;
459 TEST(!C_isupper(ch));
460 TEST(C_islower(ch));
461 TEST(C_isalpha(ch));
462 TEST(C_isalnum(ch));
463 TEST(!C_isdigit(ch));
464 TEST(!C_isxdigit(ch));
465 TEST(!C_isspace(ch));
466 TEST(C_isnotupper(ch));
467 TEST(!C_isnotlower(ch));
468 TEST(!C_isnotalpha(ch));
469 TEST(!C_isnotalnum(ch));
470 TEST(C_isnotdigit(ch));
471 TEST(C_isnotxdigit(ch));
472 TEST(C_isnotspace(ch));
475 for (const char *p = "\t\n\f\r "; *p; ++p) {
476 int ch = *p;
477 tested[ch] = 1;
478 TEST(!C_isupper(ch));
479 TEST(!C_islower(ch));
480 TEST(!C_isalpha(ch));
481 TEST(!C_isalnum(ch));
482 TEST(!C_isdigit(ch));
483 TEST(!C_isxdigit(ch));
484 TEST(C_isspace(ch));
485 TEST(C_isnotupper(ch));
486 TEST(C_isnotlower(ch));
487 TEST(C_isnotalpha(ch));
488 TEST(C_isnotalnum(ch));
489 TEST(C_isnotdigit(ch));
490 TEST(C_isnotxdigit(ch));
491 TEST(!C_isnotspace(ch));
494 // Check remaining non-top-bit-set characters aren't anything.
495 for (int ch = 0; ch != 128; ++ch) {
496 if (tested[ch]) continue;
497 TEST(!C_isupper(ch));
498 TEST(!C_islower(ch));
499 TEST(!C_isalpha(ch));
500 TEST(!C_isalnum(ch));
501 TEST(!C_isdigit(ch));
502 TEST(!C_isxdigit(ch));
503 TEST(!C_isspace(ch));
504 TEST(C_isnotupper(ch));
505 TEST(C_isnotlower(ch));
506 TEST(C_isnotalpha(ch));
507 TEST(C_isnotalnum(ch));
508 TEST(C_isnotdigit(ch));
509 TEST(C_isnotxdigit(ch));
510 TEST(C_isnotspace(ch));
513 // Non-ASCII characters aren't anything for these functions.
514 for (unsigned char ch = 128; ch != 0; ++ch) {
515 TEST(!C_isupper(ch));
516 TEST(!C_islower(ch));
517 TEST(!C_isalpha(ch));
518 TEST(!C_isalnum(ch));
519 TEST(!C_isdigit(ch));
520 TEST(!C_isxdigit(ch));
521 TEST(!C_isspace(ch));
522 TEST(C_isnotupper(ch));
523 TEST(C_isnotlower(ch));
524 TEST(C_isnotalpha(ch));
525 TEST(C_isnotalnum(ch));
526 TEST(C_isnotdigit(ch));
527 TEST(C_isnotxdigit(ch));
528 TEST(C_isnotspace(ch));
531 // Check signed char values work the same way.
532 for (signed char ch = -128; ch != 0; ++ch) {
533 TEST(!C_isupper(ch));
534 TEST(!C_islower(ch));
535 TEST(!C_isalpha(ch));
536 TEST(!C_isalnum(ch));
537 TEST(!C_isdigit(ch));
538 TEST(!C_isxdigit(ch));
539 TEST(!C_isspace(ch));
540 TEST(C_isnotupper(ch));
541 TEST(C_isnotlower(ch));
542 TEST(C_isnotalpha(ch));
543 TEST(C_isnotalnum(ch));
544 TEST(C_isnotdigit(ch));
545 TEST(C_isnotxdigit(ch));
546 TEST(C_isnotspace(ch));
550 // ##################################################################
551 // # End of actual tests #
552 // ##################################################################
554 /// The lists of tests to perform
555 static const test_desc tests[] = {
556 TESTCASE(exception1),
557 TESTCASE(refcnt1),
558 TESTCASE(refcnt2),
559 TESTCASE(autoptr1),
560 TESTCASE(stringcomp1),
561 TESTCASE(temporarydtor1),
562 TESTCASE(pack_uint_preserving_sort1),
563 TESTCASE(pack_uint_preserving_sort2),
564 TESTCASE(chartype1),
565 {0, 0}
568 int main(int argc, char **argv)
569 try {
570 test_driver::parse_command_line(argc, argv);
571 return test_driver::run(tests);
572 } catch (const char * e) {
573 cout << e << endl;
574 return 1;