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();
204 std::snprintf(msg,
sizeof(msg),
"QChar: '%c' (0x%x)",
char(uc),
unsigned(uc));
207 return qstrdup(qPrintable(QString::fromLatin1(
"QChar: '%1' (0x%2)").arg(c).arg(QString::number(
static_cast<
int>(c.unicode()), 16))));
210#if QT_CONFIG(itemmodel)
217 static_cast<
const void*>(
idx.
model()));
226 std::snprintf(msg,
sizeof(msg),
"QPoint(%d,%d)", p.x(), p.y());
234 std::snprintf(msg,
sizeof(msg),
"QSize(%dx%d)", s.width(), s.height());
242 std::snprintf(msg,
sizeof(msg),
"QRect(%d,%d %dx%d) (bottomright %d,%d)",
243 s.left(), s.top(), s.width(), s.height(), s.right(), s.bottom());
251 std::snprintf(msg,
sizeof(msg),
"QPointF(%g,%g)", p.x(), p.y());
259 std::snprintf(msg,
sizeof(msg),
"QSizeF(%gx%g)", s.width(), s.height());
267 std::snprintf(msg,
sizeof(msg),
"QRectF(%g,%g %gx%g) (bottomright %g,%g)",
268 s.left(), s.top(), s.width(), s.height(), s.right(), s.bottom());
275 return qstrdup(qPrintable(QLatin1StringView(
"Invalid URL: ") + uri.errorString()));
276 return qstrdup(uri.toEncoded().constData());
279template <>
inline char *
toString(
const QUuid &uuid)
281 return qstrdup(uuid.toByteArray().constData());
286 QByteArray vstring(
"QVariant(");
288 QByteArray type(v.typeName());
289 if (type.isEmpty()) {
290 type = QByteArray::number(v.userType());
292 vstring.append(type);
295 if (v.canConvert<QString>()) {
296 vstring.append(v.toString().toLocal8Bit());
299 vstring.append(
"<value not representable as string>");
305 return qstrdup(vstring.constData());
308template<>
inline char *
toString(
const QPartialOrdering &o)
310 if (o == QPartialOrdering::Less)
311 return qstrdup(
"Less");
312 if (o == QPartialOrdering::Equivalent)
313 return qstrdup(
"Equivalent");
314 if (o == QPartialOrdering::Greater)
315 return qstrdup(
"Greater");
316 if (o == QPartialOrdering::Unordered)
317 return qstrdup(
"Unordered");
318 return qstrdup(
"<invalid>");
326 enum { BufferLen = 256 };
328 static UP createBuffer() {
return q20::make_unique_for_overwrite<
char[]>(BufferLen); }
330 static UP formatSimpleType(QCborSimpleType st)
332 auto buf = createBuffer();
333 std::snprintf(buf.get(), BufferLen,
"QCborValue(QCborSimpleType(%d))",
int(st));
337 static UP formatTag(QCborTag tag,
const QCborValue &taggedValue)
339 auto buf = createBuffer();
340 const std::unique_ptr<
char[]> hold(format(taggedValue));
341 std::snprintf(buf.get(), BufferLen,
"QCborValue(QCborTag(%llu), %s)",
342 qToUnderlying(tag), hold.get());
346 static UP innerFormat(QCborValue::Type t,
const UP &str)
348 static const QMetaEnum typeEnum = []() {
349 int idx = QCborValue::staticMetaObject.indexOfEnumerator(
"Type");
350 return QCborValue::staticMetaObject.enumerator(idx);
353 auto buf = createBuffer();
354 const char *typeName = typeEnum.valueToKey(t);
356 std::snprintf(buf.get(), BufferLen,
"QCborValue(%s, %s)", typeName, str ? str.get() :
"");
358 std::snprintf(buf.get(), BufferLen,
"QCborValue(<unknown type 0x%02x>)", t);
362 template<
typename T>
static UP format(QCborValue::Type type,
const T &t)
364 const std::unique_ptr<
char[]> hold(
QTest::toString(t));
365 return innerFormat(type, hold);
373 case QCborValue::Integer:
374 return format(v.type(), v.toInteger());
375 case QCborValue::ByteArray:
376 return format(v.type(), v.toByteArray());
377 case QCborValue::String:
378 return format(v.type(), v.toString());
379 case QCborValue::Array:
380 return innerFormat(v.type(), format(v.toArray()));
381 case QCborValue::Map:
382 return innerFormat(v.type(), format(v.toMap()));
383 case QCborValue::Tag:
384 return formatTag(v.tag(), v.taggedValue());
385 case QCborValue::SimpleType:
387 case QCborValue::True:
388 return UP{qstrdup(
"QCborValue(true)")};
389 case QCborValue::False:
390 return UP{qstrdup(
"QCborValue(false)")};
391 case QCborValue::Null:
392 return UP{qstrdup(
"QCborValue(nullptr)")};
393 case QCborValue::Undefined:
394 return UP{qstrdup(
"QCborValue()")};
395 case QCborValue::Double:
396 return format(v.type(), v.toDouble());
397 case QCborValue::DateTime:
398 case QCborValue::Url:
399 case QCborValue::RegularExpression:
400 return format(v.type(), v.taggedValue().toString());
401 case QCborValue::Uuid:
402 return format(v.type(), v.toUuid());
403 case QCborValue::Invalid:
404 return UP{qstrdup(
"QCborValue(<invalid>)")};
407 if (v.isSimpleType())
408 return formatSimpleType(v.toSimpleType());
409 return innerFormat(v.type(),
nullptr);
414 QByteArray out(1,
'[');
415 const char *comma =
"";
416 for (QCborValueConstRef v : a) {
417 const std::unique_ptr<
char[]> s(format(v));
423 return UP{qstrdup(out.constData())};
428 QByteArray out(1,
'{');
429 const char *comma =
"";
430 for (
auto pair : m) {
431 const std::unique_ptr<
char[]> key(format(pair.first));
432 const std::unique_ptr<
char[]> value(format(pair.second));
440 return UP{qstrdup(out.constData())};
445template<>
inline char *
toString(
const QCborValue &v)
447 return Internal::QCborValueFormatter::format(v).release();
450template<>
inline char *
toString(
const QCborValueRef &v)
452 return toString(QCborValue(v));
455template<>
inline char *
toString(
const QCborArray &a)
457 return Internal::QCborValueFormatter::format(a).release();
462 return Internal::QCborValueFormatter::format(m).release();
478template <
typename T1,
typename T2>
479inline char *
toString(
const std::pair<T1, T2> &pair)
481 const std::unique_ptr<
char[]> first(toString(pair.first));
482 const std::unique_ptr<
char[]> second(toString(pair.second));
483 return formatString(
"std::pair(",
")", 2, first.get(), second.get());
486template <
typename Tuple,
std::size_t... I>
488 using UP = std::unique_ptr<
char[]>;
493 UP(toString(std::get<I>(tuple)))..., UP{}
495 return formatString(
"std::tuple(",
")",
sizeof...(I), data[I].get()...);
498template <
class... Types>
499inline char *
toString(
const std::tuple<Types...> &tuple)
501 return tupleToString(tuple, std::make_index_sequence<
sizeof...(Types)>{});
506 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)