diff options
48 files changed, 776 insertions, 544 deletions
diff --git a/examples/network/loopback/dialog.cpp b/examples/network/loopback/dialog.cpp index 99317b9c77..b4e6b0fd5e 100644 --- a/examples/network/loopback/dialog.cpp +++ b/examples/network/loopback/dialog.cpp @@ -48,11 +48,11 @@ ** ****************************************************************************/ -#include <QtWidgets> -#include <QtNetwork> - #include "dialog.h" +#include <QtNetwork> +#include <QtWidgets> + static const int TotalBytes = 50 * 1024 * 1024; static const int PayloadSize = 64 * 1024; // 64 KB @@ -71,15 +71,15 @@ Dialog::Dialog(QWidget *parent) buttonBox->addButton(startButton, QDialogButtonBox::ActionRole); buttonBox->addButton(quitButton, QDialogButtonBox::RejectRole); - connect(startButton, SIGNAL(clicked()), this, SLOT(start())); - connect(quitButton, SIGNAL(clicked()), this, SLOT(close())); - connect(&tcpServer, SIGNAL(newConnection()), - this, SLOT(acceptConnection())); - connect(&tcpClient, SIGNAL(connected()), this, SLOT(startTransfer())); - connect(&tcpClient, SIGNAL(bytesWritten(qint64)), - this, SLOT(updateClientProgress(qint64))); - connect(&tcpClient, SIGNAL(error(QAbstractSocket::SocketError)), - this, SLOT(displayError(QAbstractSocket::SocketError))); + connect(startButton, &QAbstractButton::clicked, this, &Dialog::start); + connect(quitButton, &QAbstractButton::clicked, this, &QWidget::close); + connect(&tcpServer, &QTcpServer::newConnection, + this, &Dialog::acceptConnection); + connect(&tcpClient, &QAbstractSocket::connected, this, &Dialog::startTransfer); + connect(&tcpClient, &QIODevice::bytesWritten, + this, &Dialog::updateClientProgress); + connect(&tcpClient, QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::error), + this, &Dialog::displayError); QVBoxLayout *mainLayout = new QVBoxLayout; mainLayout->addWidget(clientProgressBar); @@ -124,10 +124,18 @@ void Dialog::start() void Dialog::acceptConnection() { tcpServerConnection = tcpServer.nextPendingConnection(); - connect(tcpServerConnection, SIGNAL(readyRead()), - this, SLOT(updateServerProgress())); - connect(tcpServerConnection, SIGNAL(error(QAbstractSocket::SocketError)), - this, SLOT(displayError(QAbstractSocket::SocketError))); + if (!tcpServerConnection) { + serverStatusLabel->setText(tr("Error: got invalid pending connection!")); + return; + } + + connect(tcpServerConnection, &QIODevice::readyRead, + this, &Dialog::updateServerProgress); + connect(tcpServerConnection, + QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::error), + this, &Dialog::displayError); + connect(tcpServerConnection, &QTcpSocket::disconnected, + tcpServerConnection, &QTcpSocket::deleteLater); serverStatusLabel->setText(tr("Accepted connection")); tcpServer.close(); @@ -136,13 +144,13 @@ void Dialog::acceptConnection() void Dialog::startTransfer() { // called when the TCP client connected to the loopback server - bytesToWrite = TotalBytes - (int)tcpClient.write(QByteArray(PayloadSize, '@')); + bytesToWrite = TotalBytes - int(tcpClient.write(QByteArray(PayloadSize, '@'))); clientStatusLabel->setText(tr("Connected")); } void Dialog::updateServerProgress() { - bytesReceived += (int)tcpServerConnection->bytesAvailable(); + bytesReceived += int(tcpServerConnection->bytesAvailable()); tcpServerConnection->readAll(); serverProgressBar->setMaximum(TotalBytes); @@ -161,17 +169,16 @@ void Dialog::updateServerProgress() void Dialog::updateClientProgress(qint64 numBytes) { - // callen when the TCP client has written some bytes - bytesWritten += (int)numBytes; + // called when the TCP client has written some bytes + bytesWritten += int(numBytes); // only write more if not finished and when the Qt write buffer is below a certain size. - if (bytesToWrite > 0 && tcpClient.bytesToWrite() <= 4*PayloadSize) - bytesToWrite -= (int)tcpClient.write(QByteArray(qMin(bytesToWrite, PayloadSize), '@')); + if (bytesToWrite > 0 && tcpClient.bytesToWrite() <= 4 * PayloadSize) + bytesToWrite -= tcpClient.write(QByteArray(qMin(bytesToWrite, PayloadSize), '@')); clientProgressBar->setMaximum(TotalBytes); clientProgressBar->setValue(bytesWritten); - clientStatusLabel->setText(tr("Sent %1MB") - .arg(bytesWritten / (1024 * 1024))); + clientStatusLabel->setText(tr("Sent %1MB").arg(bytesWritten / (1024 * 1024))); } void Dialog::displayError(QAbstractSocket::SocketError socketError) diff --git a/examples/network/loopback/dialog.h b/examples/network/loopback/dialog.h index b23cfa030b..a70c20550a 100644 --- a/examples/network/loopback/dialog.h +++ b/examples/network/loopback/dialog.h @@ -60,9 +60,6 @@ class QDialogButtonBox; class QLabel; class QProgressBar; class QPushButton; -class QTcpServer; -class QTcpSocket; -class QAction; QT_END_NAMESPACE class Dialog : public QDialog @@ -70,7 +67,7 @@ class Dialog : public QDialog Q_OBJECT public: - Dialog(QWidget *parent = 0); + Dialog(QWidget *parent = nullptr); public slots: void start(); @@ -81,21 +78,21 @@ public slots: void displayError(QAbstractSocket::SocketError socketError); private: - QProgressBar *clientProgressBar; - QProgressBar *serverProgressBar; - QLabel *clientStatusLabel; - QLabel *serverStatusLabel; + QProgressBar *clientProgressBar = nullptr; + QProgressBar *serverProgressBar = nullptr; + QLabel *clientStatusLabel = nullptr; + QLabel *serverStatusLabel = nullptr; - QPushButton *startButton; - QPushButton *quitButton; - QDialogButtonBox *buttonBox; + QPushButton *startButton = nullptr; + QPushButton *quitButton = nullptr; + QDialogButtonBox *buttonBox = nullptr; QTcpServer tcpServer; QTcpSocket tcpClient; - QTcpSocket *tcpServerConnection; - int bytesToWrite; - int bytesWritten; - int bytesReceived; + QTcpSocket *tcpServerConnection = nullptr; + int bytesToWrite = 0; + int bytesWritten = 0; + int bytesReceived = 0; }; #endif diff --git a/examples/network/loopback/main.cpp b/examples/network/loopback/main.cpp index 9959c472f4..094a11d4fc 100644 --- a/examples/network/loopback/main.cpp +++ b/examples/network/loopback/main.cpp @@ -48,10 +48,10 @@ ** ****************************************************************************/ -#include <QApplication> - #include "dialog.h" +#include <QApplication> + int main(int argc, char *argv[]) { QApplication app(argc, argv); diff --git a/qmake/generators/mac/pbuilder_pbx.cpp b/qmake/generators/mac/pbuilder_pbx.cpp index 57a1bff3a0..13d707a881 100644 --- a/qmake/generators/mac/pbuilder_pbx.cpp +++ b/qmake/generators/mac/pbuilder_pbx.cpp @@ -542,6 +542,10 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) QTextStream mkt(&mkf); writeHeader(mkt); mkt << "QMAKE = " << var("QMAKE_QMAKE") << endl; + project->values("QMAKE_MAKE_QMAKE_EXTRA_COMMANDS") + << "@echo 'warning: Xcode project has been regenerated, custom settings have been lost. " \ + "Use CONFIG+=no_autoqmake to prevent this behavior in the future, " \ + "at the cost of requiring manual project change tracking.'"; writeMakeQmake(mkt); mkt.flush(); mkf.close(); @@ -1878,33 +1882,28 @@ ProjectBuilderMakefileGenerator::keyFor(const QString &block) bool ProjectBuilderMakefileGenerator::openOutput(QFile &file, const QString &build) const { - if(QDir::isRelativePath(file.fileName())) - file.setFileName(Option::output_dir + "/" + file.fileName()); //pwd when qmake was run + Q_ASSERT_X(QDir::isRelativePath(file.fileName()), "ProjectBuilderMakefileGenerator", + "runQMake() should have normalized the filename and made it relative"); + QFileInfo fi(fileInfo(file.fileName())); - if(fi.suffix() != "pbxproj" || file.fileName().isEmpty()) { + if (fi.suffix() != "pbxproj") { QString output = file.fileName(); - if(fi.isDir()) - output += QDir::separator(); - if(!output.endsWith(projectSuffix())) { - if(file.fileName().isEmpty() || fi.isDir()) { - if(project->first("TEMPLATE") == "subdirs" || project->isEmpty("QMAKE_ORIG_TARGET")) + if (!output.endsWith(projectSuffix())) { + if (fi.fileName().isEmpty()) { + if (project->first("TEMPLATE") == "subdirs" || project->isEmpty("QMAKE_ORIG_TARGET")) output += fileInfo(project->projectFile()).baseName(); else output += project->first("QMAKE_ORIG_TARGET").toQString(); } output += projectSuffix() + QDir::separator(); - } else if(output[(int)output.length() - 1] != QDir::separator()) { + } else { output += QDir::separator(); } output += QString("project.pbxproj"); file.setFileName(output); - bool ret = UnixMakefileGenerator::openOutput(file, build); - ((ProjectBuilderMakefileGenerator*)this)->pbx_dir = Option::output_dir.section(Option::dir_sep, 0, -1); - Option::output_dir = pbx_dir.section(Option::dir_sep, 0, -2); - return ret; } - ((ProjectBuilderMakefileGenerator*)this)->pbx_dir = Option::output_dir; + pbx_dir = Option::output_dir + Option::dir_sep + file.fileName().section(Option::dir_sep, 0, 0); return UnixMakefileGenerator::openOutput(file, build); } diff --git a/qmake/generators/mac/pbuilder_pbx.h b/qmake/generators/mac/pbuilder_pbx.h index 1d5cbc538d..f92436c215 100644 --- a/qmake/generators/mac/pbuilder_pbx.h +++ b/qmake/generators/mac/pbuilder_pbx.h @@ -36,7 +36,7 @@ QT_BEGIN_NAMESPACE class ProjectBuilderMakefileGenerator : public UnixMakefileGenerator { bool writingUnixMakefileGenerator; - QString pbx_dir; + mutable QString pbx_dir; int pbuilderVersion() const; bool writeSubDirs(QTextStream &); bool writeMakeParts(QTextStream &); diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp index cec4892e1f..de75bcc569 100644 --- a/qmake/generators/makefile.cpp +++ b/qmake/generators/makefile.cpp @@ -2771,6 +2771,9 @@ MakefileGenerator::writeMakeQmake(QTextStream &t, bool noDummyQmakeAll) const ProStringList &included = escapeDependencyPaths(project->values("QMAKE_INTERNAL_INCLUDED_FILES")); t << included.join(QString(" \\\n\t\t")) << "\n\t" << qmake << endl; + const ProStringList &extraCommands = project->values("QMAKE_MAKE_QMAKE_EXTRA_COMMANDS"); + if (!extraCommands.isEmpty()) + t << "\t" << extraCommands.join(QString("\n\t")) << endl; for(int include = 0; include < included.size(); ++include) { const ProString &i = included.at(include); if(!i.isEmpty()) @@ -3164,54 +3167,31 @@ MakefileGenerator::specdir() bool MakefileGenerator::openOutput(QFile &file, const QString &build) const { - { - QString outdir; - if(!file.fileName().isEmpty()) { - if(QDir::isRelativePath(file.fileName())) - file.setFileName(Option::output_dir + "/" + file.fileName()); //pwd when qmake was run - QFileInfo fi(fileInfo(file.fileName())); - if(fi.isDir()) - outdir = file.fileName() + '/'; - } - if(!outdir.isEmpty() || file.fileName().isEmpty()) { - QString fname = "Makefile"; - if(!project->isEmpty("MAKEFILE")) - fname = project->first("MAKEFILE").toQString(); - file.setFileName(outdir + fname); - } - } - if(QDir::isRelativePath(file.fileName())) { - QString fname = Option::output_dir; //pwd when qmake was run - if(!fname.endsWith("/")) - fname += "/"; - fname += file.fileName(); - file.setFileName(fname); - } - if(!build.isEmpty()) + debug_msg(3, "asked to open output file '%s' in %s", + qPrintable(file.fileName()), qPrintable(Option::output_dir)); + + if (file.fileName().isEmpty()) { + file.setFileName(!project->isEmpty("MAKEFILE") + ? project->first("MAKEFILE").toQString() : "Makefile"); + } + + file.setFileName(QDir(Option::output_dir).absoluteFilePath(file.fileName())); + + if (!build.isEmpty()) file.setFileName(file.fileName() + "." + build); - if(project->isEmpty("QMAKE_MAKEFILE")) + + if (project->isEmpty("QMAKE_MAKEFILE")) project->values("QMAKE_MAKEFILE").append(file.fileName()); + + // Make required directories. Note that we do this based on the + // filename, not Option::output_dir, as the filename may include + // generator specific directories not included in output_dir. int slsh = file.fileName().lastIndexOf('/'); - if(slsh != -1) + if (slsh != -1) mkdir(file.fileName().left(slsh)); - if(file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) { - QFileInfo fi(fileInfo(Option::output.fileName())); - QString od; - if(fi.isSymLink()) - od = fileInfo(fi.readLink()).absolutePath(); - else - od = fi.path(); - od = QDir::fromNativeSeparators(od); - if(QDir::isRelativePath(od)) { - QString dir = Option::output_dir; - if (!dir.endsWith('/') && !od.isEmpty()) - dir += '/'; - od.prepend(dir); - } - Option::output_dir = od; - return true; - } - return false; + + debug_msg(3, "opening output file %s", qPrintable(file.fileName())); + return file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate); } QString diff --git a/qmake/generators/projectgenerator.cpp b/qmake/generators/projectgenerator.cpp index 073d315aab..27b7e9dfdc 100644 --- a/qmake/generators/projectgenerator.cpp +++ b/qmake/generators/projectgenerator.cpp @@ -473,18 +473,11 @@ ProjectGenerator::getWritableVar(const char *vk, bool) bool ProjectGenerator::openOutput(QFile &file, const QString &build) const { - QString outdir; - if(!file.fileName().isEmpty()) { - QFileInfo fi(fileInfo(file.fileName())); - if(fi.isDir()) - outdir = fi.path() + QDir::separator(); - } - if(!outdir.isEmpty() || file.fileName().isEmpty()) { - QString dir = qmake_getpwd(); - int s = dir.lastIndexOf('/'); - if(s != -1) - dir = dir.right(dir.length() - (s + 1)); - file.setFileName(outdir + dir + Option::pro_ext); + ProString fileName = file.fileName(); + if (!fileName.endsWith(Option::pro_ext)) { + if (fileName.isEmpty()) + fileName = fileInfo(Option::output_dir).fileName(); + file.setFileName(fileName + Option::pro_ext); } return MakefileGenerator::openOutput(file, build); } diff --git a/qmake/generators/win32/msvc_vcproj.cpp b/qmake/generators/win32/msvc_vcproj.cpp index 24d1657552..b812e3a326 100644 --- a/qmake/generators/win32/msvc_vcproj.cpp +++ b/qmake/generators/win32/msvc_vcproj.cpp @@ -1617,20 +1617,15 @@ QString VcprojGenerator::replaceExtraCompilerVariables( bool VcprojGenerator::openOutput(QFile &file, const QString &/*build*/) const { - QString outdir; - if(!file.fileName().isEmpty()) { - QFileInfo fi(fileInfo(file.fileName())); - if(fi.isDir()) - outdir = file.fileName() + QDir::separator(); - } - if(!outdir.isEmpty() || file.fileName().isEmpty()) { - ProString ext = project->first("VCPROJ_EXTENSION"); - if(project->first("TEMPLATE") == "vcsubdirs") - ext = project->first("VCSOLUTION_EXTENSION"); - ProString outputName = project->first("TARGET"); - if (!project->first("MAKEFILE").isEmpty()) - outputName = project->first("MAKEFILE"); - file.setFileName(outdir + outputName + ext); + ProString fileName = file.fileName(); + ProString extension = project->first("TEMPLATE") == "vcsubdirs" + ? project->first("VCSOLUTION_EXTENSION") : project->first("VCPROJ_EXTENSION"); + if (!fileName.endsWith(extension)) { + if (fileName.isEmpty()) { + fileName = !project->first("MAKEFILE").isEmpty() + ? project->first("MAKEFILE") : project->first("TARGET"); + } + file.setFileName(fileName + extension); } return Win32MakefileGenerator::openOutput(file, QString()); } diff --git a/qmake/main.cpp b/qmake/main.cpp index 85709dc9bf..316e4b494f 100644 --- a/qmake/main.cpp +++ b/qmake/main.cpp @@ -455,28 +455,22 @@ int runQMake(int argc, char **argv) QString oldpwd = qmake_getpwd(); Option::output_dir = oldpwd; //for now this is the output dir - if(Option::output.fileName() != "-") { + if (!Option::output.fileName().isEmpty() && Option::output.fileName() != "-") { + // The output 'filename', as given by the -o option, might include one + // or more directories, so we may need to rebase the output directory. QFileInfo fi(Option::output); - QString dir; - if(fi.isDir()) { - dir = fi.filePath(); - } else { - QString tmp_dir = fi.path(); - if(!tmp_dir.isEmpty() && QFile::exists(tmp_dir)) - dir = tmp_dir; - } -#ifdef Q_OS_MAC - if (fi.fileName().endsWith(QLatin1String(".pbxproj")) - && dir.endsWith(QLatin1String(".xcodeproj"))) - dir += QStringLiteral("/.."); -#endif - if(!dir.isNull() && dir != ".") - Option::output_dir = dir; - if (QDir::isRelativePath(Option::output_dir)) { - Option::output.setFileName(fi.fileName()); - Option::output_dir.prepend(oldpwd + QLatin1Char('/')); + + QDir dir(QDir::cleanPath(fi.isDir() ? fi.absoluteFilePath() : fi.absolutePath())); + + // Don't treat Xcode project directory as part of OUT_PWD + if (dir.dirName().endsWith(QLatin1String(".xcodeproj"))) { + // Note: we're intentionally not using cdUp(), as the dir may not exist + dir.setPath(QDir::cleanPath(dir.filePath(".."))); } - Option::output_dir = QDir::cleanPath(Option::output_dir); + + Option::output_dir = dir.path(); + QString absoluteFilePath = QDir::cleanPath(fi.absoluteFilePath()); + Option::output.setFileName(absoluteFilePath.mid(Option::output_dir.length() + 1)); } QMakeProperty prop; diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h index 9906425f5b..2b85ea0815 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -1153,9 +1153,17 @@ #endif #if defined(__cpp_enumerator_attributes) && __cpp_enumerator_attributes >= 201411 +#if defined(Q_CC_MSVC) +// Can't mark enum values as __declspec(deprecated) with MSVC, also can't move +// everything to [[deprecated]] because MSVC gives a compilation error when marking +// friend methods of a class as [[deprecated("text")]], breaking qstring.h +# define Q_DECL_ENUMERATOR_DEPRECATED [[deprecated]] +# define Q_DECL_ENUMERATOR_DEPRECATED_X(x) [[deprecated(x)]] +#else # define Q_DECL_ENUMERATOR_DEPRECATED Q_DECL_DEPRECATED # define Q_DECL_ENUMERATOR_DEPRECATED_X(x) Q_DECL_DEPRECATED_X(x) #endif +#endif /* * Fallback macros to certain compiler features diff --git a/src/corelib/global/qnumeric_p.h b/src/corelib/global/qnumeric_p.h index 5f8a124bcc..9c8514f5a3 100644 --- a/src/corelib/global/qnumeric_p.h +++ b/src/corelib/global/qnumeric_p.h @@ -163,6 +163,58 @@ Q_DECL_CONST_FUNCTION static inline bool qt_is_finite(float f) #ifndef Q_CLANG_QDOC namespace { +/*! + Returns true if the double \a v can be converted to type \c T, false if + it's out of range. If the conversion is successful, the converted value is + stored in \a value; if it was not successful, \a value will contain the + minimum or maximum of T, depending on the sign of \a d. If \c T is + unsigned, then \a value contains the absolute value of \a v. + + This function works for v containing infinities, but not NaN. It's the + caller's responsibility to exclude that possibility before calling it. +*/ +template <typename T> static inline bool convertDoubleTo(double v, T *value) +{ + Q_STATIC_ASSERT(std::numeric_limits<T>::is_integer); + + // The [conv.fpint] (7.10 Floating-integral conversions) section of the C++ + // standard says only exact conversions are guaranteed. Converting + // integrals to floating-point with loss of precision has implementation- + // defined behavior whether the next higher or next lower is returned; + // converting FP to integral is UB if it can't be represented. + // + // That means we can't write UINT64_MAX+1. Writing ldexp(1, 64) would be + // correct, but Clang, ICC and MSVC don't realize that it's a constant and + // the math call stays in the compiled code. + + double supremum; + if (std::numeric_limits<T>::is_signed) { + supremum = -1.0 * std::numeric_limits<T>::min(); // -1 * (-2^63) = 2^63, exact (for T = qint64) + *value = std::numeric_limits<T>::min(); + if (v < std::numeric_limits<T>::min()) + return false; + } else { + using ST = typename std::make_signed<T>::type; + supremum = -2.0 * std::numeric_limits<ST>::min(); // -2 * (-2^63) = 2^64, exact (for T = quint64) + v = fabs(v); + } + + *value = std::numeric_limits<T>::max(); + if (v >= supremum) + return false; + + // Now we can convert, these two conversions cannot be UB + *value = T(v); + +QT_WARNING_PUSH +QT_WARNING_DISABLE_GCC("-Wfloat-equal") +QT_WARNING_DISABLE_CLANG("-Wfloat-equal") + + return *value == v; + +QT_WARNING_POP +} + // Overflow math. // This provides efficient implementations for int, unsigned, qsizetype and // size_t. Implementations for 8- and 16-bit types will work but may not be as diff --git a/src/corelib/serialization/qcbordiagnostic.cpp b/src/corelib/serialization/qcbordiagnostic.cpp new file mode 100644 index 0000000000..8e641ff7cf --- /dev/null +++ b/src/corelib/serialization/qcbordiagnostic.cpp @@ -0,0 +1,281 @@ +/**************************************************************************** +** +** Copyright (C) 2018 Intel Corporation. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** 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-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qcborvalue.h" +#include "qcborvalue_p.h" + +#include "qcborarray.h" +#include "qcbormap.h" + +#include <private/qnumeric_p.h> +#include <qstack.h> + +QT_BEGIN_NAMESPACE + +namespace { +class DiagnosticNotation +{ +public: + static QString create(const QCborValue &v, QCborValue::DiagnosticNotationOptions opts) + { + DiagnosticNotation dn(opts); + dn.appendValue(v); + return dn.result; + } + +private: + QStack<int> byteArrayFormatStack; + QString separator; + QString result; + QCborValue::DiagnosticNotationOptions opts; + int nestingLevel = 0; + + struct Nest { + enum { IndentationWidth = 4 }; + DiagnosticNotation *dn; + Nest(DiagnosticNotation *that) : dn(that) + { + ++dn->nestingLevel; + static const char indent[IndentationWidth + 1] = " "; + if (dn->opts & QCborValue::LineWrapped) + dn->separator += QLatin1String(indent, IndentationWidth); + } + ~Nest() + { + --dn->nestingLevel; + if (dn->opts & QCborValue::LineWrapped) + dn->separator.chop(IndentationWidth); + } + }; + + DiagnosticNotation(QCborValue::DiagnosticNotationOptions opts_) + : separator(QLatin1String(opts_ & QCborValue::LineWrapped ? "\n" : "")), opts(opts_) + { + byteArrayFormatStack.push(int(QCborKnownTags::ExpectedBase16)); + } + + void appendString(const QString &s); + void appendArray(const QCborArray &a); + void appendMap(const QCborMap &m); + void appendValue(const QCborValue &v); +}; +} + +static QString makeFpString(double d) +{ + QString s; + quint64 v; + if (qt_is_inf(d)) { + s = (d < 0) ? QStringLiteral("-inf") : QStringLiteral("inf"); + } else if (qt_is_nan(d)) { + s = QStringLiteral("nan"); + } else if (convertDoubleTo(d, &v)) { + s = QString::fromLatin1("%1.0").arg(v); + if (d < 0) + s.prepend(QLatin1Char('-')); + } else { + s = QString::number(d, 'g', QLocale::FloatingPointShortest); + if (!s.contains(QLatin1Char('.')) && !s.contains('e')) + s += QLatin1Char('.'); + } + return s; +} + +static bool isByteArrayEncodingTag(QCborTag tag) +{ + switch (quint64(tag)) { + case quint64(QCborKnownTags::ExpectedBase16): + case quint64(QCborKnownTags::ExpectedBase64): + case quint64(QCborKnownTags::ExpectedBase64url): + return true; + } + return false; +} + +void DiagnosticNotation::appendString(const QString &s) +{ + result += QLatin1Char('"') + + QString(s) + .replace(QLatin1Char('\\'), QLatin1String("\\\\")) + .replace(QLatin1Char('"'), QLatin1String("\\\"")) + + QLatin1Char('"'); +} + +void DiagnosticNotation::appendArray(const QCborArray &a) +{ + result += QLatin1Char('['); + + // length 2 (including the space) when not line wrapping + QLatin1String commaValue(", ", opts & QCborValue::LineWrapped ? 1 : 2); + { + Nest n(this); + QLatin1String comma; + for (auto v : a) { + result += comma + separator; + comma = commaValue; + appendValue(v); + } + } + + result += separator + QLatin1Char(']'); +} + +void DiagnosticNotation::appendMap(const QCborMap &m) +{ + result += QLatin1Char('{'); + + // length 2 (including the space) when not line wrapping + QLatin1String commaValue(", ", opts & QCborValue::LineWrapped ? 1 : 2); + { + Nest n(this); + QLatin1String comma; + for (auto v : m) { + result += comma + separator; + comma = commaValue; + appendValue(v.first); + result += QLatin1String(": "); + appendValue(v.second); + } + } + + result += separator + QLatin1Char('}'); +}; + +void DiagnosticNotation::appendValue(const QCborValue &v) +{ + switch (v.type()) { + case QCborValue::Integer: + result += QString::number(v.toInteger()); + return; + case QCborValue::ByteArray: + switch (byteArrayFormatStack.top()) { + case int(QCborKnownTags::ExpectedBase16): + result += QString::fromLatin1("h'" + + v.toByteArray().toHex(opts & QCborValue::ExtendedFormat ? ' ' : '\0') + + '\''); + return; + case int(QCborKnownTags::ExpectedBase64): + result += QString::fromLatin1("b64'" + v.toByteArray().toBase64() + '\''); + return; + default: + case int(QCborKnownTags::ExpectedBase64url): + result += QString::fromLatin1("b64'" + + v.toByteArray().toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals) + + '\''); + return; + } + case QCborValue::String: + return appendString(v.toString()); + case QCborValue::Array: + return appendArray(v.toArray()); + case QCborValue::Map: + return appendMap(v.toMap()); + case QCborValue::False: + result += QLatin1String("false"); + return; + case QCborValue::True: + result += QLatin1String("true"); + return; + case QCborValue::Null: + result += QLatin1String("null"); + return; + case QCborValue::Undefined: + result += QLatin1String("undefined"); + return; + case QCborValue::Double: + result += makeFpString(v.toDouble()); + return; + case QCborValue::Invalid: + result += QStringLiteral("<invalid>"); + return; + + default: + // Only tags, extended types, and simple types remain; see below. + break; + } + + if (v.isTag()) { + // We handle all extended types as regular tags, so it won't matter + // whether we understand that tag or not. + bool byteArrayFormat = opts & QCborValue::ExtendedFormat && isByteArrayEncodingTag(v.tag()); + if (byteArrayFormat) + byteArrayFormatStack.push(int(v.tag())); + result += QString::number(quint64(v.tag())) + QLatin1Char('('); + appendValue(v.taggedValue()); + result += QLatin1Char(')'); + if (byteArrayFormat) + byteArrayFormatStack.pop(); + } else { + // must be a simple type + result += QString::fromLatin1("simple(%1)").arg(quint8(v.toSimpleType())); + } +} + +/*! + Creates the diagnostic notation equivalent of this CBOR object and returns + it. The \a opts parameter controls the dialect of the notation. Diagnostic + notation is useful in debugging, to aid the developer in understanding what + value is stored in the QCborValue or in a CBOR stream. For that reason, the + Qt API provides no support for parsing the diagnostic back into the + in-memory format or CBOR stream, though the representation is unique and it + would be possible. + + CBOR diagnostic notation is specified by + \l{https://tools.ietf.org/html/rfc7049#section-6}{section 6} of RFC 7049. + It is a text representation of the CBOR stream and it is very similar to + JSON, but it supports the CBOR types not found in JSON. The extended format + enabled by the \l{DiagnosticNotationOption}{ExtendedFormat} flag is + currently in some IETF drafts and its format is subject to change. + + This function produces the equivalent representation of the stream that + toCbor() would produce, without any transformation option provided there. + This also implies this function may not produce a representation of the + stream that was used to create the object, if it was created using + fromCbor(), as that function may have applied transformations. For a + high-fidelity notation of a stream, without transformation, see the \c + cbordump example. + + \sa toCbor(), toJsonDocument(), QJsonDocument::toJson() + */ +QString QCborValue::toDiagnosticNotation(DiagnosticNotationOptions opts) const +{ + return DiagnosticNotation::create(*this, opts); +} + +QT_END_NAMESPACE diff --git a/src/corelib/serialization/qcborvalue.cpp b/src/corelib/serialization/qcborvalue.cpp index 0ec84c12d1..4108418550 100644 --- a/src/corelib/serialization/qcborvalue.cpp +++ b/src/corelib/serialization/qcborvalue.cpp @@ -47,9 +47,7 @@ #include <qendian.h> #include <qlocale.h> #include <private/qnumeric_p.h> -#include <qscopedvaluerollback.h> #include <private/qsimd_p.h> -#include <qstack.h> #include <new> @@ -768,58 +766,6 @@ using namespace QtCbor; // in qcborstream.cpp extern void qt_cbor_stream_set_error(QCborStreamReaderPrivate *d, QCborError error); -/*! - Returns true if the double \a v can be converted to type \c T, false if - it's out of range. If the conversion is successful, the converted value is - stored in \a value; if it was not successful, \a value will contain the - minimum or maximum of T, depending on the sign of \a d. If \c T is - unsigned, then \a value contains the absolute value of \a v. - - This function works for v containing infinities, but not NaN. It's the - caller's responsibility to exclude that possibility before calling it. -*/ -template <typename T> static inline bool convertDoubleTo(double v, T *value) -{ - Q_STATIC_ASSERT(std::numeric_limits<T>::is_integer); - - // The [conv.fpint] (7.10 Floating-integral conversions) section of the C++ - // standard says only exact conversions are guaranteed. Converting - // integrals to floating-point with loss of precision has implementation- - // defined behavior whether the next higher or next lower is returned; - // converting FP to integral is UB if it can't be represented. - // - // That means we can't write UINT64_MAX+1. Writing ldexp(1, 64) would be - // correct, but only Clang, ICC and MSVC don't realize that it's a constant - // and the math call stays in the compiled code. - - double supremum; - if (std::numeric_limits<T>::is_signed) { - supremum = -1.0 * std::numeric_limits<T>::min(); // -1 * (-2^63) = 2^63, exact (for T = qint64) - *value = std::numeric_limits<T>::min(); - if (v < std::numeric_limits<T>::min()) - return false; - } else { - using ST = typename std::make_signed<T>::type; - supremum = -2.0 * std::numeric_limits<ST>::min(); // -2 * (-2^63) = 2^64, exact (for T = quint64) - v = fabs(v); - } - - *value = std::numeric_limits<T>::max(); - if (v >= supremum) - return false; - - // Now we can convert, these two conversions cannot be UB - *value = T(v); - -QT_WARNING_PUSH -QT_WARNING_DISABLE_GCC("-Wfloat-equal") -QT_WARNING_DISABLE_CLANG("-Wfloat-equal") - - return *value == v; - -QT_WARNING_POP -} - static void writeDoubleToCbor(QCborStreamWriter &writer, double d, QCborValue::EncodingOptions opt) { if (qt_is_nan(d)) { @@ -869,146 +815,6 @@ static inline int typeOrder(Element e1, Element e2) return comparable(e1) - comparable(e2); } -namespace { -class DiagnosticNotation -{ -public: - static QString create(const QCborValue &v, QCborValue::DiagnosticNotationOptions opts) - { - DiagnosticNotation dn(opts); - return dn.createFromValue(v); - } - -private: - QStack<int> byteArrayFormatStack; - QCborValue::DiagnosticNotationOptions opts; - int nestingLevel = 0; - - DiagnosticNotation(QCborValue::DiagnosticNotationOptions opts_) - : opts(opts_) - { - byteArrayFormatStack.push(int(QCborKnownTags::ExpectedBase16)); - } - - QString createFromValue(const QCborValue &v); -}; -} - -QString DiagnosticNotation::createFromValue(const QCborValue &v) -{ - QString indent(1, QLatin1Char(' ')); - QString indented = indent; - if (opts & QCborValue::LineWrapped) { - indent = QLatin1Char('\n') + QString(4 * nestingLevel, QLatin1Char(' ')); - indented = indent + QLatin1String(" "); - } - QScopedValueRollback<int> rollback(nestingLevel); - ++nestingLevel; - - auto createFromArray = [=](const QCborArray &a) { - QString result; - QLatin1String comma; - for (auto v : a) { - result += comma + indented + createFromValue(v); - comma = QLatin1String(","); - } - return result; - }; - auto createFromMap = [=](const QCborMap &m) { - QString result; - QLatin1String comma; - for (auto v : m) { - result += comma + indented + createFromValue(v.first) + - QLatin1String(": ") + createFromValue(v.second); - comma = QLatin1String(","); - } - return result; - }; - auto makeFpString = [](double d) { - QString s; - quint64 v; - if (qt_is_inf(d)) { - s = (d < 0) ? QStringLiteral("-inf") : QStringLiteral("inf"); - } else if (qt_is_nan(d)) { - s = QStringLiteral("nan"); - } else if (convertDoubleTo(d, &v)) { - s = QString::fromLatin1("%1.0").arg(v); - if (d < 0) - s.prepend(QLatin1Char('-')); - } else { - s = QString::number(d, 'g', QLocale::FloatingPointShortest); - if (!s.contains(QLatin1Char('.')) && !s.contains('e')) - s += QLatin1Char('.'); - } - return s; - }; - auto isByteArrayEncodingTag = [](QCborTag tag) { - switch (quint64(tag)) { - case quint64(QCborKnownTags::ExpectedBase16): - case quint64(QCborKnownTags::ExpectedBase64): - case quint64(QCborKnownTags::ExpectedBase64url): - return true; - } - return false; - }; - - switch (v.type()) { - case QCborValue::Integer: - return QString::number(v.toInteger()); - case QCborValue::ByteArray: - switch (byteArrayFormatStack.top()) { - case int(QCborKnownTags::ExpectedBase16): - return QString::fromLatin1("h'" + - v.toByteArray().toHex(opts & QCborValue::ExtendedFormat ? ' ' : '\0') + - '\''); - case int(QCborKnownTags::ExpectedBase64): - return QString::fromLatin1("b64'" + v.toByteArray().toBase64() + '\''); - default: - case int(QCborKnownTags::ExpectedBase64url): - return QString::fromLatin1("b64'" + - v.toByteArray().toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals) + - '\''); - } - case QCborValue::String: - // ### TODO: Needs escaping! - return QLatin1Char('"') + v.toString() + QLatin1Char('"'); - case QCborValue::Array: - return QLatin1Char('[') + createFromArray(v.toArray()) + indent + QLatin1Char(']'); - case QCborValue::Map: - return QLatin1Char('{') + createFromMap(v.toMap()) + indent + QLatin1Char('}'); - case QCborValue::False: - return QStringLiteral("false"); - case QCborValue::True: - return QStringLiteral("true"); - case QCborValue::Null: - return QStringLiteral("null"); - case QCborValue::Undefined: - return QStringLiteral("undefined"); - case QCborValue::Double: - return makeFpString(v.toDouble()); - case QCborValue::Invalid: - return QStringLiteral("<invalid>"); - - case QCborValue::Tag: - case QCborValue::SimpleType: - default: // tags and other simple types that are recognized - break; // are all handled below - } - - if (v.isTag()) { - bool byteArrayFormat = opts & QCborValue::ExtendedFormat && isByteArrayEncodingTag(v.tag()); - if (byteArrayFormat) - byteArrayFormatStack.push(int(v.tag())); - QString result = QString::fromLatin1("%1(%2)").arg(quint64(v.tag())).arg(createFromValue(v.taggedValue())); - if (byteArrayFormat) - byteArrayFormatStack.pop(); - return result; - } - - // must be a simple type - return QString::fromLatin1("simple(%1)").arg(quint8(v.toSimpleType())); -} - QCborContainerPrivate::~QCborContainerPrivate() { // delete our elements @@ -2508,37 +2314,6 @@ Q_NEVER_INLINE void QCborValue::toCbor(QCborStreamWriter &writer, EncodingOption } } -/*! - Creates the diagnostic notation equivalent of this CBOR object and return - it. The \a opts parameter controls the dialect of the notation. Diagnostic - notation is useful in debugging, to aid the developer in understanding what - value is stored in the QCborValue or in a CBOR stream. For that reason, the - Qt API provides no support for parsing the diagnostic back into the - in-memory format or CBOR stream, though the representation is unique and it - would be possible. - - CBOR diagnostic notation is specified by - \l{https://tools.ietf.org/html/rfc7049#section-6}{section 6} of RFC 7049. - It is a text representation of the CBOR stream and it is very similar to - JSON, but it supports the CBOR types not found in JSON. The extended format - enabled by the \l{DiagnosticNotationOption}{ExtendedFormat} flag is - currently in some IETF drafts and its format is subject to change. - - This function produces the equivalent representation of the stream that - toCbor() would produce, without any transformation option provided there. - This also implies this function may not produce a representation of the - stream that was used to create the object, if it was created using - fromCbor(), as that function may have applied transformations. For a - high-fidelity notation of a stream, without transformation, see the \c - cbordump example. - - \sa toCbor(), toJsonDocument(), QJsonDocument::toJson() - */ -QString QCborValue::toDiagnosticNotation(DiagnosticNotationOptions opts) const -{ - return DiagnosticNotation::create(*this, opts); -} - void QCborValueRef::toCbor(QCborStreamWriter &writer, QCborValue::EncodingOptions opt) { concrete().toCbor(writer, opt); diff --git a/src/corelib/serialization/qcborvalue_p.h b/src/corelib/serialization/qcborvalue_p.h index 02aa05bcdb..3a28707056 100644 --- a/src/corelib/serialization/qcborvalue_p.h +++ b/src/corelib/serialization/qcborvalue_p.h @@ -56,6 +56,8 @@ #include <private/qglobal_p.h> #include <private/qutfcodec_p.h> +#include <math.h> + QT_BEGIN_NAMESPACE namespace QtCbor { diff --git a/src/corelib/serialization/serialization.pri b/src/corelib/serialization/serialization.pri index 73b99b8e64..4f2dc64e4f 100644 --- a/src/corelib/serialization/serialization.pri +++ b/src/corelib/serialization/serialization.pri @@ -24,6 +24,7 @@ HEADERS += \ SOURCES += \ serialization/qcborstream.cpp \ + serialization/qcbordiagnostic.cpp \ serialization/qcborvalue.cpp \ serialization/qdatastream.cpp \ serialization/qjson.cpp \ diff --git a/src/gui/kernel/qplatformsurface.cpp b/src/gui/kernel/qplatformsurface.cpp index f091c04ebb..fdb2cf567d 100644 --- a/src/gui/kernel/qplatformsurface.cpp +++ b/src/gui/kernel/qplatformsurface.cpp @@ -38,6 +38,10 @@ ****************************************************************************/ #include "qplatformsurface.h" +#ifndef QT_NO_DEBUG_STREAM +#include <QtCore/qdebug.h> +#include <QtGui/qwindow.h> +#endif QT_BEGIN_NAMESPACE @@ -64,5 +68,26 @@ QPlatformSurface::QPlatformSurface(QSurface *surface) : m_surface(surface) { } +#ifndef QT_NO_DEBUG_STREAM +Q_GUI_EXPORT QDebug operator<<(QDebug debug, const QPlatformSurface *surface) +{ + QDebugStateSaver saver(debug); + debug.nospace(); + debug << "QPlatformSurface(" << (const void *)surface; + if (surface) { + QSurface *s = surface->surface(); + auto surfaceClass = s->surfaceClass(); + debug << ", class=" << surfaceClass; + debug << ", type=" << s->surfaceType(); + if (surfaceClass == QSurface::Window) + debug << ", window=" << static_cast<QWindow *>(s); + else + debug << ", surface=" << s; + } + debug << ')'; + return debug; +} +#endif // !QT_NO_DEBUG_STREAM + QT_END_NAMESPACE diff --git a/src/gui/kernel/qplatformsurface.h b/src/gui/kernel/qplatformsurface.h index 76e8767a05..4d8854fb40 100644 --- a/src/gui/kernel/qplatformsurface.h +++ b/src/gui/kernel/qplatformsurface.h @@ -58,6 +58,10 @@ QT_BEGIN_NAMESPACE class QPlatformScreen; +#ifndef QT_NO_DEBUG_STREAM +class QDebug; +#endif + class Q_GUI_EXPORT QPlatformSurface { public: @@ -76,6 +80,11 @@ private: friend class QPlatformOffscreenSurface; }; + +#ifndef QT_NO_DEBUG_STREAM +Q_GUI_EXPORT QDebug operator<<(QDebug debug, const QPlatformSurface *surface); +#endif + QT_END_NAMESPACE #endif //QPLATFORMSURFACE_H diff --git a/src/gui/kernel/qsurface.h b/src/gui/kernel/qsurface.h index e3e5106e3a..521593ea5c 100644 --- a/src/gui/kernel/qsurface.h +++ b/src/gui/kernel/qsurface.h @@ -55,11 +55,13 @@ class QSurfacePrivate; class Q_GUI_EXPORT QSurface { + Q_GADGET public: enum SurfaceClass { Window, Offscreen }; + Q_ENUM(SurfaceClass) enum SurfaceType { RasterSurface, @@ -69,6 +71,7 @@ public: VulkanSurface, MetalSurface }; + Q_ENUM(SurfaceType) virtual ~QSurface(); diff --git a/src/gui/kernel/qtestsupport_gui.h b/src/gui/kernel/qtestsupport_gui.h index 1d84591060..82a81e9214 100644 --- a/src/gui/kernel/qtestsupport_gui.h +++ b/src/gui/kernel/qtestsupport_gui.h @@ -40,7 +40,7 @@ #ifndef QTESTSUPPORT_GUI_H #define QTESTSUPPORT_GUI_H -#include "qtguiglobal.h" +#include <QtGui/qtguiglobal.h> QT_BEGIN_NAMESPACE diff --git a/src/gui/text/qtextdocumentfragment.cpp b/src/gui/text/qtextdocumentfragment.cpp index 3ad49b3f88..f0eff2d4f3 100644 --- a/src/gui/text/qtextdocumentfragment.cpp +++ b/src/gui/text/qtextdocumentfragment.cpp @@ -724,9 +724,9 @@ QTextHtmlImporter::ProcessNodeResult QTextHtmlImporter::processSpecialNodes() cursor.insertImage(fmt, QTextFrameFormat::Position(currentNode->cssFloat)); - cursor.movePosition(QTextCursor::Left, QTextCursor::KeepAnchor); + cursor.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor); cursor.mergeCharFormat(currentNode->charFormat); - cursor.movePosition(QTextCursor::Right); + cursor.movePosition(QTextCursor::NextCharacter); compressNextWhitespace = CollapseWhiteSpace; hasBlock = false; diff --git a/src/network/ssl/qdtls_openssl.cpp b/src/network/ssl/qdtls_openssl.cpp index 2e5a26d596..a8f6ebcf7f 100644 --- a/src/network/ssl/qdtls_openssl.cpp +++ b/src/network/ssl/qdtls_openssl.cpp @@ -1054,7 +1054,7 @@ bool QDtlsPrivateOpenSSL::continueHandshake(QUdpSocket *socket, const QByteArray || (dtlsConfiguration.peerVerifyMode == QSslSocket::AutoVerifyPeer && mode == QSslSocket::SslClientMode); - if (!doVerifyPeer || verifyPeer()) { + if (!doVerifyPeer || verifyPeer() || tlsErrorsWereIgnored()) { connectionEncrypted = true; handshakeState = QDtls::HandshakeComplete; return true; diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h index e13777f661..4404a04f49 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.h +++ b/src/plugins/platforms/xcb/qxcbscreen.h @@ -217,7 +217,6 @@ private: xcb_randr_crtc_t m_crtc; xcb_randr_mode_t m_mode = XCB_NONE; bool m_primary = false; - uint8_t m_rotation = XCB_RANDR_ROTATION_ROTATE_0; QString m_outputName; QSizeF m_outputSizeMillimeters; diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm index 2e2d176308..dd7959f3cf 100644 --- a/src/plugins/styles/mac/qmacstyle_mac.mm +++ b/src/plugins/styles/mac/qmacstyle_mac.mm @@ -1870,20 +1870,46 @@ NSCell *QMacStylePrivate::cocoaCell(CocoaControl widget) const return cell; } -void QMacStylePrivate::drawNSViewInRect(NSView *view, const QRectF &qtRect, QPainter *p, +void QMacStylePrivate::drawNSViewInRect(NSView *view, const QRectF &rect, QPainter *p, __attribute__((noescape)) DrawRectBlock drawRectBlock) const { QMacCGContext ctx(p); setupNSGraphicsContext(ctx, YES); - const CGRect rect = qtRect.toCGRect(); + // FIXME: The rect that we get in is relative to the widget that we're drawing + // style on behalf of, and doesn't take into account the offset of that widget + // to the widget that owns the backingstore, which we are placing the native + // view into below. This means most of the views are placed in the upper left + // corner of backingStoreNSView, which does not map to where the actual widget + // is, and which may cause problems such as triggering a setNeedsDisplay of the + // backingStoreNSView for the wrong rect. We work around this by making the view + // layer-backed, which prevents triggering display of the backingStoreNSView, but + // but there may be other issues lurking here due to the wrong position. QTBUG-68023 + view.wantsLayer = YES; + + // FIXME: We are also setting the frame of the incoming view a lot at the call + // sites of this function, making it unclear who's actually responsible for + // maintaining the size and position of the view. In theory the call sites + // should ensure the _size_ of the view is correct, and then let this code + // take care of _positioning_ the view at the right place inside backingStoreNSView. + // For now we pass on the rect as is, to prevent any regressions until this + // can be investigated properly. + view.frame = rect.toCGRect(); [backingStoreNSView addSubview:view]; - view.frame = rect; + + // FIXME: Based on the code below, this method isn't drawing an NSView into + // a rect, it's drawing _part of the NSView_, defined by the incoming clip + // or dirty rect, into the current graphics context. We're doing some manual + // translations at the call sites that would indicate that this relationship + // is a bit fuzzy. + const CGRect dirtyRect = rect.toCGRect(); + if (drawRectBlock) - drawRectBlock(ctx, rect); + drawRectBlock(ctx, dirtyRect); else - [view drawRect:rect]; + [view drawRect:dirtyRect]; + [view removeFromSuperviewWithoutNeedingDisplay]; restoreNSGraphicsContext(ctx); diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index c1b4577157..d9fbfcffa8 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -87,7 +87,6 @@ #if defined(Q_OS_LINUX) #include <sys/types.h> -#include <unistd.h> #include <fcntl.h> #endif @@ -101,6 +100,7 @@ #include <errno.h> #include <signal.h> #include <time.h> +#include <unistd.h> # if !defined(Q_OS_INTEGRITY) # include <sys/resource.h> # endif @@ -1472,8 +1472,13 @@ void FatalSignalHandler::signal(int signum) { const int msecsFunctionTime = qRound(QTestLog::msecsFunctionTime()); const int msecsTotalTime = qRound(QTestLog::msecsTotalTime()); - if (signum != SIGINT) + if (signum != SIGINT) { stackTrace(); + if (qEnvironmentVariableIsSet("QTEST_PAUSE_ON_CRASH")) { + fprintf(stderr, "Pausing process %d for debugging\n", getpid()); + raise(SIGSTOP); + } + } qFatal("Received signal %d\n" " Function time: %dms Total time: %dms", signum, msecsFunctionTime, msecsTotalTime); diff --git a/tests/auto/corelib/kernel/qelapsedtimer/BLACKLIST b/tests/auto/corelib/kernel/qelapsedtimer/BLACKLIST index 4cd3c2f0c8..4dd71ca9f4 100644 --- a/tests/auto/corelib/kernel/qelapsedtimer/BLACKLIST +++ b/tests/auto/corelib/kernel/qelapsedtimer/BLACKLIST @@ -1,3 +1,4 @@ [elapsed] windows osx-10.12 +osx-10.13 diff --git a/tests/auto/corelib/kernel/qobject/qobject.pro b/tests/auto/corelib/kernel/qobject/qobject.pro index 978aab86c1..75ad7b5f14 100644 --- a/tests/auto/corelib/kernel/qobject/qobject.pro +++ b/tests/auto/corelib/kernel/qobject/qobject.pro @@ -1,8 +1,4 @@ TEMPLATE = subdirs -!winrt { - test.depends = signalbug - SUBDIRS += signalbug -} - -SUBDIRS += test +SUBDIRS += test.pro +!winrt: SUBDIRS += signalbug diff --git a/tests/auto/corelib/kernel/qobject/signalbug/signalbug.pro b/tests/auto/corelib/kernel/qobject/signalbug/signalbug.pro index 755fecbd04..d21b3a62a9 100644 --- a/tests/auto/corelib/kernel/qobject/signalbug/signalbug.pro +++ b/tests/auto/corelib/kernel/qobject/signalbug/signalbug.pro @@ -1,20 +1,6 @@ -CONFIG -= app_bundle -CONFIG += console -debug_and_release { - CONFIG(debug, debug|release) { - TARGET = ../../debug/signalbug_helper - } else { - TARGET = ../../release/signalbug_helper - } -} else { - TARGET = ../signalbug_helper -} - QT = core HEADERS += signalbug.h SOURCES += signalbug.cpp -# This app is testdata for tst_qobject -target.path = $$[QT_INSTALL_TESTS]/tst_qobject/$$TARGET -INSTALLS += target +load(qt_test_helper) diff --git a/tests/auto/corelib/kernel/qobject/test.pro b/tests/auto/corelib/kernel/qobject/test.pro new file mode 100644 index 0000000000..af5203e152 --- /dev/null +++ b/tests/auto/corelib/kernel/qobject/test.pro @@ -0,0 +1,10 @@ +CONFIG += testcase console + +QT = core-private network testlib +TARGET = tst_qobject +SOURCES = tst_qobject.cpp + +# Force C++17 if available (needed due to P0012R1) +contains(QT_CONFIG, c++1z): CONFIG += c++1z + +DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/corelib/kernel/qobject/test/test.pro b/tests/auto/corelib/kernel/qobject/test/test.pro deleted file mode 100644 index be15074523..0000000000 --- a/tests/auto/corelib/kernel/qobject/test/test.pro +++ /dev/null @@ -1,29 +0,0 @@ -CONFIG += testcase console -debug_and_release { - CONFIG(debug, debug|release) { - TARGET = ../../debug/tst_qobject - } else { - TARGET = ../../release/tst_qobject - } -} else { - TARGET = ../tst_qobject -} - -QT = core-private network testlib -SOURCES = ../tst_qobject.cpp - -# Force C++17 if available (needed due to P0012R1) -contains(QT_CONFIG, c++1z): CONFIG += c++1z - -!winrt { - debug_and_release { - CONFIG(debug, debug|release) { - TEST_HELPER_INSTALLS = ../debug/signalbug_helper - } else { - TEST_HELPER_INSTALLS = ../release/signalbug_helper - } - } else { - TEST_HELPER_INSTALLS = ../signalbug_helper - } -} -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/corelib/kernel/qsharedmemory/sharedmemoryhelper/main.cpp b/tests/auto/corelib/kernel/qsharedmemory/producerconsumer/main.cpp index ffbad37d82..ffbad37d82 100644 --- a/tests/auto/corelib/kernel/qsharedmemory/sharedmemoryhelper/main.cpp +++ b/tests/auto/corelib/kernel/qsharedmemory/producerconsumer/main.cpp diff --git a/tests/auto/corelib/kernel/qsharedmemory/producerconsumer/producerconsumer.pro b/tests/auto/corelib/kernel/qsharedmemory/producerconsumer/producerconsumer.pro new file mode 100644 index 0000000000..a6156ed5b6 --- /dev/null +++ b/tests/auto/corelib/kernel/qsharedmemory/producerconsumer/producerconsumer.pro @@ -0,0 +1,5 @@ +QT = core testlib + +SOURCES += main.cpp + +load(qt_test_helper) diff --git a/tests/auto/corelib/kernel/qsharedmemory/qsharedmemory.pro b/tests/auto/corelib/kernel/qsharedmemory/qsharedmemory.pro index 3a4697750e..323d5bbd37 100644 --- a/tests/auto/corelib/kernel/qsharedmemory/qsharedmemory.pro +++ b/tests/auto/corelib/kernel/qsharedmemory/qsharedmemory.pro @@ -1,6 +1,6 @@ TEMPLATE = subdirs qtConfig(sharedmemory) { - !winrt: SUBDIRS = sharedmemoryhelper - SUBDIRS += test + !winrt: SUBDIRS = producerconsumer + SUBDIRS += test.pro } diff --git a/tests/auto/corelib/kernel/qsharedmemory/sharedmemoryhelper/sharedmemoryhelper.pro b/tests/auto/corelib/kernel/qsharedmemory/sharedmemoryhelper/sharedmemoryhelper.pro deleted file mode 100644 index 389015d504..0000000000 --- a/tests/auto/corelib/kernel/qsharedmemory/sharedmemoryhelper/sharedmemoryhelper.pro +++ /dev/null @@ -1,17 +0,0 @@ -QT = core testlib - -win32: CONFIG += console -mac:CONFIG -= app_bundle - -SOURCES += main.cpp -TARGET = helperbinary - -CONFIG(debug_and_release) { - CONFIG(debug, debug|release) { - DESTDIR = ../debug - } else { - DESTDIR = ../release - } -} else { - DESTDIR = .. -} diff --git a/tests/auto/corelib/kernel/qsharedmemory/test.pro b/tests/auto/corelib/kernel/qsharedmemory/test.pro new file mode 100644 index 0000000000..8b3badadb0 --- /dev/null +++ b/tests/auto/corelib/kernel/qsharedmemory/test.pro @@ -0,0 +1,8 @@ +CONFIG += testcase + +QT = core-private testlib + +TARGET = tst_qsharedmemory +SOURCES += tst_qsharedmemory.cpp + +linux: LIBS += -lrt diff --git a/tests/auto/corelib/kernel/qsharedmemory/test/test.pro b/tests/auto/corelib/kernel/qsharedmemory/test/test.pro deleted file mode 100644 index 61124c27ee..0000000000 --- a/tests/auto/corelib/kernel/qsharedmemory/test/test.pro +++ /dev/null @@ -1,18 +0,0 @@ -CONFIG += testcase - -QT = core-private testlib - -linux:LIBS += -lrt - -SOURCES += tst_qsharedmemory.cpp -TARGET = tst_qsharedmemory - -CONFIG(debug_and_release) { - CONFIG(debug, debug|release) { - DESTDIR = ../debug - } else { - DESTDIR = ../release - } -} else { - DESTDIR = .. -} diff --git a/tests/auto/corelib/kernel/qsharedmemory/test/tst_qsharedmemory.cpp b/tests/auto/corelib/kernel/qsharedmemory/tst_qsharedmemory.cpp index f81324b894..55deb8eb1a 100644 --- a/tests/auto/corelib/kernel/qsharedmemory/test/tst_qsharedmemory.cpp +++ b/tests/auto/corelib/kernel/qsharedmemory/tst_qsharedmemory.cpp @@ -51,7 +51,6 @@ public: public Q_SLOTS: void init(); - void initTestCase(); void cleanup(); @@ -101,7 +100,6 @@ private slots: void uniqueKey(); protected: - static QString helperBinary(); int remove(const QString &key); QString rememberKey(const QString &key) @@ -125,7 +123,7 @@ private: tst_QSharedMemory::tst_QSharedMemory() : existingSharedMemory(0) - , m_helperBinary(tst_QSharedMemory::helperBinary()) + , m_helperBinary("producerconsumer_helper") { } @@ -133,13 +131,6 @@ tst_QSharedMemory::~tst_QSharedMemory() { } -void tst_QSharedMemory::initTestCase() -{ -#if QT_CONFIG(process) - QVERIFY2(!m_helperBinary.isEmpty(), "Could not find helper binary"); -#endif -} - void tst_QSharedMemory::init() { existingSharedMemory = new QSharedMemory(EXISTING_SHARE); @@ -179,15 +170,6 @@ void tst_QSharedMemory::cleanup() #include <errno.h> #endif -QString tst_QSharedMemory::helperBinary() -{ - QString binary = QStringLiteral("helperbinary"); -#ifdef Q_OS_WIN - binary += QStringLiteral(".exe"); -#endif - return QFINDTESTDATA(binary); -} - int tst_QSharedMemory::remove(const QString &key) { #ifdef Q_OS_WIN diff --git a/tests/auto/corelib/kernel/qsystemsemaphore/acquirerelease/acquirerelease.pro b/tests/auto/corelib/kernel/qsystemsemaphore/acquirerelease/acquirerelease.pro new file mode 100644 index 0000000000..a6156ed5b6 --- /dev/null +++ b/tests/auto/corelib/kernel/qsystemsemaphore/acquirerelease/acquirerelease.pro @@ -0,0 +1,5 @@ +QT = core testlib + +SOURCES += main.cpp + +load(qt_test_helper) diff --git a/tests/auto/corelib/kernel/qsystemsemaphore/systemsemaphorehelper/main.cpp b/tests/auto/corelib/kernel/qsystemsemaphore/acquirerelease/main.cpp index 7bfb6b16cc..7bfb6b16cc 100644 --- a/tests/auto/corelib/kernel/qsystemsemaphore/systemsemaphorehelper/main.cpp +++ b/tests/auto/corelib/kernel/qsystemsemaphore/acquirerelease/main.cpp diff --git a/tests/auto/corelib/kernel/qsystemsemaphore/qsystemsemaphore.pro b/tests/auto/corelib/kernel/qsystemsemaphore/qsystemsemaphore.pro index f8a49254d2..70526426aa 100644 --- a/tests/auto/corelib/kernel/qsystemsemaphore/qsystemsemaphore.pro +++ b/tests/auto/corelib/kernel/qsystemsemaphore/qsystemsemaphore.pro @@ -1,3 +1,3 @@ TEMPLATE = subdirs -SUBDIRS = systemsemaphorehelper test +SUBDIRS = acquirerelease test.pro diff --git a/tests/auto/corelib/kernel/qsystemsemaphore/systemsemaphorehelper/systemsemaphorehelper.pro b/tests/auto/corelib/kernel/qsystemsemaphore/systemsemaphorehelper/systemsemaphorehelper.pro deleted file mode 100644 index 389015d504..0000000000 --- a/tests/auto/corelib/kernel/qsystemsemaphore/systemsemaphorehelper/systemsemaphorehelper.pro +++ /dev/null @@ -1,17 +0,0 @@ -QT = core testlib - -win32: CONFIG += console -mac:CONFIG -= app_bundle - -SOURCES += main.cpp -TARGET = helperbinary - -CONFIG(debug_and_release) { - CONFIG(debug, debug|release) { - DESTDIR = ../debug - } else { - DESTDIR = ../release - } -} else { - DESTDIR = .. -} diff --git a/tests/auto/corelib/kernel/qsystemsemaphore/test.pro b/tests/auto/corelib/kernel/qsystemsemaphore/test.pro new file mode 100644 index 0000000000..13bd1fa270 --- /dev/null +++ b/tests/auto/corelib/kernel/qsystemsemaphore/test.pro @@ -0,0 +1,7 @@ +CONFIG += testcase +QT = core testlib + +SOURCES += tst_qsystemsemaphore.cpp +TARGET = tst_qsystemsemaphore + +win32: CONFIG += console diff --git a/tests/auto/corelib/kernel/qsystemsemaphore/test/test.pro b/tests/auto/corelib/kernel/qsystemsemaphore/test/test.pro deleted file mode 100644 index f60207eb01..0000000000 --- a/tests/auto/corelib/kernel/qsystemsemaphore/test/test.pro +++ /dev/null @@ -1,17 +0,0 @@ -CONFIG += testcase -QT = core testlib - -win32: CONFIG += console - -SOURCES += tst_qsystemsemaphore.cpp -TARGET = tst_qsystemsemaphore - -CONFIG(debug_and_release) { - CONFIG(debug, debug|release) { - DESTDIR = ../debug - } else { - DESTDIR = ../release - } -} else { - DESTDIR = .. -} diff --git a/tests/auto/corelib/kernel/qsystemsemaphore/test/tst_qsystemsemaphore.cpp b/tests/auto/corelib/kernel/qsystemsemaphore/tst_qsystemsemaphore.cpp index 6ff1e14976..5f010ae3d1 100644 --- a/tests/auto/corelib/kernel/qsystemsemaphore/test/tst_qsystemsemaphore.cpp +++ b/tests/auto/corelib/kernel/qsystemsemaphore/tst_qsystemsemaphore.cpp @@ -42,7 +42,6 @@ public: tst_QSystemSemaphore(); public Q_SLOTS: - void initTestCase(); void init(); void cleanup(); @@ -65,22 +64,16 @@ private slots: void initialValue(); private: - static QString helperBinary(); QSystemSemaphore *existingLock; const QString m_helperBinary; }; tst_QSystemSemaphore::tst_QSystemSemaphore() - : m_helperBinary(helperBinary()) + : m_helperBinary("acquirerelease_helper") { } -void tst_QSystemSemaphore::initTestCase() -{ - QVERIFY2(!m_helperBinary.isEmpty(), "Could not find helper binary"); -} - void tst_QSystemSemaphore::init() { existingLock = new QSystemSemaphore(EXISTING_SHARE, 1, QSystemSemaphore::Create); @@ -294,14 +287,6 @@ void tst_QSystemSemaphore::initialValue() #endif } -QString tst_QSystemSemaphore::helperBinary() -{ - QString binary = QStringLiteral("helperbinary"); -#ifdef Q_OS_WIN - binary += QStringLiteral(".exe"); -#endif - return QFINDTESTDATA(binary); -} QTEST_MAIN(tst_QSystemSemaphore) #include "tst_qsystemsemaphore.moc" diff --git a/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp b/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp index 8ab43f9fc9..e469bffa4f 100644 --- a/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp +++ b/tests/auto/corelib/serialization/qcborvalue/tst_qcborvalue.cpp @@ -95,6 +95,8 @@ private slots: void fromCbor(); void validation_data(); void validation(); + void toDiagnosticNotation_data(); + void toDiagnosticNotation(); }; // Get the validation data from TinyCBOR (see src/3rdparty/tinycbor/tests/parser/data.cpp) @@ -1517,6 +1519,169 @@ void tst_QCborValue::validation() } } +void tst_QCborValue::toDiagnosticNotation_data() +{ + QTest::addColumn<QCborValue>("v"); + QTest::addColumn<int>("opts"); + QTest::addColumn<QString>("expected"); + QDateTime dt = QDateTime::currentDateTimeUtc(); + QUuid uuid = QUuid::createUuid(); + + QMetaEnum me = QMetaEnum::fromType<QCborValue::Type>(); + auto st = [](QCborSimpleType t) { return QVariant::fromValue<SimpleTypeWrapper>(t); }; + auto add = [me](const QCborValue &v, const QString &exp) { + auto addRow = [=](const char *prefix) -> QTestData & { + QCborValue::Type t = v.type(); + if (t == QCborValue::Integer) + return QTest::addRow("%sInteger:%lld", prefix, v.toInteger()); + if (t == QCborValue::Double) + return QTest::addRow("%sDouble:%g", prefix, v.toDouble()); + if (t == QCborValue::ByteArray) + return QTest::addRow("%sByteArray:%d", prefix, v.toByteArray().size()); + if (t == QCborValue::String) + return QTest::addRow("%sString:%d", prefix, v.toString().size()); + + QByteArray typeString = me.valueToKey(t); + Q_ASSERT(!typeString.isEmpty()); + return QTest::newRow(prefix + typeString); + }; + addRow("") << v << int(QCborValue::DiagnosticNotationOptions{}) << exp; + addRow("LW:") << v << int(QCborValue::LineWrapped) << exp; + addRow("Array:") << QCborValue(QCborArray{v}) << int(QCborValue::DiagnosticNotationOptions{}) << '[' + exp + ']'; + addRow("Mapped:") << QCborValue(QCborMap{{2, v}}) << int(QCborValue::DiagnosticNotationOptions{}) << "{2: " + exp + '}'; + addRow("Mapping:") << QCborValue(QCborMap{{v, 2}}) << int(QCborValue::DiagnosticNotationOptions{}) << '{' + exp + ": 2}"; + }; + + // empty arrays and maps + QTest::newRow("EmptyArray") + << QCborValue(QCborArray()) << int(QCborValue::DiagnosticNotationOptions{}) + << "[]"; + QTest::newRow("EmptyMap") + << QCborValue(QCborMap()) << int(QCborValue::DiagnosticNotationOptions{}) + << "{}"; + + add(QCborValue(), "undefined"); + add(QCborValue::Null, "null"); + add(false, "false"); + add(true, "true"); + add(QCborSimpleType(0), "simple(0)"); + QTest::newRow("SimpleType-255") + << QCborValue(QCborSimpleType(255)) << int(QCborValue::DiagnosticNotationOptions{}) + << "simple(255)"; + add(0, "0"); + add(1, "1"); + add(-1, "-1"); + add(std::numeric_limits<qint64>::min(), QString::number(std::numeric_limits<qint64>::min())); + add(std::numeric_limits<qint64>::max(), QString::number(std::numeric_limits<qint64>::max())); + add(0., "0.0"); + add(1.25, "1.25"); + add(-1.25, "-1.25"); + add(qInf(), "inf"); + add(-qInf(), "-inf"); + add(qQNaN(), "nan"); + add(QByteArray(), "h''"); + add(QByteArray("Hello"), "h'48656c6c6f'"); + add(QLatin1String(), QLatin1String("\"\"")); + add("Hello", "\"Hello\""); + add("\"Hello\\World\"", "\"\\\"Hello\\\\World\\\"\""); + add(QCborValue(dt), "0(\"" + dt.toString(Qt::ISODateWithMs) + "\")"); + add(QCborValue(QUrl("http://example.com")), "32(\"http://example.com\")"); + add(QCborValue(QRegularExpression("^.*$")), "35(\"^.*$\")"); + add(QCborValue(uuid), "37(h'" + uuid.toString(QUuid::Id128) + "')"); + + // arrays and maps with more than one element + QTest::newRow("2Array") + << QCborValue(QCborArray{0, 1}) << int(QCborValue::DiagnosticNotationOptions{}) + << "[0, 1]"; + QTest::newRow("2Map") + << QCborValue(QCborMap{{0, 1}, {"foo", "bar"}}) << int(QCborValue::DiagnosticNotationOptions{}) + << "{0: 1, \"foo\": \"bar\"}"; + + // line wrapping in arrays and maps + QTest::newRow("LW:EmptyArray") + << QCborValue(QCborArray()) << int(QCborValue::LineWrapped) + << "[\n]"; + QTest::newRow("LW:EmptyMap") + << QCborValue(QCborMap()) << int(QCborValue::LineWrapped) + << "{\n}"; + QTest::newRow("LW:Array:Integer:0") + << QCborValue(QCborArray{0}) << int(QCborValue::LineWrapped) + << "[\n 0\n]"; + QTest::newRow("LW:Array:String:5") + << QCborValue(QCborArray{"Hello"}) << int(QCborValue::LineWrapped) + << "[\n \"Hello\"\n]"; + QTest::newRow("LW:Map:0-0") + << QCborValue(QCborMap{{0, 0}}) << int(QCborValue::LineWrapped) + << "{\n 0: 0\n}"; + QTest::newRow("LW:Map:String:5") + << QCborValue(QCborMap{{0, "Hello"}}) << int(QCborValue::LineWrapped) + << "{\n 0: \"Hello\"\n}"; + QTest::newRow("LW:2Array") + << QCborValue(QCborArray{0, 1}) << int(QCborValue::LineWrapped) + << "[\n 0,\n 1\n]"; + QTest::newRow("LW:2Map") + << QCborValue(QCborMap{{0, 0}, {"foo", "bar"}}) << int(QCborValue::LineWrapped) + << "{\n 0: 0,\n \"foo\": \"bar\"\n}"; + + // nested arrays and maps + QTest::newRow("Array:EmptyArray") + << QCborValue(QCborArray() << QCborArray()) << int(QCborValue::DiagnosticNotationOptions{}) + << "[[]]"; + QTest::newRow("Array:EmptyMap") + << QCborValue(QCborArray() << QCborMap()) << int(QCborValue::DiagnosticNotationOptions{}) + << "[{}]"; + QTest::newRow("LW:Array:EmptyArray") + << QCborValue(QCborArray() << QCborArray()) << int(QCborValue::LineWrapped) + << "[\n [\n ]\n]"; + QTest::newRow("LW:Array:EmptyMap") + << QCborValue(QCborArray() << QCborMap()) << int(QCborValue::LineWrapped) + << "[\n {\n }\n]"; + QTest::newRow("LW:Array:2Array") + << QCborValue(QCborArray() << QCborArray{0, 1}) << int(QCborValue::LineWrapped) + << "[\n [\n 0,\n 1\n ]\n]"; + QTest::newRow("LW:Map:2Array") + << QCborValue(QCborMap{{0, QCborArray{0, 1}}}) << int(QCborValue::LineWrapped) + << "{\n 0: [\n 0,\n 1\n ]\n}"; + QTest::newRow("LW:Map:2Map") + << QCborValue(QCborMap{{-1, QCborMap{{0, 0}, {"foo", "bar"}}}}) << int(QCborValue::LineWrapped) + << "{\n -1: {\n 0: 0,\n \"foo\": \"bar\"\n }\n}"; + + // extended formatting for byte arrays + QTest::newRow("Extended:ByteArray:0") + << QCborValue(QByteArray()) << int(QCborValue::ExtendedFormat) + << "h''"; + QTest::newRow("Extended:ByteArray:5") + << QCborValue(QByteArray("Hello")) << int(QCborValue::ExtendedFormat) + << "h'48 65 6c 6c 6f'"; + QTest::newRow("Extended:ByteArray:Base64url") + << QCborValue(QCborKnownTags::ExpectedBase64url, QByteArray("\xff\xef")) + << int(QCborValue::ExtendedFormat) << "21(b64'_-8')"; + QTest::newRow("Extended:ByteArray:Base64") + << QCborValue(QCborKnownTags::ExpectedBase64, QByteArray("\xff\xef")) + << int(QCborValue::ExtendedFormat) << "22(b64'/+8=')"; + + // formatting applies through arrays too + QTest::newRow("Extended:Array:ByteArray:Base64url") + << QCborValue(QCborKnownTags::ExpectedBase64url, QCborArray{QByteArray("\xff\xef")}) + << int(QCborValue::ExtendedFormat) << "21([b64'_-8'])"; + // and only the innermost applies + QTest::newRow("ByteArray:multiple-tags") + << QCborValue(QCborKnownTags::ExpectedBase64url, + QCborArray{QCborValue(QCborKnownTags::ExpectedBase16, QByteArray("Hello")), + QByteArray("\xff\xef")}) + << int(QCborValue::ExtendedFormat) << "21([23(h'48 65 6c 6c 6f'), b64'_-8'])"; +} + +void tst_QCborValue::toDiagnosticNotation() +{ + QFETCH(QCborValue, v); + QFETCH(QString, expected); + QFETCH(int, opts); + + QString result = v.toDiagnosticNotation(QCborValue::DiagnosticNotationOptions(opts)); + QCOMPARE(result, expected); +} + QTEST_MAIN(tst_QCborValue) #include "tst_qcborvalue.moc" diff --git a/tests/auto/corelib/serialization/qcborvalue_json/tst_qcborvalue_json.cpp b/tests/auto/corelib/serialization/qcborvalue_json/tst_qcborvalue_json.cpp index ad4c48450a..56245a7173 100644 --- a/tests/auto/corelib/serialization/qcborvalue_json/tst_qcborvalue_json.cpp +++ b/tests/auto/corelib/serialization/qcborvalue_json/tst_qcborvalue_json.cpp @@ -300,12 +300,12 @@ void tst_QCborValue_Json::nonStringKeysInMaps_data() QTest::newRow("base64") << QCborValue(QCborKnownTags::ExpectedBase64, data) << "/wE="; QTest::newRow("hex") << QCborValue(QCborKnownTags::ExpectedBase16, data) << "ff01"; - QTest::newRow("emptyarray") << QCborValue(QCborValue::Array) << "[ ]"; - QTest::newRow("emptymap") << QCborValue(QCborValue::Map) << "{ }"; + QTest::newRow("emptyarray") << QCborValue(QCborValue::Array) << "[]"; + QTest::newRow("emptymap") << QCborValue(QCborValue::Map) << "{}"; QTest::newRow("array") << QCborValue(QCborArray{1, true, 2.5, "Hello"}) - << "[ 1, true, 2.5, \"Hello\" ]"; + << "[1, true, 2.5, \"Hello\"]"; QTest::newRow("map") << QCborValue(QCborMap{{"Hello", 0}, {0, "Hello"}}) - << "{ \"Hello\": 0, 0: \"Hello\" }"; + << "{\"Hello\": 0, 0: \"Hello\"}"; QDateTime dt = QDateTime::currentDateTimeUtc(); QUrl url("https://example.com"); diff --git a/tests/auto/corelib/tools/qtimeline/BLACKLIST b/tests/auto/corelib/tools/qtimeline/BLACKLIST index 74f84a4a6d..958563d15e 100644 --- a/tests/auto/corelib/tools/qtimeline/BLACKLIST +++ b/tests/auto/corelib/tools/qtimeline/BLACKLIST @@ -1,6 +1,7 @@ [interpolation] windows osx-10.12 +osx-10.13 [duration] windows [frameRate] diff --git a/tests/auto/network/ssl/qdtls/tst_qdtls.cpp b/tests/auto/network/ssl/qdtls/tst_qdtls.cpp index 571d341126..60ab87d6f2 100644 --- a/tests/auto/network/ssl/qdtls/tst_qdtls.cpp +++ b/tests/auto/network/ssl/qdtls/tst_qdtls.cpp @@ -41,6 +41,7 @@ #include <QtCore/qcryptographichash.h> #include <QtCore/qbytearray.h> +#include <QtCore/qvector.h> #include <QtCore/qstring.h> #include <QtCore/qobject.h> @@ -99,6 +100,7 @@ private slots: void protocolVersionMatching(); void verificationErrors_data(); void verificationErrors(); + void ignoreExpectedErrors(); void verifyServerCertificate_data(); void verifyServerCertificate(); void verifyClientCertificate_data(); @@ -685,6 +687,31 @@ void tst_QDtls::verificationErrors() } } +void tst_QDtls::ignoreExpectedErrors() +{ + connectHandshakeReadingSlots(); + + auto serverConfig = defaultServerConfig; + serverConfig.setPrivateKey(serverKeySS); + serverConfig.setLocalCertificate(selfSignedCert); + QVERIFY(serverCrypto->setDtlsConfiguration(serverConfig)); + + const QVector<QSslError> expectedErrors = {{QSslError::HostNameMismatch, selfSignedCert}, + {QSslError::SelfSignedCertificate, selfSignedCert}}; + + clientCrypto->ignoreVerificationErrors(expectedErrors); + QVERIFY(clientCrypto->setPeer(serverAddress, serverPort)); + QVERIFY(clientCrypto->doHandshake(&clientSocket)); + + testLoop.enterLoopMSecs(handshakeTimeoutMS); + + QVERIFY(!testLoop.timeout()); + + QDTLS_VERIFY_HANDSHAKE_SUCCESS(serverCrypto); + QCOMPARE(clientCrypto->handshakeState(), QDtls::HandshakeComplete); + QVERIFY(clientCrypto->isConnectionEncrypted()); +} + void tst_QDtls::verifyServerCertificate_data() { QTest::addColumn<QSslSocket::PeerVerifyMode>("verifyMode"); diff --git a/tests/auto/widgets/kernel/qwidget/BLACKLIST b/tests/auto/widgets/kernel/qwidget/BLACKLIST index d135b15c6e..a9fbf02923 100644 --- a/tests/auto/widgets/kernel/qwidget/BLACKLIST +++ b/tests/auto/widgets/kernel/qwidget/BLACKLIST @@ -32,6 +32,7 @@ osx [showMinimizedKeepsFocus] osx-10.11 ci osx-10.12 ci +osx-10.13 ci [maskedUpdate] opensuse-42.3 [moveInResizeEvent] |