xapian-core  1.4.26
unittest.cc
Go to the documentation of this file.
1 
4 /* Copyright (C) 2006-2024 Olly Betts
5  * Copyright (C) 2007 Richard Boulton
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as
9  * published by the Free Software Foundation; either version 2 of the
10  * License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
20  * USA
21  */
22 
23 #include <config.h>
24 
25 #include <cctype>
26 #include <cerrno>
27 #include <cfloat>
28 #include <climits>
29 #include <cmath>
30 #include <cstring>
31 #include <iostream>
32 #include <limits>
33 #include <utility>
34 
35 #include "safeunistd.h"
36 
37 #define XAPIAN_UNITTEST
38 static const char * unittest_assertion_failed = NULL;
39 #define UNITTEST_CHECK_EXCEPTION \
40  if (unittest_assertion_failed) { \
41  const char * unittest_assertion_failed_ = unittest_assertion_failed;\
42  unittest_assertion_failed = NULL;\
43  throw unittest_assertion_failed_;\
44  }
45 
46 #include "testsuite.h"
47 
48 using namespace std;
49 
50 #define UNITTEST_ASSERT_LOCATION__(LINE,MSG) __FILE__":"#LINE": "#MSG
51 #define UNITTEST_ASSERT_LOCATION_(LINE,MSG) UNITTEST_ASSERT_LOCATION__(LINE,MSG)
52 #define UNITTEST_ASSERT_LOCATION(MSG) UNITTEST_ASSERT_LOCATION_(__LINE__,MSG)
53 #define UNITTEST_ASSERT_NOTHROW(COND, RET) \
54  do {\
55  if (rare(!(COND))) {\
56  unittest_assertion_failed = UNITTEST_ASSERT_LOCATION(COND);\
57  return RET;\
58  }\
59  } while (false)
60 
61 // Utility code we use:
62 #include "../common/stringutils.h"
63 #include "../common/log2.h"
64 
65 // Simpler version of TEST_EXCEPTION macro.
66 #define TEST_EXCEPTION(TYPE, CODE) \
67  do { \
68  try { \
69  CODE; \
70  UNITTEST_CHECK_EXCEPTION \
71  FAIL_TEST("Expected exception "#TYPE" not thrown"); \
72  } catch (const TYPE &) { \
73  } \
74  } while (0)
75 
76 // Code we're unit testing:
77 #include "../common/closefrom.cc"
78 #include "../common/errno_to_string.cc"
79 #include "../common/io_utils.cc"
80 #include "../common/fileutils.cc"
81 #include "../common/overflow.h"
82 #include "../common/parseint.h"
83 #include "../common/posixy_wrapper.cc"
84 #include "../common/serialise-double.cc"
85 #include "../common/str.cc"
86 #include "../backends/uuids.cc"
87 #include "../net/length.cc"
88 #include "../net/serialise-error.cc"
89 #include "../api/error.cc"
90 #include "../api/sortable-serialise.cc"
91 
92 // fileutils.cc uses opendir(), etc though not in a function we currently test.
93 #include "../common/msvc_dirent.cc"
94 
95 // The UUID code uses hex_decode().
96 #include "../api/constinfo.cc"
97 
98 // Stub replacement, which doesn't deal with escaping or producing valid UTF-8.
99 // The full implementation needs Xapian::Utf8Iterator and
100 // Xapian::Unicode::append_utf8().
101 void
102 description_append(std::string & desc, const std::string &s)
103 {
104  desc += s;
105 }
106 
107 DEFINE_TESTCASE_(simple_exceptions_work1) {
108  try {
109  throw 42;
110  } catch (int val) {
111  TEST_EQUAL(val, 42);
112  }
113 }
114 
115 class TestException { };
116 
117 DEFINE_TESTCASE_(class_exceptions_work1) {
118  try {
119  throw TestException();
120  } catch (const TestException &) {
121  }
122 }
123 
124 static inline string
125 r_r_p(string a, const string & b)
126 {
127  resolve_relative_path(a, b);
128  return a;
129 }
130 
131 DEFINE_TESTCASE_(resolverelativepath1) {
132  TEST_EQUAL(r_r_p("/abs/o/lute", ""), "/abs/o/lute");
133  TEST_EQUAL(r_r_p("/abs/o/lute", "/"), "/abs/o/lute");
134  TEST_EQUAL(r_r_p("/abs/o/lute", "//"), "/abs/o/lute");
135  TEST_EQUAL(r_r_p("/abs/o/lute", "foo"), "/abs/o/lute");
136  TEST_EQUAL(r_r_p("/abs/o/lute", "foo/"), "/abs/o/lute");
137  TEST_EQUAL(r_r_p("/abs/o/lute", "/foo"), "/abs/o/lute");
138  TEST_EQUAL(r_r_p("/abs/o/lute", "/foo/"), "/abs/o/lute");
139  TEST_EQUAL(r_r_p("/abs/o/lute", "foo/bar"), "/abs/o/lute");
140  TEST_EQUAL(r_r_p("/abs/o/lute", "foo/bar/"), "/abs/o/lute");
141  TEST_EQUAL(r_r_p("/abs/o/lute", "/foo/bar"), "/abs/o/lute");
142  TEST_EQUAL(r_r_p("/abs/o/lute", "/foo/bar/"), "/abs/o/lute");
143  TEST_EQUAL(r_r_p("rel/a/tive", ""), "rel/a/tive");
144  TEST_EQUAL(r_r_p("rel/a/tive", "/"), "/rel/a/tive");
145  TEST_EQUAL(r_r_p("rel/a/tive", "//"), "//rel/a/tive");
146  TEST_EQUAL(r_r_p("rel/a/tive", "foo"), "rel/a/tive");
147  TEST_EQUAL(r_r_p("rel/a/tive", "foo/"), "foo/rel/a/tive");
148  TEST_EQUAL(r_r_p("rel/a/tive", "/foo"), "/rel/a/tive");
149  TEST_EQUAL(r_r_p("rel/a/tive", "/foo/"), "/foo/rel/a/tive");
150  TEST_EQUAL(r_r_p("rel/a/tive", "foo/bar"), "foo/rel/a/tive");
151  TEST_EQUAL(r_r_p("rel/a/tive", "foo/bar/"), "foo/bar/rel/a/tive");
152  TEST_EQUAL(r_r_p("rel/a/tive", "/foo/bar"), "/foo/rel/a/tive");
153  TEST_EQUAL(r_r_p("rel/a/tive", "/foo/bar/"), "/foo/bar/rel/a/tive");
154 #ifndef __WIN32__
155  TEST_EQUAL(r_r_p("/abs/o/lute", "/foo\\bar"), "/abs/o/lute");
156  TEST_EQUAL(r_r_p("rel/a/tive", "/foo\\bar"), "/rel/a/tive");
157 #else
158  TEST_EQUAL(r_r_p("\\dos\\path", ""), "\\dos\\path");
159  TEST_EQUAL(r_r_p("\\dos\\path", "/"), "\\dos\\path");
160  TEST_EQUAL(r_r_p("\\dos\\path", "\\"), "\\dos\\path");
161  TEST_EQUAL(r_r_p("\\dos\\path", "c:"), "c:\\dos\\path");
162  TEST_EQUAL(r_r_p("\\dos\\path", "c:\\"), "c:\\dos\\path");
163  TEST_EQUAL(r_r_p("\\dos\\path", "c:\\temp"), "c:\\dos\\path");
164  TEST_EQUAL(r_r_p("\\dos\\path", "c:\\temp\\"), "c:\\dos\\path");
165  TEST_EQUAL(r_r_p("rel/a/tive", "\\"), "\\rel/a/tive");
166  TEST_EQUAL(r_r_p("rel/a/tive", "foo\\"), "foo\\rel/a/tive");
167  TEST_EQUAL(r_r_p("rel\\a\\tive", "/foo/"), "/foo/rel\\a\\tive");
168  TEST_EQUAL(r_r_p("rel/a/tive", "c:/foo/bar"), "c:/foo/rel/a/tive");
169  TEST_EQUAL(r_r_p("rel/a/tive", "c:foo/bar/"), "c:foo/bar/rel/a/tive");
170  TEST_EQUAL(r_r_p("rel/a/tive", "c:"), "c:rel/a/tive");
171  TEST_EQUAL(r_r_p("rel/a/tive", "c:\\"), "c:\\rel/a/tive");
172  TEST_EQUAL(r_r_p("C:rel/a/tive", "c:\\foo\\bar"), "C:\\foo\\rel/a/tive");
173  TEST_EQUAL(r_r_p("C:rel/a/tive", "c:"), "C:rel/a/tive");
174  // This one is impossible to reliably resolve without knowing the current
175  // drive - if it is C:, then the answer is: "C:/abs/o/rel/a/tive"
176  TEST_EQUAL(r_r_p("C:rel/a/tive", "/abs/o/lute"), "C:rel/a/tive");
177  // UNC paths tests:
178  TEST_EQUAL(r_r_p("\\\\SRV\\VOL\\FILE", "/a/b"), "\\\\SRV\\VOL\\FILE");
179  TEST_EQUAL(r_r_p("rel/a/tive", "\\\\SRV\\VOL\\DIR\\FILE"), "\\\\SRV\\VOL\\DIR\\rel/a/tive");
180  TEST_EQUAL(r_r_p("/abs/o/lute", "\\\\SRV\\VOL\\FILE"), "\\\\SRV\\VOL/abs/o/lute");
181  TEST_EQUAL(r_r_p("/abs/o/lute", "\\\\S\\V\\FILE"), "\\\\S\\V/abs/o/lute");
182  TEST_EQUAL(r_r_p("/abs/o/lute", "\\\\S\\V\\"), "\\\\S\\V/abs/o/lute");
183  TEST_EQUAL(r_r_p("/abs/o/lute", "\\\\S\\V"), "\\\\S\\V/abs/o/lute");
184  TEST_EQUAL(r_r_p("//SRV/VOL/FILE", "/a/b"), "//SRV/VOL/FILE");
185  TEST_EQUAL(r_r_p("rel/a/tive", "//SRV/VOL/DIR/FILE"), "//SRV/VOL/DIR/rel/a/tive");
186  TEST_EQUAL(r_r_p("/abs/o/lute", "//SRV/VOL/FILE"), "//SRV/VOL/abs/o/lute");
187  TEST_EQUAL(r_r_p("/abs/o/lute", "//S/V/FILE"), "//S/V/abs/o/lute");
188  TEST_EQUAL(r_r_p("/abs/o/lute", "//S/V/"), "//S/V/abs/o/lute");
189  TEST_EQUAL(r_r_p("/abs/o/lute", "//S/V"), "//S/V/abs/o/lute");
190  TEST_EQUAL(r_r_p("/abs/o/lute", "\\\\?\\C:\\wibble"), "\\\\?\\C:\\abs\\o\\lute");
191  TEST_EQUAL(r_r_p("/abs/o/lute", "\\\\?\\UNC\\S\\V"), "\\\\?\\UNC\\S\\V\\abs\\o\\lute");
192  TEST_EQUAL(r_r_p("/abs/o/lute", "\\\\?\\UNC\\S\\V\\"), "\\\\?\\UNC\\S\\V\\abs\\o\\lute");
193  TEST_EQUAL(r_r_p("/abs/o/lute", "\\\\?\\UNC\\S\\V\\TMP\\README.TXT"), "\\\\?\\UNC\\S\\V\\abs\\o\\lute");
194  TEST_EQUAL(r_r_p("r/elativ/e", "\\\\?\\C:\\wibble"), "\\\\?\\C:\\r\\elativ\\e");
195  TEST_EQUAL(r_r_p("r/elativ/e", "\\\\?\\C:\\wibble\\wobble"), "\\\\?\\C:\\wibble\\r\\elativ\\e");
196 #if 0 // Is this a valid testcase? It fails, but isn't relevant to Xapian.
197  TEST_EQUAL(r_r_p("r/elativ/e", "\\\\?\\UNC\\S\\V"), "\\\\?\\UNC\\S\\V\\r\\elativ\\e");
198 #endif
199  TEST_EQUAL(r_r_p("r/elativ/e", "\\\\?\\UNC\\S\\V\\"), "\\\\?\\UNC\\S\\V\\r\\elativ\\e");
200  TEST_EQUAL(r_r_p("r/elativ/e", "\\\\?\\UNC\\S\\V\\TMP\\README.TXT"), "\\\\?\\UNC\\S\\V\\TMP\\r\\elativ\\e");
201 #endif
202 }
203 
204 static void
206 {
207  // Commonly C++ string implementations keep the string nul-terminated, and
208  // encoded.data() returns a pointer to a buffer including the nul (the same
209  // as encoded.c_str()). This means that valgrind won't catch a read one
210  // past the end of the serialised value, so we copy just the serialised
211  // value into a temporary buffer.
212  char buf[16];
213  string encoded = serialise_double(u);
214  TEST(encoded.size() < sizeof(buf));
215  memcpy(buf, encoded.data(), encoded.size());
216  // Put a NULL pointer either side, to catch incrementing/decrementing at
217  // the wrong level of indirection (regression test for a bug in an
218  // unreleased version).
219  const char * ptr[3] = { NULL, buf, NULL };
220  const char * end = ptr[1] + encoded.size();
221  double v = unserialise_double(&(ptr[1]), end);
222  if (ptr[1] != end || u != v) {
223  cout << u << " -> " << v << ", difference = " << v - u << '\n';
224  cout << "FLT_RADIX = " << FLT_RADIX << '\n';
225  cout << "DBL_MAX_EXP = " << DBL_MAX_EXP << '\n';
226  }
227  TEST_EQUAL(static_cast<const void*>(ptr[1]), static_cast<const void*>(end));
228 }
229 
230 // Check serialisation of doubles.
231 DEFINE_TESTCASE_(serialisedouble1) {
232  static const double test_values[] = {
233  3.14159265,
234  1e57,
235  123.1,
236  257.12,
237  1234.567e123,
238  255.5,
239  256.125,
240  257.03125,
241  };
242 
247  check_double_serialisation(-DBL_MAX);
249  check_double_serialisation(-DBL_MIN);
250 
251  const double *p;
252  for (p = test_values; p < test_values + sizeof(test_values) / sizeof(double); ++p) {
253  double val = *p;
256  check_double_serialisation(1.0 / val);
257  check_double_serialisation(-1.0 / val);
258  }
259 }
260 
261 #ifdef XAPIAN_HAS_REMOTE_BACKEND
262 // Check serialisation of lengths.
264 {
265  size_t n = 0;
266  while (n < 0xff000000) {
267  string s = encode_length(n);
268  const char *p = s.data();
269  const char *p_end = p + s.size();
270  size_t decoded_n;
271  decode_length(&p, p_end, decoded_n);
272  if (n != decoded_n || p != p_end) tout << "[" << s << "]\n";
273  TEST_EQUAL(n, decoded_n);
274  TEST_EQUAL(p_end - p, 0);
275  if (n < 5000) {
276  ++n;
277  } else {
278  n += 53643;
279  }
280  }
281 }
282 
283 // Regression test: vetting the remaining buffer length
285 {
286  // Special case tests for 0
287  {
288  string s = encode_length(0);
289  {
290  const char *p = s.data();
291  const char *p_end = p + s.size();
292  size_t r;
293  decode_length_and_check(&p, p_end, r);
294  TEST(r == 0);
295  TEST(p == p_end);
296  }
297  s += 'x';
298  {
299  const char *p = s.data();
300  const char *p_end = p + s.size();
301  size_t r;
302  decode_length_and_check(&p, p_end, r);
303  TEST(r == 0);
304  TEST_EQUAL(p_end - p, 1);
305  }
306  }
307  // Special case tests for 1
308  {
309  string s = encode_length(1);
310  TEST_EXCEPTION(Xapian_NetworkError,
311  const char *p = s.data();
312  const char *p_end = p + s.size();
313  size_t r;
314  decode_length_and_check(&p, p_end, r);
315  (void)r;
316  );
317  s += 'x';
318  {
319  const char *p = s.data();
320  const char *p_end = p + s.size();
321  size_t r;
322  decode_length_and_check(&p, p_end, r);
323  TEST(r == 1);
324  TEST_EQUAL(p_end - p, 1);
325  }
326  s += 'x';
327  {
328  const char *p = s.data();
329  const char *p_end = p + s.size();
330  size_t r;
331  decode_length_and_check(&p, p_end, r);
332  TEST(r == 1);
333  TEST_EQUAL(p_end - p, 2);
334  }
335  }
336  // Nothing magic here, just test a range of odd and even values.
337  for (size_t n = 2; n < 1000; n = (n + 1) * 2 + (n >> 1)) {
338  string s = encode_length(n);
339  TEST_EXCEPTION(Xapian_NetworkError,
340  const char *p = s.data();
341  const char *p_end = p + s.size();
342  size_t r;
343  decode_length_and_check(&p, p_end, r);
344  (void)r;
345  );
346  s.append(n - 1, 'x');
347  TEST_EXCEPTION(Xapian_NetworkError,
348  const char *p = s.data();
349  const char *p_end = p + s.size();
350  size_t r;
351  decode_length_and_check(&p, p_end, r);
352  (void)r;
353  );
354  s += 'x';
355  {
356  const char *p = s.data();
357  const char *p_end = p + s.size();
358  size_t r;
359  decode_length_and_check(&p, p_end, r);
360  TEST(r == n);
361  TEST_EQUAL(size_t(p_end - p), n);
362  }
363  s += 'x';
364  {
365  const char *p = s.data();
366  const char *p_end = p + s.size();
367  size_t r;
368  decode_length_and_check(&p, p_end, r);
369  TEST(r == n);
370  TEST_EQUAL(size_t(p_end - p), n + 1);
371  }
372  }
373 }
374 
375 // Check serialisation of Xapian::Error.
376 static void test_serialiseerror1()
377 {
378  string enoent_msg = errno_to_string(ENOENT);
379  Xapian::DatabaseOpeningError e("Failed to open database", ENOENT);
380  // Regression test for bug in 1.0.0 - it didn't convert errno values for
381  // get_description() if they hadn't already been converted.
382  TEST_STRINGS_EQUAL(e.get_description(), "DatabaseOpeningError: Failed to open database (" + enoent_msg + ")");
383 
384  TEST_STRINGS_EQUAL(e.get_error_string(), enoent_msg);
385 
386  string serialisation = serialise_error(e);
387 
388  // Test if unserialise_error() throws with a flag to avoid the possibility
389  // of an "unreachable code" warning when we get around to marking
390  // unserialise_error() as "noreturn".
391  bool threw = false;
392  try {
393  // unserialise_error throws an exception.
394  unserialise_error(serialisation, "", "");
395  } catch (const Xapian::Error & ecaught) {
396  TEST_STRINGS_EQUAL(ecaught.get_error_string(), enoent_msg);
397  threw = true;
398  }
399  TEST(threw);
400 
401  // Check that the original is still OK.
402  TEST_STRINGS_EQUAL(e.get_error_string(), enoent_msg);
403 
404  // Regression test - in 1.0.0, copying used to duplicate the error_string
405  // pointer, resulting in double calls to free().
407  TEST_STRINGS_EQUAL(ecopy.get_error_string(), enoent_msg);
408 }
409 #endif
410 
411 // Test log2() (which might be our replacement version).
412 static void test_log2()
413 {
414  TEST_EQUAL(log2(1.0), 0.0);
415  TEST_EQUAL(log2(2.0), 1.0);
416  TEST_EQUAL(log2(1024.0), 10.0);
417  TEST_EQUAL(log2(0.5), -1.0);
418 }
419 
420 static const double test_sortableserialise_numbers[] = {
421  -HUGE_VAL,
422  -DBL_MAX,
423  -exp2(1022),
424  -1024.5,
425  -3.14159265358979323846,
426  -3,
427  -2,
428  -1.8,
429  -1.1,
430  -1,
431  -0.5,
432  -0.2,
433  -0.1,
434  -0.000005,
435  -0.000002,
436  -0.000001,
437  -exp2(-1023),
438  -exp2(-1024),
439  -exp2(-1074),
440  -DBL_MIN,
441  0,
442  DBL_MIN,
443  exp2(-1074),
444  exp2(-1024),
445  exp2(-1023),
446  0.000001,
447  0.000002,
448  0.000005,
449  0.1,
450  0.2,
451  0.5,
452  1,
453  1.1,
454  1.8,
455  2,
456  3,
457  3.14159265358979323846,
458  1024.5,
459  exp2(1022),
460  DBL_MAX,
461  HUGE_VAL,
462 
463  64 // Magic number which we stop at.
464 };
465 
466 // Test serialisation and unserialisation of various numbers.
467 // This is actually a public API, but we want extra assertions in the code
468 // while we test it.
470 {
471  double prevnum = 0;
472  string prevstr;
473  bool started = false;
474  for (const double *p = test_sortableserialise_numbers; *p != 64; ++p) {
475  double num = *p;
476  tout << "Number: " << num << '\n';
477  string str = Xapian::sortable_serialise(num);
478  tout << "String: " << str << '\n';
480 
481  if (started) {
482  int num_cmp = 0;
483  if (prevnum < num) {
484  num_cmp = -1;
485  } else if (prevnum > num) {
486  num_cmp = 1;
487  }
488  int str_cmp = 0;
489  if (prevstr < str) {
490  str_cmp = -1;
491  } else if (prevstr > str) {
492  str_cmp = 1;
493  }
494 
495  TEST_AND_EXPLAIN(num_cmp == str_cmp,
496  "Numbers " << prevnum << " and " << num <<
497  " don't sort the same way as their string "
498  "counterparts");
499  }
500 
501  prevnum = num;
502  prevstr = str;
503  started = true;
504  }
505 }
506 
507 template<typename S>
508 inline static void tostring_helper() {
509  const S max_val = numeric_limits<S>::max();
510  const S min_val = numeric_limits<S>::min();
511  tout << "Testing with tostring_helper\n";
512  std::ostringstream oss;
513  oss << (long long)max_val;
514  TEST_EQUAL(str(max_val), oss.str());
515  oss.str("");
516  oss.clear();
517 
518  oss << (long long)min_val;
519  TEST_EQUAL(str(min_val), oss.str());
520  oss.str("");
521  oss.clear();
522 }
523 
524 static void test_tostring1()
525 {
526  TEST_EQUAL(str(0), "0");
527  TEST_EQUAL(str(0u), "0");
528  TEST_EQUAL(str(1), "1");
529  TEST_EQUAL(str(1u), "1");
530  TEST_EQUAL(str(9), "9");
531  TEST_EQUAL(str(9u), "9");
532  TEST_EQUAL(str(10), "10");
533  TEST_EQUAL(str(10u), "10");
534  TEST_EQUAL(str(-1), "-1");
535  TEST_EQUAL(str(-9), "-9");
536  TEST_EQUAL(str(-10), "-10");
537  TEST_EQUAL(str(0x7f), "127");
538  TEST_EQUAL(str(-0x80), "-128");
539  TEST_EQUAL(str(0x7fff), "32767");
540  TEST_EQUAL(str(0xffffffff), "4294967295");
541  TEST_EQUAL(str(0x7fffffff), "2147483647");
542  TEST_EQUAL(str(0x7fffffffu), "2147483647");
543  TEST_EQUAL(str(-0x7fffffff), "-2147483647");
544 
545  tostring_helper<char>();
546  tostring_helper<short>();
547  tostring_helper<int>();
548  tostring_helper<long>();
549  tostring_helper<long long>();
550 
551 #ifdef __WIN32__
552  /* Test the 64 bit integer conversion to string.
553  * (Currently only exists for windows.)
554  */
555  TEST_EQUAL(str(10ll), "10");
556  TEST_EQUAL(str(-10ll), "-10");
557  TEST_EQUAL(str(0x200000000ll), "8589934592");
558 // We don't currently have an "unsigned long long" version since it's not required
559 // anywhere in the library.
560 // TEST_EQUAL(str(0x200000000ull), "8589934592");
561 #endif
562 }
563 
565 static void test_strbool1()
566 {
567  TEST_EQUAL(str(true), "1");
568  TEST_EQUAL(str(false), "0");
569 }
570 
571 static void test_closefrom1()
572 {
573 #ifndef __WIN32__
574  // Simple test. Start from 13 as on macOS the FDTracker seems to get fd
575  // 10 and we don't want to collide with that.
576  closefrom(13);
577 
578  // Simple test when there are definitely no fds to close.
579  closefrom(42);
580 
581  // Test passing a really high threshold.
582  closefrom(INT_MAX);
583 
584  // Open some fds and check the expected ones are closed.
585  TEST_EQUAL(dup2(1, 14), 14);
586  TEST_EQUAL(dup2(1, 15), 15);
587  TEST_EQUAL(dup2(1, 18), 18);
588  closefrom(15);
589  TEST_EQUAL(close(14), 0);
590  TEST(close(15) == -1 && errno == EBADF);
591  TEST(close(18) == -1 && errno == EBADF);
592 #endif
593 }
594 
595 static void test_uuid1()
596 {
597  Uuid uuid, uuid2;
598 
599  // Test a generated uuid.
600  uuid.generate();
601  TEST(!uuid.is_null());
602  string str = uuid.to_string();
603  TEST_EQUAL(str.size(), 36);
604  TEST_NOT_EQUAL(str, "00000000-0000-0000-0000-000000000000");
605  // Check UUID pattern is correct and that upper case is not used.
606  for (int i = 0; i != 8; ++i) {
607  unsigned char ch = str[i];
608  TEST(isxdigit(ch));
609  TEST(!isupper(ch));
610  }
611  TEST_EQUAL(str[8], '-');
612  for (int i = 9; i != 13; ++i) {
613  unsigned char ch = str[i];
614  TEST(isxdigit(ch));
615  TEST(!isupper(ch));
616  }
617  TEST_EQUAL(str[13], '-');
618  for (int i = 14; i != 18; ++i) {
619  unsigned char ch = str[i];
620  TEST(isxdigit(ch));
621  TEST(!isupper(ch));
622  }
623  TEST_EQUAL(str[18], '-');
624  for (int i = 19; i != 23; ++i) {
625  unsigned char ch = str[i];
626  TEST(isxdigit(ch));
627  TEST(!isupper(ch));
628  }
629  TEST_EQUAL(str[23], '-');
630  for (int i = 24; i != 36; ++i) {
631  unsigned char ch = str[i];
632  TEST(isxdigit(ch));
633  TEST(!isupper(ch));
634  }
635 
636  uuid2.parse(str);
637  TEST(memcmp(uuid.data(), uuid2.data(), uuid.BINARY_SIZE) == 0);
638 
639  // Check the variant is "10x" and the version between 1 and 5. Mostly this
640  // is to catch bugs where the platform's API for generating UUIDs uses a
641  // different endianness for fields (which we've run into under both WIN32
642  // and FreeBSD).
643  TEST_EQUAL(uuid.data()[8] & 0xc0, 0x80);
644  TEST_REL(str[19], >=, '8');
645  TEST_REL(str[19], <=, 'b');
646  TEST_REL(int(uuid.data()[6]), >=, 0x10);
647  TEST_REL(int(uuid.data()[6]), <=, 0x5f);
648  TEST_REL(str[14], >=, '1');
649  TEST_REL(str[14], <=, '5');
650 
651  // Test generating another uuid gives us a different non-null uuid.
652  uuid2.generate();
653  TEST(!uuid2.is_null());
654  TEST(memcmp(uuid.data(), uuid2.data(), uuid.BINARY_SIZE) != 0);
655 
656  // Test null uuid.
657  uuid.clear();
658  TEST(uuid.is_null());
659  str = uuid.to_string();
660  TEST_EQUAL(str, "00000000-0000-0000-0000-000000000000");
661  uuid2.generate();
662  TEST(!uuid2.is_null());
663  uuid2.parse(str);
664  TEST(memcmp(uuid.data(), uuid2.data(), uuid.BINARY_SIZE) == 0);
665 }
666 
667 // Classes used by movesupport1 test
669  int x = 0;
670  public:
671  explicit A(int x_) : x(x_) {}
672 
673  int get_x() const {
674  return x;
675  }
676 };
677 
679  int x = 0;
680  bool & alive;
681  public:
682  B(int x_, bool & alive_) : x(x_), alive(alive_) {
683  alive = true;
684  }
685 
686  ~B() {
687  alive = false;
688  }
689 
690  int get_x() const {
691  return x;
692  }
693 
694  B * release() {
695  opt_intrusive_base::release();
696  return this;
697  }
698 };
699 
700 static void test_movesupport1()
701 {
702  {
703  // Test move semantics support for intrusive_ptr class
706 
707  // Test move constructor
708  Xapian::Internal::intrusive_ptr<A> p2(std::move(p1));
709  TEST_EQUAL(p2->get_x(), 5);
710  TEST_EQUAL(p1.get(), 0);
711 
712  // Test move assignment
713  p3 = std::move(p2);
714  TEST_EQUAL(p3->get_x(), 5);
715  TEST_EQUAL(p2.get(), 0);
716  }
717 
718  bool alive = false;
719  {
720  // Same test for opt_intrusive_ptr class
721  B * b1 = new B{5, alive};
722  b1->release();
725 
726  // Test move constructor
727  Xapian::Internal::opt_intrusive_ptr<B> p2(std::move(p1));
728  TEST_EQUAL(p2->get_x(), 5);
729  TEST_EQUAL(p1.get(), 0);
730  TEST_EQUAL(alive, true);
731 
732  // Test move assignment
733  p3 = std::move(p2);
734  TEST_EQUAL(p3->get_x(), 5);
735  TEST_EQUAL(p2.get(), 0);
736  TEST_EQUAL(alive, true);
737  }
738  // Test that object b1 has been deleted.
739  TEST_EQUAL(alive, false);
740 }
741 
742 static void test_addoverflows1()
743 {
744  const auto ulong_max = numeric_limits<unsigned long>::max();
745  const auto uint_max = numeric_limits<unsigned int>::max();
746  const auto ushort_max = numeric_limits<unsigned short>::max();
747  const auto uchar_max = numeric_limits<unsigned char>::max();
748 
749  unsigned long res_ulong;
750  unsigned res_uint;
751  unsigned short res_ushort;
752  unsigned char res_uchar;
753 
754  TEST(!add_overflows(0UL, 0UL, res_ulong));
755  TEST_EQUAL(res_ulong, 0);
756  TEST(!add_overflows(0UL, 0UL, res_uint));
757  TEST_EQUAL(res_uint, 0);
758  TEST(!add_overflows(0UL, 0UL, res_ushort));
759  TEST_EQUAL(res_ushort, 0);
760  TEST(!add_overflows(0UL, 0UL, res_uchar));
761  TEST_EQUAL(res_uchar, 0);
762 
763  TEST(add_overflows(ulong_max, 1UL, res_ulong));
764  TEST_EQUAL(res_ulong, 0);
765  TEST(add_overflows(uint_max, 1UL, res_uint));
766  TEST_EQUAL(res_uint, 0);
767  TEST(add_overflows(ushort_max, 1UL, res_ushort));
768  TEST_EQUAL(res_ushort, 0);
769  TEST(add_overflows(uchar_max, 1UL, res_uchar));
770  TEST_EQUAL(res_uchar, 0);
771 
772  TEST(add_overflows(1UL, ulong_max, res_ulong));
773  TEST_EQUAL(res_ulong, 0);
774  TEST(add_overflows(1UL, uint_max, res_uint));
775  TEST_EQUAL(res_uint, 0);
776  TEST(add_overflows(1UL, ushort_max, res_ushort));
777  TEST_EQUAL(res_ushort, 0);
778  TEST(add_overflows(1UL, uchar_max, res_uchar));
779  TEST_EQUAL(res_uchar, 0);
780 
781  TEST(add_overflows(ulong_max, ulong_max, res_ulong));
782  TEST_EQUAL(res_ulong, ulong_max - 1UL);
783  TEST(add_overflows(uint_max, uint_max, res_uint));
784  TEST_EQUAL(res_uint, uint_max - 1UL);
785  TEST(add_overflows(ushort_max, ushort_max, res_ushort));
786  TEST_EQUAL(res_ushort, ushort_max - 1UL);
787  TEST(add_overflows(uchar_max, uchar_max, res_uchar));
788  TEST_EQUAL(res_uchar, uchar_max - 1UL);
789 
790  res_uchar = 1;
791  TEST(add_overflows(res_uchar, unsigned(uchar_max) + 1U, res_uchar));
792  TEST_EQUAL(res_uchar, 1);
793 }
794 
795 static void test_suboverflows1()
796 {
797  unsigned long res;
798  TEST(!sub_overflows(0UL, 0UL, res));
799  TEST_EQUAL(res, 0);
800 
801  TEST(sub_overflows(0UL, 1UL, res));
802  TEST_EQUAL(res, ULONG_MAX);
803 
804  TEST(sub_overflows(ULONG_MAX - 1UL, ULONG_MAX, res));
805  TEST_EQUAL(res, ULONG_MAX);
806 
807  TEST(sub_overflows(0UL, ULONG_MAX, res));
808  TEST_EQUAL(res, 1);
809 }
810 
811 static void test_muloverflows1()
812 {
813  unsigned long res;
814  TEST(!mul_overflows(0UL, 0UL, res));
815  TEST_EQUAL(res, 0);
816 
817  TEST(!mul_overflows(ULONG_MAX, 0UL, res));
818  TEST_EQUAL(res, 0);
819 
820  TEST(!mul_overflows(0UL, ULONG_MAX, res));
821  TEST_EQUAL(res, 0);
822 
823  TEST(!mul_overflows(ULONG_MAX, 1UL, res));
824  TEST_EQUAL(res, ULONG_MAX);
825 
826  TEST(!mul_overflows(1UL, ULONG_MAX, res));
827  TEST_EQUAL(res, ULONG_MAX);
828 
829  TEST(mul_overflows((ULONG_MAX >> 1UL) + 1UL, 2UL, res));
830  TEST_EQUAL(res, 0);
831 
832  TEST(mul_overflows(2UL, (ULONG_MAX >> 1UL) + 1UL, res));
833  TEST_EQUAL(res, 0);
834 
835  TEST(mul_overflows(ULONG_MAX, ULONG_MAX, res));
836 }
837 
838 template<typename U>
839 inline static void parseunsigned_helper() {
840  U val;
841  const U max_val = numeric_limits<U>::max();
842  tout << "Testing with parseunsigned_helper\n";
843  TEST(parse_unsigned("0", val));
844  TEST_EQUAL(val, 0);
845  TEST(parse_unsigned("99", val));
846  TEST_EQUAL(val, 99);
847  TEST(parse_unsigned(str(max_val).c_str(), val));
848  TEST_EQUAL(val, max_val);
849  TEST(!parse_unsigned("", val));
850  TEST(!parse_unsigned("-1", val));
851  TEST(!parse_unsigned("abc", val));
852  TEST(!parse_unsigned("0a", val));
853  // Only test if we can construct a value one larger easily.
854  if (max_val + 1ull != 0)
855  TEST(!parse_unsigned(str(max_val + 1ull).c_str(), val));
856 }
857 
858 static void test_parseunsigned1()
859 {
860  parseunsigned_helper<unsigned char>();
861  parseunsigned_helper<unsigned short>();
862  parseunsigned_helper<unsigned>();
863  parseunsigned_helper<unsigned long>();
864  parseunsigned_helper<unsigned long long>();
865 }
866 
867 template<typename S>
868 inline static void parsesigned_helper() {
869  S val;
870  const S max_val = numeric_limits<S>::max();
871  const S min_val = numeric_limits<S>::min();
872  tout << "Testing with parsesigned_helper\n";
873  TEST(parse_signed("0", val));
874  TEST_EQUAL(val, 0);
875  TEST(parse_signed("99", val));
876  TEST_EQUAL(val, 99);
877  TEST(parse_signed("-99", val));
878  TEST_EQUAL(val, -99);
879  TEST(parse_signed(str(max_val).c_str(), val));
880  TEST_EQUAL(val, max_val);
881  TEST(parse_signed(str(min_val).c_str(), val));
882  TEST_EQUAL(val, min_val);
883  TEST(!parse_signed("", val));
884  TEST(!parse_signed("abc", val));
885  TEST(!parse_signed("0a", val));
886  TEST(!parse_signed("-99a", val));
887  TEST(!parse_signed("-a99", val));
888  TEST(!parse_signed("--99", val));
889 
890  unsigned long long one_too_large = max_val + 1ull;
891  TEST(!parse_signed(str(one_too_large).c_str(), val));
892 
893  unsigned long long one_too_small_negated = 1ull - min_val;
894  TEST(!parse_signed(("-" + str(one_too_small_negated)).c_str(), val));
895 }
896 
897 static void test_parsesigned1()
898 {
899  parsesigned_helper<signed char>();
900  parsesigned_helper<short>();
901  parsesigned_helper<int>();
902  parsesigned_helper<long>();
903  parsesigned_helper<long long>();
904 }
905 
907 static void test_ioblock1()
908 try {
909  const char* tmp_file = ".unittest_ioutils1";
910  int fd = -1;
911  try {
912  constexpr int BLOCK_SIZE = 1024;
913 
914  fd = io_open_block_wr(tmp_file, true);
915  TEST_REL(fd, >=, 0);
916 
917  string buf(BLOCK_SIZE, 'x');
918  string out;
919 
920  // ZFS default blocksize is 128K so we need to write at least that far
921  // into the file to be able to successfully detect support for sparse
922  // files below. We won't detect sparse file support if the blocksize
923  // is larger, but that's not a problem.
924  io_write_block(fd, buf.data(), BLOCK_SIZE, 128);
925  out.resize(BLOCK_SIZE);
926  io_read_block(fd, &out[0], BLOCK_SIZE, 128);
927  TEST(buf == out);
928 
929  // Call io_sync() and check it claims to work. Checking it actually has
930  // any effect is much harder to do.
931  TEST(io_sync(fd));
932 
933  io_write_block(fd, buf.data(), BLOCK_SIZE, 129);
934  out.resize(BLOCK_SIZE);
935  io_read_block(fd, &out[0], BLOCK_SIZE, 129);
936  TEST(buf == out);
937 
938  // Call io_full_sync() and check it claims to work. Checking it actually
939  // has any effect is much harder to do.
940  TEST(io_full_sync(fd));
941 
942  if (sizeof(off_t) <= 4) {
943  SKIP_TEST("Skipping rest of testcase - no Large File Support");
944  }
945 
946 #ifdef SEEK_HOLE
947  struct stat statbuf;
948  TEST(fstat(fd, &statbuf) == 0);
949 
950  off_t hole = lseek(fd, 0, SEEK_HOLE);
951  if (hole < 0) {
952  SKIP_TEST("Skipping rest of testcase - SEEK_HOLE failed");
953  }
954  if (hole >= statbuf.st_size) {
955  SKIP_TEST("Skipping rest of testcase - sparse file support not "
956  "detected");
957  }
958 
959  // Write a block at an offset a little above 4GB and check that we wrote
960  // the specified block by checking the filesize. This should catch bugs
961  // which truncate the offset used.
962  constexpr off_t high_offset = (off_t{1} << 32) + BLOCK_SIZE;
963  constexpr off_t high_block = high_offset / BLOCK_SIZE;
964  try {
965  io_write_block(fd, buf.data(), BLOCK_SIZE, high_block);
966  } catch (const Xapian::DatabaseError& e) {
967  if (e.get_error_string() == errno_to_string(EFBIG))
968  SKIP_TEST("Skipping rest of testcase - FS doesn't allow a > 4GB "
969  "file");
970  throw;
971  }
972  TEST(fstat(fd, &statbuf) == 0);
973  TEST_EQUAL(statbuf.st_size, high_offset + BLOCK_SIZE);
974 
975  close(fd);
976 
977  fd = io_open_block_rd(tmp_file);
978 
979  // We can't easily test that io_readahead_block() actually does anything if
980  // it returns true, but we can at least call it to check it doesn't crash.
981  (void)io_readahead_block(fd, BLOCK_SIZE, high_block);
982 
983  // Check we can read back the same data we wrote.
984  io_read_block(fd, &out[0], BLOCK_SIZE, high_block);
985  TEST(buf == out);
986 
987  close(fd);
988  fd = -1;
989  io_unlink(tmp_file);
990 #else
991  SKIP_TEST("Skipping rest of testcase - SEEK_HOLE not supported");
992 #endif
993  } catch (...) {
994  close(fd);
995  io_unlink(tmp_file);
996  throw;
997  }
998 } catch (const Xapian::Error& e) {
999  // Translate Xapian::Error exceptions to std::string exceptions which
1000  // utestsuite can catch.
1001  throw e.get_description();
1002 }
1003 
1004 static const test_desc tests[] = {
1005  TESTCASE(simple_exceptions_work1),
1006  TESTCASE(class_exceptions_work1),
1007  TESTCASE(resolverelativepath1),
1008  TESTCASE(serialisedouble1),
1009 #ifdef XAPIAN_HAS_REMOTE_BACKEND
1010  TESTCASE(serialiselength1),
1011  TESTCASE(serialiselength2),
1012  TESTCASE(serialiseerror1),
1013 #endif
1014  TESTCASE(log2),
1015  TESTCASE(sortableserialise1),
1016  TESTCASE(tostring1),
1017  TESTCASE(strbool1),
1018  TESTCASE(closefrom1),
1019  TESTCASE(uuid1),
1020  TESTCASE(movesupport1),
1021  TESTCASE(addoverflows1),
1022  TESTCASE(suboverflows1),
1023  TESTCASE(muloverflows1),
1024  TESTCASE(parseunsigned1),
1025  TESTCASE(parsesigned1),
1026  TESTCASE(ioblock1),
1028 };
1029 
1030 int main(int argc, char **argv)
1031 try {
1032  test_driver::parse_command_line(argc, argv);
1033  return test_driver::run(tests);
1034 } catch (const char * e) {
1035  cout << e << '\n';
1036  return 1;
1037 }
int close(FD &fd)
Definition: fd.h:63
~B()
Definition: unittest.cc:686
int io_open_block_rd(const char *fname)
Open a block-based file for reading.
Definition: io_utils.h:38
Definition: unittest.cc:678
static void test_serialiseerror1()
Definition: unittest.cc:376
static void test_serialiselength2()
Definition: unittest.cc:284
std::enable_if< std::is_unsigned< T1 >::value &&std::is_unsigned< T2 >::value &&std::is_unsigned< R >::value, bool >::type add_overflows(T1 a, T2 b, R &res)
Addition with overflow checking.
Definition: overflow.h:58
static void test_parsesigned1()
Definition: unittest.cc:897
static void check_double_serialisation(double u)
Definition: unittest.cc:205
#define TEST(a)
Test a condition, without an additional explanation for failure.
Definition: testsuite.h:275
bool io_unlink(const std::string &filename)
Delete a file.
Definition: io_utils.cc:52
static void parse_command_line(int argc, char **argv)
Parse the command line arguments.
Definition: testsuite.cc:828
void closefrom(int fd)
Definition: closefrom.cc:89
DatabaseOpeningError indicates failure to open a database.
Definition: error.h:581
void io_read_block(int fd, char *p, size_t n, off_t b, off_t o)
Read block b size n bytes into buffer p from file descriptor fd, offset o.
Definition: io_utils.cc:180
static void parseunsigned_helper()
Definition: unittest.cc:839
#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
static void test_suboverflows1()
Definition: unittest.cc:795
bool io_sync(int fd)
Ensure all data previously written to file descriptor fd has been written to disk.
Definition: io_utils.h:73
int io_open_block_wr(const char *fname, bool anew)
Open a block-based file for writing.
Definition: io_utils.cc:67
a generic test suite engine
static void test_uuid1()
Definition: unittest.cc:595
bool io_readahead_block(int, size_t, off_t, off_t=0)
Readahead block b size n bytes from file descriptor fd.
Definition: io_utils.h:133
STL namespace.
string serialise_error(const Xapian::Error &e)
Serialise a Xapian::Error object to a string.
std::string sortable_serialise(double value)
Convert a floating point number to a string, preserving sort order.
Definition: queryparser.h:1382
Definition: unittest.cc:668
std::string encode_length(T len)
Encode a length as a variable-length string.
Definition: length.h:36
static string r_r_p(string a, const string &b)
Definition: unittest.cc:125
int get_x() const
Definition: unittest.cc:690
static void parsesigned_helper()
Definition: unittest.cc:868
static void test_serialiselength1()
Definition: unittest.cc:263
void unserialise_error(const string &serialised_error, const string &prefix, const string &new_context)
Unserialise a Xapian::Error object and throw it.
#define TEST_REL(A, REL, B)
Test a relation holds,e.g. TEST_REL(a,>,b);.
Definition: testmacros.h:32
static const char * unittest_assertion_failed
Definition: unittest.cc:38
#define TEST_NOT_EQUAL(a, b)
Test for non-equality of two things.
Definition: testsuite.h:305
bool io_full_sync(int fd)
Definition: io_utils.h:88
double unserialise_double(const char **p, const char *end)
Unserialise a double serialised by serialise_double.
void description_append(std::string &desc, const std::string &s)
Definition: unittest.cc:102
std::ostringstream tout
The debug printing stream.
Definition: testsuite.cc:104
void errno_to_string(int e, string &s)
A(int x_)
Definition: unittest.cc:671
#define BLOCK_SIZE
#define TEST_EXCEPTION(TYPE, CODE)
Definition: unittest.cc:66
B(int x_, bool &alive_)
Definition: unittest.cc:682
static void test_parseunsigned1()
Definition: unittest.cc:858
void io_write_block(int fd, const char *p, size_t n, off_t b, off_t o)
Write block b size n bytes from buffer p to file descriptor fd, offset o.
Definition: io_utils.cc:228
void clear()
Definition: uuids.h:45
static void test_tostring1()
Definition: unittest.cc:524
#define END_OF_TESTCASES
Definition: testmacros.h:29
string str(int value)
Convert int to std::string.
Definition: str.cc:90
std::string to_string() const
Definition: uuids.cc:120
static void test_ioblock1()
Test working with a block-based file using functions from io_utils.h.
Definition: unittest.cc:907
static void test_sortableserialise1()
Definition: unittest.cc:469
B * release()
Definition: unittest.cc:694
void parse(const char *in)
Definition: uuids.cc:111
Base class for objects managed by intrusive_ptr.
Definition: intrusive_ptr.h:49
Base class for objects managed by opt_intrusive_ptr.
static void test_muloverflows1()
Definition: unittest.cc:811
double sortable_unserialise(const std::string &serialised)
Convert a string encoded using sortable_serialise back to a floating point number.
std::string get_description() const
Return a string describing this object.
Definition: error.cc:93
static void test_closefrom1()
Definition: unittest.cc:571
void resolve_relative_path(string &path, const string &base)
Resolve path relative to base.
Definition: fileutils.cc:105
double log2(double x)
Definition: log2.h:31
std::string serialise_double(double v)
Serialise a double to a string.
void decode_length_and_check(const char **p, const char *end, unsigned &out)
Decode a length encoded by encode_length.
Definition: length.cc:112
#define SKIP_TEST(MSG)
Skip the current testcase with message MSG.
Definition: testsuite.h:74
static void test_movesupport1()
Definition: unittest.cc:700
bool is_null() const
Definition: uuids.h:50
#define TESTCASE(T)
Definition: testmacros.h:28
int get_x() const
Definition: unittest.cc:673
static void tostring_helper()
Definition: unittest.cc:508
const char * get_error_string() const
Returns any system error string associated with this exception.
Definition: error.cc:50
static constexpr unsigned BINARY_SIZE
The size of a UUID in bytes.
Definition: uuids.h:31
bool parse_signed(const char *p, T &res)
Definition: parseint.h:43
All exceptions thrown by Xapian are subclasses of Xapian::Error.
Definition: error.h:43
static const double test_sortableserialise_numbers[]
Definition: unittest.cc:420
std::enable_if< std::is_unsigned< T1 >::value &&std::is_unsigned< T2 >::value &&std::is_unsigned< R >::value, bool >::type sub_overflows(T1 a, T2 b, R &res)
Subtraction with overflow checking.
Definition: overflow.h:125
#define TEST_STRINGS_EQUAL(a, b)
Test for equality of two strings.
Definition: testsuite.h:287
Definition: uuids.h:28
static void test_strbool1()
Regression test for bug fixed in 1.1.1.
Definition: unittest.cc:565
static int run(const test_desc *tests)
Definition: testsuite.cc:913
std::enable_if< std::is_unsigned< T1 >::value &&std::is_unsigned< T2 >::value &&std::is_unsigned< R >::value, bool >::type mul_overflows(T1 a, T2 b, R &res)
Multiplication with overflow checking.
Definition: overflow.h:188
<unistd.h>, but with compat.
static const test_desc tests[]
Definition: unittest.cc:1004
int main(int argc, char **argv)
Definition: unittest.cc:1030
static void test_log2()
Definition: unittest.cc:412
static void test_addoverflows1()
Definition: unittest.cc:742
const char * data() const
Definition: uuids.h:60
Structure holding a description of a test.
Definition: testsuite.h:77
DatabaseError indicates some sort of database related error.
Definition: error.h:367
bool parse_unsigned(const char *p, T &res)
Definition: parseint.h:28
#define TEST_EQUAL(a, b)
Test for equality of two things.
Definition: testsuite.h:278
A smart pointer that optionally uses intrusive reference counting.
A smart pointer that uses intrusive reference counting.
Definition: intrusive_ptr.h:81
void decode_length(const char **p, const char *end, unsigned &out)
Decode a length encoded by encode_length.
Definition: length.cc:94
bool & alive
Definition: unittest.cc:680
DEFINE_TESTCASE_(simple_exceptions_work1)
Definition: unittest.cc:107
void generate()
Definition: uuids.cc:63