xapian-core  1.4.20
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,2003,2006,2007,2008,2009,2010,2011,2012,2015 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  TEST_EQUAL(hex_digit(ch), ch - '0');
399  }
400 
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);
418  }
419 
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));
436  }
437 
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);
455  }
456 
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));
473  }
474 
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));
492  }
493 
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));
511  }
512 
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));
529  }
530 
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));
547  }
548 }
549 
550 // ##################################################################
551 // # End of actual tests #
552 // ##################################################################
553 
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}
566 };
567 
568 int main(int argc, char **argv)
569 try {
571  return test_driver::run(tests);
572 } catch (const char * e) {
573  cout << e << endl;
574  return 1;
575 }
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:799
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:188
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:145
bool C_islower(char ch)
Definition: stringutils.h:150
bool C_isdigit(char ch)
Definition: stringutils.h:134
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:174
bool C_isspace(char ch)
Definition: stringutils.h:165
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 an "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:160
#define FAIL_TEST(MSG)
Fail the current testcase with message MSG.
Definition: testsuite.h:68
bool C_isalpha(char ch)
Definition: stringutils.h:155
#define TESTCASE(T)
Definition: testmacros.h:28
Pack types into strings and unpack them again.
Xapian-specific test helper functions and macros.
bool C_isnotlower(char ch)
Definition: stringutils.h:173
static int run(const test_desc *tests)
Definition: testsuite.cc:886
bool C_isxdigit(char ch)
Definition: stringutils.h:139
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:170
A smart pointer that uses intrusive reference counting.
Definition: intrusive_ptr.h:81
bool C_isnotxdigit(char ch)
Definition: stringutils.h:171
bool C_isnotspace(char ch)
Definition: stringutils.h:176
test_autoptr(bool &deleted_)
bool C_isnotupper(char ch)
Definition: stringutils.h:172
static void test_refcnt1()
Definition: internaltest.cc:87
Wrapper around standard unique_ptr template.
bool C_isnotalnum(char ch)
Definition: stringutils.h:175
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