xapian-core  2.0.0
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, see
21  * <https://www.gnu.org/licenses/>.
22  */
23 
24 #include <config.h>
25 
26 #include <xapian.h>
27 
28 #include <iostream>
29 #include <string>
30 
31 using namespace std;
32 
33 #include "testsuite.h"
34 #include "testutils.h"
35 
36 #include "pack.h"
37 #include "str.h"
38 
40  public:
41  int value;
42  Test_Exception(int value_) : value(value_) {}
43 };
44 
45 // test that nested exceptions work correctly.
46 static void test_exception1()
47 {
48  try {
49  try {
50  throw Test_Exception(1);
51  } catch (...) {
52  try {
53  throw Test_Exception(2);
54  } catch (...) {
55  }
56  throw;
57  }
58  } catch (const Test_Exception& e) {
59  TEST_EQUAL(e.value, 1);
60  }
61 }
62 
63 // ###########################################
64 // # Tests of the reference counted pointers #
65 // ###########################################
66 
68  bool& deleted;
69 
70  public:
71  test_refcnt(bool& deleted_) : deleted(deleted_) {
72  tout << "constructor\n";
73  }
74 
77  }
78 
80  deleted = true;
81  tout << "destructor\n";
82  }
83 };
84 
85 static void test_refcnt1()
86 {
87  bool deleted = false;
88 
89  test_refcnt* p = new test_refcnt(deleted);
90 
91  TEST_EQUAL(p->_refs, 0);
92 
93  {
95 
96  TEST_EQUAL(rcp->_refs, 1);
97 
98  {
100  rcp2 = rcp;
101  TEST_EQUAL(rcp->_refs, 2);
102  // rcp2 goes out of scope here
103  }
104 
105  TEST_AND_EXPLAIN(!deleted, "Object prematurely deleted!");
106  TEST_EQUAL(rcp->_refs, 1);
107  // rcp goes out of scope here
108  }
109 
110  TEST_AND_EXPLAIN(deleted, "Object not properly deleted");
111 }
112 
113 // This is a regression test - our home-made equivalent of intrusive_ptr
114 // (which was called RefCntPtr) used to delete the object pointed to if you
115 // assigned it to itself and the reference count was 1.
116 static void test_refcnt2()
117 {
118  bool deleted = false;
119 
120  test_refcnt* p = new test_refcnt(deleted);
121 
123 
124 #ifdef __has_warning
125 # if __has_warning("-Wself-assign-overloaded")
126  // Suppress warning from newer clang about self-assignment so we can
127  // test that self-assignment works!
128 # pragma clang diagnostic push
129 # pragma clang diagnostic ignored "-Wself-assign-overloaded"
130 # endif
131 #endif
132  rcp = rcp;
133 #ifdef __has_warning
134 # if __has_warning("-Wself-assign-overloaded")
135 # pragma clang diagnostic pop
136 # endif
137 #endif
138 
139  TEST_AND_EXPLAIN(!deleted, "Object deleted by self-assignment");
140 }
141 
142 // test string comparisons
143 static void test_stringcomp1()
144 {
145  string s1;
146  string s2;
147 
148  s1 = "foo";
149  s2 = "foo";
150 
151  if ((s1 != s2) || (s1 > s2)) {
152  FAIL_TEST("String comparisons BADLY wrong");
153  }
154 
155  s1 += '\0';
156 
157  if ((s1 == s2) || (s1 < s2)) {
158  FAIL_TEST("String comparisons don't cope with extra nulls");
159  }
160 
161  s2 += '\0';
162 
163  s1 += 'a';
164  s2 += 'z';
165 
166  if ((s1.length() != 5) || (s2.length() != 5)) {
167  FAIL_TEST("Lengths with added nulls wrong");
168  }
169 
170  if ((s1 == s2) || !(s1 < s2)) {
171  FAIL_TEST("Characters after a null ignored in comparisons");
172  }
173 }
174 
175 // By default Sun's C++ compiler doesn't call the destructor on a
176 // temporary object until the end of the block (contrary to what
177 // ISO C++ requires). This is done in the name of "compatibility".
178 // Passing -features=tmplife to CC fixes this. This check ensures
179 // that this actually works for Sun's C++ and any other compilers
180 // that might have this problem.
181 struct TempDtorTest {
182  static int count;
183  static TempDtorTest factory() { return TempDtorTest(); }
184  TempDtorTest() { ++count; }
185  ~TempDtorTest() { --count; }
186 };
187 
188 int TempDtorTest::count = 0;
189 
190 static void test_temporarydtor1()
191 {
195 }
196 
199 {
200  string prev_packed;
201  for (unsigned int i = 0; i != 1000; ++i) {
202  string packed;
203  pack_uint_preserving_sort(packed, i);
204  const char* ptr = packed.data();
205  const char* end = ptr + packed.size();
206  unsigned int result;
207  TEST(unpack_uint_preserving_sort(&ptr, end, &result));
208  TEST_EQUAL(result, i);
209  TEST(ptr == end);
210  TEST_REL(prev_packed, <, packed);
211  swap(prev_packed, packed);
212  }
213  for (unsigned int i = 2345; i < 65000; i += 113) {
214  string packed;
215  pack_uint_preserving_sort(packed, i);
216  const char* ptr = packed.data();
217  const char* end = ptr + packed.size();
218  unsigned int result;
219  TEST(unpack_uint_preserving_sort(&ptr, end, &result));
220  TEST_EQUAL(result, i);
221  TEST(ptr == end);
222  TEST_REL(prev_packed, <, packed);
223  swap(prev_packed, packed);
224  }
225  unsigned int prev = 64999;
226  for (unsigned int i = 65000; i > prev; prev = i, i = (i << 1) ^ 1337) {
227  string packed;
228  pack_uint_preserving_sort(packed, i);
229  const char* ptr = packed.data();
230  const char* end = ptr + packed.size();
231  unsigned int result;
232  TEST(unpack_uint_preserving_sort(&ptr, end, &result));
233  TEST_EQUAL(result, i);
234  TEST(ptr == end);
235  TEST_REL(prev_packed, <, packed);
236  swap(prev_packed, packed);
237  }
238 
239  /* Test packing multiple numbers to one string. */
240  string packed;
241  for (unsigned int i = 23456; i < 765432; i += 1131) {
242  pack_uint_preserving_sort(packed, i);
243  }
244  const char* ptr = packed.data();
245  const char* end = ptr + packed.size();
246  for (unsigned int i = 23456; i < 765432; i += 1131) {
247  unsigned int result;
248  TEST(unpack_uint_preserving_sort(&ptr, end, &result));
249  TEST_EQUAL(result, i);
250  }
251  TEST(ptr == end);
252 }
253 
255 static void test_chartype1()
256 {
257  char tested[128];
258  memset(tested, 0, sizeof(tested));
259  for (int ch = '0'; ch != '9' + 1; ++ch) {
260  tested[ch] = 1;
261  TEST(!C_isupper(ch));
262  TEST(!C_islower(ch));
263  TEST(!C_isalpha(ch));
264  TEST(C_isalnum(ch));
265  TEST(C_isdigit(ch));
266  TEST(C_isxdigit(ch));
267  TEST(!C_isspace(ch));
268  TEST(C_isnotupper(ch));
269  TEST(C_isnotlower(ch));
270  TEST(C_isnotalpha(ch));
271  TEST(!C_isnotalnum(ch));
272  TEST(!C_isnotdigit(ch));
273  TEST(!C_isnotxdigit(ch));
274  TEST(C_isnotspace(ch));
275  int v = ch - '0';
276  TEST_EQUAL(hex_digit(ch), v);
277  TEST_EQUAL(hex_decode('0', ch), char(v));
278  TEST_EQUAL(hex_decode(ch, '0'), char(v << 4));
279  TEST_EQUAL(hex_decode(ch, ch), char((v << 4) | v));
280  }
281 
282  for (int ch = 'A'; ch != 'F' + 1; ++ch) {
283  tested[ch] = 1;
284  TEST(C_isupper(ch));
285  TEST(!C_islower(ch));
286  TEST(C_isalpha(ch));
287  TEST(C_isalnum(ch));
288  TEST(!C_isdigit(ch));
289  TEST(C_isxdigit(ch));
290  TEST(!C_isspace(ch));
291  TEST(!C_isnotupper(ch));
292  TEST(C_isnotlower(ch));
293  TEST(!C_isnotalpha(ch));
294  TEST(!C_isnotalnum(ch));
295  TEST(C_isnotdigit(ch));
296  TEST(!C_isnotxdigit(ch));
297  TEST(C_isnotspace(ch));
298  int v = ch - 'A' + 10;
299  TEST_EQUAL(hex_digit(ch), v);
300  TEST_EQUAL(hex_decode('0', ch), char(v));
301  TEST_EQUAL(hex_decode(ch, '0'), char(v << 4));
302  TEST_EQUAL(hex_decode(ch, ch), char((v << 4) | v));
303  }
304 
305  for (int ch = 'G'; ch != 'Z' + 1; ++ch) {
306  tested[ch] = 1;
307  TEST(C_isupper(ch));
308  TEST(!C_islower(ch));
309  TEST(C_isalpha(ch));
310  TEST(C_isalnum(ch));
311  TEST(!C_isdigit(ch));
312  TEST(!C_isxdigit(ch));
313  TEST(!C_isspace(ch));
314  TEST(!C_isnotupper(ch));
315  TEST(C_isnotlower(ch));
316  TEST(!C_isnotalpha(ch));
317  TEST(!C_isnotalnum(ch));
318  TEST(C_isnotdigit(ch));
319  TEST(C_isnotxdigit(ch));
320  TEST(C_isnotspace(ch));
321  }
322 
323  for (int ch = 'a'; ch != 'f' + 1; ++ch) {
324  tested[ch] = 1;
325  TEST(!C_isupper(ch));
326  TEST(C_islower(ch));
327  TEST(C_isalpha(ch));
328  TEST(C_isalnum(ch));
329  TEST(!C_isdigit(ch));
330  TEST(C_isxdigit(ch));
331  TEST(!C_isspace(ch));
332  TEST(C_isnotupper(ch));
333  TEST(!C_isnotlower(ch));
334  TEST(!C_isnotalpha(ch));
335  TEST(!C_isnotalnum(ch));
336  TEST(C_isnotdigit(ch));
337  TEST(!C_isnotxdigit(ch));
338  TEST(C_isnotspace(ch));
339  int v = ch - 'a' + 10;
340  TEST_EQUAL(hex_digit(ch), v);
341  TEST_EQUAL(hex_decode('0', ch), char(v));
342  TEST_EQUAL(hex_decode(ch, '0'), char(v << 4));
343  TEST_EQUAL(hex_decode(ch, ch), char((v << 4) | v));
344  }
345 
346  for (int ch = 'g'; ch != 'z' + 1; ++ch) {
347  tested[ch] = 1;
348  TEST(!C_isupper(ch));
349  TEST(C_islower(ch));
350  TEST(C_isalpha(ch));
351  TEST(C_isalnum(ch));
352  TEST(!C_isdigit(ch));
353  TEST(!C_isxdigit(ch));
354  TEST(!C_isspace(ch));
355  TEST(C_isnotupper(ch));
356  TEST(!C_isnotlower(ch));
357  TEST(!C_isnotalpha(ch));
358  TEST(!C_isnotalnum(ch));
359  TEST(C_isnotdigit(ch));
360  TEST(C_isnotxdigit(ch));
361  TEST(C_isnotspace(ch));
362  }
363 
364  for (const char* p = "\t\n\f\r "; *p; ++p) {
365  int ch = *p;
366  tested[ch] = 1;
367  TEST(!C_isupper(ch));
368  TEST(!C_islower(ch));
369  TEST(!C_isalpha(ch));
370  TEST(!C_isalnum(ch));
371  TEST(!C_isdigit(ch));
372  TEST(!C_isxdigit(ch));
373  TEST(C_isspace(ch));
374  TEST(C_isnotupper(ch));
375  TEST(C_isnotlower(ch));
376  TEST(C_isnotalpha(ch));
377  TEST(C_isnotalnum(ch));
378  TEST(C_isnotdigit(ch));
379  TEST(C_isnotxdigit(ch));
380  TEST(!C_isnotspace(ch));
381  }
382 
383  // Check remaining non-top-bit-set characters aren't anything.
384  for (int ch = 0; ch != 128; ++ch) {
385  if (tested[ch]) continue;
386  TEST(!C_isupper(ch));
387  TEST(!C_islower(ch));
388  TEST(!C_isalpha(ch));
389  TEST(!C_isalnum(ch));
390  TEST(!C_isdigit(ch));
391  TEST(!C_isxdigit(ch));
392  TEST(!C_isspace(ch));
393  TEST(C_isnotupper(ch));
394  TEST(C_isnotlower(ch));
395  TEST(C_isnotalpha(ch));
396  TEST(C_isnotalnum(ch));
397  TEST(C_isnotdigit(ch));
398  TEST(C_isnotxdigit(ch));
399  TEST(C_isnotspace(ch));
400  }
401 
402  // Non-ASCII characters aren't anything for these functions.
403  for (unsigned char ch = 128; ch != 0; ++ch) {
404  TEST(!C_isupper(ch));
405  TEST(!C_islower(ch));
406  TEST(!C_isalpha(ch));
407  TEST(!C_isalnum(ch));
408  TEST(!C_isdigit(ch));
409  TEST(!C_isxdigit(ch));
410  TEST(!C_isspace(ch));
411  TEST(C_isnotupper(ch));
412  TEST(C_isnotlower(ch));
413  TEST(C_isnotalpha(ch));
414  TEST(C_isnotalnum(ch));
415  TEST(C_isnotdigit(ch));
416  TEST(C_isnotxdigit(ch));
417  TEST(C_isnotspace(ch));
418  }
419 
420  // Check signed char values work the same way.
421  for (signed char ch = -128; ch != 0; ++ch) {
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 
439 // ##################################################################
440 // # End of actual tests #
441 // ##################################################################
442 
444 static const test_desc tests[] = {
445  TESTCASE(exception1),
446  TESTCASE(refcnt1),
447  TESTCASE(refcnt2),
448  TESTCASE(stringcomp1),
449  TESTCASE(temporarydtor1),
450  TESTCASE(pack_uint_preserving_sort1),
451  TESTCASE(chartype1),
452  {0, 0}
453 };
454 
455 int main(int argc, char** argv)
456 try {
458  return test_driver::run(tests);
459 } catch (const char* e) {
460  cout << e << '\n';
461  return 1;
462 }
Test_Exception(int value_)
Definition: internaltest.cc:42
Base class for objects managed by intrusive_ptr.
Definition: intrusive_ptr.h:50
unsigned _refs
Reference count.
Definition: intrusive_ptr.h:74
A smart pointer that uses intrusive reference counting.
Definition: intrusive_ptr.h:83
static void parse_command_line(int argc, char **argv)
Parse the command line arguments.
Definition: testsuite.cc:866
static int run(const test_desc *tests)
Definition: testsuite.cc:955
bool & deleted
Definition: internaltest.cc:68
Xapian::Internal::intrusive_ptr< const test_refcnt > test()
Definition: internaltest.cc:75
test_refcnt(bool &deleted_)
Definition: internaltest.cc:71
PositionList * p
static void test_pack_uint_preserving_sort1()
Test pack_uint_preserving_sort()
static void test_refcnt1()
Definition: internaltest.cc:85
int main(int argc, char **argv)
static void test_stringcomp1()
static void test_temporarydtor1()
static const test_desc tests[]
The lists of tests to perform.
static void test_exception1()
Definition: internaltest.cc:46
static void test_chartype1()
Test C_isupper() etc.
static void test_refcnt2()
Pack types into strings and unpack them again.
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:251
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:204
Convert types to std::string.
bool C_isupper(char ch)
Definition: stringutils.h:193
bool C_isalnum(char ch)
Definition: stringutils.h:208
bool C_isnotalnum(char ch)
Definition: stringutils.h:223
bool C_isalpha(char ch)
Definition: stringutils.h:203
char hex_decode(char ch1, char ch2)
Decode a pair of ASCII hex digits.
Definition: stringutils.h:248
bool C_isnotalpha(char ch)
Definition: stringutils.h:222
bool C_isspace(char ch)
Definition: stringutils.h:213
int hex_digit(char ch)
Definition: stringutils.h:236
bool C_isnotdigit(char ch)
Definition: stringutils.h:218
bool C_isxdigit(char ch)
Definition: stringutils.h:187
bool C_isnotlower(char ch)
Definition: stringutils.h:221
bool C_isnotxdigit(char ch)
Definition: stringutils.h:219
bool C_isnotupper(char ch)
Definition: stringutils.h:220
bool C_isdigit(char ch)
Definition: stringutils.h:182
bool C_isnotspace(char ch)
Definition: stringutils.h:224
bool C_islower(char ch)
Definition: stringutils.h:198
static TempDtorTest factory()
static int count
Structure holding a description of a test.
Definition: testsuite.h:74
#define TESTCASE(T)
Definition: testmacros.h:31
#define TEST_REL(A, REL, B)
Test a relation holds,e.g. TEST_REL(a,>,b);.
Definition: testmacros.h:35
std::ostringstream tout
The debug printing stream.
Definition: testsuite.cc:104
a generic test suite engine
#define FAIL_TEST(MSG)
Fail the current testcase with message MSG.
Definition: testsuite.h:65
#define TEST_EQUAL(a, b)
Test for equality of two things.
Definition: testsuite.h:276
#define TEST(a)
Test a condition, without an additional explanation for failure.
Definition: testsuite.h:273
#define TEST_AND_EXPLAIN(a, b)
Test a condition, and display the test with an extra explanation if the condition fails.
Definition: testsuite.h:265
Xapian-specific test helper functions and macros.
Public interfaces for the Xapian library.