8#include <QtTest/qttestglobal.h>
10#include <QtCore/qttypetraits.h>
12#if QT_CONFIG(itemmodel)
13# include <QtCore/qabstractitemmodel.h>
15#include <QtCore/qbitarray.h>
16#include <QtCore/qbytearray.h>
17#include <QtCore/qcborarray.h>
18#include <QtCore/qcborcommon.h>
19#include <QtCore/qcbormap.h>
20#include <QtCore/qcborvalue.h>
21#include <QtCore/qdebug.h>
22#include <QtCore/qdatetime.h>
23#include <QtCore/qmetaobject.h>
24#include <QtCore/qmetatype.h>
25#include <QtCore/qobject.h>
26#include <QtCore/qpoint.h>
27#include <QtCore/qrect.h>
28#include <QtCore/qsize.h>
29#include <QtCore/qstring.h>
30#include <QtCore/qstringlist.h>
31#include <QtCore/qurl.h>
32#include <QtCore/quuid.h>
33#include <QtCore/qvariant.h>
36#include <QtCore/q20memory.h>
60#ifndef QT_NO_DEBUG_STREAM
65 "Built-in type must implement debug streaming operator "
66 "or provide QTest::toString specialization");
91 const char *expected,
const char *file,
int line);
100 return Internal::toString(t);
103template <
typename T1,
typename T2>
104inline char *
toString(
const std::pair<T1, T2> &pair);
106template <
class... Types>
107inline char *
toString(
const std::tuple<Types...> &tuple);
117#define QTEST_COMPARE_DECL(KLASS)
118 template<> Q_TESTLIB_EXPORT char *toString<KLASS >(const KLASS &);
137#undef QTEST_COMPARE_DECL
139template <>
inline char *
toString(
const QStringView &str)
141 return QTest::toPrettyUnicode(str);
144template<>
inline char *
toString(
const QString &str)
146 return toString(QStringView(str));
149template<>
inline char *
toString(
const QLatin1StringView &str)
151 return toString(QString(str));
154template<>
inline char *
toString(
const QByteArray &ba)
156 return QTest::toPrettyCString(ba.constData(), ba.size());
159template<>
inline char *
toString(
const QBitArray &ba)
161 qsizetype size = ba.size();
162 char *str =
new char[size + 1];
163 for (qsizetype i = 0; i < size; ++i)
164 str[i] =
"01"[ba.testBit(i)];
169#if QT_CONFIG(datestring)
188 :
qstrdup(
"Invalid QDateTime");
192template<>
inline char *
toString(
const QCborError &c)
195 return toString(c.c);
200 const ushort uc = c.unicode();
203 std::snprintf(msg,
sizeof(msg),
"QChar: '%c' (0x%x)",
char(uc),
unsigned(uc));
206 return qstrdup(qPrintable(QString::fromLatin1(
"QChar: '%1' (0x%2)").arg(c).arg(QString::number(
static_cast<
int>(c.unicode()), 16))));
209#if QT_CONFIG(itemmodel)
215 static_cast<
const void*>(
idx.
model()));
223 std::snprintf(msg,
sizeof(msg),
"QPoint(%d,%d)", p.x(), p.y());
230 std::snprintf(msg,
sizeof(msg),
"QSize(%dx%d)", s.width(), s.height());
237 std::snprintf(msg,
sizeof(msg),
"QRect(%d,%d %dx%d) (bottomright %d,%d)",
238 s.left(), s.top(), s.width(), s.height(), s.right(), s.bottom());
245 std::snprintf(msg,
sizeof(msg),
"QPointF(%g,%g)", p.x(), p.y());
252 std::snprintf(msg,
sizeof(msg),
"QSizeF(%gx%g)", s.width(), s.height());
259 std::snprintf(msg,
sizeof(msg),
"QRectF(%g,%g %gx%g) (bottomright %g,%g)",
260 s.left(), s.top(), s.width(), s.height(), s.right(), s.bottom());
267 return qstrdup(qPrintable(QLatin1StringView(
"Invalid URL: ") + uri.errorString()));
268 return qstrdup(uri.toEncoded().constData());
271template <>
inline char *
toString(
const QUuid &uuid)
273 return qstrdup(uuid.toByteArray().constData());
278 QByteArray vstring(
"QVariant(");
280 QByteArray type(v.typeName());
281 if (type.isEmpty()) {
282 type = QByteArray::number(v.userType());
284 vstring.append(type);
287 if (v.canConvert<QString>()) {
288 vstring.append(v.toString().toLocal8Bit());
291 vstring.append(
"<value not representable as string>");
297 return qstrdup(vstring.constData());
300template<>
inline char *
toString(
const QPartialOrdering &o)
302 if (o == QPartialOrdering::Less)
303 return qstrdup(
"Less");
304 if (o == QPartialOrdering::Equivalent)
305 return qstrdup(
"Equivalent");
306 if (o == QPartialOrdering::Greater)
307 return qstrdup(
"Greater");
308 if (o == QPartialOrdering::Unordered)
309 return qstrdup(
"Unordered");
310 return qstrdup(
"<invalid>");
318 enum { BufferLen = 256 };
320 static UP createBuffer() {
return q20::make_unique_for_overwrite<
char[]>(BufferLen); }
322 static UP formatSimpleType(QCborSimpleType st)
324 auto buf = createBuffer();
325 std::snprintf(buf.get(), BufferLen,
"QCborValue(QCborSimpleType(%d))",
int(st));
329 static UP formatTag(QCborTag tag,
const QCborValue &taggedValue)
331 auto buf = createBuffer();
332 const std::unique_ptr<
char[]> hold(format(taggedValue));
333 std::snprintf(buf.get(), BufferLen,
"QCborValue(QCborTag(%llu), %s)",
334 qToUnderlying(tag), hold.get());
338 static UP innerFormat(QCborValue::Type t,
const UP &str)
340 static const QMetaEnum typeEnum = []() {
341 int idx = QCborValue::staticMetaObject.indexOfEnumerator(
"Type");
342 return QCborValue::staticMetaObject.enumerator(idx);
345 auto buf = createBuffer();
346 const char *typeName = typeEnum.valueToKey(t);
348 std::snprintf(buf.get(), BufferLen,
"QCborValue(%s, %s)", typeName, str ? str.get() :
"");
350 std::snprintf(buf.get(), BufferLen,
"QCborValue(<unknown type 0x%02x>)", t);
354 template<
typename T>
static UP format(QCborValue::Type type,
const T &t)
356 const std::unique_ptr<
char[]> hold(
QTest::toString(t));
357 return innerFormat(type, hold);
365 case QCborValue::Integer:
366 return format(v.type(), v.toInteger());
367 case QCborValue::ByteArray:
368 return format(v.type(), v.toByteArray());
369 case QCborValue::String:
370 return format(v.type(), v.toString());
371 case QCborValue::Array:
372 return innerFormat(v.type(), format(v.toArray()));
373 case QCborValue::Map:
374 return innerFormat(v.type(), format(v.toMap()));
375 case QCborValue::Tag:
376 return formatTag(v.tag(), v.taggedValue());
377 case QCborValue::SimpleType:
379 case QCborValue::True:
380 return UP{qstrdup(
"QCborValue(true)")};
381 case QCborValue::False:
382 return UP{qstrdup(
"QCborValue(false)")};
383 case QCborValue::Null:
384 return UP{qstrdup(
"QCborValue(nullptr)")};
385 case QCborValue::Undefined:
386 return UP{qstrdup(
"QCborValue()")};
387 case QCborValue::Double:
388 return format(v.type(), v.toDouble());
389 case QCborValue::DateTime:
390 case QCborValue::Url:
391 case QCborValue::RegularExpression:
392 return format(v.type(), v.taggedValue().toString());
393 case QCborValue::Uuid:
394 return format(v.type(), v.toUuid());
395 case QCborValue::Invalid:
396 return UP{qstrdup(
"QCborValue(<invalid>)")};
399 if (v.isSimpleType())
400 return formatSimpleType(v.toSimpleType());
401 return innerFormat(v.type(),
nullptr);
406 QByteArray out(1,
'[');
407 const char *comma =
"";
408 for (QCborValueConstRef v : a) {
409 const std::unique_ptr<
char[]> s(format(v));
415 return UP{qstrdup(out.constData())};
420 QByteArray out(1,
'{');
421 const char *comma =
"";
422 for (
auto pair : m) {
423 const std::unique_ptr<
char[]> key(format(pair.first));
424 const std::unique_ptr<
char[]> value(format(pair.second));
432 return UP{qstrdup(out.constData())};
437template<>
inline char *
toString(
const QCborValue &v)
439 return Internal::QCborValueFormatter::format(v).release();
442template<>
inline char *
toString(
const QCborValueRef &v)
444 return toString(QCborValue(v));
447template<>
inline char *
toString(
const QCborArray &a)
449 return Internal::QCborValueFormatter::format(a).release();
454 return Internal::QCborValueFormatter::format(m).release();
470template <
typename T1,
typename T2>
471inline char *
toString(
const std::pair<T1, T2> &pair)
473 const std::unique_ptr<
char[]> first(toString(pair.first));
474 const std::unique_ptr<
char[]> second(toString(pair.second));
475 return formatString(
"std::pair(",
")", 2, first.get(), second.get());
478template <
typename Tuple,
std::size_t... I>
480 using UP = std::unique_ptr<
char[]>;
485 UP(toString(std::get<I>(tuple)))..., UP{}
487 return formatString(
"std::tuple(",
")",
sizeof...(I), data[I].get()...);
490template <
class... Types>
491inline char *
toString(
const std::tuple<Types...> &tuple)
493 return tupleToString(tuple, std::make_index_sequence<
sizeof...(Types)>{});
498 return toString(QStringView(u"nullptr"));
Q_TESTLIB_EXPORT char * toString(const char *)
Q_TESTLIB_EXPORT char * toString(const volatile QObject *)
char * toString(const std::pair< T1, T2 > &pair)
char * toString(const T &t)
Q_TESTLIB_EXPORT char * toString(const volatile void *)
char * toString(std::nullptr_t)
char * toString(const MyPoint &point)
char * tupleToString(const Tuple &tuple, std::index_sequence< I... >)
char * formatString(const char *prefix, const char *suffix, size_t numArguments,...)
char * toPrettyCString(const char *p, qsizetype length)
char * toHexRepresentation(const char *ba, qsizetype length)
Returns a pointer to a string that is the string ba represented as a space-separated sequence of hex ...
Q_TESTLIB_EXPORT bool compare_string_helper(const char *t1, const char *t2, const char *actual, const char *expected, const char *file, int line)
char * toString(std::chrono::duration< Rep, Period > duration)
Q_TESTLIB_EXPORT char * toString(const QObject *)
char * toPrettyUnicode(QStringView string)
char * toString(const std::tuple< Types... > &tuple)
#define QTEST_COMPARE_DECL(KLASS)