Support: quest -f cjk_ngram
[xapian.git] / xapian-core / tests / internaltest.cc
blob0ed97041e66dc8a7415bd9a4e588857bf5c0ce35
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 return true;
339 /// Test C_isupper() etc.
340 static bool test_chartype1()
342 char tested[128];
343 memset(tested, 0, sizeof(tested));
344 for (int ch = '0'; ch != '9' + 1; ++ch) {
345 tested[ch] = 1;
346 TEST(!C_isupper(ch));
347 TEST(!C_islower(ch));
348 TEST(!C_isalpha(ch));
349 TEST(C_isalnum(ch));
350 TEST(C_isdigit(ch));
351 TEST(C_isxdigit(ch));
352 TEST(!C_isspace(ch));
353 TEST(C_isnotupper(ch));
354 TEST(C_isnotlower(ch));
355 TEST(C_isnotalpha(ch));
356 TEST(!C_isnotalnum(ch));
357 TEST(!C_isnotdigit(ch));
358 TEST(!C_isnotxdigit(ch));
359 TEST(C_isnotspace(ch));
360 TEST_EQUAL(hex_digit(ch), ch - '0');
363 for (int ch = 'A'; ch != 'F' + 1; ++ch) {
364 tested[ch] = 1;
365 TEST(C_isupper(ch));
366 TEST(!C_islower(ch));
367 TEST(C_isalpha(ch));
368 TEST(C_isalnum(ch));
369 TEST(!C_isdigit(ch));
370 TEST(C_isxdigit(ch));
371 TEST(!C_isspace(ch));
372 TEST(!C_isnotupper(ch));
373 TEST(C_isnotlower(ch));
374 TEST(!C_isnotalpha(ch));
375 TEST(!C_isnotalnum(ch));
376 TEST(C_isnotdigit(ch));
377 TEST(!C_isnotxdigit(ch));
378 TEST(C_isnotspace(ch));
379 TEST_EQUAL(hex_digit(ch), ch - 'A' + 10);
382 for (int ch = 'G'; ch != 'Z' + 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));
400 for (int ch = 'a'; ch != 'f' + 1; ++ch) {
401 tested[ch] = 1;
402 TEST(!C_isupper(ch));
403 TEST(C_islower(ch));
404 TEST(C_isalpha(ch));
405 TEST(C_isalnum(ch));
406 TEST(!C_isdigit(ch));
407 TEST(C_isxdigit(ch));
408 TEST(!C_isspace(ch));
409 TEST(C_isnotupper(ch));
410 TEST(!C_isnotlower(ch));
411 TEST(!C_isnotalpha(ch));
412 TEST(!C_isnotalnum(ch));
413 TEST(C_isnotdigit(ch));
414 TEST(!C_isnotxdigit(ch));
415 TEST(C_isnotspace(ch));
416 TEST_EQUAL(hex_digit(ch), ch - 'a' + 10);
419 for (int ch = 'g'; ch != 'z' + 1; ++ch) {
420 tested[ch] = 1;
421 TEST(!C_isupper(ch));
422 TEST(C_islower(ch));
423 TEST(C_isalpha(ch));
424 TEST(C_isalnum(ch));
425 TEST(!C_isdigit(ch));
426 TEST(!C_isxdigit(ch));
427 TEST(!C_isspace(ch));
428 TEST(C_isnotupper(ch));
429 TEST(!C_isnotlower(ch));
430 TEST(!C_isnotalpha(ch));
431 TEST(!C_isnotalnum(ch));
432 TEST(C_isnotdigit(ch));
433 TEST(C_isnotxdigit(ch));
434 TEST(C_isnotspace(ch));
437 for (const char *p = "\t\n\f\r "; *p; ++p) {
438 int ch = *p;
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));
456 // Check remaining non-top-bit-set characters aren't anything.
457 for (int ch = 0; ch != 128; ++ch) {
458 if (tested[ch]) continue;
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 // Non-ASCII characters aren't anything for these functions.
476 for (int ch = 128; ch != 256; ++ch) {
477 TEST(!C_isupper(ch));
478 TEST(!C_islower(ch));
479 TEST(!C_isalpha(ch));
480 TEST(!C_isalnum(ch));
481 TEST(!C_isdigit(ch));
482 TEST(!C_isxdigit(ch));
483 TEST(!C_isspace(ch));
484 TEST(C_isnotupper(ch));
485 TEST(C_isnotlower(ch));
486 TEST(C_isnotalpha(ch));
487 TEST(C_isnotalnum(ch));
488 TEST(C_isnotdigit(ch));
489 TEST(C_isnotxdigit(ch));
490 TEST(C_isnotspace(ch));
493 // Check signed char values work the same way.
494 for (int ch = -128; ch != 0; ++ch) {
495 TEST(!C_isupper(ch));
496 TEST(!C_islower(ch));
497 TEST(!C_isalpha(ch));
498 TEST(!C_isalnum(ch));
499 TEST(!C_isdigit(ch));
500 TEST(!C_isxdigit(ch));
501 TEST(!C_isspace(ch));
502 TEST(C_isnotupper(ch));
503 TEST(C_isnotlower(ch));
504 TEST(C_isnotalpha(ch));
505 TEST(C_isnotalnum(ch));
506 TEST(C_isnotdigit(ch));
507 TEST(C_isnotxdigit(ch));
508 TEST(C_isnotspace(ch));
511 return true;
514 // ##################################################################
515 // # End of actual tests #
516 // ##################################################################
518 /// The lists of tests to perform
519 static const test_desc tests[] = {
520 {"exception1", test_exception1},
521 {"refcnt1", test_refcnt1},
522 {"refcnt2", test_refcnt2},
523 {"autoptr1", test_autoptr1},
524 {"stringcomp1", test_stringcomp1},
525 {"temporarydtor1", test_temporarydtor1},
526 {"static_assert1", test_static_assert1},
527 {"pack1", test_pack_uint_preserving_sort1},
528 TESTCASE(chartype1),
529 {0, 0}
532 int main(int argc, char **argv)
533 try {
534 test_driver::parse_command_line(argc, argv);
535 return test_driver::run(tests);
536 } catch (const char * e) {
537 cout << e << endl;
538 return 1;