summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/io/qdebug/tst_qdebug.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/corelib/io/qdebug/tst_qdebug.cpp')
-rw-r--r--tests/auto/corelib/io/qdebug/tst_qdebug.cpp603
1 files changed, 573 insertions, 30 deletions
diff --git a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp
index 9b9696d7c1..15da0758d0 100644
--- a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp
+++ b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp
@@ -1,31 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2016 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QtCore/QCoreApplication>
@@ -39,8 +14,23 @@
#include <QLine>
#include <QMimeType>
#include <QMimeDatabase>
+#include <QMetaType>
+
+#include <q20chrono.h>
+
+#ifdef __cpp_lib_memory_resource
+# include <memory_resource>
+namespace pmr = std::pmr;
+#else
+namespace pmr = std;
+#endif
+
+using namespace std::chrono;
+using namespace q20::chrono;
+using namespace Qt::StringLiterals;
static_assert(QTypeTraits::has_ostream_operator_v<QDebug, int>);
+static_assert(QTypeTraits::has_ostream_operator_v<QDebug, QMetaType>);
static_assert(QTypeTraits::has_ostream_operator_v<QDebug, QList<int>>);
static_assert(QTypeTraits::has_ostream_operator_v<QDebug, QMap<int, QString>>);
struct NonStreamable {};
@@ -52,6 +42,10 @@ struct ConvertsToQVariant {
};
static_assert(!QTypeTraits::has_ostream_operator_v<QDebug, ConvertsToQVariant>);
+#if defined(Q_OS_DARWIN)
+#include <objc/runtime.h>
+#include <Foundation/Foundation.h>
+#endif
class tst_QDebug: public QObject
{
@@ -75,19 +69,39 @@ private slots:
void stateSaver() const;
void veryLongWarningMessage() const;
void qDebugQChar() const;
+ void qDebugQMetaType() const;
void qDebugQString() const;
void qDebugQStringView() const;
void qDebugQUtf8StringView() const;
void qDebugQLatin1String() const;
+ void qDebugStdString() const;
+ void qDebugStdStringView() const;
+ void qDebugStdWString() const;
+ void qDebugStdWStringView() const;
+ void qDebugStdU8String() const;
+ void qDebugStdU8StringView() const;
+ void qDebugStdU16String() const;
+ void qDebugStdU16StringView() const;
+ void qDebugStdU32String() const;
+ void qDebugStdU32StringView() const;
void qDebugQByteArray() const;
void qDebugQByteArrayView() const;
void qDebugQFlags() const;
+ void qDebugStdChrono_data() const;
+ void qDebugStdChrono() const;
+ void qDebugStdOptional() const;
void textStreamModifiers() const;
void resetFormat() const;
void defaultMessagehandler() const;
void threadSafety() const;
void toString() const;
void noQVariantEndlessRecursion() const;
+#if defined(Q_OS_DARWIN)
+ void objcInCppMode_data() const;
+ void objcInCppMode() const;
+ void objcInObjcMode_data() const;
+ void objcInObjcMode() const;
+#endif
};
void tst_QDebug::assignment() const
@@ -305,11 +319,17 @@ void tst_QDebug::debugNoQuotes() const
MessageHandlerSetter mhs(myMessageHandler);
{
QDebug d = qDebug();
+ QVERIFY(d.quoteStrings());
d << QStringLiteral("Hello");
+ QVERIFY(d.quoteStrings());
d.noquote();
+ QVERIFY(!d.quoteStrings());
d << QStringLiteral("Hello");
+ QVERIFY(!d.quoteStrings());
d.quote();
+ QVERIFY(d.quoteStrings());
d << QStringLiteral("Hello");
+ QVERIFY(d.quoteStrings());
}
QCOMPARE(s_msg, QString::fromLatin1("\"Hello\" Hello \"Hello\""));
@@ -318,7 +338,7 @@ void tst_QDebug::debugNoQuotes() const
d << QChar('H');
d << QLatin1String("Hello");
d << QByteArray("Hello");
- d.noquote();
+ d.setQuoteStrings(false);
d << QChar('H');
d << QLatin1String("Hello");
d << QByteArray("Hello");
@@ -443,6 +463,25 @@ void tst_QDebug::qDebugQChar() const
}
+void tst_QDebug::qDebugQMetaType() const
+{
+ QString file, function;
+ int line = 0;
+ MessageHandlerSetter mhs(myMessageHandler);
+ {
+ QDebug d = qDebug();
+ d << QMetaType::fromType<int>() << QMetaType::fromType<QString>();
+ }
+#ifndef QT_NO_MESSAGELOGCONTEXT
+ file = __FILE__; line = __LINE__ - 4; function = Q_FUNC_INFO;
+#endif
+ QCOMPARE(s_msgType, QtDebugMsg);
+ QCOMPARE(s_msg, R"(QMetaType(int) QMetaType(QString))"_L1);
+ QCOMPARE(QString::fromLatin1(s_file), file);
+ QCOMPARE(s_line, line);
+ QCOMPARE(QString::fromLatin1(s_function), function);
+}
+
void tst_QDebug::qDebugQString() const
{
/* Use a basic string. */
@@ -639,6 +678,324 @@ void tst_QDebug::qDebugQLatin1String() const
QCOMPARE(s_msg, QString("\"\\nSm\\u00F8rg\\u00E5sbord\\\\\""));
}
+void tst_QDebug::qDebugStdString() const
+{
+ QString file, function;
+ int line = 0;
+ MessageHandlerSetter mhs(myMessageHandler);
+ {
+ QDebug d = qDebug();
+ d << pmr::string("foo") << std::string("") << std::string("barbaz", 3);
+ d.nospace().noquote() << std::string("baz");
+ }
+#ifndef QT_NO_MESSAGELOGCONTEXT
+ file = __FILE__; line = __LINE__ - 5; function = Q_FUNC_INFO;
+#endif
+ QCOMPARE(s_msgType, QtDebugMsg);
+ QCOMPARE(s_msg, QString::fromLatin1("\"foo\" \"\" \"bar\" baz"));
+ QCOMPARE(QString::fromLatin1(s_file), file);
+ QCOMPARE(s_line, line);
+ QCOMPARE(QString::fromLatin1(s_function), function);
+
+ /* simpler tests from now on */
+ std::string string("\"Hello\"");
+ qDebug() << string;
+ QCOMPARE(s_msg, QString("\"\\\"Hello\\\"\""));
+
+ qDebug().noquote().nospace() << string;
+ QCOMPARE(s_msg, QString::fromStdString(string));
+
+ qDebug().noquote().nospace() << qSetFieldWidth(8) << string;
+ QCOMPARE(s_msg, " " + QString::fromStdString(string));
+}
+
+void tst_QDebug::qDebugStdStringView() const
+{
+ QString file, function;
+ int line = 0;
+ MessageHandlerSetter mhs(myMessageHandler);
+ {
+ QDebug d = qDebug();
+ d << std::string_view("foo") << std::string_view("") << std::string_view("barbaz", 3);
+ d.nospace().noquote() << std::string_view("baz");
+ }
+#ifndef QT_NO_MESSAGELOGCONTEXT
+ file = __FILE__; line = __LINE__ - 5; function = Q_FUNC_INFO;
+#endif
+ QCOMPARE(s_msgType, QtDebugMsg);
+ QCOMPARE(s_msg, QString::fromLatin1("\"foo\" \"\" \"bar\" baz"));
+ QCOMPARE(QString::fromLatin1(s_file), file);
+ QCOMPARE(s_line, line);
+ QCOMPARE(QString::fromLatin1(s_function), function);
+
+ /* simpler tests from now on */
+ std::string_view string("\"Hello\"");
+ qDebug() << string;
+ QCOMPARE(s_msg, QString("\"\\\"Hello\\\"\""));
+
+ qDebug().noquote().nospace() << string;
+ QCOMPARE(s_msg, QString::fromStdString(std::string(string)));
+
+ qDebug().noquote().nospace() << qSetFieldWidth(8) << string;
+ QCOMPARE(s_msg, " " + QString::fromStdString(std::string(string)));
+}
+
+void tst_QDebug::qDebugStdWString() const
+{
+ QString file, function;
+ int line = 0;
+ MessageHandlerSetter mhs(myMessageHandler);
+ {
+ QDebug d = qDebug();
+ d << pmr::wstring(L"foo") << std::wstring(L"") << std::wstring(L"barbaz", 3);
+ d.nospace().noquote() << std::wstring(L"baz");
+ }
+#ifndef QT_NO_MESSAGELOGCONTEXT
+ file = __FILE__; line = __LINE__ - 5; function = Q_FUNC_INFO;
+#endif
+ QCOMPARE(s_msgType, QtDebugMsg);
+ QCOMPARE(s_msg, QString::fromLatin1("\"foo\" \"\" \"bar\" baz"));
+ QCOMPARE(QString::fromLatin1(s_file), file);
+ QCOMPARE(s_line, line);
+ QCOMPARE(QString::fromLatin1(s_function), function);
+
+ /* simpler tests from now on */
+ std::wstring string(L"\"Hello\"");
+ qDebug() << string;
+ QCOMPARE(s_msg, QString("\"\\\"Hello\\\"\""));
+
+ qDebug().noquote().nospace() << string;
+ QCOMPARE(s_msg, QString::fromStdWString(string));
+
+ qDebug().noquote().nospace() << qSetFieldWidth(8) << string;
+ QCOMPARE(s_msg, " " + QString::fromStdWString(string));
+}
+
+void tst_QDebug::qDebugStdWStringView() const
+{
+ QString file, function;
+ int line = 0;
+ MessageHandlerSetter mhs(myMessageHandler);
+ {
+ QDebug d = qDebug();
+ d << std::wstring_view(L"foo") << std::wstring_view(L"") << std::wstring_view(L"barbaz", 3);
+ d.nospace().noquote() << std::wstring_view(L"baz");
+ }
+#ifndef QT_NO_MESSAGELOGCONTEXT
+ file = __FILE__; line = __LINE__ - 5; function = Q_FUNC_INFO;
+#endif
+ QCOMPARE(s_msgType, QtDebugMsg);
+ QCOMPARE(s_msg, QString::fromLatin1("\"foo\" \"\" \"bar\" baz"));
+ QCOMPARE(QString::fromLatin1(s_file), file);
+ QCOMPARE(s_line, line);
+ QCOMPARE(QString::fromLatin1(s_function), function);
+
+ /* simpler tests from now on */
+ std::wstring_view string(L"\"Hello\"");
+ qDebug() << string;
+ QCOMPARE(s_msg, QString("\"\\\"Hello\\\"\""));
+
+ qDebug().noquote().nospace() << string;
+ QCOMPARE(s_msg, QString::fromStdWString(std::wstring(string)));
+
+ qDebug().noquote().nospace() << qSetFieldWidth(8) << string;
+ QCOMPARE(s_msg, " " + QString::fromStdWString(std::wstring(string)));
+}
+
+void tst_QDebug::qDebugStdU8String() const
+{
+#ifndef __cpp_lib_char8_t
+ QSKIP("This test requires C++20 char8_t support enabled in the compiler.");
+#else
+ QString file, function;
+ int line = 0;
+ MessageHandlerSetter mhs(myMessageHandler);
+ {
+ QDebug d = qDebug();
+ d << pmr::u8string(u8"foo") << std::u8string(u8"") << std::u8string(u8"barbaz", 3);
+ d.nospace().noquote() << std::u8string(u8"baz");
+ }
+#ifndef QT_NO_MESSAGELOGCONTEXT
+ file = __FILE__; line = __LINE__ - 5; function = Q_FUNC_INFO;
+#endif
+ QCOMPARE(s_msgType, QtDebugMsg);
+ QCOMPARE(s_msg, QString::fromLatin1("\"foo\" \"\" \"bar\" baz"));
+ QCOMPARE(QString::fromLatin1(s_file), file);
+ QCOMPARE(s_line, line);
+ QCOMPARE(QString::fromLatin1(s_function), function);
+
+ /* simpler tests from now on */
+ std::u8string string(u8"\"Hello\"");
+ qDebug() << string;
+ QCOMPARE(s_msg, QString("\"\\\"Hello\\\"\""));
+
+ qDebug().noquote().nospace() << string;
+ QCOMPARE(s_msg, QUtf8StringView(string).toString());
+
+ qDebug().noquote().nospace() << qSetFieldWidth(8) << string;
+ QCOMPARE(s_msg, " " + QUtf8StringView(string).toString());
+#endif // __cpp_lib_char8_t
+}
+
+void tst_QDebug::qDebugStdU8StringView() const
+{
+#ifndef __cpp_lib_char8_t
+ QSKIP("This test requires C++20 char8_t support enabled in the compiler.");
+#else
+ QString file, function;
+ int line = 0;
+ MessageHandlerSetter mhs(myMessageHandler);
+ {
+ QDebug d = qDebug();
+ d << std::u16string_view(u"foo") << std::u16string_view(u"") << std::u16string_view(u"barbaz", 3);
+ d.nospace().noquote() << std::u16string_view(u"baz");
+ }
+#ifndef QT_NO_MESSAGELOGCONTEXT
+ file = __FILE__; line = __LINE__ - 5; function = Q_FUNC_INFO;
+#endif
+ QCOMPARE(s_msgType, QtDebugMsg);
+ QCOMPARE(s_msg, QString::fromLatin1("\"foo\" \"\" \"bar\" baz"));
+ QCOMPARE(QString::fromLatin1(s_file), file);
+ QCOMPARE(s_line, line);
+ QCOMPARE(QString::fromLatin1(s_function), function);
+
+ /* simpler tests from now on */
+ std::u16string_view string(u"\"Hello\"");
+ qDebug() << string;
+ QCOMPARE(s_msg, QString("\"\\\"Hello\\\"\""));
+
+ qDebug().noquote().nospace() << string;
+ QCOMPARE(s_msg, QString::fromStdU16String(std::u16string(string)));
+
+ qDebug().noquote().nospace() << qSetFieldWidth(8) << string;
+ QCOMPARE(s_msg, " " + QString::fromStdU16String(std::u16string(string)));
+#endif // __cpp_lib_char8_t
+}
+
+void tst_QDebug::qDebugStdU16String() const
+{
+ QString file, function;
+ int line = 0;
+ MessageHandlerSetter mhs(myMessageHandler);
+ {
+ QDebug d = qDebug();
+ d << pmr::u16string(u"foo") << std::u16string(u"") << std::u16string(u"barbaz", 3);
+ d.nospace().noquote() << std::u16string(u"baz");
+ }
+#ifndef QT_NO_MESSAGELOGCONTEXT
+ file = __FILE__; line = __LINE__ - 5; function = Q_FUNC_INFO;
+#endif
+ QCOMPARE(s_msgType, QtDebugMsg);
+ QCOMPARE(s_msg, QString::fromLatin1("\"foo\" \"\" \"bar\" baz"));
+ QCOMPARE(QString::fromLatin1(s_file), file);
+ QCOMPARE(s_line, line);
+ QCOMPARE(QString::fromLatin1(s_function), function);
+
+ /* simpler tests from now on */
+ std::u16string string(u"\"Hello\"");
+ qDebug() << string;
+ QCOMPARE(s_msg, QString("\"\\\"Hello\\\"\""));
+
+ qDebug().noquote().nospace() << string;
+ QCOMPARE(s_msg, QString::fromStdU16String(string));
+
+ qDebug().noquote().nospace() << qSetFieldWidth(8) << string;
+ QCOMPARE(s_msg, " " + QString::fromStdU16String(string));
+}
+
+void tst_QDebug::qDebugStdU16StringView() const
+{
+ QString file, function;
+ int line = 0;
+ MessageHandlerSetter mhs(myMessageHandler);
+ {
+ QDebug d = qDebug();
+ d << std::u16string_view(u"foo") << std::u16string_view(u"") << std::u16string_view(u"barbaz", 3);
+ d.nospace().noquote() << std::u16string_view(u"baz");
+ }
+#ifndef QT_NO_MESSAGELOGCONTEXT
+ file = __FILE__; line = __LINE__ - 5; function = Q_FUNC_INFO;
+#endif
+ QCOMPARE(s_msgType, QtDebugMsg);
+ QCOMPARE(s_msg, QString::fromLatin1("\"foo\" \"\" \"bar\" baz"));
+ QCOMPARE(QString::fromLatin1(s_file), file);
+ QCOMPARE(s_line, line);
+ QCOMPARE(QString::fromLatin1(s_function), function);
+
+ /* simpler tests from now on */
+ std::u16string_view string(u"\"Hello\"");
+ qDebug() << string;
+ QCOMPARE(s_msg, QString("\"\\\"Hello\\\"\""));
+
+ qDebug().noquote().nospace() << string;
+ QCOMPARE(s_msg, QString::fromStdU16String(std::u16string(string)));
+
+ qDebug().noquote().nospace() << qSetFieldWidth(8) << string;
+ QCOMPARE(s_msg, " " + QString::fromStdU16String(std::u16string(string)));
+}
+
+void tst_QDebug::qDebugStdU32String() const
+{
+ QString file, function;
+ int line = 0;
+ MessageHandlerSetter mhs(myMessageHandler);
+ {
+ QDebug d = qDebug();
+ d << pmr::u32string(U"foo") << std::u32string(U"") << std::u32string(U"barbaz", 3);
+ d.nospace().noquote() << std::u32string(U"baz");
+ }
+#ifndef QT_NO_MESSAGELOGCONTEXT
+ file = __FILE__; line = __LINE__ - 5; function = Q_FUNC_INFO;
+#endif
+ QCOMPARE(s_msgType, QtDebugMsg);
+ QCOMPARE(s_msg, QString::fromLatin1("\"foo\" \"\" \"bar\" baz"));
+ QCOMPARE(QString::fromLatin1(s_file), file);
+ QCOMPARE(s_line, line);
+ QCOMPARE(QString::fromLatin1(s_function), function);
+
+ /* simpler tests from now on */
+ std::u32string string(U"\"Hello\"");
+ qDebug() << string;
+ QCOMPARE(s_msg, QString("\"\\\"Hello\\\"\""));
+
+ qDebug().noquote().nospace() << string;
+ QCOMPARE(s_msg, QString::fromStdU32String(string));
+
+ qDebug().noquote().nospace() << qSetFieldWidth(8) << string;
+ QCOMPARE(s_msg, " " + QString::fromStdU32String(string));
+}
+
+void tst_QDebug::qDebugStdU32StringView() const
+{
+ QString file, function;
+ int line = 0;
+ MessageHandlerSetter mhs(myMessageHandler);
+ {
+ QDebug d = qDebug();
+ d << std::u32string_view(U"foo") << std::u32string_view(U"") << std::u32string_view(U"barbaz", 3);
+ d.nospace().noquote() << std::u32string_view(U"baz");
+ }
+#ifndef QT_NO_MESSAGELOGCONTEXT
+ file = __FILE__; line = __LINE__ - 5; function = Q_FUNC_INFO;
+#endif
+ QCOMPARE(s_msgType, QtDebugMsg);
+ QCOMPARE(s_msg, QString::fromLatin1("\"foo\" \"\" \"bar\" baz"));
+ QCOMPARE(QString::fromLatin1(s_file), file);
+ QCOMPARE(s_line, line);
+ QCOMPARE(QString::fromLatin1(s_function), function);
+
+ /* simpler tests from now on */
+ std::u32string_view string(U"\"Hello\"");
+ qDebug() << string;
+ QCOMPARE(s_msg, QString("\"\\\"Hello\\\"\""));
+
+ qDebug().noquote().nospace() << string;
+ QCOMPARE(s_msg, QString::fromStdU32String(std::u32string(string)));
+
+ qDebug().noquote().nospace() << qSetFieldWidth(8) << string;
+ QCOMPARE(s_msg, " " + QString::fromStdU32String(std::u32string(string)));
+}
+
void tst_QDebug::qDebugQByteArray() const
{
QString file, function;
@@ -758,6 +1115,129 @@ void tst_QDebug::qDebugQFlags() const
QCOMPARE(s_msg, QString::fromLatin1("QFlags<tst_QDebug::FlagType>(EnumFlag1)"));
}
+using ToStringFunction = std::function<QString()>;
+void tst_QDebug::qDebugStdChrono_data() const
+{
+ using attoseconds = duration<int64_t, std::atto>;
+ using femtoseconds = duration<int64_t, std::femto>;
+ using picoseconds = duration<int64_t, std::pico>;
+ using centiseconds = duration<int64_t, std::centi>;
+ using deciseconds = duration<int64_t, std::deci>;
+
+ using quadriennia = duration<int, std::ratio_multiply<std::ratio<4>, years::period>>;
+ using decades = duration<int, std::ratio_multiply<years::period, std::deca>>; // decayears
+ using centuries = duration<int16_t, std::ratio_multiply<years::period, std::hecto>>; // hectoyears
+ using millennia = duration<int16_t, std::ratio_multiply<years::period, std::kilo>>; // kiloyears
+ using gigayears = duration<int8_t, std::ratio_multiply<years::period, std::giga>>;
+ using fortnights = duration<int, std::ratio_multiply<days::period, std::ratio<14>>>;
+ using microfortnights = duration<int64_t, std::ratio_multiply<fortnights::period, std::micro>>;
+ using telecom = duration<int64_t, std::ratio<1, 8000>>; // 8 kHz
+
+ using kiloseconds = duration<int64_t, std::kilo>;
+ using exaseconds = duration<int8_t, std::exa>;
+ using meter_per_light = duration<int64_t, std::ratio<1, 299'792'458>>;
+ using kilometer_per_light = duration<int64_t, std::ratio<1000, 299'792'458>>;
+
+ QTest::addColumn<ToStringFunction>("fn");
+ QTest::addColumn<QString>("expected");
+
+ auto addRow = [](const char *name, auto duration, const char *expected) {
+ auto toString = [duration]() { return QDebug::toString(duration); };
+ QTest::newRow(name) << ToStringFunction(toString) << expected;
+ };
+
+ addRow("1as", attoseconds{1}, "1as");
+ addRow("1fs", femtoseconds{1}, "1fs");
+ addRow("1ps", picoseconds{1}, "1ps");
+ addRow("0ns", 0ns, "0ns");
+ addRow("1000ns", 1000ns, "1000ns");
+ addRow("0us", 0us, "0us");
+ addRow("0ms", 0ms, "0ms");
+ addRow("1cs", centiseconds{1}, "1cs");
+ addRow("2ds", deciseconds{2}, "2ds");
+ addRow("-1s", -1s, "-1s");
+ addRow("0s", 0s, "0s");
+ addRow("1s", 1s, "1s");
+ addRow("60s", 60s, "60s");
+ addRow("1min", 1min, "1min");
+ addRow("1h", 1h, "1h");
+ addRow("1days", days{1}, "1d");
+ addRow("365days", days{365}, "365d");
+ addRow("1weeks", weeks{1}, "1wk");
+ addRow("1years", years{1}, "1yr"); // 365.2425 days
+ addRow("42years", years{42}, "42yr");
+
+ addRow("1ks", kiloseconds{1}, "1[1000]s");
+ addRow("2fortnights", fortnights{2}, "2[2]wk");
+ addRow("1quadriennia", quadriennia{1}, "1[4]yr");
+ addRow("1decades", decades{1}, "1[10]yr");
+ addRow("1centuries", centuries{1}, "1[100]yr");
+ addRow("1millennia", millennia{1}, "1[1000]yr");
+#if defined(Q_OS_LINUX) || defined(Q_OS_DARWIN)
+ // some OSes print the exponent differently
+ addRow("1Es", exaseconds{1}, "1[1e+18]s");
+ addRow("13gigayears", gigayears{13}, "13[1e+09]yr");
+#endif
+
+ // months are one twelfth of a Gregorian year, not 30 days
+ addRow("1months", months{1}, "1[2629746]s");
+
+ // weird units
+ addRow("2microfortnights", microfortnights{2}, "2[756/625]s");
+ addRow("1telecom", telecom{1}, "1[1/8000]s");
+ addRow("10m/c", meter_per_light{10}, "10[1/299792458]s");
+ addRow("10km/c", kilometer_per_light{10}, "10[500/149896229]s");
+
+ // real floting point
+ using fpsec = duration<double>;
+ using fpmsec = duration<double, std::milli>;
+ using fpnsec = duration<double, std::nano>;
+ addRow("1.0s", fpsec{1}, "1s");
+ addRow("1.5s", fpsec{1.5}, "1.5s");
+ addRow("1.0ms", fpmsec{1}, "1ms");
+ addRow("1.5ms", fpmsec{1.5}, "1.5ms");
+ addRow("1.0ns", fpnsec{1}, "1ns");
+ addRow("1.5ns", fpnsec{1.5}, "1.5ns");
+
+ // and some precision setting too
+ QTest::newRow("1.00000ns")
+ << ToStringFunction([]() {
+ QString buffer;
+ QDebug d(&buffer);
+ d.nospace() << qSetRealNumberPrecision(5) << Qt::fixed << fpnsec{1};
+ return buffer;
+ }) << "1.00000ns";
+}
+
+void tst_QDebug::qDebugStdChrono() const
+{
+ QFETCH(ToStringFunction, fn);
+ QFETCH(QString, expected);
+ QCOMPARE(fn(), expected);
+}
+
+void tst_QDebug::qDebugStdOptional() const
+{
+ QString file, function;
+ int line = 0;
+ MessageHandlerSetter mhs(myMessageHandler);
+ {
+ std::optional<QByteArray> notSet = std::nullopt;
+ std::optional<QByteArray> set("foo");
+ auto no = std::nullopt;
+ QDebug d = qDebug();
+ d << notSet << set << no;
+ }
+#ifndef QT_NO_MESSAGELOGCONTEXT
+ file = __FILE__; line = __LINE__ - 4; function = Q_FUNC_INFO;
+#endif
+ QCOMPARE(s_msgType, QtDebugMsg);
+ QCOMPARE(s_msg, QString::fromLatin1("nullopt std::optional(\"foo\") nullopt"));
+ QCOMPARE(QString::fromLatin1(s_file), file);
+ QCOMPARE(s_line, line);
+ QCOMPARE(QString::fromLatin1(s_function), function);
+}
+
void tst_QDebug::textStreamModifiers() const
{
QString file, function;
@@ -837,7 +1317,7 @@ void tst_QDebug::threadSafety() const
s_sema.release(numThreads);
sync.waitForFinished();
QMutexLocker lock(&s_mutex);
- QCOMPARE(s_messages.count(), numThreads);
+ QCOMPARE(s_messages.size(), numThreads);
for (int i = 0; i < numThreads; ++i) {
QCOMPARE(s_messages.at(i), QStringLiteral("doDebug"));
}
@@ -873,6 +1353,69 @@ void tst_QDebug::noQVariantEndlessRecursion() const
qDebug() << var;
}
+#if defined(Q_OS_DARWIN)
+
+@interface MyObjcClass : NSObject
+@end
+
+@implementation MyObjcClass : NSObject
+- (NSString *)description
+{
+ return @"MyObjcClass is the best";
+}
+@end
+
+void tst_QDebug::objcInCppMode_data() const
+{
+ QTest::addColumn<objc_object *>("object");
+ QTest::addColumn<QString>("message");
+
+ QTest::newRow("nil") << static_cast<objc_object*>(nullptr) << QString::fromLatin1("(null)");
+
+ // Not an NSObject subclass
+ auto *nsproxy = reinterpret_cast<objc_object *>(class_createInstance(objc_getClass("NSProxy"), 0));
+ QTest::newRow("NSProxy") << nsproxy << QString::fromLatin1("<NSProxy: 0x%1>").arg(uintptr_t(nsproxy), 1, 16);
+
+ // Plain NSObject
+ auto *nsobject = reinterpret_cast<objc_object *>(class_createInstance(objc_getClass("NSObject"), 0));
+ QTest::newRow("NSObject") << nsobject << QString::fromLatin1("<NSObject: 0x%1>").arg(uintptr_t(nsobject), 1, 16);
+
+ auto str = QString::fromLatin1("foo");
+ QTest::newRow("NSString") << reinterpret_cast<objc_object*>(str.toNSString()) << str;
+
+ // Custom debug description
+ QTest::newRow("MyObjcClass") << reinterpret_cast<objc_object*>([[MyObjcClass alloc] init])
+ << QString::fromLatin1("MyObjcClass is the best");
+}
+
+void tst_QDebug::objcInCppMode() const
+{
+ QFETCH(objc_object *, object);
+ QFETCH(QString, message);
+
+ MessageHandlerSetter mhs(myMessageHandler);
+ { qDebug() << object; }
+
+ QCOMPARE(s_msg, message);
+}
+
+void tst_QDebug::objcInObjcMode_data() const
+{
+ objcInCppMode_data();
+}
+
+void tst_QDebug::objcInObjcMode() const
+{
+ QFETCH(objc_object *, object);
+ QFETCH(QString, message);
+
+ MessageHandlerSetter mhs(myMessageHandler);
+ { qDebug() << static_cast<id>(object); }
+
+ QCOMPARE(s_msg, message);
+}
+#endif
+
// Should compile: instentiation of unrelated operator<< should not cause cause compilation
// error in QDebug operators (QTBUG-47375)
class TestClassA {};