xapian-core  1.4.25
internaltest.cc
Go to the documentation of this file.
1 
4 /* Copyright 1999,2000,2001 BrightStation PLC
5  * Copyright 2002 Ananova Ltd
6  * Copyright 2002-2022 Olly Betts
7  * Copyright 2006 Lemur Consulting Ltd
8  *
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.
13  *
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.
18  *
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
23  */
24 
25 #include <config.h>
26 
27 #include <xapian.h>
28 
29 #include <iostream>
30 #include <string>
31 
32 using namespace std;
33 
34 #include "autoptr.h"
35 #include "testsuite.h"
36 #include "testutils.h"
37 
38 #include "pack.h"
39 #include "str.h"
40 
42  public:
43  int value;
44  Test_Exception(int value_) : value(value_) {}
45 };
46 
47 // test that nested exceptions work correctly.
48 static void test_exception1()
49 {
50  try {
51  try {
52  throw Test_Exception(1);
53  } catch (...) {
54  try {
55  throw Test_Exception(2);
56  } catch (...) {
57  }
58  throw;
59  }
60  } catch (const Test_Exception& e) {
61  TEST_EQUAL(e.value, 1);
62  }
63 }
64 
65 // ###########################################
66 // # Tests of the reference counted pointers #
67 // ###########################################
68 
70  bool& deleted;
71 
72  public:
73  test_refcnt(bool& deleted_) : deleted(deleted_) {
74  tout << "constructor\n";
75  }
76 
79  }
80 
82  deleted = true;
83  tout << "destructor\n";
84  }
85 };
86 
87 static void test_refcnt1()
88 {
89  bool deleted = false;
90 
91  test_refcnt* p = new test_refcnt(deleted);
92 
93  TEST_EQUAL(p->_refs, 0);
94 
95  {
97 
98  TEST_EQUAL(rcp->_refs, 1);
99 
100  {
102  rcp2 = rcp;
103  TEST_EQUAL(rcp->_refs, 2);
104  // rcp2 goes out of scope here
105  }
106 
107  TEST_AND_EXPLAIN(!deleted, "Object prematurely deleted!");
108  TEST_EQUAL(rcp->_refs, 1);
109  // rcp goes out of scope here
110  }
111 
112  TEST_AND_EXPLAIN(deleted, "Object not properly deleted");
113 }
114 
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()
119 {
120  bool deleted = false;
121 
122  test_refcnt* p = new test_refcnt(deleted);
123 
125 
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
140 
141  TEST_AND_EXPLAIN(!deleted, "Object deleted by self-assignment");
142 }
143 
144 // Class for testing AutoPtr<>.
146  bool &deleted;
147  public:
148  test_autoptr(bool &deleted_) : deleted(deleted_) {
149  tout << "test_autoptr constructor\n";
150  }
152  deleted = true;
153  tout << "test_autoptr destructor\n";
154  }
155 };
156 
157 // Test autoptr self-assignment.
158 static void test_autoptr1()
159 {
160  bool deleted = false;
161 
162  test_autoptr * raw_ptr = new test_autoptr(deleted);
163  {
164  AutoPtr<test_autoptr> ptr(raw_ptr);
165 
166  TEST_EQUAL(ptr.get(), raw_ptr);
167  TEST(!deleted);
168 
169  ptr.reset(ptr.release());
170 
171  TEST_EQUAL(ptr.get(), raw_ptr);
172  TEST(!deleted);
173 
174  ptr.swap(ptr);
175 
176  TEST_EQUAL(ptr.get(), raw_ptr);
177  TEST(!deleted);
178 
179  swap(ptr, ptr);
180 
181  TEST_EQUAL(ptr.get(), raw_ptr);
182  TEST(!deleted);
183  }
184 
185  TEST(deleted);
186 
187  deleted = false;
188  raw_ptr = new test_autoptr(deleted);
189 
190  bool deleted2 = false;
191  test_autoptr * raw_ptr2 = new test_autoptr(deleted2);
192  AutoPtr<test_autoptr> ptr(raw_ptr2);
193 
194  TEST_EQUAL(ptr.get(), raw_ptr2);
195  TEST(!deleted);
196  TEST(!deleted2);
197 
198  ptr.reset(raw_ptr);
199  TEST_EQUAL(ptr.get(), raw_ptr);
200  TEST(!deleted);
201  TEST(deleted2);
202 
203  ptr.reset();
204  TEST_EQUAL(ptr.get(), static_cast<test_autoptr*>(0));
205  TEST(deleted);
206 }
207 
208 // test string comparisons
209 static void test_stringcomp1()
210 {
211  string s1;
212  string s2;
213 
214  s1 = "foo";
215  s2 = "foo";
216 
217  if ((s1 != s2) || (s1 > s2)) {
218  FAIL_TEST("String comparisons BADLY wrong");
219  }
220 
221  s1 += '\0';
222 
223  if ((s1 == s2) || (s1 < s2)) {
224  FAIL_TEST("String comparisons don't cope with extra nulls");
225  }
226 
227  s2 += '\0';
228 
229  s1 += 'a';
230  s2 += 'z';
231 
232  if ((s1.length() != 5) || (s2.length() != 5)) {
233  FAIL_TEST("Lengths with added nulls wrong");
234  }
235 
236  if ((s1 == s2) || !(s1 < s2)) {
237  FAIL_TEST("Characters after a null ignored in comparisons");
238  }
239 }
240 
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; }
252 };
253 
254 int TempDtorTest::count = 0;
255 
256 static void test_temporarydtor1()
257 {
261 }
262 
265 {
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);
278  }
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);
290  }
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);
303  }
304 
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);
309  }
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);
316  }
317  TEST(ptr == end);
318 }
319 
322 {
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);
335  }
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);
347  }
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);
360  }
361 
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);
366  }
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);
373  }
374  TEST(ptr == end);
375 }
376 
378 static void test_chartype1()
379 {
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  int v = ch - '0';
399  TEST_EQUAL(hex_digit(ch), v);
400  TEST_EQUAL(hex_decode('0', ch), char(v));
401  TEST_EQUAL(hex_decode(ch, '0'), char(v << 4));
402  TEST_EQUAL(hex_decode(ch, ch), char((v << 4) | v));
403  }
404 
405  for (int ch = 'A'; ch != 'F' + 1; ++ch) {
406  tested[ch] = 1;
407  TEST(C_isupper(ch));
408  TEST(!C_islower(ch));
409  TEST(C_isalpha(ch));
410  TEST(C_isalnum(ch));
411  TEST(!C_isdigit(ch));
412  TEST(C_isxdigit(ch));
413  TEST(!C_isspace(ch));
414  TEST(!C_isnotupper(ch));
415  TEST(C_isnotlower(ch));
416  TEST(!C_isnotalpha(ch));
417  TEST(!C_isnotalnum(ch));
418  TEST(C_isnotdigit(ch));
419  TEST(!C_isnotxdigit(ch));
420  TEST(C_isnotspace(ch));
421  int v = ch - 'A' + 10;
422  TEST_EQUAL(hex_digit(ch), v);
423  TEST_EQUAL(hex_decode('0', ch), char(v));
424  TEST_EQUAL(hex_decode(ch, '0'), char(v << 4));
425  TEST_EQUAL(hex_decode(ch, ch), char((v << 4) | v));
426  }
427 
428  for (int ch = 'G'; ch != 'Z' + 1; ++ch) {
429  tested[ch] = 1;
430  TEST(C_isupper(ch));
431  TEST(!C_islower(ch));
432  TEST(C_isalpha(ch));
433  TEST(C_isalnum(ch));
434  TEST(!C_isdigit(ch));
435  TEST(!C_isxdigit(ch));
436  TEST(!C_isspace(ch));
437  TEST(!C_isnotupper(ch));
438  TEST(C_isnotlower(ch));
439  TEST(!C_isnotalpha(ch));
440  TEST(!C_isnotalnum(ch));
441  TEST(C_isnotdigit(ch));
442  TEST(C_isnotxdigit(ch));
443  TEST(C_isnotspace(ch));
444  }
445 
446  for (int ch = 'a'; ch != 'f' + 1; ++ch) {
447  tested[ch] = 1;
448  TEST(!C_isupper(ch));
449  TEST(C_islower(ch));
450  TEST(C_isalpha(ch));
451  TEST(C_isalnum(ch));
452  TEST(!C_isdigit(ch));
453  TEST(C_isxdigit(ch));
454  TEST(!C_isspace(ch));
455  TEST(C_isnotupper(ch));
456  TEST(!C_isnotlower(ch));
457  TEST(!C_isnotalpha(ch));
458  TEST(!C_isnotalnum(ch));
459  TEST(C_isnotdigit(ch));
460  TEST(!C_isnotxdigit(ch));
461  TEST(C_isnotspace(ch));
462  int v = ch - 'a' + 10;
463  TEST_EQUAL(hex_digit(ch), v);
464  TEST_EQUAL(hex_decode('0', ch), char(v));
465  TEST_EQUAL(hex_decode(ch, '0'), char(v << 4));
466  TEST_EQUAL(hex_decode(ch, ch), char((v << 4) | v));
467  }
468 
469  for (int ch = 'g'; ch != 'z' + 1; ++ch) {
470  tested[ch] = 1;
471  TEST(!C_isupper(ch));
472  TEST(C_islower(ch));
473  TEST(C_isalpha(ch));
474  TEST(C_isalnum(ch));
475  TEST(!C_isdigit(ch));
476  TEST(!C_isxdigit(ch));
477  TEST(!C_isspace(ch));
478  TEST(C_isnotupper(ch));
479  TEST(!C_isnotlower(ch));
480  TEST(!C_isnotalpha(ch));
481  TEST(!C_isnotalnum(ch));
482  TEST(C_isnotdigit(ch));
483  TEST(C_isnotxdigit(ch));
484  TEST(C_isnotspace(ch));
485  }
486 
487  for (const char* p = "\t\n\f\r "; *p; ++p) {
488  int ch = *p;
489  tested[ch] = 1;
490  TEST(!C_isupper(ch));
491  TEST(!C_islower(ch));
492  TEST(!C_isalpha(ch));
493  TEST(!C_isalnum(ch));
494  TEST(!C_isdigit(ch));
495  TEST(!C_isxdigit(ch));
496  TEST(C_isspace(ch));
497  TEST(C_isnotupper(ch));
498  TEST(C_isnotlower(ch));
499  TEST(C_isnotalpha(ch));
500  TEST(C_isnotalnum(ch));
501  TEST(C_isnotdigit(ch));
502  TEST(C_isnotxdigit(ch));
503  TEST(!C_isnotspace(ch));
504  }
505 
506  // Check remaining non-top-bit-set characters aren't anything.
507  for (int ch = 0; ch != 128; ++ch) {
508  if (tested[ch]) continue;
509  TEST(!C_isupper(ch));
510  TEST(!C_islower(ch));
511  TEST(!C_isalpha(ch));
512  TEST(!C_isalnum(ch));
513  TEST(!C_isdigit(ch));
514  TEST(!C_isxdigit(ch));
515  TEST(!C_isspace(ch));
516  TEST(C_isnotupper(ch));
517  TEST(C_isnotlower(ch));
518  TEST(C_isnotalpha(ch));
519  TEST(C_isnotalnum(ch));
520  TEST(C_isnotdigit(ch));
521  TEST(C_isnotxdigit(ch));
522  TEST(C_isnotspace(ch));
523  }
524 
525  // Non-ASCII characters aren't anything for these functions.
526  for (unsigned char ch = 128; ch != 0; ++ch) {
527  TEST(!C_isupper(ch));
528  TEST(!C_islower(ch));
529  TEST(!C_isalpha(ch));
530  TEST(!C_isalnum(ch));
531  TEST(!C_isdigit(ch));
532  TEST(!C_isxdigit(ch));
533  TEST(!C_isspace(ch));
534  TEST(C_isnotupper(ch));
535  TEST(C_isnotlower(ch));
536  TEST(C_isnotalpha(ch));
537  TEST(C_isnotalnum(ch));
538  TEST(C_isnotdigit(ch));
539  TEST(C_isnotxdigit(ch));
540  TEST(C_isnotspace(ch));
541  }
542 
543  // Check signed char values work the same way.
544  for (signed char ch = -128; ch != 0; ++ch) {
545  TEST(!C_isupper(ch));
546  TEST(!C_islower(ch));
547  TEST(!C_isalpha(ch));
548  TEST(!C_isalnum(ch));
549  TEST(!C_isdigit(ch));
550  TEST(!C_isxdigit(ch));
551  TEST(!C_isspace(ch));
552  TEST(C_isnotupper(ch));
553  TEST(C_isnotlower(ch));
554  TEST(C_isnotalpha(ch));
555  TEST(C_isnotalnum(ch));
556  TEST(C_isnotdigit(ch));
557  TEST(C_isnotxdigit(ch));
558  TEST(C_isnotspace(ch));
559  }
560 }
561 
562 // ##################################################################
563 // # End of actual tests #
564 // ##################################################################
565 
567 static const test_desc tests[] = {
568  TESTCASE(exception1),
569  TESTCASE(refcnt1),
570  TESTCASE(refcnt2),
571  TESTCASE(autoptr1),
572  TESTCASE(stringcomp1),
573  TESTCASE(temporarydtor1),
574  TESTCASE(pack_uint_preserving_sort1),
575  TESTCASE(pack_uint_preserving_sort2),
576  TESTCASE(chartype1),
577  {0, 0}
578 };
579 
580 int main(int argc, char** argv)
581 try {
583  return test_driver::run(tests);
584 } catch (const char* e) {
585  cout << e << '\n';
586  return 1;
587 }
int main(int argc, char **argv)
Xapian::Internal::intrusive_ptr< const test_refcnt > test()
Definition: internaltest.cc:77
test_refcnt(bool &deleted_)
Definition: internaltest.cc:73
static TempDtorTest factory()
#define TEST(a)
Test a condition, without an additional explanation for failure.
Definition: testsuite.h:275
static void parse_command_line(int argc, char **argv)
Parse the command line arguments.
Definition: testsuite.cc:805
static void test_exception1()
Definition: internaltest.cc:48
Test_Exception(int value_)
Definition: internaltest.cc:44
static void test_temporarydtor1()
#define TEST_AND_EXPLAIN(a, b)
Test a condition, and display the test with an extra explanation if the condition fails...
Definition: testsuite.h:267
unsigned _refs
Reference count.
Definition: intrusive_ptr.h:73
a generic test suite engine
int hex_digit(char ch)
Definition: stringutils.h:231
STL namespace.
Convert types to std::string.
#define TEST_REL(A, REL, B)
Test a relation holds,e.g. TEST_REL(a,>,b);.
Definition: testmacros.h:32
bool C_isupper(char ch)
Definition: stringutils.h:188
bool C_islower(char ch)
Definition: stringutils.h:193
bool C_isdigit(char ch)
Definition: stringutils.h:177
std::ostringstream tout
The debug printing stream.
Definition: testsuite.cc:103
void C_pack_uint_preserving_sort(std::string &s, U value)
Append an encoded unsigned integer to a string, preserving the sort order.
Definition: pack.h:149
bool C_unpack_uint_preserving_sort(const char **p, const char *end, U *result)
Decode an "sort preserved" unsigned integer from a string.
Definition: pack.h:185
Public interfaces for the Xapian library.
bool & deleted
Definition: internaltest.cc:70
bool C_isnotalpha(char ch)
Definition: stringutils.h:217
bool C_isspace(char ch)
Definition: stringutils.h:208
static void test_pack_uint_preserving_sort2()
Test C_pack_uint_preserving_sort()
static void test_stringcomp1()
static void test_autoptr1()
static void test_chartype1()
Test C_isupper() etc.
static const test_desc tests[]
The lists of tests to perform.
bool unpack_uint_preserving_sort(const char **p, const char *end, U *result)
Decode a "sort preserved" unsigned integer from a string.
Definition: pack.h:318
Base class for objects managed by intrusive_ptr.
Definition: intrusive_ptr.h:49
bool C_isalnum(char ch)
Definition: stringutils.h:203
#define FAIL_TEST(MSG)
Fail the current testcase with message MSG.
Definition: testsuite.h:68
bool C_isalpha(char ch)
Definition: stringutils.h:198
#define TESTCASE(T)
Definition: testmacros.h:28
Pack types into strings and unpack them again.
Xapian-specific test helper functions and macros.
char hex_decode(char ch1, char ch2)
Decode a pair of ASCII hex digits.
Definition: stringutils.h:243
bool C_isnotlower(char ch)
Definition: stringutils.h:216
static int run(const test_desc *tests)
Definition: testsuite.cc:892
bool C_isxdigit(char ch)
Definition: stringutils.h:182
static void test_pack_uint_preserving_sort1()
Test pack_uint_preserving_sort()
static int count
static void test_refcnt2()
Structure holding a description of a test.
Definition: testsuite.h:77
#define TEST_EQUAL(a, b)
Test for equality of two things.
Definition: testsuite.h:278
bool C_isnotdigit(char ch)
Definition: stringutils.h:213
A smart pointer that uses intrusive reference counting.
Definition: intrusive_ptr.h:81
bool C_isnotxdigit(char ch)
Definition: stringutils.h:214
bool C_isnotspace(char ch)
Definition: stringutils.h:219
test_autoptr(bool &deleted_)
bool C_isnotupper(char ch)
Definition: stringutils.h:215
static void test_refcnt1()
Definition: internaltest.cc:87
Wrapper around standard unique_ptr template.
bool C_isnotalnum(char ch)
Definition: stringutils.h:218
void pack_uint_preserving_sort(std::string &s, U value)
Append an encoded unsigned integer to a string, preserving the sort order.
Definition: pack.h:269