1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
|
// Test "long long" support, if available
#define PQXX_ALLOW_LONG_LONG
// We need some libpqxx-internal configuration items. DON'T INCLUDE THIS HEADER
// IN NORMAL CLIENT PROGRAMS!
#include "pqxx/config-internal-compiler.h"
#ifdef PQXX_HAVE_LOCALE
#include <locale>
#endif
#include "test_helpers.hxx"
using namespace PGSTD;
using namespace pqxx;
// Initial test program for libpqxx. Test functionality that doesn't require a
// running database.
namespace
{
template<typename T> void testitems(const T &I, typename T::size_type s)
{
PQXX_CHECK_EQUAL(I.size(), s, "Wrong size in items class.");
for ( ; s; --s)
{
const typename T::size_type value = typename T::size_type((I[s-1]));
PQXX_CHECK_EQUAL(value, s, "Wrong value in items object.");
}
}
void check(string ref, string val, string vdesc)
{
PQXX_CHECK_EQUAL(val, ref, "String mismatch for " + vdesc);
}
template<typename T> inline void strconv(string type,
const T &Obj,
string expected)
{
const string Objstr(to_string(Obj));
check(expected, Objstr, type);
T NewObj;
from_string(Objstr, NewObj);
check(expected, to_string(NewObj), "recycled " + type);
}
// There's no from_string<const char *>()...
inline void strconv(string type, const char Obj[], string expected)
{
const string Objstr(to_string(Obj));
check(expected, Objstr, type);
}
const double not_a_number =
#if defined(PQXX_HAVE_QUIET_NAN)
numeric_limits<double>::quiet_NaN();
#elif defined(PQXX_HAVE_C_NAN)
NAN;
#elif defined(PQXX_HAVE_NAN)
nan("");
#else
0.0/0.0;
#endif
struct intderef
{
intderef(){} // Silences bogus warning in some gcc versions
template<typename ITER>
int operator()(ITER i) const throw () { return int(*i); }
};
void test_000(transaction_base &)
{
PQXX_CHECK_EQUAL(oid_none,
0u,
"InvalidIod is not zero as it used to be. This may conceivably "
"cause problems in libpqxx.");
PQXX_CHECK(
cursor_base::prior() < 0 && cursor_base::backward_all() < 0,
"cursor_base::difference_type appears to be unsigned.");
// Test items template
items<int> I0;
testitems(I0, 0);
items<int> I1(1);
testitems(I1, 1);
items<int> I2(1,2);
testitems(I2,2);
items<int> I3(1,2,3);
testitems(I3,3);
items<int> I4(1,2,3,4);
testitems(I4,4);
items<int> I5(1,2,3,4,5);
testitems(I5,5);
items<int> Ivar;
Ivar(1);
testitems(Ivar,1);
const string l = separated_list(",",I5.begin(),I5.end(),intderef());
PQXX_CHECK_EQUAL(l, "1,2,3,4,5", "separated_list is broken.");
vector<int> V2(I2);
testitems(items<int>(V2),2);
const char weird[] = "foo\t\n\0bar";
const string weirdstr(weird, sizeof(weird)-1);
// Test string conversions
strconv("const char[]", "", "");
strconv("const char[]", "foo", "foo");
strconv("int", 0, "0");
strconv("int", 100, "100");
strconv("int", -1, "-1");
#if defined(PQXX_HAVE_LIMITS) && !defined(_MSC_VER)
const long long_min = PGSTD::numeric_limits<long>::min(),
long_max = PGSTD::numeric_limits<long>::max();
#else
const long long_min = LONG_MIN, long_max = LONG_MAX;
#endif
stringstream lminstr, lmaxstr, llminstr, llmaxstr, ullmaxstr;
#if defined(PQXX_HAVE_IMBUE)
lminstr.imbue(locale("C"));
lmaxstr.imbue(locale("C"));
llminstr.imbue(locale("C"));
llmaxstr.imbue(locale("C"));
ullmaxstr.imbue(locale("C"));
#endif
lminstr << long_min;
lmaxstr << long_max;
#if defined(PQXX_HAVE_LONG_LONG)
typedef long long longlong;
typedef unsigned long long ulonglong;
const unsigned long long ullong_max = ~ulonglong(0);
const long long llong_max = longlong(ullong_max >> 2),
llong_min = -1 - llong_max;
llminstr << llong_min;
llmaxstr << llong_max;
ullmaxstr << ullong_max;
#endif
strconv("long", 0, "0");
strconv("long", long_min, lminstr.str());
strconv("long", long_max, lmaxstr.str());
strconv("double", not_a_number, "nan");
strconv("string", string(), "");
strconv("string", weirdstr, weirdstr);
#if defined(PQXX_HAVE_LONG_LONG)
strconv("long long", 0LL, "0");
strconv("long long", llong_min, llminstr.str());
strconv("long long", llong_max, llmaxstr.str());
strconv("unsigned long long", 0ULL, "0");
strconv("unsigned long long", ullong_max, ullmaxstr.str());
#endif
const char zerobuf[] = "0";
string zero;
from_string(zerobuf, zero, sizeof(zerobuf)-1);
PQXX_CHECK_EQUAL(
zero,
zerobuf,
"Converting \"0\" with explicit length failed.");
const char nulbuf[] = "\0string\0with\0nuls\0";
const string nully(nulbuf, sizeof(nulbuf)-1);
string nully_parsed;
from_string(nulbuf, nully_parsed, sizeof(nulbuf)-1);
PQXX_CHECK_EQUAL(nully_parsed.size(), nully.size(), "Nul truncates string.");
PQXX_CHECK_EQUAL(nully_parsed, nully, "String conversion breaks on nuls.");
from_string(nully.c_str(), nully_parsed, nully.size());
PQXX_CHECK_EQUAL(nully_parsed, nully, "Nul conversion breaks on strings.");
stringstream ss;
strconv("empty stringstream", ss, "");
ss << -3.1415;
strconv("stringstream", ss, ss.str());
// TODO: Test binarystring reversibility
#ifdef PQXX_HAVE_PQENCRYPTPASSWORD
const string pw = encrypt_password("foo", "bar");
PQXX_CHECK(!pw.empty(), "Encrypting a password returned no data.");
PQXX_CHECK_NOT_EQUAL(
pw,
encrypt_password("splat", "blub"),
"Password encryption is broken.");
PQXX_CHECK(
pw.find("bar") == string::npos,
"Encrypted password contains original.");
#endif
// Test error handling for failed connections
{
nullconnection nc;
PQXX_CHECK_THROWS(
work w(nc),
broken_connection,
"nullconnection fails to fail.");
}
{
nullconnection nc("");
PQXX_CHECK_THROWS(
work w(nc),
broken_connection,
"nullconnection(const char[]) is broken.");
}
{
string n;
nullconnection nc(n);
PQXX_CHECK_THROWS(
work w(nc),
broken_connection,
"nullconnection(const string &) is broken.");
}
// Now that we know nullconnections throw errors as expected, test
// pqxx_exception.
try
{
nullconnection nc;
work w(nc);
}
catch (const pqxx_exception &e)
{
PQXX_CHECK(
dynamic_cast<const broken_connection *>(&e.base()),
"Downcast pqxx_exception is not a broken_connection");
pqxx::test::expected_exception(e.base().what());
PQXX_CHECK_EQUAL(
dynamic_cast<const broken_connection &>(e.base()).what(),
e.base().what(),
"Inconsistent what() message in exception.");
}
}
} // namespace
PQXX_REGISTER_TEST_NODB(test_000)
|