33 #include <string_view>
38 #define XAPIAN_UNITTEST
40 #define UNITTEST_CHECK_EXCEPTION \
41 if (unittest_assertion_failed) { \
42 const char * unittest_assertion_failed_ = unittest_assertion_failed;\
43 unittest_assertion_failed = NULL;\
44 throw unittest_assertion_failed_;\
49 #define UNITTEST_ASSERT_LOCATION__(LINE,MSG) __FILE__":"#LINE": "#MSG
50 #define UNITTEST_ASSERT_LOCATION_(LINE,MSG) UNITTEST_ASSERT_LOCATION__(LINE,MSG)
51 #define UNITTEST_ASSERT_LOCATION(MSG) UNITTEST_ASSERT_LOCATION_(__LINE__,MSG)
52 #define UNITTEST_ASSERT_NOTHROW(COND, RET) \
55 unittest_assertion_failed = UNITTEST_ASSERT_LOCATION(COND);\
61 #include "../backends/multi.h"
62 #include "../common/stringutils.h"
65 #define TEST_EXCEPTION(TYPE, CODE) \
69 UNITTEST_CHECK_EXCEPTION \
70 FAIL_TEST("Expected exception "#TYPE" not thrown"); \
71 } catch (const TYPE &) { \
76 #include "../backends/uuids.cc"
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/pack.cc"
83 #include "../common/parseint.h"
84 #include "../common/posixy_wrapper.cc"
85 #include "../common/serialise-double.cc"
86 #include "../common/str.cc"
87 #include "../net/serialise-error.cc"
88 #include "../api/error.cc"
89 #include "../api/smallvector.cc"
90 #include "../api/sortable-serialise.cc"
91 #include "../include/xapian/intrusive_ptr.h"
94 #include "../common/msvc_dirent.cc"
97 #include "../api/constinfo.cc"
175 TEST_EQUAL(
r_r_p(
"C:rel/a/tive",
"c:\\foo\\bar"),
"C:\\foo\\rel/a/tive");
182 TEST_EQUAL(
r_r_p(
"rel/a/tive",
"\\\\SRV\\VOL\\DIR\\FILE"),
"\\\\SRV\\VOL\\DIR\\rel/a/tive");
183 TEST_EQUAL(
r_r_p(
"/abs/o/lute",
"\\\\SRV\\VOL\\FILE"),
"\\\\SRV\\VOL/abs/o/lute");
184 TEST_EQUAL(
r_r_p(
"/abs/o/lute",
"\\\\S\\V\\FILE"),
"\\\\S\\V/abs/o/lute");
188 TEST_EQUAL(
r_r_p(
"rel/a/tive",
"//SRV/VOL/DIR/FILE"),
"//SRV/VOL/DIR/rel/a/tive");
189 TEST_EQUAL(
r_r_p(
"/abs/o/lute",
"//SRV/VOL/FILE"),
"//SRV/VOL/abs/o/lute");
193 TEST_EQUAL(
r_r_p(
"/abs/o/lute",
"\\\\?\\C:\\wibble"),
"\\\\?\\C:\\abs\\o\\lute");
194 TEST_EQUAL(
r_r_p(
"/abs/o/lute",
"\\\\?\\UNC\\S\\V"),
"\\\\?\\UNC\\S\\V\\abs\\o\\lute");
195 TEST_EQUAL(
r_r_p(
"/abs/o/lute",
"\\\\?\\UNC\\S\\V\\"),
"\\\\?\\UNC\\S\\V\\abs\\o\\lute");
196 TEST_EQUAL(
r_r_p(
"/abs/o/lute",
"\\\\?\\UNC\\S\\V\\TMP\\README.TXT"),
"\\\\?\\UNC\\S\\V\\abs\\o\\lute");
197 TEST_EQUAL(
r_r_p(
"r/elativ/e",
"\\\\?\\C:\\wibble"),
"\\\\?\\C:\\r\\elativ\\e");
198 TEST_EQUAL(
r_r_p(
"r/elativ/e",
"\\\\?\\C:\\wibble\\wobble"),
"\\\\?\\C:\\wibble\\r\\elativ\\e");
200 TEST_EQUAL(
r_r_p(
"r/elativ/e",
"\\\\?\\UNC\\S\\V"),
"\\\\?\\UNC\\S\\V\\r\\elativ\\e");
202 TEST_EQUAL(
r_r_p(
"r/elativ/e",
"\\\\?\\UNC\\S\\V\\"),
"\\\\?\\UNC\\S\\V\\r\\elativ\\e");
203 TEST_EQUAL(
r_r_p(
"r/elativ/e",
"\\\\?\\UNC\\S\\V\\TMP\\README.TXT"),
"\\\\?\\UNC\\S\\V\\TMP\\r\\elativ\\e");
217 TEST(encoded.size() <
sizeof(buf));
218 memcpy(buf, encoded.data(), encoded.size());
222 const char * ptr[3] = { NULL, buf, NULL };
223 const char * end = ptr[1] + encoded.size();
225 if (ptr[1] != end || u != v) {
226 cout << u <<
" -> " << v <<
", difference = " << v - u <<
'\n';
227 cout <<
"FLT_RADIX = " << FLT_RADIX <<
'\n';
228 cout <<
"DBL_MAX_EXP = " << DBL_MAX_EXP <<
'\n';
230 TEST_EQUAL(
static_cast<const void*
>(ptr[1]),
static_cast<const void*
>(end));
235 static const double test_values[] = {
254 for (
double val : test_values) {
266 while (n < 0xff000000) {
269 const char*
p = s.data();
270 const char* p_end =
p + s.size();
273 if (n != decoded_n ||
p != p_end)
tout <<
"[" << s <<
"]\n";
290 const char*
p = s.data();
291 const char* p_end =
p + s.size();
301 const char*
p = s.data();
302 const char* p_end =
p + s.size();
311 size_t trunc_len = s.size() - 2;
313 const char*
p = s.data();
314 const char* p_end =
p + trunc_len;
328 for (
size_t n = 2; n < 1000; n = (n + 1) * 2 + (n >> 1)) {
343 #ifdef XAPIAN_HAS_REMOTE_BACKEND
345 static void test_serialiseerror1()
351 TEST_STRINGS_EQUAL(e.get_description(),
"DatabaseOpeningError: Failed to open database (" + enoent_msg +
")");
385 -3.14159265358979323846,
417 3.14159265358979323846,
433 bool started =
false;
436 tout <<
"Number: " << num <<
'\n';
438 tout <<
"String: " <<
str <<
'\n';
445 }
else if (prevnum > num) {
451 }
else if (prevstr >
str) {
456 "Numbers " << prevnum <<
" and " << num <<
457 " don't sort the same way as their string "
469 const S max_val = numeric_limits<S>::max();
470 const S min_val = numeric_limits<S>::min();
471 tout <<
"Testing with tostring_helper\n";
472 std::ostringstream oss;
473 oss << (
long long)max_val;
478 oss << (
long long)min_val;
505 tostring_helper<char>();
506 tostring_helper<short>();
507 tostring_helper<int>();
508 tostring_helper<long>();
509 tostring_helper<long long>();
588 for (
int i = 0; i != 8; ++i) {
589 unsigned char ch =
str[i];
594 for (
int i = 9; i != 13; ++i) {
595 unsigned char ch =
str[i];
600 for (
int i = 14; i != 18; ++i) {
601 unsigned char ch =
str[i];
606 for (
int i = 19; i != 23; ++i) {
607 unsigned char ch =
str[i];
612 for (
int i = 24; i != 36; ++i) {
613 unsigned char ch =
str[i];
653 explicit A(
int x_) : x(x_) {}
664 B(
int x_,
bool & alive_) : x(x_), alive(alive_) {
677 opt_intrusive_base::release();
723 B * b1 =
new B{5, alive};
750 const auto ulong_max = numeric_limits<unsigned long>::max();
751 const auto uint_max = numeric_limits<unsigned int>::max();
752 const auto ushort_max = numeric_limits<unsigned short>::max();
753 const auto uchar_max = numeric_limits<unsigned char>::max();
755 unsigned long res_ulong;
757 unsigned short res_ushort;
758 unsigned char res_uchar;
847 constexpr U max_val = numeric_limits<U>::max();
848 tout <<
"Testing with parseunsigned_helper\n";
860 if constexpr(max_val + 1ull != 0)
866 parseunsigned_helper<unsigned char>();
867 parseunsigned_helper<unsigned short>();
868 parseunsigned_helper<unsigned>();
869 parseunsigned_helper<unsigned long>();
870 parseunsigned_helper<unsigned long long>();
876 const S max_val = numeric_limits<S>::max();
877 const S min_val = numeric_limits<S>::min();
878 tout <<
"Testing with parsesigned_helper\n";
896 unsigned long long one_too_large = max_val + 1ull;
906 unsigned long long one_too_small_negated =
907 static_cast<unsigned long long>(-(min_val + 1)) + 2ull;
913 parsesigned_helper<signed char>();
914 parsesigned_helper<short>();
915 parsesigned_helper<int>();
916 parsesigned_helper<long>();
917 parsesigned_helper<long long>();
923 const char* tmp_file =
".unittest_ioutils1";
956 if constexpr(
sizeof(off_t) <= 4) {
957 SKIP_TEST(
"Skipping rest of testcase - no Large File Support");
962 TEST(fstat(fd, &statbuf) == 0);
964 off_t hole = lseek(fd, 0, SEEK_HOLE);
966 SKIP_TEST(
"Skipping rest of testcase - SEEK_HOLE failed");
968 if (hole >= statbuf.st_size) {
969 SKIP_TEST(
"Skipping rest of testcase - sparse file support not "
976 constexpr off_t high_offset = off_t(0x100000000 +
BLOCK_SIZE);
977 constexpr off_t high_block = high_offset /
BLOCK_SIZE;
982 SKIP_TEST(
"Skipping rest of testcase - FS doesn't allow a > 4GB "
986 TEST(fstat(fd, &statbuf) == 0);
1005 SKIP_TEST(
"Skipping rest of testcase - SEEK_HOLE not supported");
1023 for (
int i = 0; i < 100; ++i) {
1033 struct U {
int x; };
1035 for (
int i = 0; i < 100; ++i) {
1049 #ifdef XAPIAN_HAS_REMOTE_BACKEND
1074 }
catch (
const char * e) {
static constexpr unsigned BINARY_SIZE
The size of a UUID in bytes.
std::string to_string() const
void parse(const char *in)
const char * data() const
DatabaseError indicates some sort of database related error.
DatabaseOpeningError indicates failure to open a database.
All exceptions thrown by Xapian are subclasses of Xapian::Error.
const char * get_error_string() const
Returns any system error string associated with this exception.
std::string get_description() const
Return a string describing this object.
Base class for objects managed by intrusive_ptr.
A normally non-NULL smart pointer using intrusive reference counting.
A smart pointer that uses intrusive reference counting.
Base class for objects managed by opt_intrusive_ptr.
A smart pointer that optionally uses intrusive reference counting.
Suitable for "simple" type T.
static void parse_command_line(int argc, char **argv)
Parse the command line arguments.
static int run(const test_desc *tests)
void errno_to_string(int e, string &s)
void resolve_relative_path(string &path, string_view base)
Resolve path relative to base.
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.
int io_open_block_wr(const char *filename, bool anew)
Open a block-based file for writing.
bool io_unlink(const std::string &filename)
Delete a file.
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.
bool io_sync(int fd)
Ensure all data previously written to file descriptor fd has been written to disk.
bool io_full_sync(int fd)
bool io_readahead_block(int, size_t, off_t, off_t=0)
Readahead block b size n bytes from file descriptor fd.
int io_open_block_rd(const char *filename)
Open a block-based file for reading.
Xapian::doccount shard_number(Xapian::docid did, Xapian::doccount n_shards)
Convert docid in the multi-db to shard number.
Xapian::docid shard_docid(Xapian::docid did, Xapian::doccount n_shards)
Convert docid in the multi-db to the docid in the shard.
Xapian::docid unshard(Xapian::docid shard_did, Xapian::doccount shard, Xapian::doccount n_shards)
Convert shard number and shard docid to docid in multi-db.
string str(int value)
Convert int to std::string.
std::string sortable_serialise(double value)
Convert a floating point number to a string, preserving sort order.
double sortable_unserialise(std::string_view serialised) noexcept
Convert a string encoded using sortable_serialise back to a floating point number.
unsigned XAPIAN_DOCID_BASE_TYPE doccount
A count of documents.
unsigned XAPIAN_DOCID_BASE_TYPE docid
A unique identifier for a document.
std::enable_if_t< std::is_unsigned_v< T1 > &&std::is_unsigned_v< T2 > &&std::is_unsigned_v< R >, bool > sub_overflows(T1 a, T2 b, R &res)
Subtraction with overflow checking.
std::enable_if_t< std::is_unsigned_v< T1 > &&std::is_unsigned_v< T2 > &&std::is_unsigned_v< R >, bool > add_overflows(T1 a, T2 b, R &res)
Addition with overflow checking.
std::enable_if_t< std::is_unsigned_v< T1 > &&std::is_unsigned_v< T2 > &&std::is_unsigned_v< R >, bool > mul_overflows(T1 a, T2 b, R &res)
Multiplication with overflow checking.
bool unpack_string(const char **p, const char *end, std::string &result)
Decode a std::string from a string.
bool unpack_uint(const char **p, const char *end, U *result)
Decode an unsigned integer from a string.
void pack_uint(std::string &s, U value)
Append an encoded unsigned integer to a string.
void pack_string(std::string &s, std::string_view value)
Append an encoded std::string to a string.
void pack_string_empty(std::string &s)
Append an empty encoded std::string to a string.
bool parse_signed(const char *p, T &res)
bool parse_unsigned(const char *p, T &res)
<unistd.h>, but with compat.
string serialise_double(double v)
Serialise a double to a string.
double unserialise_double(const char **p, const char *end)
Unserialise a double serialised by serialise_double.
void unserialise_error(const string &serialised_error, const string &prefix, const string &new_context)
Unserialise a Xapian::Error object and throw it.
string serialise_error(const Xapian::Error &e)
Serialise a Xapian::Error object to a string.
Structure holding a description of a test.
#define TEST_REL(A, REL, B)
Test a relation holds,e.g. TEST_REL(a,>,b);.
std::ostringstream tout
The debug printing stream.
a generic test suite engine
#define SKIP_TEST(MSG)
Skip the current testcase with message MSG.
#define TEST_EQUAL(a, b)
Test for equality of two things.
#define TEST_STRINGS_EQUAL(a, b)
Test for equality of two strings.
#define TEST(a)
Test a condition, without an additional explanation for failure.
#define TEST_NOT_EQUAL(a, b)
Test for non-equality of two things.
#define TEST_AND_EXPLAIN(a, b)
Test a condition, and display the test with an extra explanation if the condition fails.
static void test_movesupport1()
static void test_suboverflows1()
static void test_packstring2()
void description_append(std::string &desc, std::string_view s)
static void tostring_helper()
DEFINE_TESTCASE(simple_exceptions_work1)
static void test_addoverflows1()
static void parsesigned_helper()
int main(int argc, char **argv)
static void test_muloverflows1()
static void test_tostring1()
static void test_parsesigned1()
static string r_r_p(string a, const string &b)
static void check_double_serialisation(double u)
static const test_desc tests[]
static void test_sortableserialise1()
static void test_shard1()
static void test_packuint1()
static const double test_sortableserialise_numbers[]
static void packstring1_helper(size_t len)
static const char * unittest_assertion_failed
static void test_closefrom1()
static void test_parseunsigned1()
static void test_packstring1()
static void test_strbool1()
Regression test for bug fixed in 1.1.1.
static void test_ioblock1()
Test working with a block-based file using functions from io_utils.h.
static void parseunsigned_helper()